shithub: scc

Download patch

ref: 994751d39485e086ef623f202fb1b84729fd5d19
parent: cae3fc327c4969ad626fbbe90f00026e977671e0
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sat May 28 04:34:45 EDT 2022

cc1: Fix hideset implementation

The correct macro expansion is based in the hideset concept.
When the macro is expanded and scanned for tokens all the
macros expanded in the context of the macro expansion must
be disabled and not expanded again. It means that the hide
set of every macro expansion cannot be represented only with
a symbol but with a set of symbols.

It is important to hide the symbols after they are expanded
in the context of the macro expansion until the macro
expansion finished.

--- a/src/cmd/cc/cc1/cc1.h
+++ b/src/cmd/cc/cc1/cc1.h
@@ -396,6 +396,7 @@
 	unsigned char token;
 };
 
+#ifdef NR_MACROARG
 struct macro {
 	Symbol *sym;
 	char *fname;
@@ -404,7 +405,9 @@
 	char *def;
 	int bufsiz;
 	int npars;
+	Symbol *hideset[NR_MACROARG];
 };
+#endif
 
 #ifdef stdin
 struct input {
--- a/src/cmd/cc/cc1/cpp.c
+++ b/src/cmd/cc/cc1/cpp.c
@@ -28,7 +28,6 @@
 		.name = name,
 		.flags = SDECLARED,
 	};
-	Macro *mp;
 
 	if (!val)
 		val = "";
@@ -38,12 +37,9 @@
 	}
 
 	sprintf(buffer, fmt, name, val);
-	mp = newmacro(sym);
-	mp->buffer = buffer;
-	mp->fname = source;
-
 	lineno = ++ncmdlines;
-	addinput(IMACRO, mp, FAIL);
+
+	addinput(IPARAM, buffer, FAIL);
 	cpp();
 	delinput();
 }
@@ -120,6 +116,7 @@
 {
 	int siz;
 	char *s, *begin, *end;
+	Input *ip = input;
 
 	begin = input->begin;
 	for (;;) {
@@ -301,10 +298,45 @@
 	error("macro expansion of \"%s\" too long", mp->sym->name);
 }
 
+static void
+addhideset(Input *ip,  Symbol *sym)
+{
+	Symbol **set;
+	Symbol **p;
+
+	set = ip->macro->hideset;
+	for (p = set; p < &set[NR_MACROARG] && *p; ++p) {
+		if (*p == sym)
+			return;
+	}
+
+	if (p == &set[NR_MACROARG])
+		error("too complex macro expansion");
+
+	*p = sym;
+	DBG("MACRO Adding %s to hideset of %s",
+	    sym->name, ip->macro->sym->name);
+}
+
+static void
+hide(Symbol *sym)
+{
+	DBG("SYM: hidding symbol %s %d", sym->name, sym->hide);
+	sym->hide = 1;
+}
+
+static void
+unhide(Symbol *sym)
+{
+	DBG("SYM: unhidding symbol %s %d", sym->name, sym->hide);
+	sym->hide = 0;
+}
+
 void
 delmacro(Macro *mp)
 {
 	int i;
+	Symbol **p;
 
 	if (!mp)
 		return;
@@ -313,6 +345,10 @@
 		for (i = 0; i < mp->npars; i++)
 			free(mp->arglist[i]);
 	}
+
+	for (p = mp->hideset; p < &mp->hideset[NR_MACROARG] && *p; ++p)
+		unhide(*p);
+
 	free(mp->arglist);
 	free(mp);
 }
@@ -323,11 +359,9 @@
 	Macro *mp;
 
 	mp = xmalloc(sizeof(*mp));
+	*mp = (Macro) {0};
 	mp->sym = sym;
-	mp->arglist = NULL;
 	mp->def = sym->u.s + 3;
-	mp->npars = 0;
-	mp->buffer = NULL;
 	if (sym->u.s)
 		mp->npars = atoi(sym->u.s);
 
@@ -337,8 +371,10 @@
 int
 expand(Symbol *sym)
 {
-	int elen;
+	int siz;
 	Macro *mp;
+	Input *ip;
+	Symbol **p;
 
 	DBG("MACRO '%s' detected disexpand=%d hide=%d",
 	    sym->name, disexpand, sym->hide);
@@ -358,8 +394,16 @@
 	mp->buffer = input->line;
 	mp->bufsiz = INPUTSIZ-1;
 
-	elen = copymacro(mp);
-	mp->buffer[elen] = '\0';
+	siz = copymacro(mp);
+	mp->buffer[siz] = '\0';
+
+	for (ip = input; ip; ip = ip->next) {
+                if ((ip->flags & ITYPE) == IMACRO)
+			addhideset(ip, sym);
+	}
+
+	for (p = mp->hideset; p < &mp->hideset[NR_MACROARG] && *p; ++p)
+		hide(*p);
 
 	DBG("MACRO '%s' expanded to :'%s'", mp->sym->name, mp->buffer);
 
--- a/src/cmd/cc/cc1/lex.c
+++ b/src/cmd/cc/cc1/lex.c
@@ -48,22 +48,6 @@
 	lineno = input->lineno = line;
 }
 
-static void
-hide(Symbol *sym)
-{
-	assert(sym->hide == 0);
-	sym->hide = 1;
-	DBG("SYM: hidding symbol %s %d", sym->name, sym->hide);
-}
-
-static void
-unhide(Symbol *sym)
-{
-	assert(sym->hide == 1);
-	DBG("SYM: unhidding symbol %s %d", sym->name, sym->hide);
-	sym->hide = 0;
-}
-
 int
 addinput(int type, void *arg, int fail)
 {
@@ -84,7 +68,6 @@
 		sym = mp->sym;
 		fname = mp->fname;
 		buffer = mp->buffer;
-		hide(sym);
 		DBG("INPUT: expanding macro %s", sym->name);
 		break;
 	case IPARAM:
@@ -162,7 +145,7 @@
 		break;
 	case IMACRO:
 		DBG("INPUT: macro %s finished", ip->macro->sym->name);
-		unhide(ip->macro->sym);
+		delmacro(ip->macro);
 		break;
 	case IPARAM:
 		DBG("INPUT: macro param finished");
@@ -175,7 +158,6 @@
 	}
 
 	input = ip->next;
-	delmacro(ip->macro);
 	free(ip->filenam);
 	free(ip->line);
 	free(ip);