Skip to content

Commit

Permalink
Merge pull request #125 from udem-dlteam/laurent/support-c99-buildin-…
Browse files Browse the repository at this point in the history
…macros

Support __{FILE,LINE,DATE,TIME,TIMESTAMP}__ macros
  • Loading branch information
laurenthuberdeau authored Jan 3, 2025
2 parents d6d74dc + 4223489 commit f13b91d
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 9 deletions.
54 changes: 48 additions & 6 deletions pnut.c
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,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 @@ -1260,8 +1267,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 @@ -1273,15 +1279,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 @@ -1364,8 +1374,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 @@ -1487,7 +1517,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
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 f13b91d

Please sign in to comment.