diff options
| author | rajdakin <rajdakin@gmail.com> | 2024-09-07 20:53:51 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-07 20:53:51 +0200 |
| commit | f30d75ae5dba339bfc95229894b22fd73e3fdc14 (patch) | |
| tree | 5cd75da181f43a7aaf29cab121069d9dba85aa2d | |
| parent | e087e7782ca9b2ce6c8ec99706a352b1c6ca12bc (diff) | |
| download | box64-f30d75ae5dba339bfc95229894b22fd73e3fdc14.tar.gz box64-f30d75ae5dba339bfc95229894b22fd73e3fdc14.zip | |
[WRAPPERHELPER] General improvements (#1804)
* [WRAPPERHELPER] Automatic headers detection, various bug fixes, added some cast support * [WRAPPERHELPER] Keep comments untouched
| -rw-r--r-- | .gitignore | 1 | ||||
| -rwxr-xr-x | wrapperhelper/Makefile | 6 | ||||
| -rw-r--r-- | wrapperhelper/example-libc.h | 28 | ||||
| -rw-r--r-- | wrapperhelper/src/cstring.c | 19 | ||||
| -rw-r--r-- | wrapperhelper/src/cstring.h | 4 | ||||
| -rw-r--r-- | wrapperhelper/src/generator.c | 192 | ||||
| -rw-r--r-- | wrapperhelper/src/generator.h | 18 | ||||
| -rw-r--r-- | wrapperhelper/src/lang.c | 82 | ||||
| -rw-r--r-- | wrapperhelper/src/machine.c | 44 | ||||
| -rw-r--r-- | wrapperhelper/src/main.c | 24 | ||||
| -rw-r--r-- | wrapperhelper/src/parse.c | 66 | ||||
| -rw-r--r-- | wrapperhelper/src/prepare.c | 82 | ||||
| -rw-r--r-- | wrapperhelper/src/prepare.h | 4 | ||||
| -rw-r--r-- | wrapperhelper/src/preproc.c | 40 | ||||
| -rw-r--r-- | wrapperhelper/src/vector.c | 1 | ||||
| -rw-r--r-- | wrapperhelper/src/vector.h | 2 |
16 files changed, 447 insertions, 166 deletions
diff --git a/.gitignore b/.gitignore index 68cda85e..f2a710c9 100644 --- a/.gitignore +++ b/.gitignore @@ -67,6 +67,7 @@ backup/ /wrapperhelper/sanaddress /wrapperhelper/sanleak /wrapperhelper/sanundefined +/wrapperhelper/src/machine.gen # macOS .DS_Store diff --git a/wrapperhelper/Makefile b/wrapperhelper/Makefile index 163d069e..a4222bee 100755 --- a/wrapperhelper/Makefile +++ b/wrapperhelper/Makefile @@ -232,9 +232,14 @@ $(eval $(call compile_wrapperhelper_c,,parse,parse)) $(eval $(call compile_wrapperhelper_c,,prepare,prepare)) $(eval $(call compile_wrapperhelper_c,,preproc,preproc)) $(eval $(call compile_wrapperhelper_c,,vector,vector)) +$(call wrapperhelper_o,,machine,machine): src/machine.gen $(call wrapperhelper_o,,preproc,preproc): CFLAGS+= -fno-analyzer $(call wrapperhelper_o,,parse,parse): CFLAGS+= -fno-analyzer +src/machine.gen: + $(call colorize,96,GEN,33,Generating $@) + $(SILENCER)echo | LC_ALL=C LANG=C $(CC) $(CPPFLAGS) -E -v - |& sed ':l; $$ ! { N; b l }; s/.*#include <...> search starts here:\n//; s/End of search list.*//; s/^ /DO_PATH("/; s/\n /")\nDO_PATH("/g; s/\n$$/")/' >src/machine.gen + #$(eval $(call compile_test_cxx,core/number)) bin/wrapperhelper: $$(OBJLIST_wrapperhelper) | $$(@D) @@ -252,6 +257,7 @@ clean: $(call remove,bin/wrapperhelper) $(call remove,$(TESTS:%=obj/$(OBJDIR)/tests/%.o)) $(call remove,$(TESTS:%=tests/%)) + $(call remove,src/machine.gen) .PHONY: clean distclean: $(call remove,makedir) diff --git a/wrapperhelper/example-libc.h b/wrapperhelper/example-libc.h index 8125f75e..81850c51 100644 --- a/wrapperhelper/example-libc.h +++ b/wrapperhelper/example-libc.h @@ -2,34 +2,6 @@ #define __USE_MISC 1 #define PORTMAP -// Based on /usr/include/clang/Basic/TokenKinds.def -// Alternate spelling for various tokens. There are GCC extensions in all -// languages, but should not be disabled in strict conformance mode. -#define __alignof__ __alignof -#define __asm asm -#define __asm__ asm -#define __complex _Complex -#define __complex__ _Complex -#define __const const -#define __const__ const -#define __decltype decltype -#define __imag__ __imag -#define __inline inline -#define __inline__ inline -#define __nullptr nullptr -#define __real__ __real -#define __restrict restrict -#define __restrict__ restrict -#define __signed signed -#define __signed__ signed -#define __typeof typeof -#define __typeof__ typeof -#define __volatile volatile -#define __volatile__ volatile - -typedef __int128 __int128_t; -typedef unsigned __int128 __uint128_t; - // TODO #define inline diff --git a/wrapperhelper/src/cstring.c b/wrapperhelper/src/cstring.c index aecfb52e..86536915 100644 --- a/wrapperhelper/src/cstring.c +++ b/wrapperhelper/src/cstring.c @@ -71,6 +71,15 @@ int string_reserve_grow(string_t *s, size_t cap) { return 1; } +int string_trim(string_t *s) { + if (s->ssize == s->scap) return 1; + void *new_buf = realloc(s->buf, sizeof(char) * (s->ssize + 1)); + if (!new_buf) return 0; + s->buf = new_buf; + s->scap = s->ssize; + return 1; +} + void string_del(string_t *s) { if (s->buf) free(s->buf); free(s); @@ -118,6 +127,16 @@ void string_pop(string_t *s) { } } +void string_clear(string_t *s) { + if (!s->ssize) return; + if (!s->scap) return; + s->buf[s->ssize = 0] = '\0'; + void *new_buf = realloc(s->buf, sizeof(char)); + if (!new_buf) return; // We don't really care if the realloc fails, we just need to not update anything + s->buf = new_buf; + s->scap = 0; +} + string_t *string_dup(string_t const *s) { string_t *ret = string_new_cap(s->ssize); if (!ret) return NULL; diff --git a/wrapperhelper/src/cstring.h b/wrapperhelper/src/cstring.h index 12c7df4c..15ecd026 100644 --- a/wrapperhelper/src/cstring.h +++ b/wrapperhelper/src/cstring.h @@ -15,12 +15,14 @@ * string_new_cap ------ Creates a new string with a given capacity. Takes the capacity. * string_new_cstr ----- Creates a new string from a given C string. Takes the string. * string_reserve ------ Ensures a string has at least a given capacity. Takes the string and the capacity. + * string_trim --------- Ensures a string has a capacity equal to its length. Takes the string. May reduce the string capacity. * string_del ---------- Frees a string. Takes the string. * string_steal -------- Frees a string, keeping the content alive. Takes the string. The content (also returned) needs to be freed separately. * string_add_char ----- Add a character at the end. Takes the string and the new character. May increase the string capacity. * string_add_string --- Add a string at the end in-place. Takes both strings. May increase the string capacity. * string_add_cstr ----- Add a C string at the end in-place. Takes both strings. May increase the string capacity. * string_pop ---------- Pops the last character. Takes the string. May reduce the string capacity. + * string_clear -------- Clears the string. Takes the string. May reduce the string capacity. * string_dup ---------- Duplicate a string. Takes the string. Does not free the old string. * string_concat ------- Concatenate two strings. Takes both strings. Does not free any string. * string_len ---------- String length. Takes the string. @@ -62,12 +64,14 @@ string_t *string_new(void); string_t *string_new_cap(size_t cap); string_t *string_new_cstr(const char *s); int string_reserve(string_t *s, size_t cap); +int string_trim(string_t *s); void string_del(string_t *s); char *string_steal(string_t *s); int string_add_char(string_t *s, char elem); int string_add_string(string_t *s1, string_t *s2); int string_add_cstr(string_t *s1, const char *s2); void string_pop(string_t *s); +void string_clear(string_t *s); string_t *string_dup(string_t const *s); string_t *string_concat(string_t const *l, string_t const *r); #define string_len(s) ((s)->ssize) diff --git a/wrapperhelper/src/generator.c b/wrapperhelper/src/generator.c index 3df744cb..98e254ed 100644 --- a/wrapperhelper/src/generator.c +++ b/wrapperhelper/src/generator.c @@ -136,7 +136,7 @@ void request_print_check(request_t *req) { } } } -void request_del(request_t *req) { +static void request_del(request_t *req) { string_del(req->obj_name); if (req->has_default) { switch (req->def.rty) { @@ -163,6 +163,16 @@ void request_del(request_t *req) { } } } +static void reference_del(reference_t *ref) { + switch (ref->typ) { + case REF_REQ: + request_del(&ref->req); + break; + case REF_LINE: + string_del(ref->line); + break; + } +} static int valid_reqtype(string_t *t) { const char *s = string_content(t); @@ -244,23 +254,34 @@ static void request_output(FILE *f, request_t *req) { } } } -void output_from_requests(FILE *f, VECTOR(requests) *reqs) { +static void reference_output(FILE *f, reference_t *ref) { + switch (ref->typ) { + case REF_REQ: + request_output(f, &ref->req); + break; + case REF_LINE: + fputs(string_content(ref->line), f); + fputc('\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(requests, req, reqs) { - request_output(f, req); + vector_for(references, req, reqs) { + reference_output(f, req); } } -VECTOR_IMPL(requests, request_del) +VECTOR_IMPL(references, reference_del) -VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { +VECTOR(references) *references_from_file(const char *filename, FILE *f) { prepare_t *prep = prepare_new_file(f, filename); if (!prep) { - printf("Failed to create the prepare structure for the requests file\n"); + printf("Failed to create the prepare structure for the reference file\n"); return NULL; } - VECTOR(requests) *ret = vector_new(requests); + VECTOR(references) *ret = vector_new(references); if (!ret) { prepare_del(prep); return NULL; @@ -273,40 +294,80 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { do { tok = pre_next_token(prep, 0); if (tok.tokt == PPTOK_NEWLINE) ++lineno; + else preproc_token_del(&tok); // NEWLINE has no destructor } while (!preproc_token_isend(&tok) && (lineno < 4)); // TODO: better conditionals handling // Also, for now assume we have no definition int if_depth = 0, entered_depth = 0; + string_t *line = string_new(); + if (!line) { + printf("Error: failed to allocate new string for new reference line\n"); + } + +#define ADD_CHAR(c, has_destr, what) \ + if (!string_add_char(line, c)) { \ + printf("Error: failed to add " what "\n"); \ + if (has_destr) preproc_token_del(&tok); \ + goto failed; \ + } +#define ADD_CSTR(cstr, has_destr, what) \ + if (!string_add_cstr(line, cstr)) { \ + printf("Error: failed to add " what "\n"); \ + if (has_destr) preproc_token_del(&tok); \ + goto failed; \ + } +#define ADD_STR(str, has_destr, what) \ + if (!string_add_string(line, str)) { \ + printf("Error: failed to add " what "\n"); \ + if (has_destr) preproc_token_del(&tok); \ + goto failed; \ + } +#define PUSH_LINE(has_destr) \ + string_trim(line); \ + if (!vector_push(references, ret, ((reference_t){.typ = REF_LINE, .line = line}))) { \ + printf("Error: failed to memorize reference line %d\n", lineno); \ + if (has_destr) preproc_token_del(&tok); \ + goto failed; \ + } \ + line = string_new(); \ + if (!line) { \ + printf("Error: failed to allocate new string for new reference line\n"); \ + } + while (1) { int is_comment = 0; tok = pre_next_token(prep, 1); - while (tok.tokt == PPTOK_START_LINE_COMMENT) { + if (tok.tokt == PPTOK_START_LINE_COMMENT) { + ADD_CSTR("//", 0, "start of comment") is_comment = 1; // Empty destructor - tok = pre_next_token(prep, 1); + tok = pre_next_token(prep, 0); // tok is IDENT, NEWLINE, INVALID or BLANK + while ((tok.tokt == PPTOK_BLANK) && ((tok.tokv.c == ' ') || (tok.tokv.c == '\t'))) { + ADD_CHAR(tok.tokv.c, 0, "start of comment") + // Empty destructor + tok = pre_next_token(prep, 0); // tok is IDENT, NEWLINE, INVALID or BLANK + } } if ((tok.tokt == PPTOK_SYM) && (tok.tokv.sym == SYM_HASH)) { - if (is_comment) { - preproc_token_del(&tok); - tok = pre_next_newline_token(prep); // Returns a newline - ++lineno; - continue; - } + ADD_CHAR('#', 0, "start of preprocessor command") tok = pre_next_token(prep, 0); if (tok.tokt != PPTOK_IDENT) { - printf("Error: invalid requests file: invalid preprocessor line\n"); + 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); if (tok.tokt != PPTOK_IDENT) { - printf("Error: invalid requests file: invalid '#ifdef' line\n"); + printf("Error: invalid reference file: invalid '#ifdef' line\n"); 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); tok = pre_next_token(prep, 0); @@ -314,10 +375,12 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { string_del(tok.tokv.str); tok = pre_next_token(prep, 0); if (tok.tokt != PPTOK_IDENT) { - printf("Error: invalid requests file: invalid '#ifndef' line\n"); + printf("Error: invalid reference file: invalid '#ifndef' line\n"); 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); @@ -333,7 +396,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { if (if_depth == entered_depth) --entered_depth; --if_depth; } else { - printf("Error: invalid requests file: invalid preprocessor command '%s'\n", string_content(tok.tokv.str)); + printf("Error: invalid reference file: invalid preprocessor command '%s'\n", string_content(tok.tokv.str)); string_del(tok.tokv.str); goto failed; } @@ -341,6 +404,7 @@ VECTOR(requests) *requests_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; @@ -350,6 +414,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { } } } else if (tok.tokt == PPTOK_NEWLINE) { + PUSH_LINE(0) ++lineno; } else if (tok.tokt == PPTOK_EOF) { goto success; @@ -362,6 +427,8 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { || !strcmp(string_content(tok.tokv.str), "GOW2") || !strcmp(string_content(tok.tokv.str), "GOWD") || !strcmp(string_content(tok.tokv.str), "GOWM"))) { + string_clear(line); + if (is_comment) prepare_mark_nocomment(prep); int isweak = (string_content(tok.tokv.str)[2] == 'W'); request_t req = { .has_default = 0, @@ -381,14 +448,14 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { string_del(tok.tokv.str); tok = pre_next_token(prep, 0); if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_LPAREN)) { - printf("Error: invalid requests file: invalid GO line %d (lparen)\n", lineno); + printf("Error: invalid reference file: invalid GO line %d (lparen)\n", lineno); preproc_token_del(&tok); goto failed; } // Empty destructor tok = pre_next_token(prep, 0); if (tok.tokt != PPTOK_IDENT) { - printf("Error: invalid requests file: invalid GO line %d (obj_name)\n", lineno); + printf("Error: invalid reference file: invalid GO line %d (obj_name)\n", lineno); preproc_token_del(&tok); goto failed; } @@ -396,7 +463,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { // Token moved tok = pre_next_token(prep, 0); if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_COMMA)) { - printf("Error: invalid requests file: invalid GO line %d (comma)\n", lineno); + printf("Error: invalid reference file: invalid GO line %d (comma)\n", lineno); string_del(req.obj_name); preproc_token_del(&tok); goto failed; @@ -410,7 +477,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { tok = pre_next_token(prep, 0); if ((req.def.rty == RQT_FUN_2) || (req.def.rty == RQT_FUN_D)) { if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_COMMA)) { - printf("Error: invalid requests file: invalid GO line %d (comma 2)\n", lineno); + printf("Error: invalid reference file: invalid GO line %d (comma 2)\n", lineno); string_del(req.obj_name); string_del(req.def.fun.typ); preproc_token_del(&tok); @@ -419,7 +486,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { // Empty destructor tok = pre_next_token(prep, 0); if (tok.tokt != PPTOK_IDENT) { - printf("Error: invalid requests file: invalid GO line %d (redirect)\n", lineno); + printf("Error: invalid reference file: invalid GO line %d (redirect)\n", lineno); string_del(req.obj_name); string_del(req.def.fun.typ); preproc_token_del(&tok); @@ -430,7 +497,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { tok = pre_next_token(prep, 0); } if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_RPAREN)) { - printf("Error: invalid requests file: invalid GO line %d (rparen)\n", lineno); + printf("Error: invalid reference file: invalid GO line %d (rparen)\n", lineno); string_del(req.obj_name); string_del(req.def.fun.typ); if (req.def.fun.fun2) string_del(req.def.fun.fun2); @@ -441,7 +508,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { tok = pre_next_token(prep, 0); } if (tok.tokt != PPTOK_NEWLINE) { - printf("Error: invalid requests file: invalid GO line %d (newline)\n", lineno); + printf("Error: invalid reference file: invalid GO line %d (newline)\n", lineno); 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); @@ -449,14 +516,16 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { goto failed; } if (if_depth == entered_depth) { - if (!vector_push(requests, ret, req)) { - printf("Error: failed to add request for %s\n", string_content(req.obj_name)); + 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); } ++lineno; } else if ((tok.tokt == PPTOK_IDENT) @@ -464,6 +533,8 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { || !strcmp(string_content(tok.tokv.str), "DATAV") || !strcmp(string_content(tok.tokv.str), "DATAB") || !strcmp(string_content(tok.tokv.str), "DATAM"))) { + string_clear(line); + if (is_comment) prepare_mark_nocomment(prep); request_t req = { .has_default = 1, .default_comment = is_comment, @@ -482,14 +553,14 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { string_del(tok.tokv.str); tok = pre_next_token(prep, 0); if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_LPAREN)) { - printf("Error: invalid requests file: invalid DATA line %d (lparen)\n", lineno); + printf("Error: invalid reference file: invalid DATA line %d (lparen)\n", lineno); preproc_token_del(&tok); goto failed; } // Empty destructor tok = pre_next_token(prep, 0); if (tok.tokt != PPTOK_IDENT) { - printf("Error: invalid requests file: invalid DATA line %d (obj_name)\n", lineno); + printf("Error: invalid reference file: invalid DATA line %d (obj_name)\n", lineno); preproc_token_del(&tok); goto failed; } @@ -497,7 +568,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { // Token moved tok = pre_next_token(prep, 0); if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_COMMA)) { - printf("Error: invalid requests file: invalid DATA line %d (comma)\n", lineno); + printf("Error: invalid reference file: invalid DATA line %d (comma)\n", lineno); string_del(req.obj_name); preproc_token_del(&tok); goto failed; @@ -507,7 +578,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { if (tok.tokt == PPTOK_NUM) { num_constant_t cst; if (!num_constant_convert(tok.tokv.str, &cst)) { - printf("Error: invalid requests file: invalid DATA line %d (num conversion)\n", lineno); + printf("Error: invalid reference file: invalid DATA line %d (num conversion)\n", lineno); string_del(req.obj_name); preproc_token_del(&tok); goto failed; @@ -516,9 +587,9 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { case NCT_FLOAT: case NCT_DOUBLE: case NCT_LDOUBLE: - printf("Error: invalid requests file: invalid DATA line %d (num conversion)\n", lineno); + printf("Error: invalid reference file: invalid DATA line %d (num conversion)\n", lineno); string_del(req.obj_name); - preproc_token_del(&tok); + string_del(tok.tokv.str); goto failed; case NCT_INT32: req.def.dat.sz = (size_t)cst.val.i32; break; case NCT_UINT32: req.def.dat.sz = (size_t)cst.val.u32; break; @@ -526,10 +597,10 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { case NCT_UINT64: req.def.dat.sz = (size_t)cst.val.u64; break; } req.def.dat.has_size = 1; - // Token moved + string_del(tok.tokv.str); // Delete token tok = pre_next_token(prep, 0); if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_RPAREN)) { - printf("Error: invalid requests file: invalid DATA line %d (rparen)\n", lineno); + printf("Error: invalid reference file: invalid DATA line %d (rparen)\n", lineno); string_del(req.obj_name); preproc_token_del(&tok); goto failed; @@ -538,28 +609,41 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { tok = pre_next_token(prep, 0); } if (tok.tokt != PPTOK_NEWLINE) { - printf("Error: invalid requests file: invalid DATA line %d (newline)\n", lineno); + printf("Error: invalid reference file: invalid DATA line %d (newline)\n", lineno); string_del(req.obj_name); preproc_token_del(&tok); goto failed; } if (if_depth == entered_depth) { - if (!vector_push(requests, ret, req)) { - printf("Error: failed to add request for %s\n", string_content(req.obj_name)); - string_del(req.obj_name); + 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 { + request_del(&req); } ++lineno; - } else { - if (is_comment) { + } else if (is_comment) { + if (tok.tokt == PPTOK_IDENT) { + ADD_STR(tok.tokv.str, 1, "comment content") + string_del(tok.tokv.str); + } else if (tok.tokt == PPTOK_BLANK) { + ADD_CHAR(tok.tokv.c, 0, "comment content") + } else { + printf("Error: unknown token type in comment %u\n", tok.tokt); preproc_token_del(&tok); - tok = pre_next_newline_token(prep); // Returns a newline - ++lineno; - continue; + goto failed; } - printf("Error: invalid requests file: invalid token:\n"); + if (!pre_next_newline_token(prep, line)) { + printf("Error: failed to add comment content\n"); + goto failed; + } + PUSH_LINE(0) + ++lineno; + } else { + printf("Error: invalid reference file: invalid token:\n"); preproc_token_print(&tok); preproc_token_del(&tok); goto failed; @@ -567,11 +651,13 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) { } failed: + string_del(line); prepare_del(prep); - vector_del(requests, ret); + vector_del(references, ret); return NULL; success: + string_del(line); prepare_del(prep); return ret; } @@ -692,7 +778,7 @@ 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_VA_LIST: has_char = 1; c = 'A'; 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); return 0; @@ -847,6 +933,7 @@ 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; @@ -913,10 +1000,11 @@ int solve_request_map(request_t *req, khash_t(type_map) *decl_map) { } return solve_request(req, kh_val(decl_map, it)); } -int solve_requests(VECTOR(requests) *reqs, khash_t(type_map) *decl_map) { +int solve_references(VECTOR(references) *refs, khash_t(type_map) *decl_map) { int ret = 1; - vector_for(requests, req, reqs) { - if (!solve_request_map(req, decl_map)) ret = 0; + vector_for(references, ref, refs) { + if (ref->typ != REF_REQ) continue; + if (!solve_request_map(&ref->req, decl_map)) ret = 0; } return ret; } diff --git a/wrapperhelper/src/generator.h b/wrapperhelper/src/generator.h index ef27ad0a..fd41862d 100644 --- a/wrapperhelper/src/generator.h +++ b/wrapperhelper/src/generator.h @@ -37,14 +37,24 @@ typedef struct request_s { }; } def, val; } request_t; -VECTOR_DECLARE(requests, request_t) +typedef struct reference_s { + enum { + REF_REQ, + REF_LINE, + } typ; + union { + request_t req; + string_t *line; + }; +} reference_t; +VECTOR_DECLARE(references, reference_t) void request_print(request_t *req); void request_print_check(request_t *req); -void output_from_requests(FILE *f, VECTOR(requests) *reqs); +void output_from_references(FILE *f, VECTOR(references) *reqs); -VECTOR(requests) *requests_from_file(const char *filename, FILE *f); // Takes ownership of f +VECTOR(references) *references_from_file(const char *filename, FILE *f); // Takes ownership of f int solve_request(request_t *req, type_t *typ); int solve_request_map(request_t *req, khash_t(type_map) *decl_map); -int solve_requests(VECTOR(requests) *reqs, khash_t(type_map) *decl_map); +int solve_references(VECTOR(references) *reqs, khash_t(type_map) *decl_map); #endif // GENERATOR_H diff --git a/wrapperhelper/src/lang.c b/wrapperhelper/src/lang.c index 1c4cba6c..3e9f2a78 100644 --- a/wrapperhelper/src/lang.c +++ b/wrapperhelper/src/lang.c @@ -349,9 +349,9 @@ int init_str2kw(void) { printf("Failed to create the string to keyword map (init)\n"); return 0; } + int iret; khiter_t it; for (enum token_keyword_type_e kw = 0; kw <= LAST_KEYWORD; ++kw) { - int iret; - khiter_t it = kh_put(str2kw, str2kw, kw2str[kw], &iret); + it = kh_put(str2kw, str2kw, kw2str[kw], &iret); if (iret < 0) { printf("Failed to create the string to keyword map (keyword %u)\n", kw); kh_destroy(str2kw, str2kw); @@ -359,6 +359,35 @@ int init_str2kw(void) { } kh_val(str2kw, it) = kw; } +#define ADD_ALIAS(alias, k) \ + it = kh_put(str2kw, str2kw, #alias, &iret); \ + if (iret < 0) { \ + printf("Failed to create the string to keyword map (keyword alias " #alias ")\n"); \ + kh_destroy(str2kw, str2kw); \ + return 0; \ + } \ + kh_val(str2kw, it) = KW_ ## k; + ADD_ALIAS(__alignof__, ALIGNOF) + // ADD_ALIAS(__asm, asm) + // ADD_ALIAS(__asm__, asm) + ADD_ALIAS(__complex, COMPLEX) + ADD_ALIAS(__complex__, COMPLEX) + ADD_ALIAS(__const, CONST) + ADD_ALIAS(__const__, CONST) + // ADD_ALIAS(__decltype, decltype) + // ADD_ALIAS(__imag__, __imag) + ADD_ALIAS(__inline, INLINE) + ADD_ALIAS(__inline__, INLINE) + // ADD_ALIAS(__nullptr, nullptr) + // ADD_ALIAS(__real__, __real) + ADD_ALIAS(__restrict, RESTRICT) + ADD_ALIAS(__restrict__, RESTRICT) + ADD_ALIAS(__signed, SIGNED) + ADD_ALIAS(__signed__, SIGNED) + // ADD_ALIAS(__typeof, typeof) + // ADD_ALIAS(__typeof__, typeof) + ADD_ALIAS(__volatile, VOLATILE) + ADD_ALIAS(__volatile__, VOLATILE) return 1; } void del_str2kw(void) { @@ -1109,7 +1138,7 @@ file_t *file_new(void) { } // Now fill in the builtin types - int iret; + int iret; khiter_t it; for (enum type_builtin_e i = 0; i < LAST_BUILTIN + 1; ++i) { type_t *t = malloc(sizeof *t); if (!t) { @@ -1162,26 +1191,33 @@ file_t *file_new(void) { } // ret is valid - // Add __builtin_va_list as a typedef - char *sdup = strdup("__builtin_va_list"); - if (!sdup) { - printf("Failed to create a new translation unit structure (va_list name)\n"); - file_del(ret); - return NULL; - } - khiter_t it = kh_put(type_map, ret->type_map, sdup, &iret); - if (iret < 0) { - printf("Failed to create a new translation unit structure (add va_list typedef)\n"); - free(sdup); - file_del(ret); - return NULL; - } else if (iret == 0) { - printf("Failed to create a new translation unit structure (__builtin_va_list is already a typedef)\n"); - file_del(ret); - return NULL; - } - kh_val(ret->type_map, it) = ret->builtins[BTT_VA_LIST]; - ++ret->builtins[BTT_VA_LIST]->nrefs; + // Add __builtin_va_list, __int128_t, __uint128_t as typedef + char *sdup; +#define ADD_TYPEDEF(name, btt) \ + sdup = strdup(#name); \ + if (!sdup) { \ + printf("Failed to create a new translation unit structure (" #name " name)\n"); \ + file_del(ret); \ + return NULL; \ + } \ + it = kh_put(type_map, ret->type_map, sdup, &iret); \ + if (iret < 0) { \ + printf("Failed to create a new translation unit structure (add " #name " typedef)\n"); \ + free(sdup); \ + file_del(ret); \ + return NULL; \ + } else if (iret == 0) { \ + printf("Failed to create a new translation unit structure (" #name " is already a typedef)\n"); \ + free(sdup); \ + file_del(ret); \ + return NULL; \ + } \ + kh_val(ret->type_map, it) = ret->builtins[BTT_ ## btt]; \ + ++ret->builtins[BTT_ ## btt]->nrefs; + + ADD_TYPEDEF(__builtin_va_list, VA_LIST) + ADD_TYPEDEF(__int128_t, INT128) + ADD_TYPEDEF(__uint128_t, UINT128) return ret; } diff --git a/wrapperhelper/src/machine.c b/wrapperhelper/src/machine.c index bd209bb6..7637a5d3 100644 --- a/wrapperhelper/src/machine.c +++ b/wrapperhelper/src/machine.c @@ -11,18 +11,23 @@ machine_t machine_x86_64; #define STRINGIFY2(a) #a #define STRINGIFY(a) STRINGIFY2(a) #define MACHINE_STR STRINGIFY(CUR_MACHINE) -#define EXTRA_PATHS \ - PASTE(machine_, CUR_MACHINE).npaths = PASTE(CUR_MACHINE, _NPATHS) + npaths; \ - if (!(PASTE(machine_, CUR_MACHINE).include_path = \ - malloc((PASTE(CUR_MACHINE, _NPATHS) + 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)); \ - } \ - for (failure_id = 0; failure_id < npaths; ++failure_id) { \ - if (!(PASTE(machine_, CUR_MACHINE).include_path[failure_id] = strdup(extra_include_path[failure_id]))) { \ - printf("Failed to add include path to " MACHINE_STR " platform\n"); \ - goto PASTE(failed_, PASTE(CUR_MACHINE, _paths)); \ - } \ +#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 ADD_PATH(path) \ if (!(PASTE(machine_, CUR_MACHINE).include_path[failure_id] = strdup(path))) { \ @@ -97,13 +102,14 @@ int init_machines(size_t npaths, const char *const *extra_include_path) { #pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" #define CUR_MACHINE x86_64 machine_x86_64.size_long = 8; -#define x86_64_NPATHS 5 - EXTRA_PATHS - ADD_PATH("include-fixed") - ADD_PATH("/usr/lib/gcc/x86_64-pc-linux-gnu/14.2.1/include") - ADD_PATH("/usr/local/include") - ADD_PATH("/usr/lib/gcc/x86_64-pc-linux-gnu/14.2.1/include-fixed") - ADD_PATH("/usr/include") + 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__) diff --git a/wrapperhelper/src/main.c b/wrapperhelper/src/main.c index ffe09146..1b5b2db2 100644 --- a/wrapperhelper/src/main.c +++ b/wrapperhelper/src/main.c @@ -12,12 +12,13 @@ static void help(char *arg0) { printf("Usage: %s --help\n" - " %s [--prepare|--preproc|--proc] <filename_in>\n" - " %s <filename_in> <filename_reqs> <filename_out>\n" + " %s {-I/path/to/include}* [--prepare|--preproc|--proc] <filename_in>\n" + " %s {-I/path/to/include}* <filename_in> <filename_reqs> <filename_out>\n" "\n" " --prepare Dump all preprocessor tokens (prepare phase)\n" " --preproc Dump all processor tokens (preprocessor phase)\n" " --proc Dump all typedefs, declarations and constants (processor phase)\n" + " -I Add a path to the list of system includes\n" "\n" " <filename_in> Parsing file\n" " <filename_reqs> Reference file (example: wrappedlibc_private.h)\n" @@ -53,11 +54,14 @@ int main(int argc, char **argv) { ms = MAIN_PREPROC; } else if (!strcmp(argv[i], "--proc")) { ms = MAIN_PROC; + } else if (!strcmp(argv[i], "-pthread")) { + // Ignore } else if (!strcmp(argv[i], "-I") && (i + 1 < argc)) { if (!vector_push(charp, paths, argv[i + 1])) { printf("Error: failed to add path to buffer\n"); return 2; } + ++i; } else if ((argv[i][0] == '-') && (argv[i][1] == 'I') && (argv[i][2] != '\0')) { if (!vector_push(charp, paths, argv[i] + 2)) { printf("Error: failed to add path to buffer\n"); @@ -127,31 +131,31 @@ int main(int argc, char **argv) { del_str2kw(); return 2; } - VECTOR(requests) *reqs = requests_from_file(ref_file, ref); + VECTOR(references) *reqs = references_from_file(ref_file, ref); if (!reqs) { file_del(content); del_machines(); del_str2kw(); return 2; } - // vector_for(requests, req, reqs) request_print(req); - if (!solve_requests(reqs, content->decl_map)) { + // vector_for(references, req, reqs) request_print(req); + if (!solve_references(reqs, content->decl_map)) { printf("Warning: failed to solve all default requests\n"); } - // vector_for(requests, req, reqs) request_print(req); - //vector_for(requests, req, reqs) request_print_check(req); + // vector_for(references, req, reqs) request_print(req); + //vector_for(references, req, reqs) request_print_check(req); FILE *out = fopen(out_file, "w"); if (!out) { err(2, "Error: failed to open %s", ref_file); file_del(content); - vector_del(requests, reqs); + vector_del(references, reqs); del_machines(); del_str2kw(); return 2; } - output_from_requests(out, reqs); + output_from_references(out, reqs); fclose(out); - vector_del(requests, reqs); + vector_del(references, reqs); file_del(content); del_machines(); del_str2kw(); diff --git a/wrapperhelper/src/parse.c b/wrapperhelper/src/parse.c index 83167bd9..cce0a115 100644 --- a/wrapperhelper/src/parse.c +++ b/wrapperhelper/src/parse.c @@ -685,6 +685,30 @@ expr_new_token: string_del(tok->tokv.str); *tok = proc_next_token(prep); goto expr_new_token; + } else if ((tok->tokt == PTOK_STRING) && !tok->tokv.sisstr) { + if (has_level != -1) { + printf("Error: invalid expression: unexpected character constant '%s'\n", string_content(tok->tokv.sstr)); + string_del(tok->tokv.sstr); + goto failed; + } + if (string_len(tok->tokv.sstr) != 1) { + printf("Error: TODO: invalid expression: multibyte character constant '%s'\n", string_content(tok->tokv.sstr)); + string_del(tok->tokv.sstr); + goto failed; + } + has_level = 0; + e = malloc(sizeof *e); + if (!e) { + printf("Error: failed to create new expression atom\n"); + string_del(tok->tokv.sstr); + goto failed; + } + e->typ = ETY_CONST; + e->val.cst.typ = NCT_INT32; + e->val.cst.val.i32 = (int32_t)string_content(tok->tokv.sstr)[0]; + string_del(tok->tokv.sstr); + *tok = proc_next_token(prep); + goto expr_new_token; } #define UNOP(toksym, opt, main_lv, right_lv) \ @@ -1397,6 +1421,18 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan if (e->val.cast.typ->typ == TYPE_BUILTIN) { switch (e->val.cast.typ->val.builtin) { + case BTT_UCHAR: + switch (dest->typ) { + case NCT_FLOAT: dest->val.u32 = (uint8_t)dest->val.f; break; + case NCT_DOUBLE: dest->val.u32 = (uint8_t)dest->val.d; break; + case NCT_LDOUBLE: dest->val.u32 = (uint8_t)dest->val.l; break; + case NCT_INT32: dest->val.u32 = (uint8_t)dest->val.i32; break; + case NCT_UINT32: dest->val.u32 = (uint8_t)dest->val.u32; break; + case NCT_INT64: dest->val.u32 = (uint8_t)dest->val.i64; break; + case NCT_UINT64: dest->val.u32 = (uint8_t)dest->val.u64; break; + } + dest->typ = NCT_UINT32; + return 1; case BTT_INT: switch (dest->typ) { case NCT_FLOAT: dest->val.i32 = (int32_t)dest->val.f; break; @@ -1409,11 +1445,35 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan } dest->typ = NCT_INT32; return 1; + case BTT_ULONG: + // Warning: assuming sizeof(long) == 8 on the current target + switch (dest->typ) { + case NCT_FLOAT: dest->val.u64 = (uint64_t)dest->val.f; break; + case NCT_DOUBLE: dest->val.u64 = (uint64_t)dest->val.d; break; + case NCT_LDOUBLE: dest->val.u64 = (uint64_t)dest->val.l; break; + case NCT_INT32: dest->val.u64 = (uint64_t)dest->val.i32; break; + case NCT_UINT32: dest->val.u64 = (uint64_t)dest->val.u32; break; + case NCT_INT64: dest->val.u64 = (uint64_t)dest->val.i64; break; + case NCT_UINT64: break; + } + dest->typ = NCT_UINT64; + return 1; + case BTT_U32: + switch (dest->typ) { + case NCT_FLOAT: dest->val.u32 = (uint32_t)dest->val.f; break; + case NCT_DOUBLE: dest->val.u32 = (uint32_t)dest->val.d; break; + case NCT_LDOUBLE: dest->val.u32 = (uint32_t)dest->val.l; break; + case NCT_INT32: dest->val.u32 = (uint32_t)dest->val.i32; break; + case NCT_UINT32: break; + case NCT_INT64: dest->val.u32 = (uint32_t)dest->val.i64; break; + case NCT_UINT64: dest->val.u32 = (uint32_t)dest->val.u64; break; + } + dest->typ = NCT_UINT32; + return 1; case BTT_VOID: case BTT_BOOL: case BTT_CHAR: case BTT_SCHAR: - case BTT_UCHAR: case BTT_SHORT: case BTT_SSHORT: case BTT_USHORT: @@ -1421,7 +1481,6 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case BTT_UINT: case BTT_LONG: case BTT_SLONG: - case BTT_ULONG: case BTT_LONGLONG: case BTT_SLONGLONG: case BTT_ULONGLONG: @@ -1433,7 +1492,6 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case BTT_S16: case BTT_U16: case BTT_S32: - case BTT_U32: case BTT_S64: case BTT_U64: case BTT_FLOAT: @@ -1447,7 +1505,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case BTT_ILONGDOUBLE: case BTT_VA_LIST: default: - printf("Error: TODO: cast to builtin in constant expression\n"); + printf("Error: TODO: cast to builtin %s in constant expression\n", builtin2str[e->val.cast.typ->val.builtin]); return 0; } } else { diff --git a/wrapperhelper/src/prepare.c b/wrapperhelper/src/prepare.c index 994d8292..616f2332 100644 --- a/wrapperhelper/src/prepare.c +++ b/wrapperhelper/src/prepare.c @@ -14,6 +14,7 @@ struct prepare_s { PREPST_INCL, PREPST_DEF, PREPST_DEFID, + PREPST_COMMENT, } st; }; @@ -154,6 +155,37 @@ static const struct symbs_s { }; preproc_token_t pre_next_token(prepare_t *src, int allow_comments) { + if (src->st == PREPST_COMMENT) { + // In comments, keep everything as 'BLANK' except for idents, newlines and EOF + int c = get_char(src); + if (c == EOF) { + // Force newline at EOF + unget_char(src, c); + src->st = PREPST_NL; + return (preproc_token_t){ + .tokt = PPTOK_NEWLINE, + .tokv.c = (char)c + }; + } else if ((c == '_') || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) { + preproc_token_t ret; + ret.tokt = PPTOK_IDENT; + ret.tokv.str = string_new_cap(1); + string_add_char(ret.tokv.str, (char)c); + fill_ident(src, ret.tokv.str); + return ret; + } else if ((c >= 0) && (c <= 0x7F)) { + return (preproc_token_t){ + .tokt = PPTOK_BLANK, + .tokv.c = (char)c + }; + } else { + return (preproc_token_t){ + .tokt = PPTOK_INVALID, + .tokv.c = (char)c + }; + } + } + start_next_token: int c = get_char(src); if (c == EOF) { @@ -259,7 +291,7 @@ start_next_token: c = get_char(src); if (c == '/') { if (allow_comments) { - src->st = PREPST_NONE; + src->st = PREPST_COMMENT; return (preproc_token_t){ .tokt = PPTOK_START_LINE_COMMENT, .tokv.c = '/' @@ -288,6 +320,14 @@ start_next_token: .tokv.c = (char)c }; } else if (c == '*') { + if (allow_comments) { + printf("Unsupported multiline comment with allow_comment in %s\n", src->srcn); + return (preproc_token_t){ + .tokt = PPTOK_INVALID, + .tokv.c = (char)c + }; + } + c = get_char(src); int last_star = 0; while ((c != EOF) && (!last_star || (c != '/'))) { @@ -349,24 +389,26 @@ start_next_token: .tokv.c = (char)c }; } -preproc_token_t pre_next_newline_token(prepare_t *src) { -start_next_token: - int c = get_char(src); - if (c == EOF) { - // Force newline at EOF - unget_char(src, c); - src->st = PREPST_NL; - return (preproc_token_t){ - .tokt = PPTOK_NEWLINE, - .tokv.c = (char)c - }; - } - if (c == '\n') { - src->st = PREPST_NL; - return (preproc_token_t){ - .tokt = PPTOK_NEWLINE, - .tokv.c = (char)c - }; + +// Warning: unsafe method +void prepare_mark_nocomment(prepare_t *src) { + src->st = PREPST_NONE; +} +int pre_next_newline_token(prepare_t *src, string_t *buf) { + while (1) { + int c = get_char(src); + if (c == EOF) { + // Force newline at EOF + unget_char(src, c); + src->st = PREPST_NL; + return 1; + } else if (c == '\n') { + src->st = PREPST_NL; + return 1; + } else if ((c >= 0) && (c <= 0x7F)) { + if (!string_add_char(buf, (char)c)) return 0; + } else { + return 0; + } } - goto start_next_token; } diff --git a/wrapperhelper/src/prepare.h b/wrapperhelper/src/prepare.h index ccb57a5f..c8424261 100644 --- a/wrapperhelper/src/prepare.h +++ b/wrapperhelper/src/prepare.h @@ -13,6 +13,8 @@ typedef struct prepare_s prepare_t; prepare_t *prepare_new_file(FILE *f, const char *filename); // Takes ownership of f void prepare_del(prepare_t *src); preproc_token_t pre_next_token(prepare_t *src, int allow_comments); -preproc_token_t pre_next_newline_token(prepare_t *src); // In a comment ignore everything until the EOL or EOF + +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 #endif // PREPARE_H diff --git a/wrapperhelper/src/preproc.c b/wrapperhelper/src/preproc.c index cdff0a4e..fddf2d1c 100644 --- a/wrapperhelper/src/preproc.c +++ b/wrapperhelper/src/preproc.c @@ -1000,6 +1000,7 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const #define OPLVL_MUL 2 #define OPLVL_DIV 2 +#define OPLVL_MOD 2 #define OPLVL_ADD 3 #define OPLVL_SUB 3 #define OPLVL_LSL 4 @@ -1017,6 +1018,7 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const #define OPLVL_BOR 11 // Boolean #define OPTYP_MUL 1 #define OPTYP_DIV 2 +#define OPTYP_MOD 3 #define OPTYP_ADD 1 #define OPTYP_SUB 2 #define OPTYP_LSL 1 @@ -1188,6 +1190,16 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret) { op_typ = OPTYP_DIV; break; } + case SYM_PERCENT: + // Binary (st0 != 0) + if (vector_last(ppeaux, stack).st0 == 0) { + printf("Invalid %snary '%s' in #if expression\n", "bi", sym2str[tok->tokv.sym]); + goto eval_fail; + } else { + op_lvl = OPLVL_MOD; + op_typ = OPTYP_MOD; + break; + } case SYM_HAT: // Binary (st0 != 0) if (vector_last(ppeaux, stack).st0 == 0) { @@ -1360,6 +1372,13 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret) { } acc = vector_last(ppeaux, stack).v2 / acc; vector_last(ppeaux, stack).st2 = 0; + } else if (vector_last(ppeaux, stack).st2 == OPTYP_MOD) { + if (!acc) { + printf("Error: division by zero\n"); + goto eval_fail; + } + acc = vector_last(ppeaux, stack).v2 % acc; + vector_last(ppeaux, stack).st2 = 0; } else if (vector_last(ppeaux, stack).st2) { printf("<internal error> Unknown st2 %d during #if evaluation\n", vector_last(ppeaux, stack).st2); goto eval_fail; @@ -1518,7 +1537,6 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret) { case SYM_VARIADIC: case SYM_DOT: case SYM_DASHGT: - case SYM_PERCENT: case SYM_EQ: case SYM_PLUSEQ: case SYM_DASHEQ: @@ -1558,6 +1576,13 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret) { } acc = vector_last(ppeaux, stack).v2 / acc; vector_last(ppeaux, stack).st2 = 0; + } else if (vector_last(ppeaux, stack).st2 == OPTYP_MOD) { + if (!acc) { + printf("Error: division by zero\n"); + goto eval_fail; + } + acc = vector_last(ppeaux, stack).v2 % acc; + vector_last(ppeaux, stack).st2 = 0; } else if (vector_last(ppeaux, stack).st2) { printf("<internal error> Unknown st2 %d during #if evaluation\n", vector_last(ppeaux, stack).st2); goto eval_fail; @@ -1793,6 +1818,13 @@ done_complete_stack: } acc = vector_last(ppeaux, stack).v2 / acc; vector_last(ppeaux, stack).st2 = 0; + } else if (vector_last(ppeaux, stack).st2 == OPTYP_MOD) { + if (!acc) { + printf("Error: division by zero\n"); + goto eval_fail; + } + acc = vector_last(ppeaux, stack).v2 % acc; + vector_last(ppeaux, stack).st2 = 0; } else if (vector_last(ppeaux, stack).st2) { printf("<internal error> Unknown st2 %d during #if evaluation\n", vector_last(ppeaux, stack).st2); goto eval_fail; @@ -2068,6 +2100,7 @@ check_if_depth: // Forbidding this code would require another 64-bits bitfield, which is redundant, thus not implemented. // Also, we only need to goto check_if_depth if we actually update ok_depth if ((ppsrc->srcv.prep.ok_depth == ppsrc->srcv.prep.cond_depth - 1) && !ppsrc->srcv.prep.entered_next_ok_cond) { + vector_last(ppsource, src->prep).srcv.prep.entered_next_ok_cond = 1; ++ppsrc->srcv.prep.ok_depth; goto preproc_ignore_remaining_goto; } else goto preproc_ignore_remaining; @@ -2297,7 +2330,7 @@ start_cur_token: if (tok.tokt == PPTOK_INCL) { incl_file = tok.tokv.sstr; // Assume we only have one #include "..." path, so include_next is always a system include - is_sys = is_next || src->is_sys || !tok.tokv.sisstr; + is_sys = is_next || !tok.tokv.sisstr; tok = ppsrc_next_token(src); // Token was moved while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { printf("Warning: ignored tokens after #include directive (%s)\n", src->cur_file); @@ -2435,7 +2468,6 @@ start_cur_token: src->st = PPST_NONE; ret.tokt = PTOK_INVALID; ret.tokv = (union proc_token_val_u){.c = tok.tokv.sisstr ? '<' : '"'}; - string_del(tok.tokv.sstr); return ret; } string_del(incl_file); @@ -3133,7 +3165,7 @@ proc_token_t proc_next_token(preproc_t *src) { if ((ret.tokt == PTOK_STRING) && ret.tokv.sisstr) { while (1) { proc_token_t ret2 = proc_next_token_aux(src); - if ((ret.tokt == PTOK_STRING) && ret.tokv.sisstr) { + if ((ret2.tokt == PTOK_STRING) && ret2.tokv.sisstr) { if (!string_add_string(ret.tokv.sstr, ret2.tokv.sstr)) { printf("Error: failed to concatenate adjacent strings\n"); string_del(ret.tokv.sstr); diff --git a/wrapperhelper/src/vector.c b/wrapperhelper/src/vector.c index dffcb493..c3f710d7 100644 --- a/wrapperhelper/src/vector.c +++ b/wrapperhelper/src/vector.c @@ -40,6 +40,7 @@ int vector_reserve_impl(VECTOR(voidp) *v, size_t elem_size, size_t cap) { } int vector_trim_impl(VECTOR(voidp) *v, size_t elem_size) { + if (v->vsize == v->vcap) return 1; if (v->vsize) { void *new_content_v = realloc(v->content_v, elem_size * v->vsize); if (!new_content_v) return 0; diff --git a/wrapperhelper/src/vector.h b/wrapperhelper/src/vector.h index 70319cc2..6e0c124a 100644 --- a/wrapperhelper/src/vector.h +++ b/wrapperhelper/src/vector.h @@ -26,7 +26,7 @@ * vector_new --------------- Creates a new vector. Takes the name. * vector_new_cap ----------- Creates a new vector with a given capacity. Takes the name and the capacity. * vector_reserve ----------- Ensures a vector has at least a given capacity. Takes the name, the vector and the capacity. May not reduce the vector capacity. - * vector_trim -------------- Ensures a vector has a capacity equal to its size. Takes the name, the vector. May reduce the vector capacity. + * vector_trim -------------- Ensures a vector has a capacity equal to its size. Takes the name and the vector. May reduce the vector capacity. * vector_del --------------- Frees a vector. Takes the name and the vector. Destructs the content of the vector. * vector_steal ------------- Frees a vector and returns the content. Takes the name and the vector. May reduce the vector capacity. * vector_del_freed --------- Frees a vector without freeing the content. Takes the name and the vector. Does not interact with the content of the vector. |