diff options
Diffstat (limited to 'wrapperhelper/src')
| -rw-r--r-- | wrapperhelper/src/generator.c | 478 | ||||
| -rw-r--r-- | wrapperhelper/src/generator.h | 15 | ||||
| -rw-r--r-- | wrapperhelper/src/lang.c | 15 | ||||
| -rw-r--r-- | wrapperhelper/src/lang.h | 4 | ||||
| -rw-r--r-- | wrapperhelper/src/main.c | 23 | ||||
| -rw-r--r-- | wrapperhelper/src/parse.c | 111 | ||||
| -rw-r--r-- | wrapperhelper/src/preproc.c | 140 |
7 files changed, 466 insertions, 320 deletions
diff --git a/wrapperhelper/src/generator.c b/wrapperhelper/src/generator.c index 98e254ed..e162d0e4 100644 --- a/wrapperhelper/src/generator.c +++ b/wrapperhelper/src/generator.c @@ -6,149 +6,173 @@ static const char *rft2str[8] = { [RQT_FUN] = "", [RQT_FUN_2] = "", - [RQT_FUN_MY] = "(my) ", - [RQT_FUN_D] = "(D) ", + [RQT_FUN_MY] = " (my)", + [RQT_FUN_D] = " (D)", [RQT_DATA] = "", - [RQT_DATAV] = "(V) ", - [RQT_DATAB] = "(B) ", - [RQT_DATAM] = "(my) ", + [RQT_DATAV] = " (V)", + [RQT_DATAB] = " (B)", + [RQT_DATAM] = " (my)", }; #define IS_RQT_FUN2(rty) (((rty) == RQT_FUN_2) || ((rty) == RQT_FUN_D)) #define IS_RQT_FUNCTION(rty) ((rty) < RQT_DATA) -void request_print(request_t *req) { - printf("%s", string_content(req->obj_name)); - if (req->has_default && req->has_val && (IS_RQT_FUNCTION(req->def.rty) != IS_RQT_FUNCTION(req->val.rty))) { - printf(" => conflict: was/is data, is/was function\n"); - } - int is_fun; - if (req->has_default) is_fun = IS_RQT_FUNCTION(req->def.rty); - else if (req->has_val) is_fun = IS_RQT_FUNCTION(req->val.rty); - else { - printf(" => (no value)\n"); - return; - } - - if (is_fun) { - printf(" => %sfunction", req->weak ? "weak " : ""); - if (req->has_default) { - printf(" with %sdefault %s%s%s%s", - req->default_comment ? "commented " : "", +void request_print(const request_t *req) { + printf("%s%s: %sdefault", string_content(req->obj_name), req->weak ? " (weak)" : "", req->default_comment ? "commented " : ""); + switch (req->def.rty) { + case RQT_FUN: + case RQT_FUN_2: + case RQT_FUN_MY: + case RQT_FUN_D: + if (req->def.fun.typ) { + printf(" function%s %s%s%s", rft2str[req->def.rty], string_content(req->def.fun.typ), - (req->def.rty == RQT_FUN_2) ? " -> " : "", - (req->def.rty == RQT_FUN_2) ? string_content(req->def.fun.fun2) : ""); - } - if (req->has_val) { - printf(" with solved %s%s%s%s", - rft2str[req->val.rty], - string_content(req->val.fun.typ), - (req->val.rty == RQT_FUN_2) ? " -> " : "", - (req->val.rty == RQT_FUN_2) ? string_content(req->val.fun.fun2) : ""); + req->def.fun.fun2 ? " -> " : "", + req->def.fun.fun2 ? string_content(req->def.fun.fun2) : ""); + } else { + printf(" untyped function%s", rft2str[req->def.rty]); } - } else { - printf(" => %sdata", req->weak ? "weak " : ""); - if (req->has_default) { - if (req->def.dat.has_size) printf(" with default %zu", req->def.dat.sz); - else printf(" with no default"); + break; + case RQT_DATA: + case RQT_DATAV: + case RQT_DATAB: + case RQT_DATAM: + if (req->def.dat.has_size) { + printf(" data%s %zu", rft2str[req->def.rty], req->def.dat.sz); + } else { + printf(" unsized data%s", rft2str[req->def.rty]); } - if (req->has_val) { - if (req->def.dat.has_size) printf(" with solved %zu", req->def.dat.sz); - else printf(" with no solved"); + break; + } + if (req->has_val) { + printf(" => solved"); + switch (req->val.rty) { + case RQT_FUN: + case RQT_FUN_2: + case RQT_FUN_MY: + case RQT_FUN_D: + if (req->val.fun.typ) { + printf(" function%s %s%s%s", + rft2str[req->val.rty], + string_content(req->val.fun.typ), + req->val.fun.fun2 ? " -> " : "", + req->val.fun.fun2 ? string_content(req->val.fun.fun2) : ""); + } else { + printf(" untyped function%s", rft2str[req->val.rty]); + } + break; + case RQT_DATA: + case RQT_DATAV: + case RQT_DATAB: + case RQT_DATAM: + if (req->val.dat.has_size) { + printf(" data%s %zu", rft2str[req->val.rty], req->val.dat.sz); + } else { + printf(" unsized data%s", rft2str[req->val.rty]); + } + break; } } printf("\n"); } -void request_print_check(request_t *req) { - if (req->has_default && req->has_val && (IS_RQT_FUNCTION(req->def.rty) != IS_RQT_FUNCTION(req->val.rty))) { - printf("%s => conflict: was/is data, is/was function\n", string_content(req->obj_name)); +void request_print_check(const request_t *req) { + if (req->ignored) { + return; } - int is_fun; - if (req->has_default) is_fun = IS_RQT_FUNCTION(req->def.rty); - else if (req->has_val) is_fun = IS_RQT_FUNCTION(req->val.rty); - else { - printf(" => (no value)\n"); + if (!req->has_val) { + // printf("%s: no value\n", string_content(req->obj_name)); return; } - if (is_fun) { - if (req->has_val) { - if (req->has_default) { - int similar = 1; - // if (req->def.rty != req->val.rty) similar = 0; - if (similar && strcmp(string_content(req->def.fun.typ), string_content(req->val.fun.typ))) { - // similar = 0; - // TODO - if (req->def.rty == RQT_FUN_MY) { - similar = - string_len(req->def.fun.typ) >= 3 && - string_content(req->def.fun.typ)[2] == 'E' && - !strncmp(string_content(req->def.fun.typ), string_content(req->val.fun.typ), 2) && - !strcmp(string_content(req->def.fun.typ) + 3, string_content(req->val.fun.typ) + 2); - if (similar) { - // We need to add the 'E' back here - } - } else { - similar = 0; - } - } - if (!similar) { - printf("%s => %sfunction with %sdefault %s%s%s%s and different solved %s%s%s%s\n", - string_content(req->obj_name), - req->weak ? "weak " : "", - req->default_comment ? "commented " : "", - rft2str[req->def.rty], - string_content(req->def.fun.typ), - (req->def.rty == RQT_FUN_2) ? " -> " : "", - (req->def.rty == RQT_FUN_2) ? string_content(req->def.fun.fun2) : "", - rft2str[req->val.rty], - string_content(req->val.fun.typ), - (req->val.rty == RQT_FUN_2) ? " -> " : "", - (req->val.rty == RQT_FUN_2) ? string_content(req->val.fun.fun2) : ""); - } - } else { - printf("%s => %sfunction with solved %s%s%s%s\n", - string_content(req->obj_name), - req->weak ? "weak " : "", - rft2str[req->val.rty], - string_content(req->val.fun.typ), - (req->val.rty == RQT_FUN_2) ? " -> " : "", - (req->val.rty == RQT_FUN_2) ? string_content(req->val.fun.fun2) : ""); - } - } else if (req->has_default) { - /* printf("%s => unsolved %sfunction with %sdefault %s%s%s%s\n", + if ((IS_RQT_FUNCTION(req->def.rty) != IS_RQT_FUNCTION(req->val.rty))) { + printf("%s: conflict: %s data, %s function\n", + string_content(req->obj_name), + IS_RQT_FUNCTION(req->def.rty) ? "is" : "was", + IS_RQT_FUNCTION(req->def.rty) ? "was" : "is"); + return; + } + if (IS_RQT_FUNCTION(req->def.rty) && !req->def.fun.typ) return; // No default (function) + if (!IS_RQT_FUNCTION(req->def.rty) && !req->def.dat.has_size) return; // No default (data) + // We have a default and a value, both are functions or data + int similar; + switch (req->def.rty) { + case RQT_FUN: + case RQT_FUN_2: + case RQT_FUN_MY: + case RQT_FUN_D: + similar = !req->default_comment || (req->val.rty != RQT_FUN); // From comment to no comment is dissimilar + if (similar && (req->def.rty != req->val.rty)) similar = 0; + if (similar && strcmp(string_content(req->def.fun.typ), string_content(req->val.fun.typ))) { + similar = 0; + } + if (!similar) { + printf("%s%s: function with %s%sdefault%s%s%s%s%s and dissimilar %ssolved%s%s%s%s%s\n", string_content(req->obj_name), - req->weak ? "weak " : "", + req->weak ? " (weak)" : "", req->default_comment ? "commented " : "", + req->def.fun.typ ? "" : "untyped ", rft2str[req->def.rty], + req->def.fun.typ ? " " : "", string_content(req->def.fun.typ), - (req->def.rty == RQT_FUN_2) ? " -> " : "", - (req->def.rty == RQT_FUN_2) ? string_content(req->def.fun.fun2) : ""); */ - } - } else { - printf("%s => %sdata", string_content(req->obj_name), req->weak ? "weak " : ""); - if (req->has_default) { - if (req->def.dat.has_size) printf(" with default %zu", req->def.dat.sz); - else printf(" with no default"); + req->def.fun.fun2 ? " -> " : "", + req->def.fun.fun2 ? string_content(req->def.fun.fun2) : "", + req->val.fun.typ ? "" : "untyped ", + rft2str[req->val.rty], + req->val.fun.typ ? " " : "", + string_content(req->val.fun.typ), + req->val.fun.fun2 ? " -> " : "", + req->val.fun.fun2 ? string_content(req->val.fun.fun2) : ""); } - if (req->has_val) { - if (req->def.dat.has_size) printf(" with solved %zu", req->def.dat.sz); - else printf(" with no solved"); + break; + case RQT_DATA: + case RQT_DATAV: + case RQT_DATAB: + case RQT_DATAM: + similar = 1; + if (similar && (req->def.rty != req->val.rty)) similar = 0; + if (similar && (!!req->def.dat.has_size != !!req->val.dat.has_size)) similar = 0; + if (similar && req->def.dat.has_size && (req->def.dat.sz != req->val.dat.sz)) similar = 0; + if (!similar) { + printf("%s%s: data with %s%sdefault%s", + string_content(req->obj_name), + req->weak ? " (weak)" : "", + req->default_comment ? "commented " : "", + req->def.fun.typ ? "" : "untyped ", + rft2str[req->def.rty]); + if (req->def.dat.has_size) { + printf(" %zu", req->def.dat.sz); + } else { + printf(" unsized"); + } + printf(" and dissimilar %ssolved%s", + req->val.fun.typ ? "" : "untyped ", + rft2str[req->val.rty]); + if (req->val.dat.has_size) { + printf(" %zu", req->val.dat.sz); + } else { + printf(" unsized"); + } + printf("\n"); } + break; + } +} +void references_print_check(const VECTOR(references) *refs) { + vector_for(references, ref, refs) { + if (ref->typ == REF_REQ) request_print_check(&ref->req); } } + static void request_del(request_t *req) { string_del(req->obj_name); - if (req->has_default) { - switch (req->def.rty) { - case RQT_FUN: string_del(req->def.fun.typ); break; - case RQT_FUN_2: string_del(req->def.fun.typ); string_del(req->def.fun.fun2); break; - case RQT_FUN_MY: string_del(req->def.fun.typ); break; - case RQT_FUN_D: string_del(req->def.fun.typ); string_del(req->def.fun.fun2); break; - case RQT_DATA: break; - case RQT_DATAV: break; - case RQT_DATAB: break; - case RQT_DATAM: break; - } + switch (req->def.rty) { + case RQT_FUN: if (req->def.fun.typ) string_del(req->def.fun.typ); break; + case RQT_FUN_2: 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_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; } if (req->has_val) { switch (req->val.rty) { @@ -169,8 +193,13 @@ static void reference_del(reference_t *ref) { request_del(&ref->req); break; case REF_LINE: + case REF_IFDEF: + case REF_IFNDEF: string_del(ref->line); break; + case REF_ELSE: + case REF_ENDIF: + break; } } @@ -194,31 +223,33 @@ static const char *rqt_suffix[8] = { [RQT_DATAM] = "M", }; -static void request_output(FILE *f, request_t *req) { +static void request_output(FILE *f, const request_t *req) { if (!req->has_val) { - if (!req->has_default) { - // printf("Warning: %s has no value and no default, assuming function\n", string_content(req->obj_name)); - fprintf(f, "//GO%s(%s, \n", req->weak ? "W" : "", string_content(req->obj_name)); - } else if (IS_RQT_FUNCTION(req->def.rty)) { - fprintf(f, "%sGO%s%s(%s, %s%s%s%s%s)%s\n", - req->default_comment ? "//" : "", - req->weak ? "W" : "", - rqt_suffix[req->def.rty], - string_content(req->obj_name), - valid_reqtype(req->def.fun.typ) ? "" : "\"", - string_content(req->def.fun.typ), - valid_reqtype(req->def.fun.typ) ? "" : "\"", - IS_RQT_FUN2(req->def.rty) ? ", " : "", - IS_RQT_FUN2(req->def.rty) ? string_content(req->def.fun.fun2) : "", - req->default_comment ? "" : " // Warning: failed to confirm"); + if (IS_RQT_FUNCTION(req->def.rty)) { + if (!req->def.fun.typ) { + fprintf(f, "//GO%s%s(%s, \n", req->weak ? "W" : "", rqt_suffix[req->def.rty], string_content(req->obj_name)); + } else { + fprintf(f, "%sGO%s%s(%s, %s%s%s%s%s)%s\n", + req->default_comment ? "//" : "", + req->weak ? "W" : "", + rqt_suffix[req->def.rty], + string_content(req->obj_name), + valid_reqtype(req->def.fun.typ) ? "" : "\"", + string_content(req->def.fun.typ), + valid_reqtype(req->def.fun.typ) ? "" : "\"", + IS_RQT_FUN2(req->def.rty) ? ", " : "", + IS_RQT_FUN2(req->def.rty) ? string_content(req->def.fun.fun2) : "", + (req->ignored || req->default_comment) ? "" : " // Warning: failed to confirm"); + } } else { if (req->def.dat.has_size) { - fprintf(f, "%sDATA%s%s(%s, %zu) // Warning: failed to confirm\n", + fprintf(f, "%sDATA%s%s(%s, %zu)%s\n", req->default_comment ? "//" : "", req->weak ? "W" : "", rqt_suffix[req->def.rty], string_content(req->obj_name), - req->def.dat.sz); + req->def.dat.sz, + (req->ignored || req->default_comment) ? "" : " // Warning: failed to confirm"); } else { fprintf(f, "//DATA%s%s(%s, \n", req->weak ? "W" : "", @@ -229,7 +260,8 @@ static void request_output(FILE *f, request_t *req) { } else { if (IS_RQT_FUNCTION(req->val.rty)) { int is_comment = - (req->has_default && !req->default_comment) ? (req->val.rty != req->def.rty) : (req->val.rty != RQT_FUN); + (IS_RQT_FUNCTION(req->def.rty) && req->def.fun.typ && !req->default_comment) + ? (req->val.rty != req->def.rty) : (req->val.rty != RQT_FUN); fprintf(f, "%sGO%s%s(%s, %s%s%s)\n", is_comment ? "//" : "", req->weak ? "W" : "", @@ -240,7 +272,7 @@ static void request_output(FILE *f, request_t *req) { IS_RQT_FUN2(req->val.rty) ? req->val.fun.fun2 ? string_content(req->val.fun.fun2) : "<error: no val>" : ""); } else { if (req->val.dat.has_size) { - int is_comment = !req->has_default || req->default_comment || (req->def.rty != req->val.rty); + 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", is_comment ? "//" : "", rqt_suffix[req->val.rty], @@ -254,7 +286,7 @@ static void request_output(FILE *f, request_t *req) { } } } -static void reference_output(FILE *f, reference_t *ref) { +static void reference_output(FILE *f, const reference_t *ref) { switch (ref->typ) { case REF_REQ: request_output(f, &ref->req); @@ -263,12 +295,24 @@ static void reference_output(FILE *f, reference_t *ref) { fputs(string_content(ref->line), f); fputc('\n', f); break; + case REF_IFDEF: + fprintf(f, "#ifdef %s\n", string_content(ref->line)); + break; + case REF_IFNDEF: + fprintf(f, "#ifndef %s\n", string_content(ref->line)); + break; + case REF_ELSE: + fputs("#else\n", f); + break; + case REF_ENDIF: + fputs("#endif\n", f); + break; } } -void output_from_references(FILE *f, VECTOR(references) *reqs) { - fprintf(f, "#if !(defined(GO) && defined(GOM) && defined(GO2) && defined(DATA))\n#error Meh...\n#endif\n\n"); - vector_for(references, req, reqs) { - reference_output(f, req); +void output_from_references(FILE *f, const VECTOR(references) *refs) { + fprintf(f, "#if !(defined(GO) && defined(GOM) && defined(GO2) && defined(DATA))\n#error Meh...\n#endif\n"); + vector_for(references, ref, refs) { + reference_output(f, ref); } } @@ -350,14 +394,13 @@ VECTOR(references) *references_from_file(const char *filename, FILE *f) { } } if ((tok.tokt == PPTOK_SYM) && (tok.tokv.sym == SYM_HASH)) { - ADD_CHAR('#', 0, "start of preprocessor command") + string_clear(line); tok = pre_next_token(prep, 0); if (tok.tokt != PPTOK_IDENT) { printf("Error: invalid reference file: invalid preprocessor line\n"); preproc_token_del(&tok); goto failed; } - ADD_STR(tok.tokv.str, 1, "preprocessor command") if (!strcmp(string_content(tok.tokv.str), "ifdef")) { string_del(tok.tokv.str); tok = pre_next_token(prep, 0); @@ -366,10 +409,12 @@ VECTOR(references) *references_from_file(const char *filename, FILE *f) { preproc_token_del(&tok); goto failed; } - ADD_CHAR(' ', 1, "preprocessor command") - ADD_STR(tok.tokv.str, 1, "preprocessor command") ++if_depth; - string_del(tok.tokv.str); + if (!vector_push(references, ret, ((reference_t){.typ = REF_IFDEF, .line = tok.tokv.str}))) { + printf("Error: failed to memorize reference line %d\n", lineno); + string_del(tok.tokv.str); + goto failed; + } tok = pre_next_token(prep, 0); } else if (!strcmp(string_content(tok.tokv.str), "ifndef")) { string_del(tok.tokv.str); @@ -379,22 +424,32 @@ VECTOR(references) *references_from_file(const char *filename, FILE *f) { preproc_token_del(&tok); goto failed; } - ADD_CHAR(' ', 1, "preprocessor command") - ADD_STR(tok.tokv.str, 1, "preprocessor command") if (if_depth == entered_depth) ++entered_depth; ++if_depth; - string_del(tok.tokv.str); + if (!vector_push(references, ret, ((reference_t){.typ = REF_IFNDEF, .line = tok.tokv.str}))) { + printf("Error: failed to memorize reference line %d\n", lineno); + string_del(tok.tokv.str); + goto failed; + } tok = pre_next_token(prep, 0); } else if (!strcmp(string_content(tok.tokv.str), "else")) { string_del(tok.tokv.str); tok = pre_next_token(prep, 0); if (if_depth == entered_depth + 1) ++entered_depth; else if (if_depth == entered_depth) --entered_depth; + if (!vector_push(references, ret, ((reference_t){.typ = REF_ELSE}))) { + printf("Error: failed to memorize reference line %d\n", lineno); + goto failed; + } } else if (!strcmp(string_content(tok.tokv.str), "endif")) { string_del(tok.tokv.str); tok = pre_next_token(prep, 0); if (if_depth == entered_depth) --entered_depth; --if_depth; + if (!vector_push(references, ret, ((reference_t){.typ = REF_ENDIF}))) { + printf("Error: failed to memorize reference line %d\n", lineno); + goto failed; + } } else { printf("Error: invalid reference file: invalid preprocessor command '%s'\n", string_content(tok.tokv.str)); string_del(tok.tokv.str); @@ -404,7 +459,6 @@ VECTOR(references) *references_from_file(const char *filename, FILE *f) { preproc_token_del(&tok); tok = pre_next_token(prep, 0); } - PUSH_LINE(0) ++lineno; if (preproc_token_isend(&tok)) { if (tok.tokt == PPTOK_EOF) goto success; @@ -431,9 +485,9 @@ VECTOR(references) *references_from_file(const char *filename, FILE *f) { if (is_comment) prepare_mark_nocomment(prep); int isweak = (string_content(tok.tokv.str)[2] == 'W'); request_t req = { - .has_default = 0, .default_comment = is_comment, .has_val = 0, + .ignored = 0, .obj_name = NULL, .weak = isweak, .def = { @@ -472,7 +526,6 @@ VECTOR(references) *references_from_file(const char *filename, FILE *f) { tok = pre_next_token(prep, 0); if ((tok.tokt == PPTOK_IDENT) || (tok.tokt == PPTOK_STRING)) { req.def.fun.typ = (tok.tokt == PPTOK_STRING) ? tok.tokv.sstr : tok.tokv.str; - req.has_default = 1; // Token moved tok = pre_next_token(prep, 0); if ((req.def.rty == RQT_FUN_2) || (req.def.rty == RQT_FUN_D)) { @@ -515,17 +568,13 @@ VECTOR(references) *references_from_file(const char *filename, FILE *f) { preproc_token_del(&tok); goto failed; } - if (if_depth == entered_depth) { - if (!vector_push(references, ret, ((reference_t){.typ = REF_REQ, .req = req}))) { - printf("Error: failed to add reference for %s\n", string_content(req.obj_name)); - string_del(req.obj_name); - if (req.def.fun.typ) string_del(req.def.fun.typ); - if (req.def.fun.fun2) string_del(req.def.fun.fun2); - // Empty destructor - goto failed; - } - } else { - request_del(&req); + if (!vector_push(references, ret, ((reference_t){.typ = REF_REQ, .req = req}))) { + printf("Error: failed to add reference for %s\n", string_content(req.obj_name)); + string_del(req.obj_name); + if (req.def.fun.typ) string_del(req.def.fun.typ); + if (req.def.fun.fun2) string_del(req.def.fun.fun2); + // Empty destructor + goto failed; } ++lineno; } else if ((tok.tokt == PPTOK_IDENT) @@ -536,9 +585,9 @@ VECTOR(references) *references_from_file(const char *filename, FILE *f) { string_clear(line); if (is_comment) prepare_mark_nocomment(prep); request_t req = { - .has_default = 1, .default_comment = is_comment, .has_val = 0, + .ignored = 0, .obj_name = NULL, .weak = (string_content(tok.tokv.str)[4] == 'V'), .def = { @@ -614,15 +663,11 @@ VECTOR(references) *references_from_file(const char *filename, FILE *f) { preproc_token_del(&tok); goto failed; } - if (if_depth == entered_depth) { - if (!vector_push(references, ret, ((reference_t){.typ = REF_REQ, .req = req}))) { - printf("Error: failed to add reference for %s\n", string_content(req.obj_name)); - request_del(&req); - // Empty destructor - goto failed; - } - } else { + if (!vector_push(references, ret, ((reference_t){.typ = REF_REQ, .req = req}))) { + printf("Error: failed to add reference for %s\n", string_content(req.obj_name)); request_del(&req); + // Empty destructor + goto failed; } ++lineno; } else if (is_comment) { @@ -663,6 +708,10 @@ success: } static int is_simple_type_ptr_to(type_t *typ, int *needs_D, int *needs_my) { + if (typ->converted) { + // printf("Warning: %s uses a converted type but is not the converted type\n", string_content(obj_name)); + *needs_my = 1; + } switch (typ->typ) { case TYPE_BUILTIN: return 1; // Assume pointers to builtin are simple @@ -670,7 +719,6 @@ static int is_simple_type_ptr_to(type_t *typ, int *needs_D, int *needs_my) { 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); case TYPE_STRUCT_UNION: - if (typ->val.st->explicit_simple) return 1; if (typ->_internal_use) return 1; // Recursive structures are OK as long as every other members are OK if (!typ->val.st->is_defined) return 1; // Undefined structures are OK since they are opaque typ->_internal_use = 1; @@ -696,6 +744,10 @@ static int is_simple_type_ptr_to(type_t *typ, int *needs_D, int *needs_my) { } } static int is_simple_type(type_t *typ, int *needs_D, int *needs_my) { + if (typ->converted) { + // printf("Warning: %s uses a converted type but is not the converted type\n", string_content(obj_name)); + *needs_my = 1; + } switch (typ->typ) { case TYPE_BUILTIN: return 1; // Assume pointers to builtin are simple @@ -703,7 +755,6 @@ static int is_simple_type(type_t *typ, int *needs_D, int *needs_my) { 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); case TYPE_STRUCT_UNION: - if (typ->val.st->explicit_simple) return 1; if (typ->_internal_use) return 1; // Recursive structures are OK as long as every other members are OK // if (!typ->val.st->is_defined) return 1; // Undefined structures are OK since they are opaque // To be safe, don't allow opaque structures @@ -732,6 +783,13 @@ static int is_simple_type(type_t *typ, int *needs_D, int *needs_my) { } static int convert_type(string_t *dest, type_t *typ, int is_ret, int *needs_D, int *needs_my, string_t *obj_name) { + if (typ->converted) { + if (!string_add_string(dest, typ->converted)) { + printf("Error: failed to add explicit type char\n"); + return 0; + } + return 1; + } if (typ->is_atomic) { printf("TODO: convert_type for atomic types\n"); return 0; @@ -831,13 +889,6 @@ static int convert_type(string_t *dest, type_t *typ, int is_ret, int *needs_D, i case TYPE_ENUM: return convert_type(dest, typ->val.typ, is_ret, needs_D, needs_my, obj_name); case TYPE_PTR: - if ((typ->val.typ->typ == TYPE_STRUCT_UNION) && typ->val.typ->val.st->tag && !strcmp(string_content(typ->val.typ->val.st->tag), "_IO_FILE")) { - if (!string_add_char(dest, 'S')) { - printf("Error: failed to add type char for %s\n", builtin2str[typ->val.builtin]); - return 0; - } - return 1; - } if (is_simple_type_ptr_to(typ->val.typ, needs_D, needs_my)) { if (!string_add_char(dest, 'p')) { printf("Error: failed to add type char for simple pointer\n"); @@ -861,6 +912,7 @@ static int convert_type(string_t *dest, type_t *typ, int is_ret, int *needs_D, i } } static int convert_type_post(string_t *dest, type_t *typ, string_t *obj_name) { + if (typ->converted) return 1; if (typ->is_atomic) { printf("TODO: convert_type_post for atomic types\n"); return 0; @@ -893,7 +945,7 @@ static int convert_type_post(string_t *dest, type_t *typ, string_t *obj_name) { int solve_request(request_t *req, type_t *typ) { if (typ->typ == TYPE_FUNCTION) { - int needs_D = 0, needs_my = req->has_default && (req->def.rty == RQT_FUN_MY), needs_2 = 0; + int needs_D = 0, needs_my = req->def.fun.typ && (req->def.rty == RQT_FUN_MY), needs_2 = 0; int convert_post; req->val.fun.typ = string_new(); if (!req->val.fun.typ) { @@ -905,7 +957,7 @@ int solve_request(request_t *req, type_t *typ) { printf("Error: failed to add convention char\n"); goto fun_fail; } - if (req->has_default && (req->def.rty == RQT_FUN_MY) && (string_content(req->def.fun.typ)[2] == 'E')) { + if (req->def.fun.typ && (req->def.rty == RQT_FUN_MY) && (string_content(req->def.fun.typ)[2] == 'E')) { if (!string_add_char(req->val.fun.typ, 'E')) { printf("Error: failed to add emu char\n"); goto fun_fail; @@ -933,23 +985,36 @@ int solve_request(request_t *req, type_t *typ) { if (!convert_type(req->val.fun.typ, typ->val.fun.args[i], 0, &needs_D, &needs_my, req->obj_name)) goto fun_fail; } if (typ->val.fun.has_varargs) { - needs_my = 1; - if (!string_add_char(req->val.fun.typ, 'V')) { - printf("Error: failed to add type char for %s\n", builtin2str[typ->val.builtin]); - goto fun_fail; + if (req->def.fun.typ + && (string_len(req->def.fun.typ) == string_len(req->val.fun.typ) + 1) + && !strncmp(string_content(req->def.fun.typ), string_content(req->val.fun.typ), string_len(req->val.fun.typ)) + && ((string_content(req->def.fun.typ)[string_len(req->val.fun.typ)] == 'M') + || (string_content(req->def.fun.typ)[string_len(req->val.fun.typ)] == 'N'))) { + if (!string_add_char(req->val.fun.typ, string_content(req->def.fun.typ)[string_len(req->val.fun.typ)])) { + printf("Error: failed to add type char '%c' for %s\n", + string_content(req->def.fun.typ)[string_len(req->val.fun.typ)], + builtin2str[typ->val.builtin]); + goto fun_fail; + } + } else { + needs_my = 1; + if (!string_add_char(req->val.fun.typ, 'V')) { + printf("Error: failed to add type char 'V' for %s\n", builtin2str[typ->val.builtin]); + goto fun_fail; + } } } } // fun_succ: - if (req->has_default && (req->def.rty == RQT_FUN_2) && !needs_my) { + if (req->def.fun.typ && (req->def.rty == RQT_FUN_2) && !needs_my) { needs_2 = 1; req->val.fun.fun2 = string_dup(req->def.fun.fun2); if (!req->val.fun.fun2) { printf("Error: failed to duplicate string (request for function %s with default redirection)\n", string_content(req->obj_name)); return 0; } - } else if (req->has_default && (req->def.rty == RQT_FUN_D) && !needs_my) { + } else if (req->def.fun.typ && (req->def.rty == RQT_FUN_D) && !needs_my) { needs_2 = 0; req->val.fun.fun2 = string_dup(req->def.fun.fun2); if (!req->val.fun.fun2) { @@ -974,10 +1039,10 @@ int solve_request(request_t *req, type_t *typ) { string_del(req->val.fun.typ); return 0; } else { - int needs_D = 0, needs_my = req->has_default && (req->def.rty == RQT_FUN_MY); + 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->has_default ? req->def.rty : req->weak ? RQT_DATAV : RQT_DATA; + req->val.rty = needs_my ? RQT_DATAM : req->def.dat.has_size ? req->def.rty : req->weak ? RQT_DATAV : RQT_DATA; req->val.dat.has_size = 1; req->val.dat.sz = typ->szinfo.size; req->has_val = 1; @@ -1002,9 +1067,34 @@ int solve_request_map(request_t *req, khash_t(type_map) *decl_map) { } int solve_references(VECTOR(references) *refs, khash_t(type_map) *decl_map) { int ret = 1; + int cond_depth = 0, ok_depth = 0; vector_for(references, ref, refs) { - if (ref->typ != REF_REQ) continue; - if (!solve_request_map(&ref->req, decl_map)) ret = 0; + switch (ref->typ) { + case REF_REQ: + if (ok_depth == cond_depth) { + if (!solve_request_map(&ref->req, decl_map)) ret = 0; + } else { + ref->req.ignored = 1; + } + break; + case REF_LINE: + break; + case REF_IFDEF: + ++cond_depth; + break; + case REF_IFNDEF: + if (cond_depth == ok_depth) ++ok_depth; + ++cond_depth; + break; + case REF_ELSE: + if (cond_depth == ok_depth) --ok_depth; + else if (cond_depth == ok_depth + 1) ++ok_depth; + break; + case REF_ENDIF: + if (cond_depth == ok_depth) --ok_depth; + --cond_depth; + break; + } } return ret; } diff --git a/wrapperhelper/src/generator.h b/wrapperhelper/src/generator.h index fd41862d..5e08577d 100644 --- a/wrapperhelper/src/generator.h +++ b/wrapperhelper/src/generator.h @@ -10,8 +10,8 @@ typedef struct request_s { string_t *obj_name; - _Bool has_default, default_comment; - _Bool has_val; + _Bool default_comment; + _Bool has_val, ignored; _Bool weak; struct { enum request_type_e { @@ -41,6 +41,10 @@ typedef struct reference_s { enum { REF_REQ, REF_LINE, + REF_IFDEF, + REF_IFNDEF, + REF_ELSE, + REF_ENDIF, } typ; union { request_t req; @@ -48,9 +52,10 @@ typedef struct reference_s { }; } reference_t; VECTOR_DECLARE(references, reference_t) -void request_print(request_t *req); -void request_print_check(request_t *req); -void output_from_references(FILE *f, VECTOR(references) *reqs); +void request_print(const request_t *req); +void request_print_check(const request_t *req); +void references_print_check(const VECTOR(references) *refs); +void output_from_references(FILE *f, const VECTOR(references) *reqs); VECTOR(references) *references_from_file(const char *filename, FILE *f); // Takes ownership of f int solve_request(request_t *req, type_t *typ); diff --git a/wrapperhelper/src/lang.c b/wrapperhelper/src/lang.c index 3e9f2a78..ddc711fe 100644 --- a/wrapperhelper/src/lang.c +++ b/wrapperhelper/src/lang.c @@ -84,7 +84,7 @@ void proc_token_del(proc_token_t *tok) { break; case PTOK_PRAGMA: switch (tok->tokv.pragma.typ) { - case PRAGMA_MARK_SIMPLE: + case PRAGMA_EXPLICIT_CONV: string_del(tok->tokv.pragma.val); break; case PRAGMA_ALLOW_INTS: @@ -288,8 +288,8 @@ void proc_token_print(const proc_token_t *tok) { case PRAGMA_ALLOW_INTS: printf("Token: %7s Allow ints\n", "PRAGMA"); break; - case PRAGMA_MARK_SIMPLE: - printf("Token: %7s Mark simple: %s\n", "PRAGMA", string_content(tok->tokv.pragma.val)); + case PRAGMA_EXPLICIT_CONV: + printf("Token: %7s Explicit conversion: destination is %s\n", "PRAGMA", string_content(tok->tokv.pragma.val)); break; default: printf("Token: %7s ???\n", "PRAGMA"); @@ -585,6 +585,7 @@ void struct_del_weak(struct_t *st) { } void type_del(type_t *typ) { if (--typ->nrefs) return; + if (typ->converted) string_del(typ->converted); switch (typ->typ) { case TYPE_BUILTIN: break; @@ -670,6 +671,7 @@ type_t *type_new(void) { } ret->szinfo.align = ret->szinfo.size = 0; ret->is_atomic = ret->is_const = ret->is_restrict = ret->is_volatile = ret->is_incomplete = ret->is_validated = ret->_internal_use = 0; + ret->converted = NULL; ret->nrefs = 1; ret->typ = TYPE_BUILTIN; ret->val.builtin = BTT_INT; @@ -683,6 +685,7 @@ type_t *type_new_ptr(type_t *target) { } ret->szinfo.align = ret->szinfo.size = 0; ret->is_atomic = ret->is_const = ret->is_restrict = ret->is_volatile = ret->is_incomplete = ret->is_validated = ret->_internal_use = 0; + ret->converted = NULL; ret->nrefs = 1; ret->typ = TYPE_PTR; ret->val.typ = target; @@ -789,7 +792,6 @@ struct_t *struct_new(int is_struct, string_t *tag) { ret->tag = tag; ret->is_defined = 0; ret->nrefs = 1; - ret->explicit_simple = 0; return ret; } @@ -973,6 +975,7 @@ void type_print(type_t *typ) { if (!typ->is_validated) printf("!<not validated> "); if (typ->is_incomplete) printf("<incomplete> "); if (typ->is_validated && !typ->is_incomplete) printf("<size=%zu align=%zu> ", typ->szinfo.size, typ->szinfo.align); + if (typ->converted) printf("<converted: %s> ", string_content(typ->converted)); if (typ->is_const) printf("const "); if (typ->is_restrict) printf("restrict "); if (typ->is_volatile) printf("volatile "); @@ -1019,9 +1022,6 @@ void type_print(type_t *typ) { } void struct_print(const struct_t *st) { printf("<" DISP_ADDR_FMT "n_uses=%zu> ", DISP_ADDR_ARG(st) st->nrefs); - if (st->explicit_simple) { - printf("<explicitly simple> "); - } if (st->is_defined) { printf( "%s %s <with %zu members%s> { ", @@ -1157,6 +1157,7 @@ file_t *file_new(void) { } t->is_atomic = t->is_const = t->is_restrict = t->is_volatile = t->_internal_use = 0; t->is_incomplete = (i == BTT_VOID); + t->converted = NULL; // Maybe should be something else? t->is_validated = 1; t->nrefs = 2; t->typ = TYPE_BUILTIN; diff --git a/wrapperhelper/src/lang.h b/wrapperhelper/src/lang.h index 2f1cf811..682bbdda 100644 --- a/wrapperhelper/src/lang.h +++ b/wrapperhelper/src/lang.h @@ -162,7 +162,7 @@ typedef struct proc_token_s { struct { enum proc_pragma_e { PRAGMA_ALLOW_INTS, - PRAGMA_MARK_SIMPLE, + PRAGMA_EXPLICIT_CONV, } typ; string_t *val; } pragma; @@ -368,6 +368,7 @@ typedef struct type_s { } fun; } val; size_info_t szinfo; + string_t *converted; // NULL for default behavior } type_t; void type_del(type_t *typ); KHASH_MAP_DECLARE_STR(type_map, type_t*) @@ -387,7 +388,6 @@ typedef struct struct_s { size_t nrefs; int is_struct; // 0 = union, 1 = struct int has_incomplete; // 1 if the last element of the structure is a VLA or if an element of the union recursively contains a VLA - int explicit_simple; size_t nmembers; st_member_t *members; } struct_t; diff --git a/wrapperhelper/src/main.c b/wrapperhelper/src/main.c index 1b5b2db2..37786f68 100644 --- a/wrapperhelper/src/main.c +++ b/wrapperhelper/src/main.c @@ -131,31 +131,31 @@ int main(int argc, char **argv) { del_str2kw(); return 2; } - VECTOR(references) *reqs = references_from_file(ref_file, ref); - if (!reqs) { + VECTOR(references) *refs = references_from_file(ref_file, ref); + if (!refs) { file_del(content); del_machines(); del_str2kw(); return 2; } - // vector_for(references, req, reqs) request_print(req); - if (!solve_references(reqs, content->decl_map)) { + // vector_for(references, req, refs) request_print(req); + if (!solve_references(refs, content->decl_map)) { printf("Warning: failed to solve all default requests\n"); } - // vector_for(references, req, reqs) request_print(req); - //vector_for(references, req, reqs) request_print_check(req); + // vector_for(references, req, refs) request_print(req); + references_print_check(refs); FILE *out = fopen(out_file, "w"); if (!out) { err(2, "Error: failed to open %s", ref_file); file_del(content); - vector_del(references, reqs); + vector_del(references, refs); del_machines(); del_str2kw(); return 2; } - output_from_references(out, reqs); + output_from_references(out, refs); fclose(out); - vector_del(references, reqs); + vector_del(references, refs); file_del(content); del_machines(); del_str2kw(); @@ -183,6 +183,11 @@ int main(int argc, char **argv) { struct_print(st); printf("\n") ) + kh_foreach_key(content->type_set, typ, + printf("Type: %p = ", typ); + type_print(typ); + printf("\n") + ) kh_foreach(content->type_map, name, typ, printf("Typedef: %s -> %p = ", name, typ); type_print(typ); diff --git a/wrapperhelper/src/parse.c b/wrapperhelper/src/parse.c index cce0a115..379df988 100644 --- a/wrapperhelper/src/parse.c +++ b/wrapperhelper/src/parse.c @@ -67,6 +67,12 @@ enum decl_spec { SPEC_BUILTIN_NOINT, SPEC_TYPE, }; +enum fun_spec { + FSPEC_NONE = 0b00, + FSPEC_INLINE = 0b01, + FSPEC_NORETURN = 0b10, + FSPEC_INLINE_NORETURN = 0b11, +}; VECTOR_DECLARE_STATIC(size_t, size_t) VECTOR_IMPL_STATIC(size_t, (void)) @@ -453,14 +459,14 @@ struct parse_declarator_dest_s { #define PDECL_TYPE_SET ((is_init && is_list) ? dest->f->type_set : (!is_init && is_list) ? dest->structms.type_set : dest->argt.type_set) #define PDECL_BUILTINS ((is_init && is_list) ? &dest->f->builtins : (!is_init && is_list) ? dest->structms.builtins : dest->argt.builtins) #define PDECL_CONST_MAP ((is_init && is_list) ? dest->f->const_map : (!is_init && is_list) ? dest->structms.const_map : dest->argt.const_map) -static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *prep, proc_token_t *tok, enum decl_storage storage, type_t *base_type, - int is_init, int is_list, int allow_decl, int allow_abstract); +static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *prep, proc_token_t *tok, enum decl_storage storage, enum fun_spec fspec, + type_t *base_type, int is_init, int is_list, int allow_decl, int allow_abstract); // declaration-specifier with storage != NULL // specifier-qualifier-list + static_assert-declaration with storage == NULL static int parse_declaration_specifier(khash_t(struct_map) *struct_map, khash_t(type_map) *type_map, khash_t(type_map) *enum_map, type_t *(*builtins)[LAST_BUILTIN + 1], khash_t(const_map) *const_map, - khash_t(type_set) *type_set, preproc_t *prep, proc_token_t *tok, enum decl_storage *storage, enum decl_spec *spec, type_t *typ); + khash_t(type_set) *type_set, preproc_t *prep, proc_token_t *tok, enum decl_storage *storage, enum fun_spec *fspec, enum decl_spec *spec, type_t *typ); void expr_print(expr_t *e) { @@ -582,7 +588,7 @@ static int parse_type_name(khash_t(struct_map) *struct_map, khash_t(type_map) *t type_t *(*builtins)[LAST_BUILTIN + 1], khash_t(const_map) *const_map, khash_t(type_set) *type_set, preproc_t *prep, proc_token_t *tok, enum token_sym_type_e end_sym, type_t **typ) { enum decl_spec spec = SPEC_NONE; - if (!parse_declaration_specifier(struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, NULL, &spec, *typ)) { + if (!parse_declaration_specifier(struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, NULL, NULL, &spec, *typ)) { type_del(*typ); goto failed; } @@ -598,7 +604,7 @@ static int parse_type_name(khash_t(struct_map) *struct_map, khash_t(type_map) *t dest2.argt.type_set = type_set; dest2.argt.builtins = builtins; dest2.argt.const_map = const_map; - if (!parse_declarator(&dest2, prep, tok, STORAGE_NONE, *typ, 0, 0, 0, 1)) { + if (!parse_declarator(&dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, *typ, 0, 0, 0, 1)) { // Token is deleted type_del(*typ); goto failed; @@ -914,11 +920,11 @@ expr_new_token: goto failed; } if (!parse_type_name(struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, SYM_RPAREN, &typ)) { - proc_token_del(tok); goto failed; } if (!typ->is_validated || typ->is_incomplete) { printf("Error: cannot get the size of an incomplete type\n"); + type_del(typ); proc_token_del(tok); goto failed; } @@ -1521,7 +1527,8 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan // specifier-qualifier-list + static_assert-declaration with storage == NULL static int parse_declaration_specifier(khash_t(struct_map) *struct_map, khash_t(type_map) *type_map, khash_t(type_map) *enum_map, type_t *(*builtins)[LAST_BUILTIN + 1], khash_t(const_map) *const_map, - khash_t(type_set) *type_set, preproc_t *prep, proc_token_t *tok, enum decl_storage *storage, enum decl_spec *spec, type_t *typ) { + khash_t(type_set) *type_set, preproc_t *prep, proc_token_t *tok, enum decl_storage *storage, + enum fun_spec *fspec, enum decl_spec *spec, type_t *typ) { if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_STATIC_ASSERT)) { // _Static_assert ( constant-expression , string-literal ) ; // Empty destructor @@ -1653,6 +1660,17 @@ parse_cur_token_decl: goto parse_cur_token_decl; } + // Function specifier + if (fspec && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_INLINE)) { + *fspec |= FSPEC_INLINE; + *tok = proc_next_token(prep); + goto parse_cur_token_decl; + } else if (fspec && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_NORETURN)) { + *fspec |= FSPEC_NORETURN; + *tok = proc_next_token(prep); + goto parse_cur_token_decl; + } + // Qualifier if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_ATOMIC)) { // Empty destructor @@ -1992,7 +2010,7 @@ parse_cur_token_decl: *tok = proc_next_token(prep); while (!proc_token_isend(tok) && ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_RBRACKET))) { enum decl_spec spec2 = SPEC_NONE; - if (!parse_declaration_specifier(struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, NULL, &spec2, typ2)) { + if (!parse_declaration_specifier(struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, NULL, NULL, &spec2, typ2)) { vector_del(st_members, members); type_del(typ2); goto failed; @@ -2039,7 +2057,7 @@ parse_cur_token_decl: dest2.structms.builtins = builtins; dest2.structms.const_map = const_map; dest2.structms.dest = members; - if (!parse_declarator(&dest2, prep, tok, STORAGE_NONE, typ2, 0, 1, 1, 1)) { + if (!parse_declarator(&dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, typ2, 0, 1, 1, 1)) { printf("Error parsing struct-declarator-list\n"); vector_del(st_members, members); type_del(typ2); @@ -2348,8 +2366,8 @@ failed: return 0; } -static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *prep, proc_token_t *tok, enum decl_storage storage, type_t *base_type, - int is_init, int is_list, int allow_decl, int allow_abstract) { +static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *prep, proc_token_t *tok, enum decl_storage storage, enum fun_spec fspec, + type_t *base_type, int is_init, int is_list, int allow_decl, int allow_abstract) { int has_list = 0, has_ident = 0; // TODO: allow_abstract and 'direct-abstract-declarator(opt) ( parameter-type-list(opt) )' @@ -2459,7 +2477,7 @@ static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *pre enum decl_storage storage2 = STORAGE_NONE; enum decl_spec spec2 = SPEC_NONE; if (!parse_declaration_specifier(PDECL_STRUCT_MAP, PDECL_TYPE_MAP, PDECL_ENUM_MAP, PDECL_BUILTINS, - PDECL_CONST_MAP, PDECL_TYPE_SET, prep, tok, &storage2, &spec2, typ2)) { + PDECL_CONST_MAP, PDECL_TYPE_SET, prep, tok, &storage2, NULL, &spec2, typ2)) { // Token is deleted vector_del(types, args); type_del(typ2); @@ -2504,7 +2522,7 @@ static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *pre dest2.argt.type_set = PDECL_TYPE_SET; dest2.argt.builtins = PDECL_BUILTINS; dest2.argt.const_map = PDECL_CONST_MAP; - if (!parse_declarator(&dest2, prep, tok, STORAGE_NONE, typ2, 0, 0, 1, 1)) { + if (!parse_declarator(&dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, typ2, 0, 0, 1, 1)) { // Token is deleted vector_del(types, args); type_del(typ2); @@ -2799,6 +2817,11 @@ static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *pre printf("Error: unexpected token in function body\n"); goto failed; } + if (fspec != FSPEC_NONE) { + printf("Error: unexpected function specifier\n"); + // Empty destructor + goto failed; + } if (storage == STORAGE_TYPEDEF) { if (!is_init || !is_list) { @@ -2965,6 +2988,11 @@ static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *pre // Empty destructor goto failed; } + if (fspec != FSPEC_NONE) { + printf("Error: unexpected function specifier\n"); + // Empty destructor + goto failed; + } size_t width; switch (eval.typ) { @@ -3163,19 +3191,31 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { } } break; } - case PRAGMA_MARK_SIMPLE: { - khiter_t it = kh_get(type_map, ret->type_map, string_content(tok.tokv.pragma.val)); - string_del(tok.tokv.pragma.val); - if (it == kh_end(ret->type_map)) { - printf("Invalid explicit_simple pragma: ident is not a typedef\n"); + case PRAGMA_EXPLICIT_CONV: { + string_t *converted = tok.tokv.pragma.val; + type_t *typ2 = type_new(); + if (!typ2) { + printf("Error: failed to create new type info structure\n"); + string_del(converted); + type_del(typ2); goto failed; } - type_t *typ0 = kh_val(ret->type_map, it); - if (typ0->typ != TYPE_STRUCT_UNION) { - printf("Invalid explicit_simple pragma: ident is not a typedef to a structure or union\n"); + tok = proc_next_token(prep); + if (!parse_type_name(ret->struct_map, ret->type_map, ret->enum_map, &ret->builtins, ret->const_map, ret->type_set, + prep, &tok, SYM_SEMICOLON, &typ2)) { + string_del(converted); goto failed; } - typ0->val.st->explicit_simple = 1; + type_del(typ2); // typ2 is in the type set, so it is already used + if (typ2->converted) { + printf("Error: type already has a conversion\n"); + string_del(converted); + // Empty destructor + goto failed; + } + string_trim(converted); + typ2->converted = converted; + // Empty destructor break; } } } else if (proc_token_iserror(&tok)) { @@ -3184,30 +3224,31 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { goto failed; } else { enum decl_storage storage = STORAGE_NONE; + enum fun_spec fspec = FSPEC_NONE; enum decl_spec spec = SPEC_NONE; if (!parse_declaration_specifier(ret->struct_map, ret->type_map, ret->enum_map, &ret->builtins, ret->const_map, - ret->type_set, prep, &tok, &storage, &spec, typ)) { + ret->type_set, prep, &tok, &storage, &fspec, &spec, typ)) { goto failed; } if (spec == SPEC_NONE) continue; // Declaration was an assert, typ is unchanged - int ok; typ = type_try_merge(typ, ret->type_set); if ((tok.tokt != PTOK_SYM) || (tok.tokv.sym != SYM_SEMICOLON)) { - ok = parse_declarator(&(struct parse_declarator_dest_s){.f = ret}, prep, &tok, storage, typ, 1, 1, 1, 0); + if (!parse_declarator(&(struct parse_declarator_dest_s){.f = ret}, prep, &tok, storage, fspec, typ, 1, 1, 1, 0)) goto failed; } else { - ok = validate_storage_type(storage, &ret->builtins, typ, tok.tokv.sym); - } - if (!ok) { - goto failed; - } else { - // Current token is ';' (or '}' for functions), ie. end of declaration - type_del(typ); - typ = type_new(); - if (!typ) { - printf("Failed to create a type info structure\n"); + if (validate_storage_type(storage, &ret->builtins, typ, tok.tokv.sym) != VALIDATION_LAST_DECL) goto failed; + if (fspec != FSPEC_NONE) { + printf("Error: unexpected function specifier\n"); + // Empty destructor goto failed; } } + // Current token is ';' (or '}' for functions), ie. end of declaration + type_del(typ); + typ = type_new(); + if (!typ) { + printf("Failed to create a type info structure\n"); + goto failed; + } } } diff --git a/wrapperhelper/src/preproc.c b/wrapperhelper/src/preproc.c index fddf2d1c..00b34e4d 100644 --- a/wrapperhelper/src/preproc.c +++ b/wrapperhelper/src/preproc.c @@ -230,6 +230,7 @@ struct preproc_s { enum preproc_state_e { PPST_NONE, PPST_NL, + PPST_PRAGMA_EXPLICIT, } st; khash_t(macros_map) *macros_map; khash_t(string_set) *macros_defined, *macros_used; @@ -1917,7 +1918,7 @@ int proc_unget_token(preproc_t *src, proc_token_t *tok) { } static proc_token_t proc_next_token_aux(preproc_t *src) { if (!vector_size(ppsource, src->prep)) { - return (proc_token_t){ .tokt = PTOK_EOF, .tokv = (union proc_token_val_u){.c = (char)EOF} }; + return (proc_token_t){ .tokt = PTOK_EOF, .tokv = {.c = (char)EOF} }; } if (vector_last(ppsource, src->prep).srct == PPSRC_PTOKEN) { proc_token_t ret = vector_last(ppsource, src->prep).srcv.ptok; @@ -1927,7 +1928,7 @@ static proc_token_t proc_next_token_aux(preproc_t *src) { check_if_depth: { if (!vector_size(ppsource, src->prep)) { - return (proc_token_t){ .tokt = PTOK_EOF, .tokv = (union proc_token_val_u){.c = (char)EOF} }; + return (proc_token_t){ .tokt = PTOK_EOF, .tokv = {.c = (char)EOF} }; } ppsource_t *ppsrc = &vector_last(ppsource, src->prep); if ((ppsrc->srct == PPSRC_PREPARE) && (ppsrc->srcv.prep.ok_depth != ppsrc->srcv.prep.cond_depth)) { @@ -1944,7 +1945,7 @@ check_if_depth: src->st = PPST_NONE; proc_token_t ret; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = tok.tokv.c}; + ret.tokv.c = tok.tokv.c; return ret; } else if (tok.tokt == PPTOK_NEWLINE) { src->st = PPST_NL; @@ -1988,7 +1989,7 @@ check_if_depth: if (!cond) { printf("Error: failed to allocate #elif condition vector\n"); src->st = PPST_NONE; - return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = (union proc_token_val_u){.c = '\0'} }; + return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = {.c = '\0'} }; } tok = ppsrc_next_token(src); while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { @@ -1996,7 +1997,7 @@ check_if_depth: printf("Error: failed to add token to #elif condition vector\n"); vector_del(preproc, cond); src->st = PPST_NONE; - return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = (union proc_token_val_u){.c = '\0'} }; + return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = {.c = '\0'} }; } tok = ppsrc_next_token(src); } @@ -2006,7 +2007,7 @@ check_if_depth: printf("Error: failed to allocate #elif solved_macros set\n"); vector_del(preproc, cond); src->st = PPST_NONE; - return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = (union proc_token_val_u){.c = '\0'} }; + return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = {.c = '\0'} }; } VECTOR(preproc) *expanded = proc_do_expand(src->macros_map, cond, solved_macros, src->macros_used); @@ -2015,7 +2016,7 @@ check_if_depth: if (!expanded) { printf("Error: failed to expand #elif condition\n"); src->st = PPST_NONE; - return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = (union proc_token_val_u){.c = '\0'} }; + return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = {.c = '\0'} }; } // Now we need to compute what is pointed by expanded, and increase cond_depth and ok_depth as needed @@ -2025,7 +2026,7 @@ check_if_depth: if (!st) { printf("Error: failed to evaluate #elif condition in (%s)\n", src->cur_file); src->st = PPST_NONE; - return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = (union proc_token_val_u){.c = '\0'} }; + return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = {.c = '\0'} }; } if (res) { vector_last(ppsource, src->prep).srcv.prep.entered_next_ok_cond = 1; @@ -2142,7 +2143,7 @@ check_if_depth: check_next_token: if (!vector_size(ppsource, src->prep)) { ret.tokt = PTOK_EOF; - ret.tokv = (union proc_token_val_u){.c = (char)EOF}; + ret.tokv.c = (char)EOF; return ret; } start_next_token: @@ -2152,10 +2153,10 @@ start_cur_token: case PPTOK_INVALID: src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = tok.tokv.c}; + ret.tokv.c = tok.tokv.c; return ret; case PPTOK_IDENT: - src->st = PPST_NONE; + src->st = (src->st == PPST_PRAGMA_EXPLICIT) ? PPST_PRAGMA_EXPLICIT : PPST_NONE; { khiter_t it = kh_get(macros_map, src->macros_map, string_content(tok.tokv.str)); if (it != kh_end(src->macros_map)) { @@ -2203,7 +2204,7 @@ start_cur_token: string_del(tok.tokv.str); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = tok.tokv.c}; + ret.tokv.c = tok.tokv.c; return ret; } // margs finishes with a SYM_RPAREN token @@ -2221,7 +2222,7 @@ start_cur_token: preproc_token_del(&tok2); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } vector_push(ppsource, src->prep, ((ppsource_t){.srct = PPSRC_PPTOKEN, .srcv.pptok = tok2})); @@ -2245,7 +2246,7 @@ start_cur_token: if (!solved) { src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } // If the expansion is empty, don't push it @@ -2255,7 +2256,7 @@ start_cur_token: vector_del(preproc, solved); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } } else { @@ -2274,7 +2275,7 @@ start_cur_token: string_del(tok.tokv.str); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } } @@ -2284,27 +2285,27 @@ start_cur_token: khiter_t it = kh_get(str2kw, str2kw, string_content(tok.tokv.str)); if (it == kh_end(str2kw)) { ret.tokt = PTOK_IDENT; - ret.tokv = (union proc_token_val_u){.str = tok.tokv.str}; + ret.tokv.str = tok.tokv.str; } else { string_del(tok.tokv.str); ret.tokt = PTOK_KEYWORD; - ret.tokv = (union proc_token_val_u){.kw = kh_val(str2kw, it)}; + ret.tokv.kw = kh_val(str2kw, it); } return ret; } case PPTOK_NUM: - src->st = PPST_NONE; + src->st = (src->st == PPST_PRAGMA_EXPLICIT) ? PPST_PRAGMA_EXPLICIT : PPST_NONE; ret.tokt = PTOK_NUM; - ret.tokv = (union proc_token_val_u){.str = tok.tokv.str}; + ret.tokv.str = tok.tokv.str; return ret; case PPTOK_STRING: - src->st = PPST_NONE; + src->st = (src->st == PPST_PRAGMA_EXPLICIT) ? PPST_PRAGMA_EXPLICIT : PPST_NONE; ret.tokt = PTOK_STRING; ret.tokv = (union proc_token_val_u){.sstr = tok.tokv.sstr, .sisstr = tok.tokv.sisstr}; return ret; case PPTOK_INCL: src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = tok.tokv.sisstr ? '<' : '"'}; + ret.tokv.c = tok.tokv.sisstr ? '<' : '"'; string_del(tok.tokv.sstr); return ret; case PPTOK_SYM: @@ -2314,7 +2315,7 @@ start_cur_token: // Empty preprocessor command if (tok.tokt == PPTOK_NEWLINE) { ret.tokt = PTOK_EOF; - ret.tokv = (union proc_token_val_u){.c = tok.tokv.c}; + ret.tokv.c = tok.tokv.c; return ret; } else { goto check_next_token; @@ -2344,7 +2345,7 @@ start_cur_token: printf("Error: failed to allocate #include tokens vector (%s)\n", src->cur_file); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { @@ -2353,7 +2354,7 @@ start_cur_token: vector_del(preproc, incl); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } tok = ppsrc_next_token(src); @@ -2365,7 +2366,7 @@ start_cur_token: vector_del(preproc, incl); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } @@ -2376,7 +2377,7 @@ start_cur_token: printf("Error: failed to expand #include tokens (%s)\n", src->cur_file); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } @@ -2385,7 +2386,7 @@ start_cur_token: printf("Error: missing #include name (%s)\n", src->cur_file); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } if (vector_content(preproc, expanded)[0].tokt == PPTOK_STRING) { @@ -2397,7 +2398,7 @@ start_cur_token: vector_del(preproc, expanded); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } else if ((vector_content(preproc, expanded)[0].tokt == PPTOK_SYM) && (vector_content(preproc, expanded)[0].tokv.sym == SYM_LT) && (vector_last(preproc, expanded).tokt == PPTOK_SYM) && (vector_last(preproc, expanded).tokv.sym == SYM_GT) @@ -2415,7 +2416,7 @@ start_cur_token: string_del(incl_file); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } break; @@ -2427,7 +2428,7 @@ start_cur_token: string_del(incl_file); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } } @@ -2447,7 +2448,7 @@ start_cur_token: string_del(incl_file); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } } @@ -2457,7 +2458,7 @@ start_cur_token: vector_del(preproc, expanded); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } } @@ -2467,7 +2468,7 @@ start_cur_token: string_del(incl_file); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = tok.tokv.sisstr ? '<' : '"'}; + ret.tokv.c = tok.tokv.sisstr ? '<' : '"'; return ret; } string_del(incl_file); @@ -2486,7 +2487,7 @@ start_cur_token: printf("Failed to allocate token vector for macro %s, returning EOF\n", string_content(defname)); string_del(defname); // Token is now freed ret.tokt = PTOK_EOF; - ret.tokv = (union proc_token_val_u){.c = (char)EOF}; + ret.tokv.c = (char)EOF; return ret; } khash_t(argid_map) *args = NULL; @@ -2499,7 +2500,7 @@ start_cur_token: string_del(defname); // Token is now freed vector_del(mtoken, m.toks); ret.tokt = PTOK_EOF; - ret.tokv = (union proc_token_val_u){.c = (char)EOF}; + ret.tokv.c = (char)EOF; return ret; } m.nargs = 0; @@ -2522,7 +2523,7 @@ start_cur_token: vector_del(mtoken, m.toks); argid_map_del(args); ret.tokt = PTOK_EOF; - ret.tokv = (union proc_token_val_u){.c = (char)EOF}; + ret.tokv.c = (char)EOF; return ret; } if (kh_ret == 0) { @@ -2555,7 +2556,7 @@ start_cur_token: vector_del(mtoken, m.toks); argid_map_del(args); ret.tokt = PTOK_EOF; - ret.tokv = (union proc_token_val_u){.c = (char)EOF}; + ret.tokv.c = (char)EOF; return ret; } if (kh_ret == 0) { @@ -2718,7 +2719,7 @@ start_cur_token: macro_del(&m); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = tok.tokv.c}; + ret.tokv.c = tok.tokv.c; return ret; } else if (iret == 0) { // Ignore @@ -2790,7 +2791,7 @@ start_cur_token: printf("\n"); vector_clear(ppsource, src->prep); ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = (char)EOF}; + ret.tokv.c = (char)EOF; return ret; } else if (!strcmp(string_content(tok.tokv.str), "warning")) { printf("Warning: #warning command (%s):", src->cur_file); @@ -2844,7 +2845,7 @@ start_cur_token: ret.tokv.pragma.typ = PRAGMA_ALLOW_INTS; return ret; } - } else if (!strcmp(string_content(tok.tokv.str), "explicit_simple")) { + } else if (!strcmp(string_content(tok.tokv.str), "type_letters")) { string_del(tok.tokv.str); tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { @@ -2852,20 +2853,11 @@ start_cur_token: goto preproc_hash_err; } string_t *id = tok.tokv.str; - tok = ppsrc_next_token(src); - while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { - preproc_token_del(&tok); - tok = ppsrc_next_token(src); - } - if (tok.tokt == PPTOK_INVALID) { - string_del(id); - goto start_cur_token; - } else { - ret.tokt = PTOK_PRAGMA; - ret.tokv.pragma.typ = PRAGMA_MARK_SIMPLE; - ret.tokv.pragma.val = id; - return ret; - } + src->st = PPST_PRAGMA_EXPLICIT; + ret.tokt = PTOK_PRAGMA; + ret.tokv.pragma.typ = PRAGMA_EXPLICIT_CONV; + ret.tokv.pragma.val = id; + return ret; } else { printf("Unknown pragma wrappers directive '%s', skipping until EOL\n", string_content(tok.tokv.str)); goto preproc_hash_err; @@ -2879,7 +2871,7 @@ start_cur_token: printf("Error: invalid #if source type %u\n", vector_last(ppsource, src->prep).srct); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } string_del(tok.tokv.str); @@ -2888,7 +2880,7 @@ start_cur_token: printf("Error: failed to allocate #if condition vector\n"); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } tok = ppsrc_next_token(src); @@ -2898,7 +2890,7 @@ start_cur_token: vector_del(preproc, cond); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } tok = ppsrc_next_token(src); @@ -2910,7 +2902,7 @@ start_cur_token: vector_del(preproc, cond); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } @@ -2921,7 +2913,7 @@ start_cur_token: printf("Error: failed to expand #if condition\n"); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } @@ -2933,7 +2925,7 @@ start_cur_token: printf("Error: failed to evaluate #if condition (%s)\n", src->cur_file); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } ++vector_last(ppsource, src->prep).srcv.prep.cond_depth; @@ -3116,22 +3108,28 @@ start_cur_token: if (tok.tokt == PPTOK_NEWLINE) goto check_if_depth; else goto start_cur_token; // Returns immediately } - src->st = PPST_NONE; + src->st = (src->st == PPST_PRAGMA_EXPLICIT) ? PPST_PRAGMA_EXPLICIT : PPST_NONE; ret.tokt = PTOK_SYM; - ret.tokv = (union proc_token_val_u){.sym = tok.tokv.sym}; + ret.tokv.sym = tok.tokv.sym; return ret; case PPTOK_NEWLINE: + if (src->st == PPST_PRAGMA_EXPLICIT) { + src->st = PPST_NL; + ret.tokt = PTOK_SYM; + ret.tokv.sym = SYM_SEMICOLON; + return ret; + } src->st = PPST_NL; goto check_next_token; case PPTOK_BLANK: src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = tok.tokv.c}; + ret.tokv.c = tok.tokv.c; return ret; case PPTOK_START_LINE_COMMENT: src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = tok.tokv.c}; + ret.tokv.c = tok.tokv.c; return ret; case PPTOK_EOF: if ((vector_last(ppsource, src->prep).srct == PPSRC_PREPARE) && vector_last(ppsource, src->prep).srcv.prep.cond_depth) { @@ -3148,6 +3146,12 @@ start_cur_token: vector_last(ppsource, src->prep).srcv.prep.old_filename = NULL; } vector_pop(ppsource, src->prep); + if (src->st == PPST_PRAGMA_EXPLICIT) { + src->st = PPST_NL; + ret.tokt = PTOK_SYM; + ret.tokv.sym = SYM_SEMICOLON; + return ret; + } src->st = PPST_NL; // Should be redundant since TOK_NEWLINE is added before TOK_EOF if required // EOF has an empty destructor // Note that since we have opened the file, the previous file also had ok_depth == cond_depth @@ -3156,7 +3160,7 @@ start_cur_token: default: printf("Unknown next pp token type %u, sending EOF\n", tok.tokt); ret.tokt = PTOK_EOF; - ret.tokv = (union proc_token_val_u){.c = (char)EOF}; + ret.tokv.c = (char)EOF; return ret; } } @@ -3172,7 +3176,7 @@ proc_token_t proc_next_token(preproc_t *src) { string_del(ret2.tokv.sstr); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } string_del(ret2.tokv.sstr); @@ -3183,7 +3187,7 @@ proc_token_t proc_next_token(preproc_t *src) { proc_token_del(&ret2); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv = (union proc_token_val_u){.c = '\0'}; + ret.tokv.c = '\0'; return ret; } return ret; |