mirror of
https://github.com/ptitSeb/box64.git
synced 2024-11-23 06:30:22 +00:00
[WRAPPERHELPER] General improvements (#1804)
* [WRAPPERHELPER] Automatic headers detection, various bug fixes, added some cast support * [WRAPPERHELPER] Keep comments untouched
This commit is contained in:
parent
e087e7782c
commit
f30d75ae5d
1
.gitignore
vendored
1
.gitignore
vendored
@ -67,6 +67,7 @@ backup/
|
||||
/wrapperhelper/sanaddress
|
||||
/wrapperhelper/sanleak
|
||||
/wrapperhelper/sanundefined
|
||||
/wrapperhelper/src/machine.gen
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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__)
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user