diff lwcc/preproc.c @ 306:b08787e5b9f3 ccdev

Add include search paths and command line macro definitions Added command line macro definitions. Also implemented include paths. There is no default include path; that will be supplied by the driver program.
author William Astle <lost@l-w.ca>
date Wed, 18 Sep 2013 20:41:41 -0600
parents 54f213c8fb81
children 9e342c4e4b66
line wrap: on
line diff
--- a/lwcc/preproc.c	Wed Sep 18 19:17:52 2013 -0600
+++ b/lwcc/preproc.c	Wed Sep 18 20:41:41 2013 -0600
@@ -22,12 +22,14 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include <lw_alloc.h>
 #include <lw_string.h>
 
 #include "cpp.h"
 #include "strbuf.h"
+#include "strpool.h"
 #include "symbol.h"
 #include "token.h"
 
@@ -280,7 +282,6 @@
 	
 	mname = lw_strdup(ct -> strval);
 	ct = preproc_next_token(pp);
-	
 	if (ct -> ttype == TOK_WSPACE)
 	{
 		/* object like macro */
@@ -338,7 +339,7 @@
 	else
 	{
 baddefine:
-		preproc_throw_error(pp, "bad #define");
+		preproc_throw_error(pp, "bad #define", ct -> ttype);
 baddefine2:
 		token_list_destroy(tl);
 		skip_eol(pp);
@@ -353,6 +354,7 @@
 	for (;;)
 	{
 		ct = preproc_next_token(pp);
+	
 		if (ct -> ttype == TOK_EOL)
 			break;
 		token_list_append(tl, token_dup(ct));
@@ -378,6 +380,23 @@
 	/* no need to check for EOL here */
 }
 
+void preproc_add_macro(struct preproc_info *pp, char *str)
+{
+	char *s;
+	
+	pp -> lexstr = lw_strdup(str);
+	pp -> lexstrloc = 0;
+	s = strchr(pp -> lexstr, '=');
+	if (s)
+		*s = ' ';
+		
+	dir_define(pp);
+	
+	lw_free(pp -> lexstr);
+	pp -> lexstr = NULL;
+	pp -> lexstrloc = 0;
+}
+
 static void dir_undef(struct preproc_info *pp)
 {
 	struct token *ct;
@@ -453,6 +472,71 @@
 	lw_free(s);
 }
 
+static char *preproc_file_exists_in_dir(char *dir, char *fn)
+{
+	int l;
+	char *f;
+	
+	l = snprintf(NULL, 0, "%s/%s", dir, fn);
+	f = lw_alloc(l + 1);
+	snprintf(f, l + 1, "%s/%s", dir, fn);
+	
+	if (access(f, R_OK) == 0)
+		return f;
+	lw_free(f);
+	return NULL;
+}
+
+static char *preproc_find_file(struct preproc_info *pp, char *fn, int sys)
+{
+	char *tstr;
+	char *pref;
+	char *rfn;
+
+	/* pass through absolute paths, dumb as they are */	
+	if (fn[0] == '/')
+		return lw_strdup(fn);
+
+	if (!sys)
+	{
+		/* look in the directory with the current file */
+		tstr = strchr(pp -> fn, '/');
+		if (!tstr)
+			pref = lw_strdup(".");
+		else
+		{
+			pref = lw_alloc(tstr - pp -> fn + 1);
+			memcpy(pref, pp -> fn, tstr - pp -> fn);
+			pref[tstr - pp -> fn] = 0;
+		}
+		rfn = preproc_file_exists_in_dir(pref, fn);
+		lw_free(pref);
+		if (rfn)
+			return rfn;
+		
+		/* look in the "quote" dir list */
+		lw_stringlist_reset(pp -> quotelist);
+		for (pref = lw_stringlist_current(pp -> quotelist); pref; pref = lw_stringlist_next(pp -> quotelist))
+		{
+			rfn = preproc_file_exists_in_dir(pref, fn);
+			if (rfn)
+				return rfn;
+		}
+	}
+	
+	/* look in the "include" dir list */
+	lw_stringlist_reset(pp -> inclist);
+	for (pref = lw_stringlist_current(pp -> inclist); pref; pref = lw_stringlist_next(pp -> inclist))
+	{
+		rfn = preproc_file_exists_in_dir(pref, fn);
+		if (rfn)
+			return rfn;
+	}
+
+	/* the default search list is provided by the driver program */	
+	return NULL;
+}
+
 static void dir_include(struct preproc_info *pp)
 {
 	FILE *fp;
@@ -550,10 +634,14 @@
 		}
 	}
 doinc:
-//	fn = preproc_find_file(pp, fn, sys);
+	fn = preproc_find_file(pp, fn, sys);
+	if (!fn)
+		goto badfile;
 	fp = fopen(fn, "rb");
 	if (!fp)
 	{
+		lw_free(fn);
+badfile:
 		preproc_throw_error(pp, "Cannot open #include file %s - this is fatal", fn);
 		exit(1);
 	}
@@ -564,7 +652,8 @@
 	fs -> n = pp -> filestack;
 	pp -> curtok = NULL;
 	pp -> filestack = fs;
-	pp -> fn = fn;
+	pp -> fn = strpool_strdup(pp -> strpool, fn);
+	lw_free(fn);
 	pp -> fp = fp;
 	pp -> ra = CPP_NOUNG;
 	pp -> ppeolseen = 1;