shithub: scc

Download patch

ref: 8fb3ee51e2eacdf956288a5434dbd2cd57a161ec
parent: 7a32845fcd3b08eb599634ef26bfd963944d630c
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri May 8 14:15:43 EDT 2015

Add include handler

It is the first version of the preprocessor handler, and it
does the correct work for include of local files.

--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -40,6 +40,7 @@
 		int i;
 		char *s;
 		uint8_t token;
+		void (*fun)(char *);
 	} u;
 	struct symbol *next;
 	struct symbol *hash;
@@ -96,6 +97,7 @@
 	NS_IDEN,
 	NS_TAG,
 	NS_LABEL,
+	NS_CPP,
 	NS_STRUCTS,
 	NR_NAMESPACES
 };
@@ -264,7 +266,7 @@
 extern void discard(void);
 extern char *filename(void);
 extern unsigned short fileline(void);
-extern void addinput(char *fname);
+extern bool addinput(char *fname);
 extern void delinput(void);
 #define accept(t) ((yytoken == (t)) ? next() : 0)
 
--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -1,4 +1,5 @@
 
+#include <assert.h>
 #include <inttypes.h>
 #include <setjmp.h>
 #include <stdio.h>
@@ -10,7 +11,7 @@
 #include "../inc/cc.h"
 #include "cc1.h"
 
-#define INPUTSIZ 128
+#define INPUTSIZ 120
 
 typedef struct input Input;
 
@@ -17,7 +18,7 @@
 struct input {
 	char *fname;
 	unsigned short nline;
-	int8_t cnt;
+	int cnt;
 	FILE *fp;
 	char *line, *ptr;
 	struct input *next;
@@ -35,32 +36,35 @@
 
 static Input *input;
 
-void
+bool
 addinput(char *fname)
 {
-	Input *ip, *oip = input;
+	Input *ip;
+	FILE *fp;
+	unsigned short nline = 1;
 
+	if (fname) {
+		if ((fp = fopen(fname, "r")) == NULL)
+			return 0;
+		fname = xstrdup(fname);
+	} else if (!input) {
+		fp = stdin;
+		fname = "(stdin)";
+	} else {
+		fname = input->fname;
+		nline = input->nline;
+		fp = NULL;
+	}
+
 	ip = xmalloc(sizeof(Input));
+	ip->fname = fname;
 	ip->next = input;
 	ip->line = NULL;
 	ip->cnt = 0;
-	ip->nline = 1;
+	ip->nline = nline;
+	ip->fp = fp;
 	input = ip;
-
-	if (fname) {
-		if ((ip->fp = fopen(fname, "r")) == NULL)
-			die("file '%s' not found", fname);
-		ip->fname = xstrdup(fname);
-		next();
-	} else if (!oip) {
-		ip->fp = stdin;
-		ip->fname = "(stdin)";
-		next();
-	} else {
-		ip->fname = oip->fname;
-		ip->fp = NULL;
-		ip->nline = input->nline;
-	}
+	return 1;
 }
 
 void
@@ -99,6 +103,110 @@
 		die("input file '%s' too long", input->fname);
 }
 
+/* TODO: preprocessor error must not rise recover */
+static void
+preprocessor(void)
+{
+	char str[IDENTSIZ+1], *p, *q;
+	unsigned short cnt, n;
+	Symbol *sym;
+
+	p = input->ptr;
+	q = &p[input->cnt-1];
+	while (q > p && isspace(*q))
+		++q;
+	while (isspace(*p))
+		++p;
+	for (q = p; isalpha(*q); ++q)
+		/* nothing */;
+	if ((n = q - p) > IDENTSIZ)
+		goto bad_directive;
+	strncpy(str, p, n);
+	str[n] = '\0';
+
+	/* discard this line for the lexer */
+	input->cnt = 0;
+	if ((sym = lookup(str, NS_CPP)) == NULL)
+		goto bad_directive;
+	(*sym->u.fun)(q);
+	return;
+
+bad_directive:
+	error("incorrect preprocessor directive");
+}
+
+void
+include(char *s)
+{
+	char fname[FILENAME_MAX], delim, c, *p;
+	size_t len;
+
+	while (isspace(*s))
+		++s;
+	if ((c = *s++) == '>')
+		delim = '>';
+	else if (c == '"')
+		delim = '"';
+	else
+		goto bad_include;
+
+	for (p = s; (c = *p) && c != delim; ++p)
+		/* nothing */;
+	if (c == '\0')
+		goto bad_include;
+
+	len = p - s;
+	if (delim == '"') {
+		if (len >= FILENAME_MAX)
+			goto too_long;
+		strncpy(fname, s, len);
+		fname[len] = '\0';
+		if (!addinput(fname))
+			goto not_found;
+		return;
+	}
+	abort();
+
+	return;
+
+not_found:
+	error("included file '%s' not found", fname);
+too_long:
+	error("file name in include too long");
+bad_include:
+	error("#include expects \"FILENAME\" or <FILENAME>");
+}
+
+void
+define(char *str)
+{
+	
+}
+
+void
+undef(char *str)
+{
+	fprintf(stderr, "Esto en un undef\n");
+}
+
+void
+ifdef(char *str)
+{
+	fprintf(stderr, "Esto en un ifdef\n");
+}
+
+void
+ifndef(char *str)
+{
+	fprintf(stderr, "Esto en un ifndef\n");
+}
+
+void
+endif(char *str)
+{
+	fprintf(stderr, "Esto en un endif\n");
+}
+
 static int
 readline(void)
 {
@@ -105,8 +213,12 @@
 	char *bp, *ptr;
 	uint8_t n;
 	int c;
-	FILE *fp = input->fp;
+	FILE *fp;
 
+repeat:
+	if (!input)
+		return EOF;
+	fp = input->fp;
 	if (!input->line)
 		input->line = xmalloc(INPUTSIZ);
 	ptr = input->line;
@@ -115,8 +227,10 @@
 		if (c == '\n')
 			newline();
 	}
-	if (c == EOF)
-		return EOF;
+	if (c == EOF) {
+		delinput();
+		goto repeat;
+	}
 	ungetc(c, fp);
 
 	for (bp = ptr; (c = getc(fp)) != EOF && c != '\n'; ) {
@@ -134,12 +248,22 @@
 	*bp = ' ';
 	input->cnt = bp - ptr;
 	input->ptr = ptr;
-	return *input->ptr++;
+
+	if ((c = *input->ptr++) == '#') {
+		*bp = '\0';
+		preprocessor();
+		goto repeat;
+	}
+	return c;
 }
 
 static int
 backchar(int c)
 {
+	if (!input) {
+		assert(c == EOF);
+		return c;
+	}
 	++input->cnt;
 	return *--input->ptr = c;
 }
--- a/cc1/main.c
+++ b/cc1/main.c
@@ -67,12 +67,10 @@
 
 	ikeywords();
 
-	addinput(*argv);
-	while (yytoken != EOFTOK)
-		extdecl();
-	delinput();
+	if (!addinput(*argv))
+		die("error opening input file '%s'", *argv);
+	for (next(); yytoken != EOFTOK; extdecl())
+		/* nothing */;
 
-	if (fclose(stdout))
-		die("error writing in output:%s", strerror(errno));
 	return 0;
 }
--- a/cc1/symbol.c
+++ b/cc1/symbol.c
@@ -107,10 +107,13 @@
 void
 ikeywords(void)
 {
-	static struct {
+	extern void include(char *), define(char *), undef(char *);
+	extern void ifdef(char *),  ifndef(char *), endif(char *);
+	static struct words {
 		char *str;
 		uint8_t token, value;
-	} *bp, buff[] = {
+		void (*fun)(char *);
+	} ccwords[] = {
 		{"auto", SCLASS, AUTO},
 		{"break", BREAK, BREAK},
 		{"_Bool", TYPE, BOOL},
@@ -146,13 +149,36 @@
 		{"volatile", TQUALIFIER, VOLATILE},
 		{"while", WHILE, WHILE},
 		{NULL, 0, 0},
+	}, cppwords[] = {
+		{"include", 0, 0, include},
+		{"define", 0, 0, define},
+		{"undef", 0, 0, undef},
+		{"ifdef", 0, 0, ifdef},
+		{"ifndef", 0, 0, ifndef},
+		{"endif", 0, 0, endif},
+		{NULL, 0, 0}
 	};
+	static struct wordlist {
+		struct words *words;
+		uint8_t ns;
+	} wordlist [] = {
+		{ccwords, NS_IDEN},
+		{cppwords, NS_CPP},
+		{NULL, 0}
+	};
+	struct wordlist *lp;
+	struct words *bp;
 	Symbol *sym;
 
-	for (bp = buff; bp->str; ++bp) {
-		sym = install(bp->str, NS_IDEN);
-		sym->token = bp->token;
-		sym->u.token = bp->value;
+	for (lp = wordlist; lp->words; ++lp) {
+		for (bp = lp->words; bp->str; ++bp) {
+			sym = install(bp->str, lp->ns);
+			sym->token = bp->token;
+			if (bp->fun)
+				sym->u.fun = bp->fun;
+			else
+				sym->u.token = bp->value;
+		}
 	}
 	globalcnt = 0;
 }