diff options
Diffstat (limited to 'wrapperhelper/src/preproc.c')
| -rw-r--r-- | wrapperhelper/src/preproc.c | 291 |
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); |