Skip to content

Commit

Permalink
Merge branch 'misc-fixes' of https://github.com/visendev/pnut into mi…
Browse files Browse the repository at this point in the history
…sc-fixes
  • Loading branch information
VisenDev committed Jan 7, 2025
2 parents d94a41c + e8f4d93 commit abd1dd4
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 24 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ jobs:
bootstrap-pnut-sh:
strategy:
matrix:
shell: ["ksh"]
shell: ["bash", "dash", "ksh", "mksh", "yash", "zsh"]
runs-on: ubuntu-latest
steps:
- name: Checkout code
Expand All @@ -138,7 +138,7 @@ jobs:
- name: Bootstrap pnut-sh.sh on ${{ matrix.shell }}
run: |
set -e
ksh ./bootstrap-pnut-sh.sh --shell ${{ matrix.shell }} --fast
./bootstrap-pnut-sh.sh --shell ${{ matrix.shell }} --fast
bootstrap-pnut-exe:
strategy:
Expand Down
10 changes: 8 additions & 2 deletions analysis/measure-file-size.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,14 @@ expand_includes() { # $1 = output-name, $2 = options
./$TEMP_DIR/pnut-sh.exe pnut.c $2 > "$TEMP_DIR/$1.sh"
./$TEMP_DIR/pnut-sh.exe "$TEMP_DIR/$1.c" $2 > "$TEMP_DIR/$1-preincluded.sh"

diff -q "$TEMP_DIR/$1.sh" "$TEMP_DIR/$1-preincluded.sh" || \
{ echo "Error: $1.sh and $1-preincluded.sh differ"; exit 1; }
# Because we use the __FILE__ macro in pnut, the preincluded.sh file will have
# a different path than the original file. We need to replace the path in the
# preincluded file with the path of the original file.
# Note: | is used as the delimiter because the path contains /
cat "$TEMP_DIR/$1-preincluded.sh" | sed "s|$TEMP_DIR/$1.c|pnut.c|" > "$TEMP_DIR/$1-preincluded-canonical.sh"

diff -q "$TEMP_DIR/$1.sh" "$TEMP_DIR/$1-preincluded-canonical.sh" || \
{ echo "Error: $1.sh and $1-preincluded-canonical.sh differ"; exit 1; }
}

included_files() {
Expand Down
2 changes: 1 addition & 1 deletion bootstrap-pnut-exe.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ if [ ! -d "$TEMP_DIR" ]; then mkdir "$TEMP_DIR"; fi
printf_timing() {
msg=$1
cmd=$2
real_time=`/usr/bin/time -p sh -c "$cmd" 2>&1 | grep '^real ' | sed 's/.* //'`
real_time=`env time -p sh -c "$cmd" 2>&1 | grep '^real ' | sed 's/.* //'`
printf "%ss %s\n" $real_time "$msg"
}

Expand Down
2 changes: 1 addition & 1 deletion bootstrap-pnut-sh.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ bootstrap_with_shell() {

echo "Bootstrap with $1"

/usr/bin/time $1 "$TEMP_DIR/pnut-sh.sh" $PNUT_SH_OPTIONS "pnut.c" > "$TEMP_DIR/pnut-sh-twice-bootstrapped.sh"
env time $1 "$TEMP_DIR/pnut-sh.sh" $PNUT_SH_OPTIONS "pnut.c" > "$TEMP_DIR/pnut-sh-twice-bootstrapped.sh"

diff "$TEMP_DIR/pnut-sh.sh" "$TEMP_DIR/pnut-sh-twice-bootstrapped.sh"

Expand Down
7 changes: 3 additions & 4 deletions examples/compiled/base64.sh
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,15 @@ _encode() {
printf \\$(((_$((_codes + (b1 >> 2))))/64))$(((_$((_codes + (b1 >> 2))))/8%8))$(((_$((_codes + (b1 >> 2))))%8))
if [ $b2 -lt 0 ] ; then
printf \\$(((_$((_codes + (63 & (b1 << 4)))))/64))$(((_$((_codes + (63 & (b1 << 4)))))/8%8))$(((_$((_codes + (63 & (b1 << 4)))))%8))
printf \\$(((__EQ__)/64))$(((__EQ__)/8%8))$(((__EQ__)%8))
printf \\$(((__EQ__)/64))$(((__EQ__)/8%8))$(((__EQ__)%8))
printf "="
printf "="
break
else
printf \\$(((_$((_codes + (63 & ((b1 << 4) | (b2 >> 4))))))/64))$(((_$((_codes + (63 & ((b1 << 4) | (b2 >> 4))))))/8%8))$(((_$((_codes + (63 & ((b1 << 4) | (b2 >> 4))))))%8))
_getchar b3
if [ $b3 -lt 0 ] ; then
printf \\$(((_$((_codes + (63 & (b2 << 2)))))/64))$(((_$((_codes + (63 & (b2 << 2)))))/8%8))$(((_$((_codes + (63 & (b2 << 2)))))%8))
printf \\$(((__EQ__)/64))$(((__EQ__)/8%8))$(((__EQ__)%8))
printf "="
break
else
printf \\$(((_$((_codes + (63 & ((b2 << 2) | (b3 >> 6))))))/64))$(((_$((_codes + (63 & ((b2 << 2) | (b3 >> 6))))))/8%8))$(((_$((_codes + (63 & ((b2 << 2) | (b3 >> 6))))))%8))
Expand Down Expand Up @@ -164,7 +164,6 @@ _main() { let argc $2; let myargv $3
readonly __NUL__=0
readonly __NEWLINE__=10
readonly __MINUS__=45
readonly __EQ__=61
readonly __d__=100
# Runtime library
__stdin_buf=
Expand Down
5 changes: 2 additions & 3 deletions examples/compiled/sha256sum.sh
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ _process_file() { let filename $2
_hex __ $h
: $((i += 1))
done
printf \\$(((__SPACE__)/64))$(((__SPACE__)/8%8))$(((__SPACE__)%8))
printf \\$(((__SPACE__)/64))$(((__SPACE__)/8%8))$(((__SPACE__)%8))
printf " "
printf " "
while [ $((_$filename)) != 0 ]; do
printf \\$(((_$filename)/64))$(((_$filename)/8%8))$(((_$filename)%8))
: $((filename += 1))
Expand All @@ -233,7 +233,6 @@ _main() { let argc $2; let myargv $3
# Character constants
readonly __NEWLINE__=10
readonly __SPACE__=32
# Runtime library
unpack_escaped_string() {
Expand Down
54 changes: 48 additions & 6 deletions pnut.c
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,13 @@ int WRITE_ID;
int OPEN_ID;
int CLOSE_ID;

// Macros that are defined by the preprocessor
int FILE__ID;
int LINE__ID;
int DATE__ID;
int TIME__ID;
int TIMESTAMP__ID;

// When we parse a macro, we generally want the tokens as they are, without expanding them.
void get_tok_macro() {
bool prev_expand_macro = expand_macro;
Expand Down Expand Up @@ -1263,8 +1270,7 @@ void get_ident() {
tok = heap[val+2];
}

int init_ident(int tok, char *name) {

int intern_str(char* name) {
int i = 0;
int prev_ch = ch; // The character may be important to the calling function, saving it

Expand All @@ -1276,15 +1282,19 @@ int init_ident(int tok, char *name) {
i += 1;
}

i = end_ident();

heap[i+2] = tok;
i = end_string();

ch = prev_ch;

return i;
}

int init_ident(int tok, char *name) {
int i = intern_str(name);
heap[i+2] = tok;
return i;
}

void init_ident_table() {

int i = 0;
Expand Down Expand Up @@ -1367,8 +1377,28 @@ void init_ident_table() {
NOT_SUPPORTED_ID = init_ident(IDENTIFIER, "NOT_SUPPORTED");
}

void init_builtin_string_macro(int macro_id, char* value) {
// Macro object shape: ([(tok, val)], arity). -1 arity means it's an object-like macro
heap[macro_id + 3] = cons(cons(cons(STRING, intern_str(value)), 0), -1);
}

void init_builtin_int_macro(int macro_id, int value) {
heap[macro_id + 3] = cons(cons(cons(INTEGER, -value), 0), -1);
}

void init_pnut_macros() {
init_ident(MACRO, "PNUT_CC");
FILE__ID = init_ident(MACRO, "__FILE__");
LINE__ID = init_ident(MACRO, "__LINE__");
DATE__ID = init_ident(MACRO, "__DATE__");
TIME__ID = init_ident(MACRO, "__TIME__");
TIMESTAMP__ID = init_ident(MACRO, "__TIMESTAMP__");

init_builtin_string_macro(FILE__ID, "<unknown>");
init_builtin_int_macro (LINE__ID, 0);
init_builtin_string_macro(DATE__ID, "Jan 1 1970");
init_builtin_string_macro(TIME__ID, "00:00:00");
init_builtin_string_macro(TIMESTAMP__ID, "Jan 1 1970 00:00:00");
}

// A macro argument is represented using a list of tokens.
Expand Down Expand Up @@ -1490,7 +1520,19 @@ bool attempt_macro_expansion(int macro) {
int tokens = car(heap[macro + 3]);
macro = val;
if (cdr(heap[macro + 3]) == -1) { // Object-like macro
play_macro(tokens, 0);
// Note: Redefining __{FILE,LINE}__ macros, either with the #define or #line
// directives is not supported.
if (macro == FILE__ID) {
play_macro(cons(cons(STRING, intern_str(fp_filepath)), 0), 0);
}
#ifdef INCLUDE_LINE_NUMBER_ON_ERROR
else if (macro == LINE__ID) {
play_macro(cons(cons(INTEGER, -line_number), 0), 0);
}
#endif
else {
play_macro(tokens, 0);
}
return true;
} else {
new_macro_args = get_macro_args_toks(macro);
Expand Down
11 changes: 8 additions & 3 deletions run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,14 @@ esac
compile_pnut() { # extra pnut compilation options: $1
pnut_source="pnut.c"
extra_opts="$1"
extra_opts_id=$(printf "%s" $extra_opts | base64)
pnut_exe="./tests/pnut-by-gcc-$extra_opts_id.exe"
pnut_exe_backend="./tests/pnut-$extra_opts_id.$ext"
if [ -z "$extra_opts" ]; then
extra_opts_id="base"
else
extra_opts_id=$(printf "%s" "$extra_opts" | md5sum | cut -c 1-16) # 16 characters should be enough
fi
extra_opts_suffix=${extra_opts_id:+"-"}$extra_opts_id # Add a dash if there are extra options
pnut_exe="./tests/pnut-by-gcc${extra_opts_suffix}.exe"
pnut_exe_backend="./tests/pnut-$extra_opts_suffix.$ext"

if [ ! -f "$pnut_exe" ]; then
gcc "$pnut_source" $PNUT_EXE_OPTIONS $extra_opts -o "$pnut_exe" 2> /dev/null || fail "Error: Failed to compile $pnut_source with $backend"
Expand Down
13 changes: 11 additions & 2 deletions sh.c
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,7 @@ ast handle_side_effects_go(ast node, bool executes_conditionally) {
ast previous_conditional_fun_calls;
ast left_conditional_fun_calls;
ast right_conditional_fun_calls;
int start_gensym_ix = gensym_ix;

if (nb_children == 0) {
if (op == IDENTIFIER || op == IDENTIFIER_INTERNAL || op == IDENTIFIER_STRING || op == IDENTIFIER_DOLLAR || op == INTEGER || op == CHARACTER) {
Expand Down Expand Up @@ -967,9 +968,11 @@ ast handle_side_effects_go(ast node, bool executes_conditionally) {
// The left side is always executed, unless the whole expression is executed conditionally.
// We could compile it as always executed, but it makes the Shell code less regular so we compile it conditionally.
sub1 = handle_side_effects_go(get_child(node, 0), true);
gensym_ix = start_gensym_ix; // Reset gensym counter because the 2 sides are independent
left_conditional_fun_calls = conditional_fun_calls;
conditional_fun_calls = 0;
sub2 = handle_side_effects_go(get_child(node, 1), true);
gensym_ix = start_gensym_ix; // Reset gensym counter because the 2 sides are independent
right_conditional_fun_calls = conditional_fun_calls;
conditional_fun_calls = previous_conditional_fun_calls;
return new_ast4(op, sub1, sub2, left_conditional_fun_calls, right_conditional_fun_calls);
Expand Down Expand Up @@ -1442,15 +1445,21 @@ text fun_call_params(ast params) {

#ifdef INCLUDE_COMP_PUTCHAR_INLINE
text comp_putchar_inline(ast param) {
text res = comp_rvalue(param, RVALUE_CTX_ARITH_EXPANSION);
text res;
ast ident;

if (get_op(param) == CHARACTER && get_val(param) >= 32 && get_val(param) <= 126) { // Printable ASCII characters
return string_concat3(wrap_str_lit("printf \""), escape_text(wrap_char(get_val(param)), true), wrap_char('\"'));
}

res = comp_rvalue(param, RVALUE_CTX_ARITH_EXPANSION);

if (contains_side_effects) {
ident = fresh_ident();
append_glo_decl(string_concat4(comp_lvalue(ident), wrap_str_lit("=$(("), res, wrap_str_lit("))")));
res = comp_lvalue(ident);
} else if (get_op(param) != IDENTIFIER) {
res = string_concat3(wrap_char('('), res, wrap_char(')'));
res = string_concat3(wrap_char('('), res, wrap_char(')')); // Wrap in parentheses to avoid priority of operations issues
}

res =
Expand Down
46 changes: 46 additions & 0 deletions tests/_all/preprocessor/macro/builtin-stubbed.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// tests for __FILE__, __LINE__, __DATE__, __TIME__, __TIMESTAMP__ built-in macros
#include <stdio.h>

#ifndef __FILE__
#error "__FILE__ is not defined"
#endif
#ifndef __LINE__
#error "__LINE__ is not defined"
#endif
#ifndef __DATE__
#error "__DATE__ is not defined"
#endif
#ifndef __TIME__
#error "__TIME__ is not defined"
#endif
#ifndef __TIMESTAMP__
#error "__TIMESTAMP__ is not defined"
#endif

void putint(int n) {
if (n < 0) {
putchar('-');
putint(-n);
} else if (n > 9) {
putint(n / 10);
putchar('0' + n % 10);
} else {
putchar('0' + n);
}
}

void putstr(char *str) {
while (*str) {
putchar(*str);
str += 1;
}
}

int main() {
putstr(__FILE__); putchar('\n');
putint(__LINE__); putchar('\n');
putstr(__DATE__); putchar('\n');
putstr(__TIME__); putchar('\n');
putstr(__TIMESTAMP__); putchar('\n');
return 0;
}
5 changes: 5 additions & 0 deletions tests/_all/preprocessor/macro/builtin-stubbed.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
tests/_all/preprocessor/macro/builtin-stubbed.c
0
Jan 1 1970
00:00:00
Jan 1 1970 00:00:00
3 changes: 3 additions & 0 deletions tests/_all/preprocessor/macro/builtin.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// tests for __FILE__, __LINE__, __DATE__, __TIME__, __TIMESTAMP__ built-in macros
// comp_pnut_opt: -DINCLUDE_LINE_NUMBER_ON_ERROR
#include "builtin-stubbed.c"
5 changes: 5 additions & 0 deletions tests/_all/preprocessor/macro/builtin.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
tests/_all/preprocessor/macro/builtin-stubbed.c
41
Jan 1 1970
00:00:00
Jan 1 1970 00:00:00

0 comments on commit abd1dd4

Please sign in to comment.