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