commit c30fd72ab5feaa2e1326dbed4feb7ffc581d937e
parent 67d7bcb3689d2a33d7e2c0cdda9332f74750d8cd
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Mon, 25 May 2015 16:39:57 +0200
Avoid nested expansion of macros
Nested expansion of macros are inhibited to avoid infinite recursion.
Diffstat:
6 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/cc1/cc1.h b/cc1/cc1.h
@@ -273,7 +273,7 @@ extern char *getfname(void);
extern unsigned short getfline(void);
extern void setfname(char *name);
extern void setfline(unsigned short line);
-extern char *addinput(char *fname);
+extern char *addinput(char *fname, Symbol *sym);
extern void setnamespace(int ns);
extern void setsafe(int type);
#define accept(t) ((yytoken == (t)) ? next() : 0)
diff --git a/cc1/cpp.c b/cc1/cpp.c
@@ -170,7 +170,7 @@ expand(Symbol *sym)
if (!parsepars(buffer, arglist, atoi(s)))
return 0;
- bp = addinput(NULL);
+ bp = addinput(NULL, sym);
len = INPUTSIZ-1;
for (s += 3; c = *s; ++s) {
if (c != '@') {
@@ -291,7 +291,7 @@ too_long:
}
static char *
-mkdefine(char *s, Symbol *sym)
+mkdefine(char *s)
{
int nargs;
char *args[NR_MACROARG], buff[LINESIZ+1];
@@ -304,9 +304,7 @@ mkdefine(char *s, Symbol *sym)
if (*s != '\0')
s = copydefine(s, args, buff+3, LINESIZ-3, nargs);
- sym->u.s = xstrdup(buff);
-
- return s;
+ return xstrdup(buff);
}
static void
@@ -327,10 +325,11 @@ define(char *s)
}
sym->flags |= ISDEFINED;
sym->ns = NS_CPP;
+ sym->ctx = UCHAR_MAX;
for (t = s + strlen(s) + 1; isspace(*--t); *t = '\0')
/* nothing */;
- mkdefine(s, sym);
+ sym->u.s = mkdefine(s);
return;
}
@@ -351,7 +350,7 @@ include(char *s)
if (!string(&s, &file, delim))
goto bad_include;
cleanup(s);
- if (delim == '"' && addinput(file))
+ if (delim == '"' && addinput(file, NULL))
return;
abort();
diff --git a/cc1/lex.c b/cc1/lex.c
@@ -19,6 +19,7 @@ struct input {
unsigned short nline;
FILE *fp;
char *line, *begin, *p;
+ Symbol *macro;
struct input *next;
};
@@ -33,7 +34,7 @@ static int safe, eof, incomment;
static Input *input;
char *
-addinput(char *fname)
+addinput(char *fname, Symbol *sym)
{
Input *ip;
FILE *fp;
@@ -58,6 +59,7 @@ addinput(char *fname)
ip = xmalloc(sizeof(Input));
ip->fname = fname;
ip->next = input;
+ ip->macro = sym;
ip->begin = ip->p = ip->line = xmalloc(INPUTSIZ);
*ip->begin = '\0';
ip->nline = nline;
@@ -389,15 +391,36 @@ repeat:
static unsigned
iden(void)
{
- char *p;
+ char *p, *t, c;
for (p = input->p; isalnum(*p) || *p == '_'; ++p)
/* nothing */;
input->p = p;
tok2str();
yylval.sym = lookup(lex_ns);
- if (yylval.sym->ns == NS_CPP && expand(yylval.sym))
- return 0;
+ if (yylval.sym->ns == NS_CPP) {
+ Symbol *sym;
+
+ if (yylval.sym != input->macro && expand(yylval.sym))
+ return 0;
+ /*
+ * it is not a correct macro call, so try to find
+ * another definition. This is going to be expensive
+ * but I think it is not going to be a common case.
+ */
+ p = yylval.sym->name;
+ c = *p;
+ for (sym = yylval.sym->hash; sym; sym = sym->hash) {
+ t = sym->name;
+ if (c == *t && !strcmp(p, t)) {
+ yylval.sym = sym;
+ goto found_iden;
+ }
+ }
+ yylval.sym = install(lex_ns);
+ yylval.sym->flags &= ~ISDEFINED;
+ }
+found_iden:
if (yylval.sym->token != IDEN)
yylval.token = yylval.sym->u.token;
return yylval.sym->token;
diff --git a/cc1/main.c b/cc1/main.c
@@ -67,7 +67,7 @@ main(int argc, char *argv[])
ikeywords();
- if (!addinput(*argv))
+ if (!addinput(*argv, NULL))
die("error opening input file '%s'", *argv);
for (next(); yytoken != EOFTOK; extdecl())
/* nothing */;
diff --git a/cc1/stmt.c b/cc1/stmt.c
@@ -164,7 +164,7 @@ Label(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
case TYPEIDEN:
/*
* We cannot call to insert() because the call to lookup in
- * lex.c was done in NS_IDEN namespace, and it is impossibe
+ * lex.c was done in NS_IDEN namespace, and it is impossibe
* to fix this point, because an identifier at the beginning
* of a statement may be part of an expression or part of a
* label. This double call to lookup() is going to generate
diff --git a/cc1/symbol.c b/cc1/symbol.c
@@ -129,9 +129,16 @@ install(unsigned ns)
return yylval.sym;
}
- h = &htab[hash(yytext)];
sym = newsym(ns);
sym->name = xstrdup(yytext);
+
+ if (yylval.sym->ns == NS_CPP) {
+ sym->hash = yylval.sym->hash;
+ yylval.sym->hash = sym;
+ return sym;
+ }
+
+ h = &htab[hash(yytext)];
sym->hash = *h;
*h = sym;
return sym;