shithub: scc

Download patch

ref: ce6b776c6933ca8ce6e078896471287b3230cf9c
parent: 532456cdf90cecdbc0bc80f1e4a6d002accb3bb2
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sun Nov 14 02:26:22 EST 2021

cc1: Remove use of globals in macro expansion

The macro expansion proccess was depending too much of global variables,
which is also a problem because parameters of macros are also expanded,
and it means that the code must be reentrant.

--- a/src/cmd/cc/cc1/cpp.c
+++ b/src/cmd/cc/cc1/cpp.c
@@ -9,8 +9,18 @@
 #include <scc/scc.h>
 #include "cc1.h"
 
-static char *argp, *macroname;
-static unsigned arglen;
+struct macroctx {
+	char *name;
+	char *argp;
+	char **arglist;
+	char **listp;
+	char *buffer;
+	char *def;
+	size_t bufsiz;
+	int arglen;
+	int npars;
+};
+
 static unsigned ncmdlines;
 static Symbol *symline, *symfile;
 static unsigned char ifstatus[NR_COND];
@@ -94,33 +104,33 @@
 }
 
 static void
-nextcpp(void)
+nextcpp(struct macroctx *mp)
 {
 	next();
 	if (yytoken == EOFTOK)
 		error("unterminated argument list invoking macro \"%s\"",
-		      macroname);
-	if (yylen + 1 > arglen)
+		      mp->name);
+	if (yylen + 1 > mp->arglen)
 		error("argument overflow invoking macro \"%s\"",
-		      macroname);
+		      mp->name);
 	if (yytoken == IDEN)
 		yylval.sym->flags |= SUSED;
-	memcpy(argp, yytext, yylen);
-	argp += yylen;
-	*argp++ = ' ';
-	arglen -= yylen + 1;
+	memcpy(mp->argp, yytext, yylen);
+	mp->argp += yylen;
+	mp->arglen -= yylen + 1;
+	*mp->argp++ = ' ';
 }
 
 static void
-paren(void)
+paren(struct macroctx *mp)
 {
 	for (;;) {
-		nextcpp();
+		nextcpp(mp);
 		switch (yytoken) {
 		case ')':
 			return;
 		case '(':
-			paren();
+			paren(mp);
 			break;
 		}
 	}
@@ -127,18 +137,18 @@
 }
 
 static void
-parameter(void)
+parameter(struct macroctx *mp)
 {
 	for (;;) {
-		nextcpp();
+		nextcpp(mp);
 		switch (yytoken) {
 		case ')':
 		case ',':
-			argp -= 3;  /* remove " , "  or " ) "*/
-			*argp++ = '\0';
+			mp->argp -= 3;  /* remove " , "  or " ) "*/
+			*mp->argp++ = '\0';
 			return;
 		case '(':
-			paren();
+			paren(mp);
 			break;
 		}
 	}
@@ -145,25 +155,23 @@
 }
 
 static int
-parsepars(char *buffer, char **listp, int nargs)
+parsepars(struct macroctx *mp)
 {
 	int n;
 
-	if (nargs == -1)
+	if (mp->npars == -1)
 		return -1;
-	if (ahead() != '(' && nargs > 0)
+	if (ahead() != '(' && mp->npars > 0)
 		return 0;
 
 	next();
 	n = 0;
-	argp = buffer;
-	arglen = INPUTSIZ;
 	if (ahead() == ')') {
 		next();
 	} else {
 		do {
-			*listp++ = argp;
-			parameter();
+			*mp->listp++ = mp->argp;
+			parameter(mp);
 		} while (++n < NR_MACROARG && yytoken == ',');
 	}
 	if (yytoken != ')')
@@ -171,10 +179,10 @@
 	disexpand = 0;
 
 	if (n == NR_MACROARG)
-		error("too many parameters in macro \"%s\"", macroname);
-	if (n != nargs) {
+		error("too many parameters in macro \"%s\"", mp->name);
+	if (n != mp->npars) {
 		error("macro \"%s\" received %d arguments, but it takes %d",
-		      macroname, n, nargs);
+		      mp->name, n, mp->npars);
 	}
 
 	return 1;
@@ -181,13 +189,15 @@
 }
 
 static size_t
-copymacro(char *buffer, char *s, size_t bufsiz, char *arglist[])
+copymacro(struct macroctx *mp)
 {
 	int delim, c, esc;
-	char *p, *arg, *bp = buffer;
-	size_t size;
+	char *s, *p, *arg, *bp;
+	size_t size, bufsiz;
 
-	for (; c = *s; ++s) {
+	bp = mp->buffer;
+	bufsiz = mp->bufsiz;
+	for (s = mp->def; c = *s; ++s) {
 		switch (c) {
 		case '$':
 			while (bp[-1] == ' ')
@@ -219,7 +229,7 @@
 			bp += size;
 			break;
 		case '#':
-			arg = arglist[atoi(s += 2)];
+			arg = mp->arglist[atoi(s += 2)];
 			s += 2;
 
 			if (bufsiz < 3)
@@ -244,7 +254,7 @@
 
 			break;
 		case '@':
-			arg = arglist[atoi(++s)];
+			arg = mp->arglist[atoi(++s)];
 			s += 2;
 
 			size = strlen(arg);
@@ -263,10 +273,10 @@
 	}
 	*bp = '\0';
 
-	return bp - buffer;
+	return bp - mp->buffer;
 
 expansion_too_long:
-	error("macro expansion of \"%s\" too long", macroname);
+	error("macro expansion of \"%s\" too long", mp->name);
 }
 
 int
@@ -273,8 +283,8 @@
 expand(Symbol *sym)
 {
 	size_t elen;
-	int n, i;
-	char *s = sym->u.s;
+	int i;
+	struct macroctx macro;
 	char *arglist[NR_MACROARG];
 	char arguments[INPUTSIZ], buffer[INPUTSIZ];
 
@@ -283,7 +293,16 @@
 	if (disexpand || sym->hide)
 		return 0;
 
-	macroname = sym->name;
+	macro.name = sym->name;
+	macro.argp = arguments;
+	macro.listp = arglist;
+	macro.arglist = arglist;
+	macro.arglen = INPUTSIZ;
+	macro.buffer = buffer;
+	macro.npars = atoi(sym->u.s);
+	macro.def = sym->u.s + 3;
+	macro.bufsiz = INPUTSIZ-1;
+
 	if (sym == symfile) {
 		elen = sprintf(buffer, "\"%s\" ", filenam);
 		goto substitute;
@@ -292,20 +311,20 @@
 		elen = sprintf(buffer, "%d ", lineno);
 		goto substitute;
 	}
-	if (!s)
+	if (!sym->u.s)
 		return 1;
 
-	n = atoi(s);
-	if (!parsepars(arguments, arglist, n))
+	macro.npars = atoi(sym->u.s);
+	if (!parsepars(&macro))
 		return 0;
-	for (i = 0; i < n; ++i)
+	for (i = 0; i < macro.npars; ++i)
 		DBG("MACRO par%d:%s", i, arglist[i]);
 
-	elen = copymacro(buffer, s+3, INPUTSIZ-1, arglist);
+	elen = copymacro(&macro);
 
 substitute:
-	DBG("MACRO '%s' expanded to :'%s'", macroname, buffer);
 	buffer[elen] = '\0';
+	DBG("MACRO '%s' expanded to :'%s'", macro.name, buffer);
 	addinput(filenam, sym, xstrdup(buffer), FAIL);
 
 	return 1;