History

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.

Michael Matz committed 9 years ago

Commit 824dceb1 parent 1f3d3955 files · +72 −11Browse files

Unified · Split

5 files
  1. libtcc.c +1 −0
  2. tccpp.c +28 −11
  3. tcctok.h +1 −0
  4. tests/pp/pp-counter.c +27 −0
  5. tests/pp/pp-counter.expect +15 −0
libtcc.c+1−0
@@ -762,6 +762,7 @@ LIBTCCAPI TCCState *tcc_new(void) · 761 unmodified lines
762 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);762 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
763 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);763 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
764 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);764 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
765 define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL);
765 {766 {
766 /* define __TINYC__ 92X */767 /* define __TINYC__ 92X */
767 char buffer[32]; int a,b,c;768 char buffer[32]; int a,b,c;
tccpp.c+28−11
@@ -2980,18 +2980,29 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) · 2979 unmodified lines
2980 str.len--;2980 str.len--;
2981 goto add_var;2981 goto add_var;
2982 }2982 }
2983 } else {
2984 for(;;) {
2985 int t1;
2986 TOK_GET(&t1, &st, &cval);
2987 if (t1 <= 0)
2988 break;
2989 tok_str_add2(&str, t1, &cval);
2990 }
2991 }2983 }
2992 } else {2984 } else {
2993 add_var:2985 add_var:
2994 macro_subst(&str, nested_list, st);2986 if (!s->next) {
2987 /* Expand arguments tokens and store them. In most
2988 cases we could also re-expand each argument if
2989 used multiple times, but not if the argument
2990 contains the __COUNTER__ macro. */
2991 TokenString str2;
2992 sym_push2(&s->next, s->v, s->type.t, 0);
2993 tok_str_new(&str2);
2994 macro_subst(&str2, nested_list, st);
2995 tok_str_add(&str2, 0);
2996 s->next->d = str2.str;
2997 }
2998 st = s->next->d;
2999 }
3000 for(;;) {
3001 int t2;
3002 TOK_GET(&t2, &st, &cval);
3003 if (t2 <= 0)
3004 break;
3005 tok_str_add2(&str, t2, &cval);
2995 }3006 }
2996 if (str.len == l0) /* expanded to empty string */3007 if (str.len == l0) /* expanded to empty string */
2997 tok_str_add(&str, TOK_PLCHLDR);3008 tok_str_add(&str, TOK_PLCHLDR);
@@ -3180,11 +3191,13 @@ static int macro_subst_tok( · 182 unmodified lines
3180 CValue cval;3191 CValue cval;
3181 CString cstr;3192 CString cstr;
3182 char buf[32];3193 char buf[32];
3194 static int counter;
3183 3195
3184 /* if symbol is a macro, prepare substitution */3196 /* if symbol is a macro, prepare substitution */
3185 /* special macros */3197 /* special macros */
3186 if (tok == TOK___LINE__) {3198 if (tok == TOK___LINE__ || tok == TOK___COUNTER__) {
3187 snprintf(buf, sizeof(buf), "%d", file->line_num);3199 t = tok == TOK___LINE__ ? file->line_num : counter++;
3200 snprintf(buf, sizeof(buf), "%d", t);
3188 cstrval = buf;3201 cstrval = buf;
3189 t1 = TOK_PPNUM;3202 t1 = TOK_PPNUM;
3190 goto add_cstr1;3203 goto add_cstr1;
@@ -3316,6 +3329,10 @@ static int macro_subst_tok( · 125 unmodified lines
3316 while (sa) {3329 while (sa) {
3317 sa1 = sa->prev;3330 sa1 = sa->prev;
3318 tok_str_free_str(sa->d);3331 tok_str_free_str(sa->d);
3332 if (sa->next) {
3333 tok_str_free_str(sa->next->d);
3334 sym_free(sa->next);
3335 }
3319 sym_free(sa);3336 sym_free(sa);
3320 sa = sa1;3337 sa = sa1;
3321 }3338 }
tcctok.h+1−0
@@ -87,6 +87,7 @@ · 86 unmodified lines
87 DEF(TOK___TIME__, "__TIME__")87 DEF(TOK___TIME__, "__TIME__")
88 DEF(TOK___FUNCTION__, "__FUNCTION__")88 DEF(TOK___FUNCTION__, "__FUNCTION__")
89 DEF(TOK___VA_ARGS__, "__VA_ARGS__")89 DEF(TOK___VA_ARGS__, "__VA_ARGS__")
90 DEF(TOK___COUNTER__, "__COUNTER__")
90 91
91/* special identifiers */92/* special identifiers */
92 DEF(TOK___FUNC__, "__func__")93 DEF(TOK___FUNC__, "__func__")
tests/pp/pp-counter.c+27−0
@@ -0,0 +1,27 @@
1X1 __COUNTER__
2X2 __COUNTER__
3#if __COUNTER__
4X3 __COUNTER__
5#endif
6#define pass(x) x
7#define a x __COUNTER__ y
8#define a2 pass(__COUNTER__)
9#define f(c) c __COUNTER__
10#define apply(d) d d __COUNTER__ x2 f(d) y2 __COUNTER__
11#define _paste(a,b) a ## b
12#define paste(a,b) _paste(a,b)
13#define _paste3(a,b,c) a ## b ## c
14#define doublepaste(a,b) _paste3(a,b,b)
15#define str(x) #x
16X4 a
17X5 f(a)
18X6 f(b)
19X7 f(__COUNTER__)
20X8 apply(a)
21X9 apply(f(a))
22X10 apply(__COUNTER__)
23X11 apply(a2)
24X12 str(__COUNTER__)
25X13 paste(x,__COUNTER__)
26X14 _paste(x,__COUNTER__)
27X15 doublepaste(x,__COUNTER__)
tests/pp/pp-counter.expect+15−0
@@ -0,0 +1,15 @@
1X1 0
2X2 1
3X3 3
4X4 x 4 y
5X5 x 5 y 6
6X6 b 7
7X7 8 9
8X8 x 10 y x 10 y 11 x2 x 10 y 12 y2 13
9X9 x 14 y 15 x 14 y 15 16 x2 x 14 y 15 17 y2 18
10X10 19 19 20 x2 19 21 y2 22
11X11 23 23 24 x2 23 25 y2 26
12X12 "__COUNTER__"
13X13 x27
14X14 x__COUNTER__
15X15 x2828

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t