ref: c30fd72ab5feaa2e1326dbed4feb7ffc581d937e
parent: 67d7bcb3689d2a33d7e2c0cdda9332f74750d8cd
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Mon May 25 12:39:57 EDT 2015
Avoid nested expansion of macros Nested expansion of macros are inhibited to avoid infinite recursion.
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -273,7 +273,7 @@
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)
--- a/cc1/cpp.c
+++ b/cc1/cpp.c
@@ -170,7 +170,7 @@
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 @@
}
static char *
-mkdefine(char *s, Symbol *sym)
+mkdefine(char *s)
{
int nargs;
char *args[NR_MACROARG], buff[LINESIZ+1];
@@ -304,9 +304,7 @@
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 @@
}
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 @@
if (!string(&s, &file, delim))
goto bad_include;
cleanup(s);
- if (delim == '"' && addinput(file))
+ if (delim == '"' && addinput(file, NULL))
return;
abort();
--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -19,6 +19,7 @@
unsigned short nline;
FILE *fp;
char *line, *begin, *p;
+ Symbol *macro;
struct input *next;
};
@@ -33,7 +34,7 @@
static Input *input;
char *
-addinput(char *fname)
+addinput(char *fname, Symbol *sym)
{
Input *ip;
FILE *fp;
@@ -58,6 +59,7 @@
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,7 +391,7 @@
static unsigned
iden(void)
{
- char *p;
+ char *p, *t, c;
for (p = input->p; isalnum(*p) || *p == '_'; ++p)
/* nothing */;
@@ -396,8 +398,29 @@
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;
--- a/cc1/main.c
+++ b/cc1/main.c
@@ -67,7 +67,7 @@
ikeywords();
- if (!addinput(*argv))
+ if (!addinput(*argv, NULL))
die("error opening input file '%s'", *argv);
for (next(); yytoken != EOFTOK; extdecl())
/* nothing */;
--- a/cc1/stmt.c
+++ b/cc1/stmt.c
@@ -164,7 +164,7 @@
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
--- a/cc1/symbol.c
+++ b/cc1/symbol.c
@@ -129,9 +129,16 @@
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;