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.
master
Michael Matz 2017-07-09 05:30:47 +02:00
parent 1f3d3957c4
commit 824dcebe59
5 changed files with 72 additions and 11 deletions

View File

@ -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;

39
tccpp.c
View File

@ -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;
}

View File

@ -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__")

View File

@ -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__)

View File

@ -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