aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Soroka <gits@joesoroka.com>2011-02-01 13:23:40 -0800
committerJoe Soroka <gits@joesoroka.com>2011-02-01 13:23:40 -0800
commit75c6695932b55b914f16b20dc32ff3ef1203ed4b (patch)
treece7a5642124f1be01525eacb5cff8baddaf5629e
parentcf08675702044c180553c866ba1fde0414f00590 (diff)
downloadtinycc-75c6695932b55b914f16b20dc32ff3ef1203ed4b.tar.gz
tinycc-75c6695932b55b914f16b20dc32ff3ef1203ed4b.tar.bz2
tccpp: fix bug in handling of recursive macros
-rw-r--r--tcc.h1
-rw-r--r--tccpp.c17
-rw-r--r--tests/tcctest.c31
3 files changed, 47 insertions, 2 deletions
diff --git a/tcc.h b/tcc.h
index 7d42607..a3a9c78 100644
--- a/tcc.h
+++ b/tcc.h
@@ -683,6 +683,7 @@ struct TCCState {
#define TOK_DOTS 0xcc /* three dots */
#define TOK_SHR 0xcd /* unsigned shift right */
#define TOK_PPNUM 0xce /* preprocessor number */
+#define TOK_NOSUBST 0xcf /* means following token has already been pp'd */
#define TOK_SHL 0x01 /* shift left */
#define TOK_SAR 0x02 /* signed shift right */
diff --git a/tccpp.c b/tccpp.c
index c461ff8..27f9870 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -2797,7 +2797,8 @@ static inline int *macro_twosharps(const int *macro_str)
if (tok == TOK_TWOSHARPS)
continue;
while (*ptr == TOK_TWOSHARPS) {
- t = *++ptr;
+ do { t = *++ptr; } while (t == TOK_NOSUBST);
+
if (t && t != TOK_TWOSHARPS) {
TOK_GET(&t, &ptr, &cval);
@@ -2856,11 +2857,20 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list,
TOK_GET(&t, &ptr, &cval);
if (t == 0)
break;
+ if (t == TOK_NOSUBST) {
+ /* following token has already been subst'd. just copy it on */
+ tok_str_add2(tok_str, TOK_NOSUBST, NULL);
+ TOK_GET(&t, &ptr, &cval);
+ goto no_subst;
+ }
s = define_find(t);
if (s != NULL) {
/* if nested substitution, do nothing */
- if (sym_find2(*nested_list, t))
+ if (sym_find2(*nested_list, t)) {
+ /* and mark it as TOK_NOSUBST, so it doesn't get subst'd again */
+ tok_str_add2(tok_str, TOK_NOSUBST, NULL);
goto no_subst;
+ }
ml.p = macro_ptr;
if (can_read_stream)
ml.prev = *can_read_stream, *can_read_stream = &ml;
@@ -2928,6 +2938,9 @@ ST_FUNC void next(void)
macro_ptr = NULL;
}
goto redo;
+ } else if (tok == TOK_NOSUBST) {
+ /* discard preprocessor's nosubst markers */
+ goto redo;
}
}
diff --git a/tests/tcctest.c b/tests/tcctest.c
index 0128957..f62983d 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -45,6 +45,7 @@
void string_test();
void expr_test();
void macro_test();
+void recursive_macro_test();
void scope_test();
void forward_test();
void funcptr_test();
@@ -281,6 +282,35 @@ comment
TEST2();
}
+
+static void print_num(char *fn, int line, int num) {
+ printf("fn %s, line %d, num %d\n", fn, line, num);
+}
+
+void recursive_macro_test(void)
+{
+#if 0 /* doesnt work yet */
+#define ELF32_ST_TYPE(val) ((val) & 0xf)
+#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+#define STB_WEAK 2 /* Weak symbol */
+#define ELFW(type) ELF##32##_##type
+ printf("%d\n", ELFW(ST_INFO)(STB_WEAK, ELFW(ST_TYPE)(123)));
+#endif
+
+#define WRAP(x) x
+
+#define print_num(x) print_num(__FILE__,__LINE__,x)
+ print_num(123);
+ WRAP(print_num(123));
+ WRAP(WRAP(print_num(123)));
+
+static struct recursive_macro { int rm_field; } G;
+#define rm_field (G.rm_field)
+ printf("rm_field = %d\n", rm_field);
+ printf("rm_field = %d\n", WRAP(rm_field));
+ WRAP((printf("rm_field = %d %d\n", rm_field, WRAP(rm_field))));
+}
+
int op(a,b)
{
return a / b;
@@ -501,6 +531,7 @@ int main(int argc, char **argv)
string_test();
expr_test();
macro_test();
+ recursive_macro_test();
scope_test();
forward_test();
funcptr_test();