Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support __{FILE,LINE,DATE,TIME,TIMESTAMP}__ macros #125

Merged
merged 3 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 47 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,18 @@ 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: We don't check if the macro was redefined by the program
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
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
Loading