about summary refs log tree commit diff stats
path: root/wrapperhelper/src/preproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'wrapperhelper/src/preproc.c')
-rw-r--r--wrapperhelper/src/preproc.c291
1 files changed, 122 insertions, 169 deletions
diff --git a/wrapperhelper/src/preproc.c b/wrapperhelper/src/preproc.c
index f402d82a..0f67762a 100644
--- a/wrapperhelper/src/preproc.c
+++ b/wrapperhelper/src/preproc.c
@@ -1,7 +1,6 @@
 // I think this file is too big for GCC to handle properly, there are curious false-positive analyzer warnings
 //  that didn't appear before adding preproc_eval
 #include "preproc.h"
-#include "preproc_private.h"
 
 #include <stdint.h>
 #include <string.h>
@@ -11,6 +10,39 @@
 #include "machine.h"
 #include "prepare.h"
 
+typedef struct mtoken_s {
+	enum mtoken_e {
+		MTOK_TOKEN,
+		MTOK_ARG,
+		MTOK_STRINGIFY,
+		MTOK_CONCAT,
+	} typ;
+	union {
+		preproc_token_t tok;
+		unsigned argid;
+		struct { struct mtoken_s *l, *r; } concat;
+	} val;
+} mtoken_t;
+static void mtoken_del(mtoken_t *tok) {
+	switch (tok->typ) {
+	case MTOK_TOKEN:
+		preproc_token_del(&tok->val.tok);
+		free(tok);
+		return;
+		
+	case MTOK_CONCAT:
+		mtoken_del(tok->val.concat.l);
+		mtoken_del(tok->val.concat.r);
+		free(tok);
+		return;
+		
+	case MTOK_ARG:
+	case MTOK_STRINGIFY:
+		free(tok);
+		return;
+	}
+}
+
 KHASH_MAP_INIT_STR(argid_map, unsigned)
 static void argid_map_del(khash_t(argid_map) *args) {
 	kh_cstr_t str;
@@ -20,21 +52,21 @@ static void argid_map_del(khash_t(argid_map) *args) {
 #pragma GCC diagnostic pop
 	kh_destroy(argid_map, args);
 }
-mtoken_t *mtoken_new_token(preproc_token_t tok) {
+static mtoken_t *mtoken_new_token(preproc_token_t tok) {
 	mtoken_t *ret = malloc(sizeof *ret);
 	if (!ret) return NULL;
 	ret->typ = MTOK_TOKEN;
 	ret->val.tok = tok;
 	return ret;
 }
-mtoken_t *mtoken_new_arg(unsigned argid, int as_string) {
+static mtoken_t *mtoken_new_arg(unsigned argid, int as_string) {
 	mtoken_t *ret = malloc(sizeof *ret);
 	if (!ret) return NULL;
 	ret->typ = as_string ? MTOK_STRINGIFY : MTOK_ARG;
 	ret->val.argid = argid;
 	return ret;
 }
-mtoken_t *mtoken_new_concat(mtoken_t *l, mtoken_t *r) { // Takes ownership of l and r
+static mtoken_t *mtoken_new_concat(mtoken_t *l, mtoken_t *r) { // Takes ownership of l and r
 	mtoken_t *ret = malloc(sizeof *ret);
 	if (!ret) {
 		mtoken_del(l);
@@ -46,48 +78,6 @@ mtoken_t *mtoken_new_concat(mtoken_t *l, mtoken_t *r) { // Takes ownership of l
 	ret->val.concat.r = r;
 	return ret;
 }
-void mtoken_del(mtoken_t *tok) {
-	switch (tok->typ) {
-	case MTOK_TOKEN:
-		preproc_token_del(&tok->val.tok);
-		free(tok);
-		return;
-		
-	case MTOK_CONCAT:
-		mtoken_del(tok->val.concat.l);
-		mtoken_del(tok->val.concat.r);
-		free(tok);
-		return;
-		
-	case MTOK_ARG:
-	case MTOK_STRINGIFY:
-		free(tok);
-		return;
-	}
-}
-mtoken_t *mtoken_dup(mtoken_t *src) {
-	switch (src->typ) {
-	case MTOK_TOKEN:
-		return mtoken_new_token(preproc_token_dup(src->val.tok));
-		
-	case MTOK_ARG:
-		return mtoken_new_arg(src->val.argid, 0);
-		
-	case MTOK_STRINGIFY:
-		return mtoken_new_arg(src->val.argid, 1);
-		
-	case MTOK_CONCAT: {
-		mtoken_t *l = mtoken_dup(src->val.concat.l);
-		if (!l) return NULL;
-		mtoken_t *r = mtoken_dup(src->val.concat.r);
-		if (!r) {
-			mtoken_del(l);
-			return NULL;
-		}
-		return mtoken_new_concat(l, r); }
-	}
-	return NULL;
-}
 
 static inline void print_macro_tok(mtoken_t *m) {
 	switch (m->typ) {
@@ -116,13 +106,21 @@ static inline void print_macro_tok(mtoken_t *m) {
 	}
 }
 
+VECTOR_DECLARE_STATIC(mtoken, mtoken_t*)
 #define mtoken_ptr_del(m) mtoken_del(*(m))
-VECTOR_IMPL(mtoken, mtoken_ptr_del)
+VECTOR_IMPL_STATIC(mtoken, mtoken_ptr_del)
 #undef mtoken_ptr_del
 
+typedef struct macro_s {
+	int is_funlike;
+	int has_varargs;
+	unsigned nargs;
+	VECTOR(mtoken) *toks;
+} macro_t;
+
 KHASH_MAP_INIT_STR(macros_map, macro_t)
 KHASH_SET_INIT_STR(string_set)
-void macro_del(macro_t *m) {
+static void macro_del(macro_t *m) {
 	vector_del(mtoken, m->toks);
 }
 static void macros_map_del(khash_t(macros_map) *args) {
@@ -143,32 +141,6 @@ static void macros_set_del(khash_t(string_set) *strset) {
 	kh_destroy(string_set, strset);
 }
 
-VECTOR(mtoken) *mtokens_dup(const VECTOR(mtoken) *src) {
-	VECTOR(mtoken) *ret = vector_new_cap(mtoken, vector_size(mtoken, src));
-	if (!ret) return NULL;
-	vector_for(mtoken, mtok, src) {
-		mtoken_t *mtok2 = mtoken_dup(*mtok);
-		if (!mtok2) {
-			vector_del(mtoken, ret);
-			return NULL;
-		}
-		if (!vector_push(mtoken, ret, mtok2)) {
-			mtoken_del(mtok2);
-			vector_del(mtoken, ret);
-			return NULL;
-		}
-	}
-	return ret;
-}
-int macro_dup(macro_t *dest, const macro_t *src) {
-	dest->is_funlike = src->is_funlike;
-	dest->has_varargs = src->has_varargs;
-	dest->nargs = src->nargs;
-	dest->toks = mtokens_dup(src->toks);
-	if (!dest->toks) return 0;
-	return 1;
-}
-
 typedef struct ppsource_s {
 	enum ppsrc_e {
 		PPSRC_PREPARE = 0,
@@ -275,6 +247,64 @@ static preproc_token_t ppsrc_next_token(preproc_t *src) {
 	}
 }
 
+static int try_open_dir(preproc_t *src, string_t *filename) {
+	size_t fnlen = string_len(filename);
+	size_t incl_len = src->dirname ? strlen(src->dirname) : 1;
+	char *fn = malloc(incl_len + fnlen + 2);
+	if (!fn) return 0;
+	if (src->dirname) {
+		memcpy(fn, src->dirname, incl_len);
+		fn[incl_len] = '/';
+	} else {
+		fn[0] = '.';
+		fn[1] = '/';
+	}
+	strcpy(fn + incl_len + 1, string_content(filename));
+	FILE *f = fopen(fn, "r");
+	// printf("Trying %s: %p\n", fn, f);
+	int ret;
+	if (f) {
+		char *new_dirname = strchr(fn, '/') ? strndup(fn, (size_t)(strrchr(fn, '/') - fn)) : NULL;
+		ret = vector_push(ppsource, src->prep, PREPARE_NEW_FILE(f, fn, src->cur_file, src->dirname, src->is_sys, src->cur_pathno));
+		if (ret) {
+			src->is_sys = 0;
+			src->cur_file = fn;
+			src->dirname = new_dirname;
+			src->cur_pathno = 0;
+		}
+	} else {
+		free(fn);
+		ret = 0;
+	}
+	return ret;
+}
+static int try_open_sys(preproc_t *src, string_t *filename, size_t array_off) {
+	size_t fnlen = string_len(filename);
+	for (; array_off < src->target->npaths; ++array_off) {
+		size_t incl_len = strlen(src->target->include_path[array_off]);
+		char *fn = malloc(incl_len + fnlen + 2);
+		if (!fn) return 0;
+		memcpy(fn, src->target->include_path[array_off], incl_len);
+		fn[incl_len] = '/';
+		strcpy(fn + incl_len + 1, string_content(filename));
+		FILE *f = fopen(fn, "r");
+		// printf("Trying %s: %p\n", fn, f);
+		if (f) {
+			char *new_dirname = strchr(fn, '/') ? strndup(fn, (size_t)(strrchr(fn, '/') - fn)) : NULL;
+			int ret = vector_push(ppsource, src->prep, PREPARE_NEW_FILE(f, fn, src->cur_file, src->dirname, src->is_sys, src->cur_pathno));
+			if (ret) {
+				src->is_sys = 1;
+				src->cur_file = fn;
+				src->dirname = new_dirname;
+				src->cur_pathno = array_off + 1;
+			}
+			return ret;
+		}
+		free(fn);
+	}
+	return 0;
+}
+
 preproc_t *preproc_new_file(machine_t *target, FILE *f, char *dirname, const char *filename) {
 	preproc_t *ret = malloc(sizeof *ret);
 	if (!ret) {
@@ -316,42 +346,7 @@ preproc_t *preproc_new_file(machine_t *target, FILE *f, char *dirname, const cha
 	ret->cur_file = NULL;
 	// ret can now be deleted by preproc_del
 	
-	// First add predefined macros
-	for (size_t i = 0; i < target->npredefs; ++i) {
-		// NL and EOF have empty destructors
-		khiter_t kh_k;
-		int iret;
-		char *mname_dup = strdup(target->predef_macros_name[i]);
-		if (!mname_dup) {
-			printf("Error: failed to initialize preprocessor (predefined macros), aborting\n");
-			preproc_del(ret);
-			return NULL;
-		}
-		kh_k = kh_put(string_set, ret->macros_defined, mname_dup, &iret);
-		// TODO: check iret?
-		if (iret >= 1) {
-			mname_dup = strdup(mname_dup);
-		}
-		kh_k = kh_put(macros_map, ret->macros_map, mname_dup, &iret);
-		if (iret < 0) {
-			printf("Error: failed to initialize preprocessor (predefined macros), aborting\n");
-			preproc_del(ret);
-			return NULL;
-		} else if (iret == 0) {
-			printf("Error: duplicated predefined macros, aborting\n");
-			preproc_del(ret);
-			return NULL;
-		}
-		if (!macro_dup(&kh_val(ret->macros_map, kh_k), target->predef_macros[i])) {
-			printf("Error: failed to initialize preprocessor (predefined macros), aborting\n");
-			free(mname_dup);
-			kh_del(macros_map, ret->macros_map, kh_k);
-			preproc_del(ret);
-			return NULL;
-		}
-	}
-	
-	// Next include the first file
+	// Include the first file
 	if (!vector_push(ppsource, ret->prep, PREPARE_NEW_FILE(f, filename, NULL, NULL, 0, 0))) {
 		preproc_del(ret);
 		return NULL;
@@ -360,72 +355,30 @@ preproc_t *preproc_new_file(machine_t *target, FILE *f, char *dirname, const cha
 		preproc_del(ret);
 		return NULL;
 	}
-	// Last finish setting up ret
+	// Next finish setting up ret
 	ret->st = PPST_NL;
 	ret->is_sys = 0;
 	ret->dirname = dirname;
 	ret->cur_file = strdup(filename);
 	ret->cur_pathno = 0;
-	return ret;
-}
-
-static int try_open_dir(preproc_t *src, string_t *filename) {
-	size_t fnlen = string_len(filename);
-	size_t incl_len = src->dirname ? strlen(src->dirname) : 1;
-	char *fn = malloc(incl_len + fnlen + 2);
-	if (!fn) return 0;
-	if (src->dirname) {
-		memcpy(fn, src->dirname, incl_len);
-		fn[incl_len] = '/';
-	} else {
-		fn[0] = '.';
-		fn[1] = '/';
+	
+	// Also include 'stdc-predef.h' (it will be parsed before the requested file)
+	string_t *stdc_predef = string_new_cstr("stdc-predef.h");
+	if (!stdc_predef) {
+		printf("Error: failed to create new string 'stdc-predef.h'\n");
+		preproc_del(ret);
+		return NULL;
 	}
-	strcpy(fn + incl_len + 1, string_content(filename));
-	FILE *f = fopen(fn, "r");
-	// printf("Trying %s: %p\n", fn, f);
-	int ret;
-	if (f) {
-		char *new_dirname = strchr(fn, '/') ? strndup(fn, (size_t)(strrchr(fn, '/') - fn)) : NULL;
-		ret = vector_push(ppsource, src->prep, PREPARE_NEW_FILE(f, fn, src->cur_file, src->dirname, src->is_sys, src->cur_pathno));
-		if (ret) {
-			src->is_sys = 0;
-			src->cur_file = fn;
-			src->dirname = new_dirname;
-			src->cur_pathno = 0;
-		}
-	} else {
-		free(fn);
-		ret = 0;
+	if (!try_open_sys(ret, stdc_predef, 0)) {
+		printf("Error: failed to open file 'stdc-predef.h'\n");
+		string_del(stdc_predef);
+		preproc_del(ret);
+		return NULL;
 	}
+	string_del(stdc_predef);
+	
 	return ret;
 }
-static int try_open_sys(preproc_t *src, string_t *filename, size_t array_off) {
-	size_t fnlen = string_len(filename);
-	for (; array_off < src->target->npaths; ++array_off) {
-		size_t incl_len = strlen(src->target->include_path[array_off]);
-		char *fn = malloc(incl_len + fnlen + 2);
-		if (!fn) return 0;
-		memcpy(fn, src->target->include_path[array_off], incl_len);
-		fn[incl_len] = '/';
-		strcpy(fn + incl_len + 1, string_content(filename));
-		FILE *f = fopen(fn, "r");
-		// printf("Trying %s: %p\n", fn, f);
-		if (f) {
-			char *new_dirname = strchr(fn, '/') ? strndup(fn, (size_t)(strrchr(fn, '/') - fn)) : NULL;
-			int ret = vector_push(ppsource, src->prep, PREPARE_NEW_FILE(f, fn, src->cur_file, src->dirname, src->is_sys, src->cur_pathno));
-			if (ret) {
-				src->is_sys = 1;
-				src->cur_file = fn;
-				src->dirname = new_dirname;
-				src->cur_pathno = array_off + 1;
-			}
-			return ret;
-		}
-		free(fn);
-	}
-	return 0;
-}
 
 static void preprocs_del(VECTOR(preproc) **p) {
 	if (!*p) return;
@@ -446,8 +399,7 @@ static VECTOR(preproc) *
 	// May change margs if m->has_varargs, but takes no ownership
 	// opt_used_macros is NULL in regular expansion, non-NULL in #if-expansions
 
-static VECTOR(preproc) *
-proc_solve_macro(const khash_t(macros_map) *macros, char *mname, const macro_t *m, VECTOR(preprocs) *margs,
+static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char *mname, const macro_t *m, VECTOR(preprocs) *margs,
                  khash_t(string_set) *solved_macros, khash_t(string_set) *opt_used_macros) {
 	if (m->is_funlike && !margs) {
 		printf("<internal error: m->is_funlike && !margs>\n");
@@ -3132,6 +3084,7 @@ start_cur_token:
 		if ((vector_last(ppsource, src->prep).srct == PPSRC_PREPARE) && vector_last(ppsource, src->prep).srcv.prep.cond_depth) {
 			printf("Error: file ended before closing all conditionals (ignoring)\n");
 		}
+		// printf("Closing %s\n", src->cur_file);
 		if (vector_last(ppsource, src->prep).srct == PPSRC_PREPARE) {
 			if (src->dirname) free(src->dirname);
 			if (src->cur_file) free(src->cur_file);