From 70a6d9674876c4622b42b8913a9ee910a9e65c12 Mon Sep 17 00:00:00 2001 From: rajdakin Date: Tue, 29 Oct 2024 16:31:05 +0100 Subject: [PATCH] [WRAPPERHELPER] Added pragma once support, fixed a preprocessor bug, fixed the wrapperhelper Makefile (#1977) --- wrapperhelper/src/generator.c | 33 ++++++--- wrapperhelper/src/main.c | 15 ++++ wrapperhelper/src/prepare.c | 46 ++++++++++-- wrapperhelper/src/prepare.h | 2 + wrapperhelper/src/preproc.c | 135 ++++++++++++++++++++++------------ wrapperhelper/src/vector.c | 1 + wrapperhelper/src/vector.h | 1 + 7 files changed, 170 insertions(+), 63 deletions(-) diff --git a/wrapperhelper/src/generator.c b/wrapperhelper/src/generator.c index a4762c5e..8061ba88 100644 --- a/wrapperhelper/src/generator.c +++ b/wrapperhelper/src/generator.c @@ -1399,7 +1399,7 @@ static enum safeness_e get_safeness(type_t *emu_typ, type_t *target_typ, int *ne } // needs_S != NULL iff type is return -static int convert_type(string_t *dest, type_t *emu_typ, type_t *target_typ, +static int convert_type(string_t *dest, type_t *emu_typ, type_t *target_typ, int allow_nesting, _Bool *needs_S, int *needs_D, int *needs_my, khash_t(conv_map) *conv_map, string_t *obj_name) { if (emu_typ->converted) { if (!string_add_string(dest, emu_typ->converted)) { @@ -1499,7 +1499,7 @@ static int convert_type(string_t *dest, type_t *emu_typ, type_t *target_typ, return 1; } size_t idx = string_len(dest); - if (!convert_type(dest, emu_typ->val.array.typ, target_typ->val.array.typ, needs_S, needs_D, needs_my, conv_map, obj_name)) + if (!convert_type(dest, emu_typ->val.array.typ, target_typ->val.array.typ, allow_nesting, needs_S, needs_D, needs_my, conv_map, obj_name)) return 0; size_t end = string_len(dest); if (idx == end) return 1; @@ -1530,13 +1530,13 @@ static int convert_type(string_t *dest, type_t *emu_typ, type_t *target_typ, return 1; } else { if ((emu_typ->val.st->nmembers == 1) && (target_typ->typ == TYPE_STRUCT_UNION) && (target_typ->val.st->nmembers == 1)) { - return convert_type(dest, emu_typ->val.st->members[0].typ, target_typ->val.st->members[0].typ, needs_S, needs_D, needs_my, conv_map, obj_name); + return convert_type(dest, emu_typ->val.st->members[0].typ, target_typ->val.st->members[0].typ, allow_nesting, needs_S, needs_D, needs_my, conv_map, obj_name); } printf("Error: TODO: convert_type on structure as argument (%s)\n", string_content(obj_name)); return 0; } case TYPE_ENUM: - return convert_type(dest, emu_typ->val.typ, target_typ->val.typ, needs_S, needs_D, needs_my, conv_map, obj_name); + return convert_type(dest, emu_typ->val.typ, target_typ->val.typ, allow_nesting, needs_S, needs_D, needs_my, conv_map, obj_name); case TYPE_PTR: switch (get_safeness_ptr(emu_typ->val.typ, target_typ->val.typ, needs_D, needs_my, conv_map, obj_name)) { default: @@ -1554,6 +1554,15 @@ static int convert_type(string_t *dest, type_t *emu_typ, type_t *target_typ, return 1; case SAFE_EXPAND: + if (!allow_nesting) { + // TODO remove this with a better rebuild_wrappers.py + *needs_my = 1; + if (!string_add_char(dest, 'p')) { + printf("Error: failed to add type char for simple pointer\n"); + return 0; + } + return 1; + } if (!string_add_char(dest, emu_typ->is_const ? 'r' : 'b')) { printf("Error: failed to add start type char for wrapping pointer\n"); return 0; @@ -1564,12 +1573,12 @@ static int convert_type(string_t *dest, type_t *emu_typ, type_t *target_typ, do_expanded: switch (emu_typ->typ) { case TYPE_BUILTIN: - if (!convert_type(dest, emu_typ, target_typ, needs_S, needs_D, needs_my, conv_map, obj_name)) { + if (!convert_type(dest, emu_typ, target_typ, 0, needs_S, needs_D, needs_my, conv_map, obj_name)) { return 0; } break; case TYPE_ARRAY: - if (!convert_type(dest, emu_typ, target_typ, needs_S, needs_D, needs_my, conv_map, obj_name)) { + if (!convert_type(dest, emu_typ, target_typ, 0, needs_S, needs_D, needs_my, conv_map, obj_name)) { return 0; } break; @@ -1584,7 +1593,7 @@ static int convert_type(string_t *dest, type_t *emu_typ, type_t *target_typ, goto do_expanded; } for (size_t i = 0; i < emu_typ->val.st->nmembers; ++i) { - if (!convert_type(dest, emu_typ->val.st->members[i].typ, target_typ->val.st->members[i].typ, needs_S, needs_D, needs_my, conv_map, obj_name)) { + if (!convert_type(dest, emu_typ->val.st->members[i].typ, target_typ->val.st->members[i].typ, 0, needs_S, needs_D, needs_my, conv_map, obj_name)) { return 0; } } @@ -1592,17 +1601,17 @@ static int convert_type(string_t *dest, type_t *emu_typ, type_t *target_typ, case TYPE_ENUM: emu_typ = emu_typ->val.typ; target_typ = target_typ->val.typ; - if (!convert_type(dest, emu_typ, target_typ, needs_S, needs_D, needs_my, conv_map, obj_name)) { + if (!convert_type(dest, emu_typ, target_typ, 0, needs_S, needs_D, needs_my, conv_map, obj_name)) { return 0; } break; case TYPE_PTR: - if (!convert_type(dest, emu_typ, target_typ, needs_S, needs_D, needs_my, conv_map, obj_name)) { + if (!convert_type(dest, emu_typ, target_typ, 0, needs_S, needs_D, needs_my, conv_map, obj_name)) { return 0; } break; case TYPE_FUNCTION: - if (!convert_type(dest, emu_typ, target_typ, needs_S, needs_D, needs_my, conv_map, obj_name)) { + if (!convert_type(dest, emu_typ, target_typ, 0, needs_S, needs_D, needs_my, conv_map, obj_name)) { return 0; } break; @@ -1666,7 +1675,7 @@ int solve_request(request_t *req, type_t *emu_typ, type_t *target_typ, khash_t(c printf("Error: failed to create function type string\n"); return 0; } - if (!convert_type(req->val.fun.typ, emu_typ->val.fun.ret, target_typ->val.fun.ret, &req->val.fun.needs_S, &needs_D, &needs_my, conv_map, req->obj_name)) + if (!convert_type(req->val.fun.typ, emu_typ->val.fun.ret, target_typ->val.fun.ret, 0, &req->val.fun.needs_S, &needs_D, &needs_my, conv_map, req->obj_name)) goto fun_fail; idx_conv = string_len(req->val.fun.typ); if (!string_add_char(req->val.fun.typ, 'F')) { @@ -1692,7 +1701,7 @@ int solve_request(request_t *req, type_t *emu_typ, type_t *target_typ, khash_t(c } } else { for (size_t i = 0; i < emu_typ->val.fun.nargs; ++i) { - if (!convert_type(req->val.fun.typ, emu_typ->val.fun.args[i], target_typ->val.fun.args[i], NULL, &needs_D, &needs_my, conv_map, req->obj_name)) + if (!convert_type(req->val.fun.typ, emu_typ->val.fun.args[i], target_typ->val.fun.args[i], 1, NULL, &needs_D, &needs_my, conv_map, req->obj_name)) goto fun_fail; } if (emu_typ->val.fun.has_varargs) { diff --git a/wrapperhelper/src/main.c b/wrapperhelper/src/main.c index 14a67ce6..f3938904 100644 --- a/wrapperhelper/src/main.c +++ b/wrapperhelper/src/main.c @@ -8,6 +8,7 @@ #include "lang.h" #include "machine.h" #include "parse.h" +#include "prepare.h" #include "khash.h" static void help(char *arg0) { @@ -237,6 +238,7 @@ int main(int argc, char **argv) { log_error_nopos("failed to parse the file\n"); del_machines(); del_str2kw(); + prepare_cleanup(); return 0; } @@ -246,6 +248,7 @@ int main(int argc, char **argv) { file_del(emu_content); del_machines(); del_str2kw(); + prepare_cleanup(); return 2; } file_t *target_content = parse_file(target, in_file, f); // Takes ownership of f @@ -254,6 +257,7 @@ int main(int argc, char **argv) { file_del(emu_content); del_machines(); del_str2kw(); + prepare_cleanup(); return 0; } @@ -264,6 +268,7 @@ int main(int argc, char **argv) { file_del(target_content); del_machines(); del_str2kw(); + prepare_cleanup(); return 2; } VECTOR(references) *refs = references_from_file(ref_file, ref); @@ -272,6 +277,7 @@ int main(int argc, char **argv) { file_del(target_content); del_machines(); del_str2kw(); + prepare_cleanup(); return 2; } // vector_for(references, req, refs) request_print(req); @@ -294,6 +300,7 @@ int main(int argc, char **argv) { vector_del(references, refs); del_machines(); del_str2kw(); + prepare_cleanup(); return 2; } output_from_references(out, refs); @@ -303,6 +310,7 @@ int main(int argc, char **argv) { file_del(target_content); del_machines(); del_str2kw(); + prepare_cleanup(); return 0; } case MAIN_PROC: { @@ -315,6 +323,7 @@ int main(int argc, char **argv) { log_error_nopos("failed to parse the file\n"); del_machines(); del_str2kw(); + prepare_cleanup(); return 0; } // print content @@ -373,6 +382,7 @@ int main(int argc, char **argv) { file_del(content); del_machines(); del_str2kw(); + prepare_cleanup(); return 0; } case MAIN_PREPARE: @@ -380,6 +390,7 @@ int main(int argc, char **argv) { dump_prepare(in_file, f); // Takes ownership of f del_machines(); del_str2kw(); + prepare_cleanup(); return 0; case MAIN_PREPROC: { @@ -390,9 +401,13 @@ int main(int argc, char **argv) { dump_preproc(arch, in_file, f); // Takes ownership of f del_machines(); del_str2kw(); + prepare_cleanup(); return 0; } } log_internal_nopos("failed to run mode %u\n", ms); + del_machines(); + del_str2kw(); + prepare_cleanup(); return 2; } diff --git a/wrapperhelper/src/prepare.c b/wrapperhelper/src/prepare.c index ff19a067..464b7937 100644 --- a/wrapperhelper/src/prepare.c +++ b/wrapperhelper/src/prepare.c @@ -2,6 +2,13 @@ #include +#include "log.h" + +static struct li_filename_s { + char *name; + struct li_filename_s *next; +} *li_filenames = NULL; + typedef struct char_s { int c; loginfo_t li; @@ -32,12 +39,21 @@ prepare_t *prepare_new_file(FILE *f, const char *filename) { return NULL; } - char *srcn = strdup(filename); + char *srcn = strdup(filename ? filename : ""); if (!srcn) { log_memory("failed to duplicate filename\n"); free(ret); return NULL; } + struct li_filename_s *new_lifn = malloc(sizeof *new_lifn); + if (!new_lifn) { + log_memory("failed to remember new filename\n"); + free(srcn); + free(ret); + return NULL; + } + *new_lifn = (struct li_filename_s){ .name = srcn, .next = li_filenames }; + li_filenames = new_lifn; *ret = (prepare_t){ .f = f, @@ -52,7 +68,6 @@ prepare_t *prepare_new_file(FILE *f, const char *filename) { void prepare_del(prepare_t *prep) { if (prep->f) fclose(prep->f); - if (prep->srcn) free(prep->srcn); free(prep); } @@ -504,9 +519,21 @@ start_next_token: void prepare_set_line(prepare_t *src, char *filename, size_t lineno) { if (filename) { - if (src->srcn) free(filename); - src->srcn = filename; - src->li.filename = filename; + char *srcn = strdup(filename ? filename : ""); + if (!srcn) { + log_memory("failed to duplicate filename from #line command\n"); + return; + } + struct li_filename_s *new_lifn = malloc(sizeof *new_lifn); + if (!new_lifn) { + log_memory("failed to remember new filename from #line command\n"); + free(srcn); + return; + } + *new_lifn = (struct li_filename_s){ .name = srcn, .next = li_filenames }; + li_filenames = new_lifn; + src->srcn = srcn; + src->li.filename = srcn; } size_t colno = 1; for (int i = src->buf_len; i--; ) { @@ -545,3 +572,12 @@ int pre_next_newline_token(prepare_t *src, string_t *buf) { } } } + +void prepare_cleanup(void) { + while (li_filenames) { + struct li_filename_s *lifn = li_filenames->next; + free(li_filenames->name); + free(li_filenames); + li_filenames = lifn; + } +} diff --git a/wrapperhelper/src/prepare.h b/wrapperhelper/src/prepare.h index 9192fc78..bcf4e782 100644 --- a/wrapperhelper/src/prepare.h +++ b/wrapperhelper/src/prepare.h @@ -19,4 +19,6 @@ void prepare_set_line(prepare_t *src, char *filename, size_t lineno); // Takes o void prepare_mark_nocomment(prepare_t *src); // Change the state (usually from COMMENT) to NONE int pre_next_newline_token(prepare_t *src, string_t *buf); // In a comment append everything until the EOL or EOF to the buffer +void prepare_cleanup(void); // Frees loginfo filenames + #endif // PREPARE_H diff --git a/wrapperhelper/src/preproc.c b/wrapperhelper/src/preproc.c index 10ac978b..fe93ace0 100644 --- a/wrapperhelper/src/preproc.c +++ b/wrapperhelper/src/preproc.c @@ -203,6 +203,7 @@ VECTOR_IMPL_STATIC(ppsource, ppsource_del) struct preproc_s { machine_t *target; VECTOR(ppsource) *prep; + VECTOR(ccharp) *pragma_once; enum preproc_state_e { PPST_NONE, PPST_NL, @@ -223,6 +224,7 @@ void preproc_del(preproc_t *src) { macros_map_del(src->macros_map); if (src->dirname) free(src->dirname); if (src->cur_file) free(src->cur_file); + vector_del(ccharp, src->pragma_once); free(src); } @@ -350,6 +352,16 @@ preproc_t *preproc_new_file(machine_t *target, FILE *f, char *dirname, const cha free(ret); return NULL; } + ret->pragma_once = vector_new(ccharp); + if (!ret->pragma_once) { + vector_del(ppsource, ret->prep); + kh_destroy(macros_map, ret->macros_map); + kh_destroy(string_set, ret->macros_defined); + kh_destroy(string_set, ret->macros_used); + fclose(f); + free(ret); + return NULL; + } ret->dirname = NULL; ret->cur_file = NULL; // ret can now be deleted by preproc_del @@ -534,45 +546,47 @@ static VECTOR(preproc) *preproc_solve_macro(loginfo_t *li, #undef ONLYDIGS } if (do_add) { - preproc_token_t tok2; preproc_token_t *tok1 = &mtok->val.tok; - switch (tok1->tokt) { - case PPTOK_INVALID: - case PPTOK_NEWLINE: - case PPTOK_BLANK: - case PPTOK_START_LINE_COMMENT: - case PPTOK_EOF: tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.c = tok1->tokv.c}; break; - case PPTOK_SYM: tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.sym = tok1->tokv.sym}; break; - case PPTOK_IDENT: - case PPTOK_IDENT_UNEXP: - case PPTOK_NUM: { - string_t *dup = string_dup(tok1->tokv.str); - if (!dup) { - LOG_MEMORY("failed to duplicate string"); + if (tok1->tokt != PPTOK_NEWLINE) { + preproc_token_t tok2; + switch (tok1->tokt) { + case PPTOK_INVALID: + case PPTOK_NEWLINE: + case PPTOK_BLANK: + case PPTOK_START_LINE_COMMENT: + case PPTOK_EOF: tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.c = tok1->tokv.c}; break; + case PPTOK_SYM: tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.sym = tok1->tokv.sym}; break; + case PPTOK_IDENT: + case PPTOK_IDENT_UNEXP: + case PPTOK_NUM: { + string_t *dup = string_dup(tok1->tokv.str); + if (!dup) { + LOG_MEMORY("failed to duplicate string"); + vector_del(preproc, ret); + ret = NULL; + goto solve_done; + } + tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.str = dup}; + break; } + case PPTOK_INCL: + case PPTOK_STRING: { + string_t *dup = string_dup(tok1->tokv.sstr); + if (!dup) { + LOG_MEMORY("failed to duplicate string"); + vector_del(preproc, ret); + ret = NULL; + goto solve_done; + } + tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.sstr = dup, .tokv.sisstr = tok1->tokv.sisstr}; + break; } + } + if (!vector_push(preproc, ret, tok2)) { + LOG_MEMORY("failed to add token to output vector"); + preproc_token_del(&tok2); vector_del(preproc, ret); ret = NULL; goto solve_done; } - tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.str = dup}; - break; } - case PPTOK_INCL: - case PPTOK_STRING: { - string_t *dup = string_dup(tok1->tokv.sstr); - if (!dup) { - LOG_MEMORY("failed to duplicate string"); - vector_del(preproc, ret); - ret = NULL; - goto solve_done; - } - tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.sstr = dup, .tokv.sisstr = tok1->tokv.sisstr}; - break; } - } - if (!vector_push(preproc, ret, tok2)) { - LOG_MEMORY("failed to add token to output vector"); - preproc_token_del(&tok2); - vector_del(preproc, ret); - ret = NULL; - goto solve_done; } } vector_pop_nodel(mtoken, st); @@ -630,7 +644,8 @@ static VECTOR(preproc) *preproc_solve_macro(loginfo_t *li, } if (len) { preproc_token_t tok2; - for (preproc_token_t *tok1 = vector_begin(preproc, toks_to_add) + tta_start; tok1 != vector_end(preproc, toks_to_add); ++tok1){ + for (preproc_token_t *tok1 = vector_begin(preproc, toks_to_add) + tta_start; tok1 != vector_end(preproc, toks_to_add); ++tok1) { + if (tok1->tokt == PPTOK_NEWLINE) continue; switch (tok1->tokt) { case PPTOK_INVALID: case PPTOK_NEWLINE: @@ -779,6 +794,7 @@ static VECTOR(preproc) *preproc_do_expand(loginfo_t *li, const khash_t(macros_ma return NULL; } vector_for(preproc, tok, toks) { + if (tok->tokt == PPTOK_NEWLINE) continue; preproc_token_t tok2; switch (tok->tokt) { case PPTOK_INVALID: @@ -2115,7 +2131,7 @@ start_cur_token: } marg = vector_new(preproc); if (!marg) goto solve_err_mem; - } else { + } else if (tok2.tokt != PPTOK_NEWLINE) { if (!vector_push(preproc, marg, tok2)) { vector_del(preproc, marg); goto solve_err_mem; @@ -2409,18 +2425,32 @@ start_cur_token: } } // cur_pathno == 0 if cur_file was from an #include "...", otherwise idx + 1 + int has_once = 0; + vector_for(ccharp, fname, src->pragma_once) { + if (!strcmp(*fname, string_content(incl_file))) { + has_once = 1; + break; + } + } + if (has_once) { #ifdef LOG_INCLUDE - printf("Opening %s as %s from system path %zu\n", string_content(incl_file), - is_sys ? "system header" : "cur header", is_next ? src->cur_pathno : 0); + printf("Skipping opening %s as %s from system path %zu\n", string_content(incl_file), + is_sys ? "system header" : "cur header", is_next ? src->cur_pathno : 0); #endif - if ((is_sys || !try_open_dir(src, incl_file)) && !try_open_sys(src, incl_file, is_next ? src->cur_pathno : 0)) { - log_error(&li, "failed to open %s\n", string_content(incl_file)); - string_del(incl_file); - src->st = PPST_NONE; - ret.tokt = PTOK_INVALID; - ret.loginfo = li; - ret.tokv.c = is_sys ? '<' : '"'; - return ret; + } else { +#ifdef LOG_INCLUDE + printf("Opening %s as %s from system path %zu\n", string_content(incl_file), + is_sys ? "system header" : "cur header", is_next ? src->cur_pathno : 0); +#endif + if ((is_sys || !try_open_dir(src, incl_file)) && !try_open_sys(src, incl_file, is_next ? src->cur_pathno : 0)) { + log_error(&li, "failed to open %s\n", string_content(incl_file)); + string_del(incl_file); + src->st = PPST_NONE; + ret.tokt = PTOK_INVALID; + ret.loginfo = li; + ret.tokv.c = is_sys ? '<' : '"'; + return ret; + } } string_del(incl_file); if (tok.tokt == PPTOK_NEWLINE) goto check_next_token; @@ -2828,6 +2858,19 @@ start_cur_token: if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { log_error(&tok.loginfo, "unknown pragma directive, skipping until EOL\n"); goto preproc_hash_err; + } else if (!strcmp(string_content(tok.tokv.str), "once")) { + const char *fname = tok.loginfo.filename; + if (!vector_push(ccharp, src->pragma_once, fname)) { + log_memory("failed to add filename to #pragma once list\n"); + vector_clear(ppsource, src->prep); + ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; + ret.tokv.c = (char)EOF; + return ret; + } + string_del(tok.tokv.str); + tok = ppsrc_next_token(src); + goto preproc_hash_err; } else if (!strcmp(string_content(tok.tokv.str), "wrappers")) { string_del(tok.tokv.str); tok = ppsrc_next_token(src); diff --git a/wrapperhelper/src/vector.c b/wrapperhelper/src/vector.c index c3f710d7..d1604e6d 100644 --- a/wrapperhelper/src/vector.c +++ b/wrapperhelper/src/vector.c @@ -3,6 +3,7 @@ VECTOR_IMPL(voidp, (void)) VECTOR_IMPL(char, (void)) VECTOR_IMPL(charp, (void)) +VECTOR_IMPL(ccharp, (void)) static void stringp_del(string_t **s) { return string_del(*s); } VECTOR_IMPL(string, stringp_del) diff --git a/wrapperhelper/src/vector.h b/wrapperhelper/src/vector.h index 6e0c124a..5573b9ac 100644 --- a/wrapperhelper/src/vector.h +++ b/wrapperhelper/src/vector.h @@ -208,6 +208,7 @@ int vector_push_vec_impl(VECTOR(voidp) *v1, VECTOR(voidp) *v2, size_t VECTOR_DECLARE(char, char) VECTOR_DECLARE(charp, char*) +VECTOR_DECLARE(ccharp, const char*) VECTOR_DECLARE(string, string_t*) #endif // VECTOR_H