[WRAPPERHELPER] General improvements (#1804)

* [WRAPPERHELPER] Automatic headers detection, various bug fixes, added some cast support

* [WRAPPERHELPER] Keep comments untouched
This commit is contained in:
rajdakin 2024-09-07 20:53:51 +02:00 committed by GitHub
parent e087e7782c
commit f30d75ae5d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 448 additions and 167 deletions

1
.gitignore vendored
View File

@ -67,6 +67,7 @@ backup/
/wrapperhelper/sanaddress
/wrapperhelper/sanleak
/wrapperhelper/sanundefined
/wrapperhelper/src/machine.gen
# macOS
.DS_Store

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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__)

View File

@ -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();

View File

@ -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 {

View File

@ -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
};
}
goto start_next_token;
// 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;
}
}
}

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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.