diff options
Diffstat (limited to 'wrapperhelper/src')
| -rw-r--r-- | wrapperhelper/src/generator.c | 34 | ||||
| -rw-r--r-- | wrapperhelper/src/generator.h | 1 | ||||
| -rw-r--r-- | wrapperhelper/src/lang.c | 4 | ||||
| -rw-r--r-- | wrapperhelper/src/lang.h | 4 | ||||
| -rw-r--r-- | wrapperhelper/src/machine.c | 171 | ||||
| -rw-r--r-- | wrapperhelper/src/machine.h | 5 | ||||
| -rw-r--r-- | wrapperhelper/src/parse.c | 227 | ||||
| -rw-r--r-- | wrapperhelper/src/preproc.c | 291 | ||||
| -rw-r--r-- | wrapperhelper/src/preproc_private.h | 39 |
9 files changed, 364 insertions, 412 deletions
diff --git a/wrapperhelper/src/generator.c b/wrapperhelper/src/generator.c index 63102f48..33ace369 100644 --- a/wrapperhelper/src/generator.c +++ b/wrapperhelper/src/generator.c @@ -9,7 +9,6 @@ static const char *rft2str[8] = { [RQT_FUN_MY] = " (my)", [RQT_FUN_D] = " (D)", [RQT_DATA] = "", - [RQT_DATAV] = " (V)", [RQT_DATAB] = " (B)", [RQT_DATAM] = " (my)", }; @@ -34,7 +33,6 @@ void request_print(const request_t *req) { } break; case RQT_DATA: - case RQT_DATAV: case RQT_DATAB: case RQT_DATAM: if (req->def.dat.has_size) { @@ -62,7 +60,6 @@ void request_print(const request_t *req) { } break; case RQT_DATA: - case RQT_DATAV: case RQT_DATAB: case RQT_DATAM: if (req->val.dat.has_size) { @@ -124,7 +121,6 @@ void request_print_check(const request_t *req) { } break; case RQT_DATA: - case RQT_DATAV: case RQT_DATAB: case RQT_DATAM: similar = 1; @@ -170,7 +166,6 @@ static void request_del(request_t *req) { case RQT_FUN_MY: if (req->def.fun.typ) string_del(req->def.fun.typ); break; case RQT_FUN_D: if (req->def.fun.typ) string_del(req->def.fun.typ); if (req->def.fun.fun2) string_del(req->def.fun.fun2); break; case RQT_DATA: break; - case RQT_DATAV: break; case RQT_DATAB: break; case RQT_DATAM: break; } @@ -181,7 +176,6 @@ static void request_del(request_t *req) { case RQT_FUN_MY: string_del(req->val.fun.typ); break; case RQT_FUN_D: string_del(req->val.fun.typ); string_del(req->val.fun.fun2); break; case RQT_DATA: break; - case RQT_DATAV: break; case RQT_DATAB: break; case RQT_DATAM: break; } @@ -218,7 +212,6 @@ static const char *rqt_suffix[8] = { [RQT_FUN_MY] = "M", [RQT_FUN_D] = "D", [RQT_DATA] = "", - [RQT_DATAV] = "V", [RQT_DATAB] = "B", [RQT_DATAM] = "M", }; @@ -245,14 +238,14 @@ static void request_output(FILE *f, const request_t *req) { if (req->def.dat.has_size) { fprintf(f, "%sDATA%s%s(%s, %zu)%s\n", req->default_comment ? "//" : "", - req->weak ? "W" : "", + req->weak ? "V" : "", rqt_suffix[req->def.rty], string_content(req->obj_name), req->def.dat.sz, (req->ignored || req->default_comment) ? "" : " // Warning: failed to confirm"); } else { fprintf(f, "//DATA%s%s(%s, \n", - req->weak ? "W" : "", + req->weak ? "V" : "", rqt_suffix[req->def.rty], string_content(req->obj_name)); } @@ -273,13 +266,15 @@ static void request_output(FILE *f, const request_t *req) { } else { if (req->val.dat.has_size) { int is_comment = IS_RQT_FUNCTION(req->def.rty) || !req->def.dat.has_size || req->default_comment || (req->def.rty != req->val.rty); - fprintf(f, "%sDATA%s(%s, %zu)\n", + fprintf(f, "%sDATA%s%s(%s, %zu)\n", is_comment ? "//" : "", + req->weak ? "V" : "", rqt_suffix[req->val.rty], string_content(req->obj_name), req->val.dat.sz); } else { - fprintf(f, "//DATA%s(%s, \n", + fprintf(f, "//DATA%s%s(%s, \n", + req->weak ? "V" : "", rqt_suffix[req->val.rty], string_content(req->obj_name)); } @@ -584,17 +579,17 @@ VECTOR(references) *references_from_file(const char *filename, FILE *f) { || !strcmp(string_content(tok.tokv.str), "DATAM"))) { string_clear(line); if (is_comment) prepare_mark_nocomment(prep); + int isweak = (string_content(tok.tokv.str)[4] == 'V'); request_t req = { .default_comment = is_comment, .has_val = 0, .ignored = 0, .obj_name = NULL, - .weak = (string_content(tok.tokv.str)[4] == 'V'), + .weak = isweak, .def = { .rty = - (string_content(tok.tokv.str)[4] == 'V') ? RQT_DATAV : - (string_content(tok.tokv.str)[4] == 'B') ? RQT_DATAB : - (string_content(tok.tokv.str)[4] == 'M') ? RQT_DATAM : RQT_DATA, + (string_content(tok.tokv.str)[isweak ? 5 : 4] == 'B') ? RQT_DATAB : + (string_content(tok.tokv.str)[isweak ? 5 : 4] == 'M') ? RQT_DATAM : RQT_DATA, .dat.has_size = 0, .dat.sz = 0, }, @@ -751,7 +746,9 @@ static int is_simple_type(type_t *typ, int *needs_D, int *needs_my) { } switch (typ->typ) { case TYPE_BUILTIN: - return 1; // Assume pointers to builtin are simple + return (typ->val.builtin != BTT_FLOAT128) + && (typ->val.builtin != BTT_CFLOAT128) + && (typ->val.builtin != BTT_IFLOAT128); // Assume builtin are simple except for __float128 case TYPE_ARRAY: if (typ->val.array.array_sz == (size_t)-1) return 0; // VLA are not simple return is_simple_type_ptr_to(typ->val.array.typ, needs_D, needs_my); @@ -837,6 +834,9 @@ static int convert_type(string_t *dest, type_t *typ, int is_ret, int *needs_D, i case BTT_LONGDOUBLE: *needs_D = 1; has_char = 1; c = 'D'; break; case BTT_CLONGDOUBLE: *needs_D = 1; has_char = 1; c = 'Y'; break; case BTT_ILONGDOUBLE: *needs_D = 1; has_char = 1; c = 'D'; break; + case BTT_FLOAT128: printf("Error: TODO: %s\n", builtin2str[typ->val.builtin]); has_char = 0; break; + case BTT_CFLOAT128: printf("Error: TODO: %s\n", builtin2str[typ->val.builtin]); has_char = 0; break; + case BTT_IFLOAT128: printf("Error: TODO: %s\n", builtin2str[typ->val.builtin]); has_char = 0; break; case BTT_VA_LIST: *needs_my = 1; has_char = 1; c = 'A'; break; default: printf("Error: convert_type on unknown builtin %u\n", typ->val.builtin); @@ -1043,7 +1043,7 @@ int solve_request(request_t *req, type_t *typ) { int needs_D = 0, needs_my = req->def.dat.has_size && (req->def.rty == RQT_DATAM); if (is_simple_type(typ, &needs_D, &needs_my)) { // TODO: Hmm... - req->val.rty = needs_my ? RQT_DATAM : req->def.dat.has_size ? req->def.rty : req->weak ? RQT_DATAV : RQT_DATA; + req->val.rty = needs_my ? RQT_DATAM : req->def.rty; req->val.dat.has_size = 1; req->val.dat.sz = typ->szinfo.size; req->has_val = 1; diff --git a/wrapperhelper/src/generator.h b/wrapperhelper/src/generator.h index 5e08577d..8e892f0e 100644 --- a/wrapperhelper/src/generator.h +++ b/wrapperhelper/src/generator.h @@ -21,7 +21,6 @@ typedef struct request_s { RQT_FUN_D, RQT_DATA, - RQT_DATAV, RQT_DATAB, RQT_DATAM, } rty; diff --git a/wrapperhelper/src/lang.c b/wrapperhelper/src/lang.c index 78cc66c1..65c8c742 100644 --- a/wrapperhelper/src/lang.c +++ b/wrapperhelper/src/lang.c @@ -233,6 +233,7 @@ const char *kw2str[LAST_KEYWORD + 1] = { [KW_ENUM] = "enum", [KW_EXTERN] = "extern", [KW_FLOAT] = "float", + [KW_FLOAT128] = "__float128", [KW_FOR] = "for", [KW_GENERIC] = "_Generic", [KW_GOTO] = "goto", @@ -963,6 +964,9 @@ const char *builtin2str[LAST_BUILTIN + 1] = { [BTT_LONGDOUBLE] = "long double", [BTT_CLONGDOUBLE] = "long double _Complex", [BTT_ILONGDOUBLE] = "long double _Imaginary", + [BTT_FLOAT128] = "__float128", + [BTT_CFLOAT128] = "__float128 _Complex", + [BTT_IFLOAT128] = "__float128 _Imaginary", [BTT_VA_LIST] = "__builtin_va_list", }; void type_print(type_t *typ) { diff --git a/wrapperhelper/src/lang.h b/wrapperhelper/src/lang.h index f5807f97..9611df82 100644 --- a/wrapperhelper/src/lang.h +++ b/wrapperhelper/src/lang.h @@ -108,6 +108,7 @@ enum token_keyword_type_e { KW_ENUM, KW_EXTERN, KW_FLOAT, + KW_FLOAT128, KW_FOR, KW_GENERIC, KW_GOTO, @@ -350,6 +351,9 @@ typedef struct type_s { BTT_LONGDOUBLE, BTT_CLONGDOUBLE, BTT_ILONGDOUBLE, + BTT_FLOAT128, + BTT_CFLOAT128, + BTT_IFLOAT128, BTT_VA_LIST, } builtin; #define LAST_BUILTIN BTT_VA_LIST diff --git a/wrapperhelper/src/machine.c b/wrapperhelper/src/machine.c index d20c3e1f..9b54df7a 100644 --- a/wrapperhelper/src/machine.c +++ b/wrapperhelper/src/machine.c @@ -1,6 +1,8 @@ #include "machine.h" -#include "preproc_private.h" +#include <stdio.h> + +#include "lang.h" machine_t machine_x86_64; // machine_t machine_x86; @@ -11,92 +13,35 @@ machine_t machine_x86_64; #define STRINGIFY2(a) #a #define STRINGIFY(a) STRINGIFY2(a) #define MACHINE_STR STRINGIFY(CUR_MACHINE) -#define INIT_PATHS \ - PASTE(machine_, CUR_MACHINE).npaths = 1 + npaths; -#define INCR_NPATHS(_path) \ - ++PASTE(machine_, CUR_MACHINE).npaths; -#define DO_PATHS \ - if (!(PASTE(machine_, CUR_MACHINE).include_path = \ - malloc(PASTE(machine_, CUR_MACHINE).npaths * sizeof *PASTE(machine_, CUR_MACHINE).include_path))) { \ - printf("Failed to add include path to " MACHINE_STR " platform\n"); \ - goto PASTE(failed_, PASTE(CUR_MACHINE, _nopath)); \ - } \ - failure_id = 0; \ - ADD_PATH("include-fixed") \ - for (; failure_id < npaths + 1; ++failure_id) { \ - if (!(PASTE(machine_, CUR_MACHINE).include_path[failure_id] = strdup(extra_include_path[failure_id - 1]))) { \ - printf("Failed to add include path to " MACHINE_STR " platform\n"); \ - goto PASTE(failed_, PASTE(CUR_MACHINE, _paths)); \ - } \ - } + +#define PATHS_OFFSET_PRE 2 // There are two paths that are always included before any other #define ADD_PATH(path) \ if (!(PASTE(machine_, CUR_MACHINE).include_path[failure_id] = strdup(path))) { \ printf("Failed to add include path to " MACHINE_STR " platform\n"); \ goto PASTE(failed_, PASTE(CUR_MACHINE, _paths)); \ } \ ++failure_id; -#define EXTRA_MACROS \ - PASTE(machine_, CUR_MACHINE).npredefs = PASTE(CUR_MACHINE, _NPREDEFS); \ - if (!(PASTE(machine_, CUR_MACHINE).predef_macros_name = \ - malloc((PASTE(CUR_MACHINE, _NPREDEFS)) * sizeof *PASTE(machine_, CUR_MACHINE).predef_macros_name))) { \ - printf("Failed to add predefined macro to " MACHINE_STR " platform\n"); \ - goto PASTE(failed_, PASTE(CUR_MACHINE, _paths)); \ - } \ - if (!(PASTE(machine_, CUR_MACHINE).predef_macros = \ - malloc((PASTE(CUR_MACHINE, _NPREDEFS)) * sizeof *PASTE(machine_, CUR_MACHINE).predef_macros))) { \ - printf("Failed to add predefined macro to " MACHINE_STR " platform\n"); \ - free(machine_x86_64.predef_macros_name); \ - goto PASTE(failed_, PASTE(CUR_MACHINE, _paths)); \ - } \ - failure_id = 0; -#define ADD_NAME(mname) \ - if (!(PASTE(machine_, CUR_MACHINE).predef_macros_name[failure_id] = strdup(#mname))) { \ - printf("Failed to add predefined macro to " MACHINE_STR " platform\n"); \ - goto PASTE(failed_, PASTE(CUR_MACHINE, _macros)); \ - } -#define ADD_MACRO(ntoks) \ - if (!(PASTE(machine_, CUR_MACHINE).predef_macros[failure_id] = \ - malloc(sizeof *PASTE(machine_, CUR_MACHINE).predef_macros[failure_id]))) { \ - printf("Failed to add predefined macro to " MACHINE_STR " platform\n"); \ - free(machine_x86_64.predef_macros_name[failure_id]); \ - goto PASTE(failed_, PASTE(CUR_MACHINE, _macros)); \ - } \ - *PASTE(machine_, CUR_MACHINE).predef_macros[failure_id] = (macro_t){ \ - .is_funlike = 0, \ - .has_varargs = 0, \ - .nargs = 0, \ - .toks = vector_new_cap(mtoken, (ntoks)), \ - }; \ - ++failure_id; \ - if (!PASTE(machine_, CUR_MACHINE).predef_macros[failure_id - 1]->toks) { \ - printf("Failed to add predefined macro to " MACHINE_STR " platform\n"); \ - goto PASTE(failed_, PASTE(CUR_MACHINE, _macros)); \ +#define INIT_PATHS \ + PASTE(machine_, CUR_MACHINE).npaths = PATHS_OFFSET_PRE + npaths + paths_offset_post; \ + if (!(PASTE(machine_, CUR_MACHINE).include_path = \ + malloc(PASTE(machine_, CUR_MACHINE).npaths * sizeof *PASTE(machine_, CUR_MACHINE).include_path))) { \ + printf("Failed to add include path to " MACHINE_STR " platform\n"); \ + goto PASTE(failed_, PASTE(CUR_MACHINE, _nopath)); \ + } \ + failure_id = 0; \ + ADD_PATH("include-override/" MACHINE_STR) \ + ADD_PATH("include-override/common") \ + while (failure_id < PATHS_OFFSET_PRE + npaths) { \ + ADD_PATH(extra_include_path[failure_id - PATHS_OFFSET_PRE]) \ } -#define ADD_SYM(s) \ - mtok = mtoken_new_token((preproc_token_t){.tokt = PPTOK_SYM, .tokv.sym = SYM_ ## s}); \ - if (!mtok) { \ - printf("Failed to add predefined macro to " MACHINE_STR " platform\n"); \ - goto PASTE(failed_, PASTE(CUR_MACHINE, _macros)); \ - } \ - vector_push(mtoken, PASTE(machine_, CUR_MACHINE).predef_macros[failure_id - 1]->toks, mtok); -#define ADD_STR(typ, n) \ - s = string_new_cstr(#n); \ - if (!s) { \ - printf("Failed to add predefined macro to " MACHINE_STR " platform\n"); \ - goto PASTE(failed_, PASTE(CUR_MACHINE, _macros)); \ - } \ - mtok = mtoken_new_token((preproc_token_t){.tokt = PPTOK_ ## typ, .tokv.str = s}); \ - if (!mtok) { \ - printf("Failed to add predefined macro to " MACHINE_STR " platform\n"); \ - string_del(s); \ - goto PASTE(failed_, PASTE(CUR_MACHINE, _macros)); \ - } \ - vector_push(mtoken, PASTE(machine_, CUR_MACHINE).predef_macros[failure_id - 1]->toks, mtok); int init_machines(size_t npaths, const char *const *extra_include_path) { size_t failure_id; - string_t *s; - mtoken_t *mtok; + + size_t paths_offset_post = 0; +#define DO_PATH(_path) ++paths_offset_post; +#include "machine.gen" +#undef DO_PATH #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" @@ -105,60 +50,14 @@ int init_machines(size_t npaths, const char *const *extra_include_path) { machine_x86_64.align_valist = 8; machine_x86_64.size_valist = 24; INIT_PATHS -#define DO_PATH INCR_NPATHS -#include "machine.gen" -#undef DO_PATH - DO_PATHS #define DO_PATH ADD_PATH #include "machine.gen" #undef DO_PATH -#define x86_64_NPREDEFS 9 - EXTRA_MACROS - ADD_NAME(__x86_64__) - ADD_MACRO(1) - ADD_STR(NUM, 1) - ADD_NAME(__WCHAR_MAX__) - ADD_MACRO(1) - ADD_STR(NUM, 2147483647) - ADD_NAME(__WCHAR_MIN__) - ADD_MACRO(5) - ADD_SYM(LPAREN) - ADD_SYM(DASH) - ADD_STR(IDENT, __WCHAR_MAX__) - ADD_SYM(DASH) - ADD_STR(NUM, 1) - ADD_NAME(__CHAR_BIT__) - ADD_MACRO(1) - ADD_STR(NUM, 8) - ADD_NAME(__SCHAR_MAX__) - ADD_MACRO(1) - ADD_STR(NUM, 127) - ADD_NAME(__SHRT_MAX__) - ADD_MACRO(1) - ADD_STR(NUM, 32767) - ADD_NAME(__INT_MAX__) - ADD_MACRO(1) - ADD_STR(NUM, 2147483647) - ADD_NAME(__LONG_MAX__) - ADD_MACRO(1) - ADD_STR(NUM, 9223372036854775807L) - ADD_NAME(__LONG_LONG_MAX__) - ADD_MACRO(1) - ADD_STR(NUM, 9223372036854775807LL) #undef CUR_MACHINE #pragma GCC diagnostic pop return 1; -failed_x86_64_macros: - while (failure_id--) { - macro_del(machine_x86_64.predef_macros[failure_id]); - free(machine_x86_64.predef_macros[failure_id]); - free(machine_x86_64.predef_macros_name[failure_id]); - } - free(machine_x86_64.predef_macros); - free(machine_x86_64.predef_macros_name); - failure_id = machine_x86_64.npaths; failed_x86_64_paths: while (failure_id--) { free(machine_x86_64.include_path[failure_id]); @@ -169,13 +68,6 @@ failed_x86_64_nopath: } static void machine_del(machine_t *m) { - for (size_t predef_id = m->npredefs; predef_id--;) { - macro_del(m->predef_macros[predef_id]); - free(m->predef_macros[predef_id]); - free(m->predef_macros_name[predef_id]); - } - free(m->predef_macros); - free(m->predef_macros_name); for (size_t path_no = m->npaths; path_no--;) { free(m->include_path[path_no]); } @@ -242,8 +134,11 @@ int validate_type(machine_t *target, type_t *typ) { case BTT_CDOUBLE: typ->szinfo.align = typ->szinfo.size = 16; break; case BTT_IDOUBLE: typ->szinfo.align = typ->szinfo.size = 8; break; case BTT_LONGDOUBLE: typ->szinfo.align = typ->szinfo.size = 16; break; - case BTT_CLONGDOUBLE: typ->szinfo.align = typ->szinfo.size = 32; break; + case BTT_CLONGDOUBLE: typ->szinfo.align = 16; typ->szinfo.size = 32; break; case BTT_ILONGDOUBLE: typ->szinfo.align = typ->szinfo.size = 16; break; + case BTT_FLOAT128: typ->szinfo.align = typ->szinfo.size = 16; break; + case BTT_CFLOAT128: typ->szinfo.align = 16; typ->szinfo.size = 32; break; + case BTT_IFLOAT128: typ->szinfo.align = typ->szinfo.size = 16; break; case BTT_VA_LIST: typ->szinfo.align = target->align_valist; typ->szinfo.size = target->size_valist; break; default: printf("Unknown builtin %u, cannot fill size info\n", typ->val.builtin); @@ -288,11 +183,12 @@ int validate_type(machine_t *target, type_t *typ) { if (typ->val.fun.nargs != (size_t)-1) { for (size_t i = 0; i < typ->val.fun.nargs; ++i) { // Adjust the argument if necessary + // Assume arrays are already converted if (typ->val.fun.args[i]->typ == TYPE_ARRAY) { - // Adjustment to pointer - typ->val.fun.args[i]->typ = TYPE_PTR; - typ->val.fun.args[i]->val.typ = typ->val.fun.args[i]->val.array.typ; - } else if (typ->val.fun.args[i]->typ == TYPE_FUNCTION) { + printf("Error: function argument %zu is an array\n", i + 1); + return 0; + } + if (typ->val.fun.args[i]->typ == TYPE_FUNCTION) { // Adjustment to pointer type_t *t2 = type_new_ptr(typ->val.fun.args[i]); if (!t2) { @@ -390,7 +286,10 @@ int validate_type(machine_t *target, type_t *typ) { typ->szinfo.size = (cur_sz + max_align - 1) & ~(max_align - 1); return 1; } case TYPE_ENUM: - if (typ->val.typ->typ != TYPE_BUILTIN) return 0; + if (typ->val.typ->typ != TYPE_BUILTIN) { + printf("Error: the underlying type of an enum is not a builtin type\n"); + return 0; + } typ->szinfo = typ->val.typ->szinfo; return 1; } diff --git a/wrapperhelper/src/machine.h b/wrapperhelper/src/machine.h index 5570a4af..b5a5b0ea 100644 --- a/wrapperhelper/src/machine.h +++ b/wrapperhelper/src/machine.h @@ -7,7 +7,6 @@ #include "khash.h" #include "vector.h" -struct macro_s; // preproc_private.h struct type_s; // lang.h typedef struct machine_s { @@ -15,10 +14,6 @@ typedef struct machine_s { size_t npaths; char **include_path; - size_t npredefs; - char **predef_macros_name; - struct macro_s **predef_macros; - // Parsing size_t size_long; size_t align_valist, size_valist; diff --git a/wrapperhelper/src/parse.c b/wrapperhelper/src/parse.c index 8b56cb15..b1f9ed90 100644 --- a/wrapperhelper/src/parse.c +++ b/wrapperhelper/src/parse.c @@ -398,6 +398,7 @@ static int is_type_spec_qual_kw(enum token_keyword_type_e kw) { (kw == KW_DOUBLE) || (kw == KW_ENUM) || (kw == KW_FLOAT) || + (kw == KW_FLOAT128) || (kw == KW_IMAGINARY) || (kw == KW_INT) || (kw == KW_INT128) || @@ -1064,7 +1065,7 @@ failed: if (e) expr_del(e); return NULL; } -static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constant_t *dest) { +static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constant_t *dest, int fatal) { // Evaluate the expression (we suppose it is constant) switch (e->typ) { case ETY_VAR: { @@ -1073,7 +1074,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan *dest = kh_val(const_map, it); return 1; } - printf("Error: failed to evaluate expression: expression is not constant (variable)\n"); + if (fatal) printf("Error: failed to evaluate expression: expression is not constant (variable)\n"); return 0; } case ETY_CONST: @@ -1083,18 +1084,18 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan // case ETY_GENERIC: case ETY_CALL: - printf("Error: failed to evaluate expression: expression is not constant (function call)\n"); + if (fatal) printf("Error: failed to evaluate expression: expression is not constant (function call)\n"); return 0; case ETY_ACCESS: case ETY_PTRACCESS: - printf("Error: failed to evaluate expression: expression is not constant (member access)\n"); + if (fatal) printf("Error: failed to evaluate expression: expression is not constant (member access)\n"); return 0; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" case ETY_UNARY: - if (!eval_expression(e->val.unary.e, const_map, dest)) return 0; + if (!eval_expression(e->val.unary.e, const_map, dest, fatal)) return 0; switch (e->val.unary.typ) { case UOT_POSTINCR: @@ -1103,7 +1104,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case UOT_PREDECR: case UOT_REF: case UOT_DEREF: - printf("Error: failed to evaluate expression: expression is not constant (assignment or memory accesses)\n"); + if (fatal) printf("Error: failed to evaluate expression: expression is not constant (assignment or memory accesses)\n"); return 0; case UOT_POS: return 1; // Nothing to do @@ -1123,7 +1124,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case NCT_FLOAT: case NCT_DOUBLE: case NCT_LDOUBLE: - printf("Error: failed to evaluate expression: cannot bitwise-negate a floating point number\n"); + if (fatal) printf("Error: failed to evaluate expression: cannot bitwise-negate a floating point number\n"); return 0; case NCT_INT32: dest->val.i32 = ~dest->val.i32; return 1; case NCT_UINT32: dest->val.u32 = ~dest->val.u32; return 1; @@ -1147,8 +1148,8 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case ETY_BINARY: { num_constant_t dest1, dest2; - if (!eval_expression(e->val.binary.e1, const_map, &dest1)) return 0; - if (!eval_expression(e->val.binary.e2, const_map, &dest2)) return 0; + if (!eval_expression(e->val.binary.e1, const_map, &dest1, fatal)) return 0; + if (!eval_expression(e->val.binary.e2, const_map, &dest2, fatal)) return 0; switch (e->val.binary.typ) { case BOT_ASSGN_EQ: @@ -1163,7 +1164,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case BOT_ASSGN_AXOR: case BOT_ASSGN_AOR: case BOT_ARRAY: // Is this possible? - printf("Error: failed to evaluate expression: expression is not constant (assignments)\n"); + if (fatal) printf("Error: failed to evaluate expression: expression is not constant (assignments)\n"); return 0; #define DOIT(op) \ promote_csts(&dest1, &dest2); \ @@ -1183,7 +1184,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case NCT_FLOAT: \ case NCT_DOUBLE: \ case NCT_LDOUBLE: \ - printf("Error: failed to evaluate expression: binary operation %u incompatible with floating point numbers\n", e->val.binary.typ); \ + if (fatal) printf("Error: failed to evaluate expression: binary operation %u incompatible with floating point numbers\n", e->val.binary.typ); \ return 0; \ case NCT_INT32: dest->val.i32 = dest1.val.i32 op dest2.val.i32; return 1; \ case NCT_UINT32: dest->val.u32 = dest1.val.u32 op dest2.val.u32; return 1; \ @@ -1230,9 +1231,9 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case ETY_TERNARY: { num_constant_t dest1, dest2, dest3; - if (!eval_expression(e->val.ternary.e1, const_map, &dest1)) return 0; - if (!eval_expression(e->val.ternary.e2, const_map, &dest2)) return 0; - if (!eval_expression(e->val.ternary.e3, const_map, &dest3)) return 0; + if (!eval_expression(e->val.ternary.e1, const_map, &dest1, fatal)) return 0; + if (!eval_expression(e->val.ternary.e2, const_map, &dest2, fatal)) return 0; + if (!eval_expression(e->val.ternary.e3, const_map, &dest3, fatal)) return 0; switch (e->val.ternary.typ) { case TOT_COND: @@ -1254,7 +1255,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan // case ETY_INIT_LIST: case ETY_CAST: - if (!eval_expression(e->val.cast.e, const_map, dest)) return 0; + if (!eval_expression(e->val.cast.e, const_map, dest, fatal)) return 0; if (e->val.cast.typ->typ == TYPE_BUILTIN) { switch (e->val.cast.typ->val.builtin) { @@ -1340,13 +1341,16 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case BTT_LONGDOUBLE: case BTT_CLONGDOUBLE: case BTT_ILONGDOUBLE: + case BTT_FLOAT128: + case BTT_CFLOAT128: + case BTT_IFLOAT128: case BTT_VA_LIST: default: - printf("Error: TODO: cast to builtin %s in constant expression\n", builtin2str[e->val.cast.typ->val.builtin]); + if (fatal) printf("Error: TODO: cast to builtin %s in constant expression\n", builtin2str[e->val.cast.typ->val.builtin]); return 0; } } else { - printf("Error: cast in constant expression\n"); + if (fatal) printf("Error: cast in constant expression\n"); return 0; } @@ -1382,7 +1386,7 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s goto failed; } num_constant_t eval; - if (!eval_expression(e, const_map, &eval)) { + if (!eval_expression(e, const_map, &eval, 1)) { expr_del(e); // Empty destructor goto failed; @@ -1567,6 +1571,8 @@ parse_cur_token_decl: *spec = SPEC_LONGCOMPLEX; } else if ((*spec == SPEC_BUILTIN) && (typ->val.builtin == BTT_FLOAT)) { typ->val.builtin = BTT_CFLOAT; + } else if ((*spec == SPEC_BUILTIN) && (typ->val.builtin == BTT_FLOAT128)) { + typ->val.builtin = BTT_CFLOAT128; } else if ((*spec == SPEC_BUILTIN) && (typ->val.builtin == BTT_DOUBLE)) { typ->val.builtin = BTT_CDOUBLE; } else if ((*spec == SPEC_BUILTIN) && (typ->val.builtin == BTT_LONGDOUBLE)) { @@ -1584,6 +1590,8 @@ parse_cur_token_decl: *spec = SPEC_LONGIMAGINARY; } else if ((*spec == SPEC_BUILTIN) && (typ->val.builtin == BTT_FLOAT)) { typ->val.builtin = BTT_IFLOAT; + } else if ((*spec == SPEC_BUILTIN) && (typ->val.builtin == BTT_FLOAT128)) { + typ->val.builtin = BTT_IFLOAT128; } else if ((*spec == SPEC_BUILTIN) && (typ->val.builtin == BTT_DOUBLE)) { typ->val.builtin = BTT_IDOUBLE; } else if ((*spec == SPEC_BUILTIN) && (typ->val.builtin == BTT_LONGDOUBLE)) { @@ -1643,6 +1651,25 @@ parse_cur_token_decl: } *tok = proc_next_token(prep); goto parse_cur_token_decl; + } else if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_FLOAT128)) { + if (*spec == SPEC_NONE) { + *spec = SPEC_BUILTIN; + typ->typ = TYPE_BUILTIN; + typ->val.builtin = BTT_FLOAT128; + } else if (*spec == SPEC_COMPLEX) { + *spec = SPEC_BUILTIN; + typ->typ = TYPE_BUILTIN; + typ->val.builtin = BTT_CFLOAT128; + } else if (*spec == SPEC_IMAGINARY) { + *spec = SPEC_BUILTIN; + typ->typ = TYPE_BUILTIN; + typ->val.builtin = BTT_IFLOAT128; + } else { + printf("Error: unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + goto failed; + } + *tok = proc_next_token(prep); + goto parse_cur_token_decl; } else if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_CHAR)) { SPEC_SIGNED(CHAR, 0) } else if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_INT)) { @@ -2058,7 +2085,7 @@ parse_cur_token_decl: proc_token_del(tok); goto failed; } - if (!eval_expression(e, const_map, &cst)) { + if (!eval_expression(e, const_map, &cst, 1)) { expr_del(e); if (tag) string_del(tag); // Empty destructor @@ -2203,6 +2230,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d int has_list = 0, has_ident = 0; // TODO: allow_abstract and 'direct-abstract-declarator(opt) ( parameter-type-list(opt) )' + _Bool array_atomic = 0, array_const = 0, array_restrict = 0, array_static = 0, array_volatile = 0; string_t *cur_ident = NULL; type_t *typ = base_type; ++typ->nrefs; type_t *cur_bottom = NULL; @@ -2324,6 +2352,27 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_RPAREN)) { // Unnamed argument + if (typ2->typ == TYPE_ARRAY) { + // Need to convert type to a pointer + type_t *typ3 = type_new(); + if (!typ3) { + printf("Error: failed to allocate new type\n"); + type_del(typ2); + // Empty destructor + goto failed; + } + if (!type_copy_into(typ3, typ2)) { + printf("Error: failed to duplicate array type to temporary type\n"); + type_del(typ3); + type_del(typ2); + // Empty destructor + goto failed; + } + type_del(typ2); + typ3->typ = TYPE_PTR; + typ3->val.typ = typ3->val.array.typ; + typ2 = type_try_merge(typ3, PDECL_TYPE_SET); + } if (!vector_push(types, args, typ2)) { printf("Error: failed to add argument to argument vector\n"); vector_del(types, args); @@ -2452,23 +2501,76 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } has_ident = 1; } + if (array_atomic || array_const || array_restrict || array_static || array_volatile) { + printf("Error: invalid array after array with type qualifier(s) and/or 'static'\n"); + // Empty destructor + goto failed; + } // Empty destructor *tok = proc_next_token(prep); - // Here we have only two array constructors: - // direct-declaration [ assignment-expression(opt) ] - // direct-declaration [ * ] (complete VLA) + // From the standard: + // direct-declarator [ type-qualifier-list(opt) assignment-expression(opt) ] + // direct-declarator [ static type-qualifier-list(opt) assignment-expression ] + // direct-declarator [ type-qualifier-list static assignment-expression ] + // direct-declarator [ type-qualifier-list(opt) * ] + // The optional type qualifiers and the keyword static shall appear only in a + // declaration of a function parameter with an array type, and then only in the outermost + // array type derivation. size_t nelems; _Bool is_incomplete; + while (1) { +#define DO_CHECKS \ + if (is_init || is_list || !allow_decl || (cur_bottom && (typ->typ != TYPE_ARRAY))) { \ + printf("Error: type qualifiers and 'static' may only appear in function argument array declarations\n"); \ + /* Empty destructor */ \ + goto failed; \ + } + if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_ATOMIC)) { + DO_CHECKS + array_atomic = 1; + *tok = proc_next_token(prep); + } else if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_CONST)) { + DO_CHECKS + array_const = 1; + *tok = proc_next_token(prep); + } else if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_RESTRICT)) { + DO_CHECKS + array_restrict = 1; + *tok = proc_next_token(prep); + } else if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_STATIC)) { + DO_CHECKS + array_static = 1; + *tok = proc_next_token(prep); + } else if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_VOLATILE)) { + DO_CHECKS + array_volatile = 1; + *tok = proc_next_token(prep); + } else break; +#undef DO_CHECKS + } if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_RSQBRACKET)) { + if (array_static) { + // Missing expression + printf("Error: unexpected token ']' in static length array declaration\n"); + // Empty destructor + goto failed; + } // Incomplete VLA nelems = (size_t)-1; is_incomplete = 1; } else if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_STAR)) { + if (array_static) { + // Missing expression + printf("Error: unexpected token '*' in static length array declaration\n"); + // Empty destructor + goto failed; + } // Complete VLA, expecting a ']' nelems = (size_t)-1; is_incomplete = 0; // Empty destructor *tok = proc_next_token(prep); if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_RSQBRACKET)) { + // TODO: ...[*expr] printf("Error: unexpected token during variable length array declaration\n"); proc_token_del(tok); goto failed; @@ -2488,27 +2590,32 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d goto failed; } num_constant_t cst; - if (!eval_expression(e, PDECL_CONST_MAP, &cst)) { + if (eval_expression(e, PDECL_CONST_MAP, &cst, is_init || is_list || !allow_decl)) { expr_del(e); - // Empty destructor - goto failed; - } - expr_del(e); - int is_neg; - switch (cst.typ) { - case NCT_FLOAT: is_neg = cst.val.f < 0; nelems = (size_t)cst.val.f; break; - case NCT_DOUBLE: is_neg = cst.val.d < 0; nelems = (size_t)cst.val.d; break; - case NCT_LDOUBLE: is_neg = cst.val.l < 0; nelems = (size_t)cst.val.l; break; - case NCT_INT32: is_neg = cst.val.i32 < 0; nelems = (size_t)cst.val.i32; break; - case NCT_UINT32: is_neg = 0; nelems = (size_t)cst.val.u32; break; - case NCT_INT64: is_neg = cst.val.i64 < 0; nelems = (size_t)cst.val.i64; break; - case NCT_UINT64: is_neg = 0; nelems = (size_t)cst.val.u64; break; - default: is_neg = 1; - } - if (is_neg) { - printf("Error: the size of an array must be nonnegative"); - // Empty destructor - goto failed; + int is_neg; + switch (cst.typ) { + case NCT_FLOAT: is_neg = cst.val.f < 0; nelems = (size_t)cst.val.f; break; + case NCT_DOUBLE: is_neg = cst.val.d < 0; nelems = (size_t)cst.val.d; break; + case NCT_LDOUBLE: is_neg = cst.val.l < 0; nelems = (size_t)cst.val.l; break; + case NCT_INT32: is_neg = cst.val.i32 < 0; nelems = (size_t)cst.val.i32; break; + case NCT_UINT32: is_neg = 0; nelems = (size_t)cst.val.u32; break; + case NCT_INT64: is_neg = cst.val.i64 < 0; nelems = (size_t)cst.val.i64; break; + case NCT_UINT64: is_neg = 0; nelems = (size_t)cst.val.u64; break; + default: is_neg = 1; + } + if (is_neg) { + printf("Error: the size of an array must be nonnegative"); + // Empty destructor + goto failed; + } + } else { + expr_del(e); + // Treated as '*' as function argument (TODO: as anything else) + if (is_init || is_list || !allow_decl) { + // Empty destructor + goto failed; + } + nelems = (size_t)-1; } } // Token is ']' @@ -2713,6 +2820,32 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d kh_val(dest->f->decl_map, it) = typ; } } else if (!is_init && !is_list) { + if (allow_decl) { + // Function argument + if (typ->typ == TYPE_ARRAY) { + // Convert to pointer + if (typ == base_type) { + typ = type_new(); + if (!typ) { + printf("Error: failed to allocate new type\n"); + // Empty destructor + goto failed; + } + if (!type_copy_into(typ, base_type)) { + printf("Error: failed to allocate new type\n"); + // Empty destructor + goto failed; + } + } + typ->typ = TYPE_PTR; + typ->val.typ = typ->val.array.typ; + if (array_atomic) typ->is_atomic = 1; + if (array_const) typ->is_const = 1; + if (array_restrict) typ->is_restrict = 1; + if (array_volatile) typ->is_volatile = 1; + typ = type_try_merge(typ, PDECL_TYPE_SET); + } + } dest->argt.dest = typ; if (cur_ident) string_del(cur_ident); goto success; @@ -2802,7 +2935,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d goto failed; } num_constant_t eval; - if (!eval_expression(e, dest->structms.const_map, &eval)) { + if (!eval_expression(e, dest->structms.const_map, &eval, 1)) { expr_del(e); // Empty destructor goto failed; @@ -3067,9 +3200,13 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { if (spec == SPEC_NONE) continue; // Declaration was an assert, typ is unchanged typ = type_try_merge(typ, ret->type_set); if ((tok.tokt != PTOK_SYM) || (tok.tokv.sym != SYM_SEMICOLON)) { - if (!parse_declarator(target, &(struct parse_declarator_dest_s){.f = ret}, prep, &tok, storage, fspec, typ, 1, 1, 1, 0)) goto failed; + if (!parse_declarator(target, &(struct parse_declarator_dest_s){.f = ret}, prep, &tok, storage, fspec, typ, 1, 1, 1, 0)) { + goto failed; + } } else { - if (validate_storage_type(target, storage, typ, tok.tokv.sym) != VALIDATION_LAST_DECL) goto failed; + if (validate_storage_type(target, storage, typ, tok.tokv.sym) != VALIDATION_LAST_DECL) { + goto failed; + } if (fspec != FSPEC_NONE) { printf("Error: unexpected function specifier\n"); // Empty destructor 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); diff --git a/wrapperhelper/src/preproc_private.h b/wrapperhelper/src/preproc_private.h deleted file mode 100644 index d1b5f804..00000000 --- a/wrapperhelper/src/preproc_private.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#ifndef PREPROC_PRIVATE_H -#define PREPROC_PRIVATE_H - -#include <stdio.h> - -#include "lang.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; - -VECTOR_DECLARE(mtoken, mtoken_t*) - -typedef struct macro_s { - int is_funlike; - int has_varargs; - unsigned nargs; - VECTOR(mtoken) *toks; -} macro_t; - -mtoken_t *mtoken_new_token(preproc_token_t tok); -mtoken_t *mtoken_new_arg(unsigned argid, int as_string); -mtoken_t *mtoken_new_concat(mtoken_t *l, mtoken_t *r); -void mtoken_del(mtoken_t *tok); -void macro_del(macro_t *m); - -#endif // PREPROC_PRIVATE_H |