From 824dcebe59f52a686b003214c1af0633cf5fe89e Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Sun, 9 Jul 2017 05:30:47 +0200 Subject: [PATCH] tccpp: Implement __COUNTER__ This requires one more change in how macro arguments are expanded: the standard requires that macro args are expanded before substituting into the replacement list. This implies expanding them only once even when they occur multiple times in the list. TCC expanded them repeatedly in that case. Without __COUNTER__ that's harmless. So, simply always expand arguments (when used without # and ##) once and store the resulting tokens. --- libtcc.c | 1 + tccpp.c | 39 +++++++++++++++++++++++++++----------- tcctok.h | 1 + tests/pp/pp-counter.c | 27 ++++++++++++++++++++++++++ tests/pp/pp-counter.expect | 15 +++++++++++++++ 5 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 tests/pp/pp-counter.c create mode 100644 tests/pp/pp-counter.expect diff --git a/libtcc.c b/libtcc.c index 0e5f55b..ba50ddf 100644 --- a/libtcc.c +++ b/libtcc.c @@ -762,6 +762,7 @@ LIBTCCAPI TCCState *tcc_new(void) define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL); define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL); define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL); + define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL); { /* define __TINYC__ 92X */ char buffer[32]; int a,b,c; diff --git a/tccpp.c b/tccpp.c index ced5cc6..dca900c 100644 --- a/tccpp.c +++ b/tccpp.c @@ -2980,18 +2980,29 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) str.len--; goto add_var; } - } else { - for(;;) { - int t1; - TOK_GET(&t1, &st, &cval); - if (t1 <= 0) - break; - tok_str_add2(&str, t1, &cval); - } } } else { add_var: - macro_subst(&str, nested_list, st); + if (!s->next) { + /* Expand arguments tokens and store them. In most + cases we could also re-expand each argument if + used multiple times, but not if the argument + contains the __COUNTER__ macro. */ + TokenString str2; + sym_push2(&s->next, s->v, s->type.t, 0); + tok_str_new(&str2); + macro_subst(&str2, nested_list, st); + tok_str_add(&str2, 0); + s->next->d = str2.str; + } + st = s->next->d; + } + for(;;) { + int t2; + TOK_GET(&t2, &st, &cval); + if (t2 <= 0) + break; + tok_str_add2(&str, t2, &cval); } if (str.len == l0) /* expanded to empty string */ tok_str_add(&str, TOK_PLCHLDR); @@ -3180,11 +3191,13 @@ static int macro_subst_tok( CValue cval; CString cstr; char buf[32]; + static int counter; /* if symbol is a macro, prepare substitution */ /* special macros */ - if (tok == TOK___LINE__) { - snprintf(buf, sizeof(buf), "%d", file->line_num); + if (tok == TOK___LINE__ || tok == TOK___COUNTER__) { + t = tok == TOK___LINE__ ? file->line_num : counter++; + snprintf(buf, sizeof(buf), "%d", t); cstrval = buf; t1 = TOK_PPNUM; goto add_cstr1; @@ -3316,6 +3329,10 @@ static int macro_subst_tok( while (sa) { sa1 = sa->prev; tok_str_free_str(sa->d); + if (sa->next) { + tok_str_free_str(sa->next->d); + sym_free(sa->next); + } sym_free(sa); sa = sa1; } diff --git a/tcctok.h b/tcctok.h index 56e1ae3..6d4ad30 100644 --- a/tcctok.h +++ b/tcctok.h @@ -87,6 +87,7 @@ DEF(TOK___TIME__, "__TIME__") DEF(TOK___FUNCTION__, "__FUNCTION__") DEF(TOK___VA_ARGS__, "__VA_ARGS__") + DEF(TOK___COUNTER__, "__COUNTER__") /* special identifiers */ DEF(TOK___FUNC__, "__func__") diff --git a/tests/pp/pp-counter.c b/tests/pp/pp-counter.c new file mode 100644 index 0000000..3978e1a --- /dev/null +++ b/tests/pp/pp-counter.c @@ -0,0 +1,27 @@ +X1 __COUNTER__ +X2 __COUNTER__ +#if __COUNTER__ +X3 __COUNTER__ +#endif +#define pass(x) x +#define a x __COUNTER__ y +#define a2 pass(__COUNTER__) +#define f(c) c __COUNTER__ +#define apply(d) d d __COUNTER__ x2 f(d) y2 __COUNTER__ +#define _paste(a,b) a ## b +#define paste(a,b) _paste(a,b) +#define _paste3(a,b,c) a ## b ## c +#define doublepaste(a,b) _paste3(a,b,b) +#define str(x) #x +X4 a +X5 f(a) +X6 f(b) +X7 f(__COUNTER__) +X8 apply(a) +X9 apply(f(a)) +X10 apply(__COUNTER__) +X11 apply(a2) +X12 str(__COUNTER__) +X13 paste(x,__COUNTER__) +X14 _paste(x,__COUNTER__) +X15 doublepaste(x,__COUNTER__) diff --git a/tests/pp/pp-counter.expect b/tests/pp/pp-counter.expect new file mode 100644 index 0000000..02fc535 --- /dev/null +++ b/tests/pp/pp-counter.expect @@ -0,0 +1,15 @@ +X1 0 +X2 1 +X3 3 +X4 x 4 y +X5 x 5 y 6 +X6 b 7 +X7 8 9 +X8 x 10 y x 10 y 11 x2 x 10 y 12 y2 13 +X9 x 14 y 15 x 14 y 15 16 x2 x 14 y 15 17 y2 18 +X10 19 19 20 x2 19 21 y2 22 +X11 23 23 24 x2 23 25 y2 26 +X12 "__COUNTER__" +X13 x27 +X14 x__COUNTER__ +X15 x2828