shithub: scc

Download patch

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;