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);