shithub: scc

Download patch

ref: 0fba7162733650be3f0dab5c60ec4513b1775201
parent: a05cda6f2efb61fe4b42e43a2ee76f80492a4e27
author: Roberto E. Vargas Caballero <[email protected]>
date: Tue May 26 18:14:51 EDT 2015

Rewrite Input system

The Input system had a lot of problems and bugs, and it was very bad written.
This version is still slow, but it is working now.

--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -256,6 +256,7 @@
 /* symbol.c */
 extern void dumpstab(char *msg);
 extern Symbol *lookup(unsigned ns);
+extern Symbol *nextsym(Symbol *sym, unsigned ns);
 extern Symbol *install(unsigned ns);
 extern Symbol *newsym(unsigned ns);
 extern void pushctx(void), popctx(void);
@@ -278,10 +279,10 @@
 extern unsigned short getfline(void);
 extern void setfname(char *name);
 extern void setfline(unsigned short line);
-extern char *addinput(char *fname, Symbol *sym);
+extern bool addinput(char *fname, Symbol *sym, char *str);
 extern void setnamespace(int ns);
 extern void setsafe(int type);
-extern void initcpp(void);
+extern void ilex(char *fname);
 #define accept(t) ((yytoken == (t)) ? next() : 0)
 
 /* code.c */
@@ -296,7 +297,8 @@
 extern Node *expr(void), *negate(Node *np);
 
 /* cpp.c */
-extern bool preprocessor(char *s);
+extern void icpp(void);
+extern bool cpp(char *s);
 extern bool expand(Symbol *sym);
 
 /*
@@ -307,6 +309,7 @@
 extern unsigned yytoken;
 extern unsigned short yylen;
 extern int cppoff;
+extern unsigned cppctx;
 
 extern Type *voidtype, *pvoidtype, *booltype,	
             *uchartype,   *chartype,
--- a/cc1/cpp.c
+++ b/cc1/cpp.c
@@ -13,13 +13,12 @@
 
 /* TODO: preprocessor error must not rise recover */
 
-static char *argp;
+static char *argp, *macroname;
 static unsigned arglen;
-static unsigned numif;
-static Symbol *lastmacro;
 static Symbol *symline, *symfile;
+static unsigned char ifstatus[NR_COND];
 
-unsigned char ifstatus[NR_COND];
+unsigned cppctx;
 
 static Symbol *
 defmacro(char *s)
@@ -33,7 +32,7 @@
 }
 
 void
-initcpp(void)
+icpp(void)
 {
 	static char sdate[17], stime[14];
 	struct tm *tm;
@@ -109,11 +108,11 @@
 	next();
 	if (yytoken == EOFTOK) {
 		error("unterminated argument list invoking macro \"%s\"",
-		      lastmacro->name);
+		      macroname);
 	}
 	if (yylen + 1 > arglen) {
 		error("argument overflow invoking macro \"%s\"",
-		      lastmacro->name);
+		      macroname);
 	}
 	memcpy(argp, yytext, yylen);
 	argp += yylen;
@@ -177,10 +176,10 @@
 	}
 
 	if (n == NR_MACROARG)
-		error("too much parameters in macro \"%s\"", lastmacro->name);
+		error("too much parameters in macro \"%s\"", macroname);
 	if (n != nargs) {
 		error("macro \"%s\" passed %d arguments, but it takes %d",
-		      lastmacro->name, n, nargs);
+		      macroname, n, nargs);
 	}
 	return 1;
 }
@@ -193,7 +192,7 @@
  * is the macro definition, where @dd@ indicates the
  * parameter number dd
  */
-#define BUFSIZE ((INPUTSIZ > FILENAME_MAX+2) ? INPUTSIZ : FILENAME_MAX+5)
+#define BUFSIZE ((INPUTSIZ > FILENAME_MAX+2) ? INPUTSIZ : FILENAME_MAX+2)
 bool
 expand(Symbol *sym)
 {
@@ -203,20 +202,18 @@
 
 	if (sym == symfile) {
 		sprintf(buffer, "\"%s\"", getfname());
-		strcpy(addinput(NULL, symfile), buffer);
-		return 1;
+		goto add_macro;
 	}
 	if (sym == symline) {
 		sprintf(buffer, "%d", getfline());
-		strcpy(addinput(NULL, symline), buffer);
-		return 1;
+		goto add_macro;
 	}
 
-	lastmacro = sym;
+	macroname = sym->name;
 	if (!parsepars(buffer, arglist, atoi(s)))
 		return 0;
 
-	bp = addinput(NULL, sym);
+	bp = buffer;
 	len = INPUTSIZ-1;
 	for (s += 3; c = *s; ++s) {
 		if (c != '@') {
@@ -237,10 +234,12 @@
 		}
 	}
 	*bp = '\0';
+add_macro:
+	addinput(NULL, sym, buffer);
 	return 1;
 
 expansion_too_long:
-	error("expansion of macro \"%s\" is too long", lastmacro->name);
+	error("expansion of macro \"%s\" is too long", macroname);
 }
 #undef BUFSIZE
 
@@ -382,7 +381,7 @@
 static void
 include(char *s)
 {
-	char **bp, delim, c, *p, *file, buff[FILENAME_MAX];
+	char **bp, delim, c, *p, *file, path[FILENAME_MAX];
 	char *sysinclude[] = {
 		PREFIX"/include/",
 		PREFIX"/local/include/",
@@ -402,7 +401,7 @@
 	if (!string(&s, &file, delim))
 		goto bad_include;
 	cleanup(s);
-	if (delim == '"' && addinput(file, NULL))
+	if (delim == '"' && addinput(file, NULL, NULL))
 		return;
 
 	filelen = strlen(file);
@@ -410,9 +409,9 @@
 		dirlen = strlen(*bp);
 		if (dirlen + filelen > FILENAME_MAX)
 			continue;
-		memcpy(buff, *bp, dirlen);
-		memcpy(buff+dirlen, file, filelen);
-		if (addinput(buff, NULL))
+		memcpy(path, *bp, dirlen);
+		memcpy(path+dirlen, file, filelen);
+		if (addinput(path, NULL, NULL))
 			return;
 	}
 	error("included file '%s' not found", file);
@@ -472,13 +471,15 @@
 ifclause(char *s, int isdef)
 {
 	Symbol *sym;
-	unsigned n = numif++;
+	unsigned n = cppctx++;
 
-	if (numif == NR_COND-1)
+	if (cppctx == NR_COND-1)
 		error("too much nesting levels of conditional inclusion");
 
-	if (!iden(&s))
-		error("#ifdef clause must have an identifier as parameter");
+	if (!iden(&s)) {
+		error("no macro name given in #%s directive",
+		      (isdef) ? "ifdef" : "ifndef");
+	}
 	cleanup(s);
 
 	sym = lookup(NS_CPP);
@@ -501,10 +502,10 @@
 static void
 endif(char *s)
 {
-	if (numif == 0)
+	if (cppctx == 0)
 		error("#endif without #if");
 	cleanup(s);
-	if (!ifstatus[--numif])
+	if (!ifstatus[--cppctx])
 		--cppoff;
 }
 
@@ -513,10 +514,10 @@
 {
 	struct ifstatus *ip;
 
-	if (numif == 0)
+	if (cppctx == 0)
 		error("#else without #if");
 	cleanup(s);
-	cppoff += (ifstatus[numif-1] ^= 1) ? -1 : 1;
+	cppoff += (ifstatus[cppctx-1] ^= 1) ? -1 : 1;
 }
 
 static void
@@ -532,7 +533,7 @@
 }
 
 bool
-preprocessor(char *s)
+cpp(char *s)
 {
 	static struct {
 		char *name;
--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -1,4 +1,5 @@
 
+#include <ctype.h>
 #include <errno.h>
 #include <inttypes.h>
 #include <setjmp.h>
@@ -5,13 +6,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 
 #include "../inc/sizes.h"
 #include "../inc/cc.h"
 #include "cc1.h"
 
-
 typedef struct input Input;
 
 struct input {
@@ -30,62 +29,103 @@
 int cppoff;
 
 static unsigned lex_ns = NS_IDEN;
-static int safe, eof, incomment;
+static int safe, eof;
 static Input *input;
 
-char *
-addinput(char *fname, Symbol *sym)
+static void
+allocinput(char *fname, FILE *fp, char *buff)
 {
 	Input *ip;
+
+	ip = xmalloc(sizeof(Input));
+	ip->fname = fname;
+	ip->next = input;
+	ip->macro = NULL;
+	ip->begin = ip->line = buff;
+	ip->nline = (fp) ? 0 : input->nline;
+	ip->fp = fp;
+	input = ip;
+}
+
+void
+ilex(char *fname)
+{
 	FILE *fp;
-	unsigned short nline = 0;
 
-	/* TODO: Add a field in input to see easier which is the case
-	   where we are */
+	/*
+	 * we can use static file names because this Input is not going
+	 * to be freed ever
+	 */
+	if (!fname) {
+		fp = stdin;
+		fname = "<stdin>";
+	} else {
+		if ((fp = fopen(fname, "r")) == NULL)
+			die("error opening output:%s", strerror(errno));
+		fname = fname;
+	}
+	allocinput(fname, fp, xmalloc(INPUTSIZ));
+	*input->begin = '\0';
+}
 
+bool
+addinput(char *fname, Symbol *sym, char *str)
+{
+	FILE *fp;
+	char flags = 0;
+
 	if (fname) {
+		/*
+		 * this call comes from an include clause, so we reuse
+		 * the buffer from the calling Input
+		 */
 		if ((fp = fopen(fname, "r")) == NULL)
-			return NULL;
+			return 0;
 		fname = xstrdup(fname);
-	} else if (!input) {
-		fp = stdin;
-		fname = xstrdup("<stdin>");
+		str = input->line;
+		*str = '\0';
 	} else {
+		/*
+		 * This call comes from a macro expansion, so we have
+		 * to duplicate the input string because it is the
+		 * expansion of the macro in a temporal buffer
+		 */
 		fname = input->fname;
-		nline = input->nline;
 		fp = NULL;
+		str = xstrdup(str);
 	}
-
-	ip = xmalloc(sizeof(Input));
-	ip->fname = fname;
-	ip->next = input;
-	ip->macro = sym;
-	ip->begin = ip->p = ip->line = xmalloc(INPUTSIZ);
-	*ip->begin = '\0';
-	ip->nline = nline;
-	ip->fp = fp;
-	input = ip;
-	return input->line;
+	allocinput(fname, fp, str);
+	input->macro = sym;
+	return 1;
 }
 
 static void
 delinput(void)
 {
-	Input *ip = input;
-	FILE *fp = ip->fp;
+	Input *ip;
 
-	if (!ip->next)
-		eof = 1;
-	if (fp) {
-		if (fclose(fp))
-			die("error reading from input file '%s'", ip->fname);
-		if (eof)
+repeat:
+	if (input->fp) {
+		/* include input */
+		if (fclose(input->fp))
+			die("error reading from input file '%s'", input->fname);
+		if (!input->next) {
+			eof = 1;
 			return;
-		free(ip->fname);
+		}
+		free(input->fname);
+	} else {
+		/* macro input */
+		free(input->line);
 	}
-	input = ip->next;
-	free(ip->line);
+	ip = input;
+	input = input->next;
 	free(ip);
+
+	if (*input->begin != '\0')
+		return;
+	if (!input->fp)
+		goto repeat;
 }
 
 void
@@ -120,13 +160,10 @@
 	FILE *fp;
 
 repeat:
-	while (!input->fp || (feof(input->fp) && !eof))
+	if (feof(input->fp))
 		delinput();
-	if (eof) {
-		if (incomment)
-			error("unterminated comment");
+	if (eof)
 		return '\0';
-	}
 	fp = input->fp;
 
 	if ((c = getc(fp)) == '\\') {
@@ -135,7 +172,7 @@
 		ungetc(c, fp);
 		c = '\\';
 	} else if (c == EOF) {
-		goto repeat;
+		c = '\n';
 	} else if (c == '\n' && ++input->nline == 0) {
 		die("error:input file '%s' too long", getfname());
 	}
@@ -143,31 +180,32 @@
 }
 
 static void
-comment(char c)
+comment(char type)
 {
-	/* TODO: Ensure that incomment == 0 after a recovery */
-	incomment = 1;
-	if (c == '*') {
-		for (;;) {
-			while (readchar() !=  '*')
-				/* nothing */;
+	if (type == '*') {
+		while (!eof) {
+			while (readchar() !=  '*' && !eof)
+				/* nothing */
 			if (readchar() == '/')
 				break;
 		}
 	} else {
-		while (readchar() != '\n')
+		while (readchar() != '\n' && !eof)
 			/* nothing */;
 	}
-	incomment = 0;
+	if (eof)
+		error("unterminated comment");
 }
 
-static void
+static bool
 readline(void)
 {
 	char *bp, *lim;
 	char c, peekc = 0;
 
-	lim = input->line + INPUTSIZ;
+	if (eof)
+		return 0;
+	lim = &input->line[INPUTSIZ-1];
 	for (bp = input->line; bp != lim; *bp++ = c) {
 		c = (peekc) ? peekc : readchar();
 		peekc = 0;
@@ -180,7 +218,7 @@
 			c = '/';
 		} else {
 			comment(c);
-			c = ' ';
+			break;
 		}
 	}
 
@@ -187,6 +225,7 @@
 	if (bp == lim)
 		error("line %u too big in file '%s'", getfline(), getfname());
 	*bp = '\0';
+	return 1;
 }
 
 bool
@@ -195,19 +234,14 @@
 	char *p;
 
 repeat:
-	if (eof)
-		return 0;
-	while (*input->begin == '\0' && !input->fp) {
+	if (!input->fp)
 		delinput();
-		if (*input->begin)
-			return 1;
-	}
-
-	*(p = input->line) = '\0';
-	readline();
+	if (!readline())
+		return 0;
+	p = input->line;
 	while (isspace(*p))
 		++p;
-	if (*p == '\0' || preprocessor(p) || cppoff)
+	if (*p == '\0' || cpp(p) || cppoff)
 		goto repeat;
 	input->p = input->begin = p;
 	return 1;
@@ -549,6 +583,8 @@
 repeat:
 	skipspaces();
 	if (eof) {
+		if (cppctx)
+			error("#endif expected");
 		strcpy(yytext, "<EOF>");
 		return yytoken = EOFTOK;
 	}
@@ -624,7 +660,7 @@
 				goto jump;
 			break;
 		}
-		if (!moreinput())
+		if (c == '\0' && !moreinput())
 			exit(-1);
 	}
 jump:
--- a/cc1/main.c
+++ b/cc1/main.c
@@ -63,11 +63,10 @@
 	if (argc > 1)
 		usage();
 
-	initcpp();
+	icpp();
 	ikeywords();
+	ilex(*argv);
 
-	if (!addinput(*argv, NULL))
-		die("error opening input file '%s'", *argv);
 	for (next(); yytoken != EOFTOK; extdecl())
 		/* nothing */;