shithub: scc

Download patch

ref: 454cbc4039b4f3c7efb737b04259c0e4ab73ba40
parent: e7f022e3a196d7473765f5f456da2e19057a7e82
author: Roberto E. Vargas Caballero <[email protected]>
date: Tue Aug 11 17:41:58 EDT 2015

Reduce amount of non declared symbols generated in cpp

There was a lot of different places where spurious symbols
were created. This patch minimizes it setting the correct
namespace before calling next(). It also avoids error()
calls, because the error recovery mechanish will conflict
with the line behaviour of the preprocessor.

--- a/cc1/cpp.c
+++ b/cc1/cpp.c
@@ -26,12 +26,8 @@
 static Symbol *
 defmacro(char *s)
 {
-	Symbol *sym;
-
 	strcpy(yytext, s);
-	sym = addmacro();
-	sym->flags |= ISDECLARED;
-	return sym;
+	return addmacro();
 }
 
 void
@@ -239,7 +235,6 @@
 getpars(Symbol *args[NR_MACROARG])
 {
 	int n = -1;
-	char *err;
 
 	if (!accept('('))
 		return n;
@@ -249,12 +244,12 @@
 
 	do {
 		if (n == NR_MACROARG) {
-			err = "too much parameters in macro";
-			goto popctx_and_error;
+			printerr("too much parameters in macro");
+			return NR_MACROARG;
 		}
 		if (yytoken != IDEN) {
-			err = "macro arguments must be identifiers";
-			goto popctx_and_error;
+			printerr("macro arguments must be identifiers");
+			return NR_MACROARG;
 		}
 		args[n++] = yylval.sym;
 		next();
@@ -262,17 +257,12 @@
 	expect(')');
 
 	return n;
-
-popctx_and_error:
-	popctx();
-	error(err);
 }
 
-static void
+static bool
 getdefs(Symbol *args[NR_MACROARG], int nargs, char *bp, size_t bufsiz)
 {
 	Symbol **argp;
-	char *err;
 	size_t len;
 	int prevc = 0, ispar;
 
@@ -288,14 +278,16 @@
 				ispar = 1;
 			}
 		}
-		if (prevc == '#' && !ispar)
-			goto bad_stringer;
+		if (prevc == '#' && !ispar) {
+			printerr("'#' is not followed by a macro parameter");
+			return 0;
+		}
 		if (yytoken == EOFTOK)
 			break;
 
 		if ((len = strlen(yytext)) >= bufsiz) {
-			err = "too long macro";
-			goto popctx_and_error;
+			printerr("too long macro");
+			return 0;
 		}
 		memcpy(bp, yytext, len);
 		bp += len;
@@ -305,13 +297,7 @@
 		next();
 	}
 	*bp = '\0';
-	return;
-
-bad_stringer:
-	err = "'#' is not followed by a macro parameter";
-popctx_and_error:
-	popctx();
-	error(err);
+	return 1;
 }
 
 static void
@@ -323,27 +309,31 @@
 
 	if (cppoff)
 		return;
+
+	setnamespace(NS_CPP);
+	next();
 	if (yytoken != IDEN)
 		error("macro names must be identifiers");
 	sym = yylval.sym;
-	if ((sym->flags & ISDECLARED) && sym->ns == NS_CPP) {
+	if (sym->flags & ISDECLARED) {
 		warn("'%s' redefined", yytext);
 		free(sym->u.s);
-	} else if (sym->ns != NS_CPP) {
+	} else {
 		sym = addmacro();
 	}
-	sym->flags |= ISDECLARED;
 
-	pushctx();
-
 	next();
-	n = getpars(args);
+	if ((n = getpars(args)) == NR_MACROARG)
+		goto delete;
 	sprintf(buff, "%02d#", n);
-	getdefs(args, n, buff+3, LINESIZ-3);
+	if (!getdefs(args, n, buff+3, LINESIZ-3))
+		goto delete;
 	sym->u.s = xstrdup(buff);
 	fprintf(stderr, "MACRO '%s' defined as '%s'\n", sym->name, buff);
+	return;
 
-	popctx();
+delete:
+	delmacro(sym);
 }
 
 static void
@@ -359,6 +349,10 @@
 
 	if (cppoff)
 		return;
+
+	setnamespace(NS_IDEN);
+	next();
+
 	switch (*yytext) {
 	case '<':
 		if ((p = strchr(input->begin, '>')) == NULL)
@@ -395,15 +389,18 @@
 		if (addinput(path))
 			break;
 	}
+
 	if (*bp)
-		error("included file '%s' not found", file);
+		printerr("included file '%s' not found", file);
 
 	return;
 
 bad_include:
-	error("#include expects \"FILENAME\" or <FILENAME>");
+	printerr("#include expects \"FILENAME\" or <FILENAME>");
+	return;
 too_long:
-	error("#include FILENAME too long");
+	printerr("#include FILENAME too long");
+	return;
 }
 
 static void
@@ -415,20 +412,29 @@
 	if (cppoff)
 		return;
 
+	setnamespace(NS_IDEN);
+	next();
 	n = strtol(yytext, &endp, 10);
-	if (n <= 0 || n > USHRT_MAX || *endp != '\0')
-		error("first parameter of #line is not a positive integer");
+	if (n <= 0 || n > USHRT_MAX || *endp != '\0') {
+		printerr("first parameter of #line is not a positive integer");
+		return;
+	}
 
-	input->nline = yylval.sym->u.i;
 	next();
 	if (yytoken == EOFTOK)
+		goto set_line;
+
+	if (*yytext != '\"' || yylen == 1) {
+		printerr("second parameter of #line is not a valid filename");
 		return;
+	}
 
-	if (*yytext != '\"' || yylen == 1)
-		error("second parameter of #line is not a valid filename");
 	free(input->fname);
 	input->fname = xstrdup(yylval.sym->u.s);
 	next();
+
+set_line:
+	input->nline = yylval.sym->u.i;
 }
 
 static void
@@ -464,15 +470,21 @@
 
 	if (isifdef) {
 		if (yytoken != IDEN) {
-			error("no macro name given in #%s directive",
-			      (negate) ? "ifndef" : "ifdef");
+			printerr("no macro name given in #%s directive",
+			         (negate) ? "ifndef" : "ifdef");
+			return;
 		}
-		sym = lookup(NS_CPP);
+		sym = yylval.sym;
 		next();
 		status = (sym->flags & ISDECLARED) != 0;
+		if (!status)
+			delmacro(sym);
 	} else {
-		if ((expr = iconstexpr()) == NULL)
-			error("parameter of #if is not an integer constant expression");
+		/* TODO: catch recovery here */
+		if ((expr = iconstexpr()) == NULL) {
+			printerr("parameter of #if is not an integer constant expression");
+			return;
+		}
 		status = expr->sym->u.i != 0;
 	}
 
@@ -485,6 +497,8 @@
 static void
 cppif(void)
 {
+	setnamespace(NS_CPP);
+	next();
 	ifclause(0, 0);
 }
 
@@ -491,6 +505,8 @@
 static void
 ifdef(void)
 {
+	setnamespace(NS_CPP);
+	next();
 	ifclause(0, 1);
 }
 
@@ -497,6 +513,8 @@
 static void
 ifndef(void)
 {
+	setnamespace(NS_CPP);
+	next();
 	ifclause(1, 1);
 }
 
@@ -507,6 +525,7 @@
 		error("#endif without #if");
 	if (!ifstatus[--cppctx])
 		--cppoff;
+	next();
 }
 
 static void
@@ -519,6 +538,7 @@
 
 	status = (ifstatus[cppctx-1] ^= 1);
 	cppoff += (status) ? -1 : 1;
+	next();
 }
 
 static void
@@ -533,12 +553,14 @@
 {
 	if (cppoff)
 		return;
+
+	setnamespace(NS_CPP);
+	next();
 	if (yytoken != IDEN) {
 		error("no macro name given in #undef directive");
 		return;
 	}
-	if (yylval.sym->ns == NS_CPP)
-		delmacro(yylval.sym);
+	delmacro(yylval.sym);
 	next();
 }
 
@@ -576,11 +598,13 @@
 		/* nothing */;
 	if (!bp->token)
 		error("incorrect preprocessor directive");
-	next();
-	(*bp->fun)();
 
+	pushctx();              /* create a new context to avoid polish */
+	(*bp->fun)();           /* the current context, and to get all  */
+	popctx();               /* the symbols freed at the  end        */
+
 	if (yytoken != EOFTOK && !cppoff)
-		error("trailing characters after preprocessor directive");
+		printerr("trailing characters after preprocessor directive");
 	disexpand = 0;
 	lexmode = CCMODE;
 
--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -379,7 +379,7 @@
 	input->p = p;
 	tok2str();
 	yylval.sym = sym = lookup(lex_ns);
-	if (sym->ns == NS_CPP) {
+	if (sym->ns == NS_CPP && lexmode == CCMODE) {
 		if (!disexpand && expand(begin, sym))
 			return next();
 		/*
--- a/cc1/symbol.c
+++ b/cc1/symbol.c
@@ -157,7 +157,7 @@
 	sym->ctx = curctx;
 	sym->token = IDEN;
 	sym->flags = ISDECLARED;
-	sym->name = NULL;
+	sym->u.s = sym->name = NULL;
 	sym->type = NULL;
 	sym->next = sym->hash = NULL;
 
@@ -219,6 +219,7 @@
 	/* Force cpp symbols to be at the beginning of the hash */
 	curctx = UCHAR_MAX;
 	sym = lookup(NS_CPP);
+	sym->flags |= ISDECLARED;
 	curctx = ctx;
 	return sym;
 }