shithub: scc

Download patch

ref: 0a859705bf32bb1462671e03b2b8e932f3d287e4
parent: 46b51055e0657109fb95d93022d2e1614290311e
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue Apr 5 10:35:05 EDT 2022

cc1: Add Macro type

Macro expansion is a complex topic, and it is better
if we add a type that can encapsulate this complexity.

--- a/src/cmd/cc/cc1/cc1.h
+++ b/src/cmd/cc/cc1/cc1.h
@@ -282,6 +282,7 @@
 typedef struct symbol Symbol;
 typedef struct swtch Switch;
 typedef struct node Node;
+typedef struct macro Macro;
 typedef struct input Input;
 typedef struct arch Arch;
 
@@ -394,6 +395,15 @@
 	unsigned char token;
 };
 
+struct macro {
+	Symbol *sym;
+	char **arglist;
+	char *buffer;
+	char *def;
+	int bufsiz;
+	int npars;
+};
+
 #ifdef stdin
 struct input {
 	char flags;
@@ -491,6 +501,9 @@
 extern void defdefine(char *macro, char *val, char *source);
 extern void undefmacro(char *s);
 extern void ppragmaln(void);
+extern void delmacro(Macro *);
+extern Macro *newmacro(Symbol *);
+
 
 /* builtin.c */
 extern void ibuilts(void);
--- a/src/cmd/cc/cc1/cpp.c
+++ b/src/cmd/cc/cc1/cpp.c
@@ -9,18 +9,6 @@
 #include <scc/scc.h>
 #include "cc1.h"
 
-struct macroctx {
-	Symbol *sym;
-	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];
@@ -87,7 +75,7 @@
 }
 
 static void
-nextcpp(struct macroctx *mp)
+nextcpp(Macro *mp)
 {
 	next();
 	if (yytoken == EOFTOK)
@@ -98,7 +86,7 @@
 }
 
 static void
-paren(struct macroctx *mp)
+paren(Macro *mp)
 {
 	for (;;) {
 		nextcpp(mp);
@@ -112,11 +100,11 @@
 	}
 }
 
-static void
-parameter(struct macroctx *mp)
+static char *
+parameter(Macro *mp)
 {
 	int siz;
-	char *begin, *end;
+	char *s, *begin, *end;
 
 	begin = input->begin;
 	for (;;) {
@@ -130,15 +118,9 @@
 				--end;
 
 			siz = end - begin;
-			if (siz+1 > mp->arglen) {
-				error("argument overflow invoking macro \"%s\"",
-				      mp->sym->name);
-			}
-			memcpy(mp->argp, begin, siz);
-			mp->argp += siz;
-			*mp->argp++ = '\0';
-			mp->arglen -= siz + 1;
-			return;
+			s = memcpy(xmalloc(siz+1), begin, siz);
+			s[siz] = '\0';
+			return s;
 		case '(':
 			paren(mp);
 			break;
@@ -147,7 +129,7 @@
 }
 
 static int
-parsepars(struct macroctx *mp)
+parsepars(Macro *mp)
 {
 	int n;
 
@@ -163,8 +145,8 @@
 		next();
 	} else {
 		do {
-			*mp->listp++ = mp->argp;
-			parameter(mp);
+			mp->arglist = xrealloc(mp->arglist, n*sizeof(char *));
+			mp->arglist[n] = parameter(mp);
 		} while (++n < NR_MACROARG && yytoken == ',');
 	}
 	if (yytoken != ')')
@@ -209,7 +191,7 @@
 }
 
 static int
-copymacro(struct macroctx *mp)
+copymacro(Macro *mp)
 {
 	int delim, c, esc;
 	char *s, *p, *arg, *bp;
@@ -300,14 +282,43 @@
 	error("macro expansion of \"%s\" too long", mp->sym->name);
 }
 
+void
+delmacro(Macro *mp)
+{
+	int i;
+
+	if (!mp)
+		return;
+
+	if (mp->arglist) {
+		for (i = 0; i < mp->npars; i++)
+			free(mp->arglist[i]);
+	}
+	free(mp->arglist);
+	free(mp);
+}
+
+Macro *
+newmacro(Symbol *sym)
+{
+	Macro *mp;
+
+	mp = xmalloc(sizeof(*mp));
+	mp->sym = sym;
+	mp->arglist = NULL;
+	mp->def = sym->u.s + 3;
+	mp->npars = 0;
+	mp->npars = atoi(sym->u.s);
+
+	return mp;
+}
+
 int
 expand(Symbol *sym)
 {
 	int elen;
-	int i;
-	struct macroctx macro;
-	char *arglist[NR_MACROARG];
-	char arguments[INPUTSIZ], buffer[INPUTSIZ];
+	Macro *mp;
+	char buffer[INPUTSIZ];
 
 	DBG("MACRO '%s' detected disexpand=%d hide=%d",
 	    sym->name, disexpand, sym->hide);
@@ -315,15 +326,9 @@
 	if (disexpand || sym->hide)
 		return 0;
 
-	macro.sym = sym;
-	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;
+	mp = newmacro(sym);
+	mp->buffer = buffer;
+	mp->bufsiz = INPUTSIZ-1;
 
 	if (sym == symfile) {
 		elen = sprintf(buffer, "\"%s\" ", filenam);
@@ -334,14 +339,19 @@
 		goto substitute;
 	}
 
-	if (!parsepars(&macro))
+	if (!parsepars(mp)) {
+		delmacro(mp);
 		return 0;
-	elen = copymacro(&macro);
+	}
+	elen = copymacro(mp);
 
 substitute:
+	mp->buffer = NULL;
+	mp->bufsiz = 0;
 	buffer[elen] = '\0';
-	DBG("MACRO '%s' expanded to :'%s'", macro.sym->name, buffer);
-	addinput(filenam, sym, xstrdup(buffer), FAIL);
+	DBG("MACRO '%s' expanded to :'%s'", mp->sym->name, buffer);
+	addinput(filenam, mp->sym, xstrdup(buffer), FAIL);
+	delmacro(mp);
 
 	return 1;
 }