changeset 300:8d6c47395653 ccdev

Implemented #include and #line Theoretically, directives are now implemented.
author William Astle <lost@l-w.ca>
date Sun, 15 Sep 2013 13:49:00 -0600
parents 856caf91ffaa
children 6f7fe78bb868
files lwcc/cpp.h lwcc/lex.c lwcc/preproc.c
diffstat 3 files changed, 201 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/lwcc/cpp.h	Sun Sep 15 13:06:00 2013 -0600
+++ b/lwcc/cpp.h	Sun Sep 15 13:49:00 2013 -0600
@@ -65,6 +65,8 @@
 	struct expand_e *expand_list;	// record of which macros are currently being expanded
 	char *lexstr;			// for lexing a string (token pasting)
 	int lexstrloc;			// ditto
+	struct preproc_info *n;	// next in file stack
+	struct preproc_info *filestack;	// stack of saved files during include
 };
 
 extern struct preproc_info *preproc_init(const char *);
--- a/lwcc/lex.c	Sun Sep 15 13:06:00 2013 -0600
+++ b/lwcc/lex.c	Sun Sep 15 13:49:00 2013 -0600
@@ -291,7 +291,7 @@
 		pp -> eolseen = 1;
 		return c;
 	}
-	
+
 	pp -> eolseen = 0;
 	
 	/* convert comments to a single space here */
@@ -351,7 +351,9 @@
 	int cl;
 	struct strbuf *strbuf;
 	struct token *t;
-						
+	struct preproc_info *fs;
+					
+fileagain:
 	c = preproc_lex_fetch_byte(pp);
 	if (c == CPP_EOF)
 	{
@@ -363,8 +365,24 @@
 	
 	if (c == CPP_EOF)
 	{
-		ttype = TOK_EOF;
-		goto out;
+		/* check if we fell off the end of an include file */
+		if (pp -> filestack)
+		{
+			if (pp -> skip_level || pp -> found_level)
+			{
+				preproc_throw_error(pp, "Unbalanced conditionals in include file");
+			}
+			fclose(pp -> fp);
+			fs = pp -> filestack;
+			*pp = *fs;
+			pp -> filestack = fs -> n;
+			goto fileagain;
+		}
+		else
+		{
+			ttype = TOK_EOF;
+			goto out;
+		}
 	}
 	if (c == CPP_EOL)
 	{
--- a/lwcc/preproc.c	Sun Sep 15 13:06:00 2013 -0600
+++ b/lwcc/preproc.c	Sun Sep 15 13:49:00 2013 -0600
@@ -19,6 +19,8 @@
 this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include <lw_alloc.h>
@@ -448,10 +450,185 @@
 
 static void dir_include(struct preproc_info *pp)
 {
+	FILE *fp;
+	struct token *ct;
+	int sys = 0;
+	char *fn;
+	struct strbuf *strbuf;
+	int i;
+	struct preproc_info *fs;
+	
+	ct = preproc_next_token_nws(pp);
+	if (ct -> ttype == TOK_STRING)
+	{
+usrinc:
+		sys = strlen(ct -> strval);
+		fn = lw_alloc(sys - 1);
+		memcpy(fn, ct -> strval + 1, sys - 2);
+		fn[sys - 1] = 0;
+		sys = 0;
+		goto doinc;
+	}
+	else if (ct -> ttype == TOK_LT)
+	{
+		strbuf = strbuf_new();
+		for (;;)
+		{
+			ct = preproc_next_token(pp);
+			if (ct -> ttype == TOK_GT)
+				break;
+			if (ct -> ttype == TOK_EOL)
+			{
+				preproc_throw_error(pp, "Bad #include");
+				lw_free(strbuf_end(strbuf));
+				return;
+			}
+			for (i = 0; ct -> strval[i]; ct++)
+			{
+				strbuf_add(strbuf, ct -> strval[i]);
+			}
+		}
+		ct = preproc_next_token_nws(pp);
+		if (ct -> ttype != TOK_EOL)
+		{
+			preproc_throw_error(pp, "Bad #include");
+			skip_eol(pp);
+			lw_free(strbuf_end(strbuf));
+			return;
+		}
+		sys = 1;
+		fn = strbuf_end(strbuf);
+		goto doinc;
+	}
+	else
+	{
+		preproc_unget_token(pp, ct);
+		// computed include
+		ct = preproc_next_processed_token_nws(pp);
+		if (ct -> ttype == TOK_STRING)
+			goto usrinc;
+		else if (ct -> ttype == TOK_LT)
+		{
+			strbuf = strbuf_new();
+			for (;;)
+			{
+				ct = preproc_next_processed_token(pp);
+				if (ct -> ttype == TOK_GT)
+					break;
+				if (ct -> ttype == TOK_EOL)
+				{
+					preproc_throw_error(pp, "Bad #include");
+					lw_free(strbuf_end(strbuf));
+					return;
+				}
+				for (i = 0; ct -> strval[i]; ct++)
+				{
+					strbuf_add(strbuf, ct -> strval[i]);
+				}
+			}
+			ct = preproc_next_processed_token_nws(pp);
+			if (ct -> ttype != TOK_EOL)
+			{
+				preproc_throw_error(pp, "Bad #include");
+				skip_eol(pp);
+				lw_free(strbuf_end(strbuf));
+				return;
+			}
+			sys = 1;
+			fn = strbuf_end(strbuf);
+			goto doinc;
+		}
+		else
+		{
+			skip_eol(pp);
+			preproc_throw_error(pp, "Bad #include");
+			return;
+		}
+	}
+doinc:
+//	fn = preproc_find_file(pp, fn, sys);
+	fp = fopen(fn, "rb");
+	if (!fp)
+	{
+		preproc_throw_error(pp, "Cannot open #include file - this is fatal");
+		exit(1);
+	}
+	
+	/* save the current include file state, etc. */
+	fs = lw_alloc(sizeof(struct preproc_info));
+	*fs = *pp;
+	fs -> n = pp -> filestack;
+	pp -> filestack = fs;
+	pp -> fn = fn;
+	pp -> fp = fp;
+	pp -> ra = CPP_NOUNG;
+	pp -> ppeolseen = 1;
+	pp -> eolstate = 0;
+	pp -> lineno = 0;
+	pp -> column = 0;
+	pp -> qseen = 0;
+	pp -> ungetbufl = 0;
+	pp -> ungetbufs = 0;
+	pp -> ungetbuf = NULL;
+	pp -> unget = 0;
+	pp -> eolseen = 0;
+	pp -> nlseen = 0;
+	pp -> skip_level = 0;
+	pp -> found_level = 0;
+	pp -> else_level = 0;
+	pp -> else_skip_level = 0;
+	
+	// now get on with processing
 }
 
 static void dir_line(struct preproc_info *pp)
 {
+	struct token *ct;
+	long lineno;
+	char *estr;
+	
+	lineno = -1;
+	
+	ct = preproc_next_processed_token_nws(pp);
+	if (ct -> ttype == TOK_NUMBER)
+	{
+		lineno = strtoul(ct -> strval, &estr, 10);
+		if (*estr)
+		{
+			preproc_throw_error(pp, "Bad #line");
+			skip_eol(pp);
+			return;
+		}
+	}
+	else
+	{
+		preproc_throw_error(pp, "Bad #line");
+		skip_eol(pp);
+		return;
+	}
+	ct = preproc_next_processed_token_nws(pp);
+	if (ct -> ttype == TOK_EOL)
+	{
+		pp -> lineno = lineno;
+		return;
+	}
+	if (ct -> ttype != TOK_STRING)
+	{
+		preproc_throw_error(pp, "Bad #line");
+		skip_eol(pp);
+		return;
+	}
+	estr = lw_strdup(ct -> strval);
+	ct = preproc_next_processed_token_nws(pp);
+	if (ct -> ttype != TOK_EOL)
+	{
+		preproc_throw_error(pp, "Bad #line");
+		skip_eol(pp);
+		lw_free(estr);
+		return;
+	}
+	pp -> fn = estr;
+	pp -> lineno = lineno;
 }
 
 static void dir_pragma(struct preproc_info *pp)