diff options
| author | rajdakin <rajdakin@gmail.com> | 2024-09-30 12:31:45 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-30 12:31:45 +0200 |
| commit | 4715ef2633534a0427a1e92006a09fde5c3faf44 (patch) | |
| tree | b3fe587555e1979d48df6666533f11496161b859 /wrapperhelper/src/preproc.c | |
| parent | 703d19b256bc533d73cf4f206e5c443579aaf4c1 (diff) | |
| download | box64-4715ef2633534a0427a1e92006a09fde5c3faf44.tar.gz box64-4715ef2633534a0427a1e92006a09fde5c3faf44.zip | |
[WRAPPERHELPER] Added box32 and line number support in the wrapperhelper (#1890)
Diffstat (limited to 'wrapperhelper/src/preproc.c')
| -rw-r--r-- | wrapperhelper/src/preproc.c | 1757 |
1 files changed, 916 insertions, 841 deletions
diff --git a/wrapperhelper/src/preproc.c b/wrapperhelper/src/preproc.c index bbef6844..10ac978b 100644 --- a/wrapperhelper/src/preproc.c +++ b/wrapperhelper/src/preproc.c @@ -10,6 +10,10 @@ #include "machine.h" #include "prepare.h" +//#define LOG_OPEN +//#define LOG_INCLUDE +//#define LOG_CLOSE + typedef struct mtoken_s { enum mtoken_e { MTOK_TOKEN, @@ -79,7 +83,7 @@ static mtoken_t *mtoken_new_concat(mtoken_t *l, mtoken_t *r) { // Takes ownershi return ret; } -static inline void print_macro_tok(mtoken_t *m) { +static inline void macro_tok_print(mtoken_t *m) { switch (m->typ) { case MTOK_TOKEN: printf("token type %u", m->val.tok.tokt); @@ -94,9 +98,9 @@ static inline void print_macro_tok(mtoken_t *m) { case MTOK_CONCAT: printf("concat {"); - print_macro_tok(m->val.concat.l); + macro_tok_print(m->val.concat.l); printf("} {"); - print_macro_tok(m->val.concat.r); + macro_tok_print(m->val.concat.r); printf("}"); return; @@ -261,7 +265,9 @@ static int try_open_dir(preproc_t *src, string_t *filename) { } strcpy(fn + incl_len + 1, string_content(filename)); FILE *f = fopen(fn, "r"); - // printf("Trying %s: %p\n", fn, f); +#ifdef LOG_OPEN + printf("Trying %s: %p\n", fn, f); +#endif int ret; if (f) { char *new_dirname = strchr(fn, '/') ? strndup(fn, (size_t)(strrchr(fn, '/') - fn)) : NULL; @@ -288,7 +294,9 @@ static int try_open_sys(preproc_t *src, string_t *filename, size_t array_off) { fn[incl_len] = '/'; strcpy(fn + incl_len + 1, string_content(filename)); FILE *f = fopen(fn, "r"); - // printf("Trying %s: %p\n", fn, f); +#ifdef LOG_OPEN + printf("Trying %s: %p\n", fn, f); +#endif if (f) { char *new_dirname = strchr(fn, '/') ? strndup(fn, (size_t)(strrchr(fn, '/') - fn)) : NULL; int ret = vector_push(ppsource, src->prep, PREPARE_NEW_FILE(f, fn, src->cur_file, src->dirname, src->is_sys, src->cur_pathno)); @@ -365,12 +373,12 @@ preproc_t *preproc_new_file(machine_t *target, FILE *f, char *dirname, const cha // Also include 'stdc-predef.h' (it will be parsed before the requested file) string_t *stdc_predef = string_new_cstr("stdc-predef.h"); if (!stdc_predef) { - printf("Error: failed to create new string 'stdc-predef.h'\n"); + log_memory("failed to create new string 'stdc-predef.h'\n"); preproc_del(ret); return NULL; } if (!try_open_sys(ret, stdc_predef, 0)) { - printf("Error: failed to open file 'stdc-predef.h'\n"); + log_error_nopos("failed to open file 'stdc-predef.h'\n"); string_del(stdc_predef); preproc_del(ret); return NULL; @@ -387,22 +395,24 @@ static void preprocs_del(VECTOR(preproc) **p) { VECTOR_DECLARE_STATIC(preprocs, VECTOR(preproc)*) VECTOR_IMPL_STATIC(preprocs, preprocs_del) -static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const VECTOR(preproc) *toks, - khash_t(string_set) *solved_macros, khash_t(string_set) *opt_used_macros); +static VECTOR(preproc) *preproc_do_expand(loginfo_t *li, const khash_t(macros_map) *macros, const VECTOR(preproc) *toks, + khash_t(string_set) *solved_macros, khash_t(string_set) *opt_used_macros); // Does not take any ownership, returns a vector with independent ownerships // opt_used_macros is NULL in regular expansion, non-NULL in #if-expansions -static VECTOR(preproc) * - proc_solve_macro(const khash_t(macros_map) *macros, char *mname, const macro_t *m, VECTOR(preprocs) *margs, - khash_t(string_set) *solved_macros, khash_t(string_set) *opt_used_macros); +static VECTOR(preproc) *preproc_solve_macro(loginfo_t *li, + const khash_t(macros_map) *macros, char *mname, const macro_t *m, VECTOR(preprocs) *margs, + khash_t(string_set) *solved_macros, khash_t(string_set) *opt_used_macros); // Moves mname to solved_macros or frees mname, returns a vector with independent ownerships // margs may be NULL if m->is_funlike is false // May change margs if m->has_varargs, but takes no ownership // opt_used_macros is NULL in regular expansion, non-NULL in #if-expansions -static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char *mname, const macro_t *m, VECTOR(preprocs) *margs, - khash_t(string_set) *solved_macros, khash_t(string_set) *opt_used_macros) { +static VECTOR(preproc) *preproc_solve_macro(loginfo_t *li, + const khash_t(macros_map) *macros, char *mname, const macro_t *m, VECTOR(preprocs) *margs, + khash_t(string_set) *solved_macros, khash_t(string_set) *opt_used_macros) { +#define LOG_MEMORY(fmt, ...) log_memory(fmt " while expanding %s\n" __VA_ARGS__, mname) if (m->is_funlike && !margs) { - printf("<internal error: m->is_funlike && !margs>\n"); + log_internal(li, "m->is_funlike && !margs in preproc_solve_macro(... %s ...)\n", mname); free(mname); return NULL; } @@ -410,7 +420,7 @@ static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char && (m->nargs != vector_size(preprocs, margs)) // General case && (!m->has_varargs || (m->nargs > vector_size(preprocs, margs))) // Variadics && (m->nargs || ((vector_size(preprocs, margs) == 1) && (vector_size(preproc, vector_last(preprocs, margs)) == 0)))) { // Zero argument - printf("Invalid argument count for macro %s\n", mname); + log_error(li, "invalid argument count for macro %s\n", mname); free(mname); return NULL; } @@ -420,12 +430,12 @@ static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char // No varargs, so add an empty one VECTOR(preproc) *marg = vector_new(preproc); if (!marg) { - printf("Failed to create __VA_ARGS__ while expanding %s\n", mname); + LOG_MEMORY("failed to create __VA_ARGS__"); free(mname); return NULL; } if (!vector_push(preprocs, margs, marg)) { - printf("Failed to add __VA_ARGS__ while expanding %s\n", mname); + LOG_MEMORY("failed to add __VA_ARGS__"); vector_del(preproc, marg); free(mname); return NULL; @@ -436,13 +446,13 @@ static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char size_t size0 = vector_size(preproc, mvarg); vector_for_from(preprocs, it, margs, m->nargs + 1) { if (!vector_push(preproc, mvarg, ((preproc_token_t){.tokt = PPTOK_SYM, .tokv.sym = SYM_COMMA}))) { - printf("Failed to add comma to __VA_ARGS__ while expanding %s\n", mname); + LOG_MEMORY("failed to add comma to __VA_ARGS__"); vector_pop_nodel_slice(preproc, mvarg, vector_size(preproc, mvarg) - size0); free(mname); return NULL; } if (!vector_push_vec(preproc, mvarg, *it)) { - printf("Failed to add extra argument to __VA_ARGS__ while expanding %s\n", mname); + LOG_MEMORY("failed to add extra argument to __VA_ARGS__"); vector_pop_nodel_slice(preproc, mvarg, vector_size(preproc, mvarg) - size0); free(mname); return NULL; @@ -453,13 +463,13 @@ static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char // Avoid 0-allocations VECTOR(preproc) **margs2 = calloc(margs ? (vector_size(preprocs, margs) ? vector_size(preprocs, margs) : 1) : 1, sizeof *margs2); if (!margs2) { - printf("Memory error while expanding %s\n", mname); + LOG_MEMORY("failed to allocate expanded arguments array"); free(mname); return NULL; } VECTOR(preproc) *ret = vector_new(preproc); if (!ret) { - printf("Memory error while expanding %s\n", mname); + LOG_MEMORY("failed to allocate return vector"); free(margs2); free(mname); return NULL; @@ -467,7 +477,7 @@ static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char VECTOR(mtoken) *st = vector_new_cap(mtoken, vector_size(mtoken, m->toks)); if (!st) { - printf("Memory error while expanding %s\n", mname); + LOG_MEMORY("failed to allocate auxiliary vector"); vector_del(preproc, ret); free(margs2); free(mname); @@ -483,6 +493,7 @@ static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char case MTOK_CONCAT: { vector_last(mtoken, st) = mtok->val.concat.r; if (!vector_push(mtoken, st, mtok->val.concat.l)) { + LOG_MEMORY("failed to add concatenation left m-token"); vector_del(preproc, ret); ret = NULL; goto solve_done; @@ -495,20 +506,32 @@ static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char if (concat_cur == 2) { preproc_token_t *tok1 = &vector_last(preproc, ret); // Guaranteed to exist preproc_token_t *tok2 = &mtok->val.tok; - if (((tok1->tokt == PPTOK_IDENT) || (tok1->tokt == PPTOK_IDENT_UNEXP) || (tok1->tokt == PPTOK_NUM)) - && ((tok2->tokt == PPTOK_IDENT) || (tok2->tokt == PPTOK_IDENT_UNEXP) || (tok2->tokt == PPTOK_NUM))) { +#define ISIDENT(tt) (((tt) == PPTOK_IDENT) || ((tt) == PPTOK_IDENT_UNEXP)) +#define FIND(s, c) strchr(string_content((s)), (c)) +#define ONLYDIGS(s) (!FIND((s), '.') && !FIND((s), '+') && !FIND((s), '-')) + if (ISIDENT(tok1->tokt) && (ISIDENT(tok2->tokt) || ((tok2->tokt == PPTOK_NUM) && ONLYDIGS(tok2->tokv.str)))) { + do_add = 0; + tok1->tokt = PPTOK_IDENT; + if (!string_add_string(tok1->tokv.str, tok2->tokv.str)) { + LOG_MEMORY("failed to concatenate identifiers"); + vector_del(preproc, ret); + ret = NULL; + goto solve_done; + } + } else if ((tok1->tokt == PPTOK_NUM) && (ISIDENT(tok2->tokt) || (tok2->tokt == PPTOK_NUM))) { do_add = 0; - // TODO: check if concat is possible, what behaviour should be in the case below - if (tok1->tokt == PPTOK_IDENT_UNEXP) tok1->tokt = PPTOK_IDENT; if (!string_add_string(tok1->tokv.str, tok2->tokv.str)) { - printf("Memory error while expanding %s\n", mname); + LOG_MEMORY("failed to concatenate identifiers"); vector_del(preproc, ret); ret = NULL; goto solve_done; } } else { - printf("Warning: unsupported concatenation between token type %u and %u while expanding %s\n", tok1->tokt, tok2->tokt, mname); + log_warning(li, "unsupported concatenation between token type %u and %u while expanding %s\n", tok1->tokt, tok2->tokt, mname); } +#undef ISIDENT +#undef FIND +#undef ONLYDIGS } if (do_add) { preproc_token_t tok2; @@ -518,33 +541,34 @@ static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char case PPTOK_NEWLINE: case PPTOK_BLANK: case PPTOK_START_LINE_COMMENT: - case PPTOK_EOF: tok2 = (preproc_token_t){.tokt = tok1->tokt, .tokv.c = tok1->tokv.c}; break; - case PPTOK_SYM: tok2 = (preproc_token_t){.tokt = tok1->tokt, .tokv.sym = tok1->tokv.sym}; break; + case PPTOK_EOF: tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.c = tok1->tokv.c}; break; + case PPTOK_SYM: tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.sym = tok1->tokv.sym}; break; case PPTOK_IDENT: case PPTOK_IDENT_UNEXP: case PPTOK_NUM: { string_t *dup = string_dup(tok1->tokv.str); if (!dup) { - printf("Failed to duplicate string while expanding %s\n", mname); + LOG_MEMORY("failed to duplicate string"); vector_del(preproc, ret); ret = NULL; goto solve_done; } - tok2 = (preproc_token_t){.tokt = tok1->tokt, .tokv.str = dup}; + tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.str = dup}; break; } case PPTOK_INCL: case PPTOK_STRING: { string_t *dup = string_dup(tok1->tokv.sstr); if (!dup) { - printf("Failed to duplicate string while expanding %s\n", mname); + LOG_MEMORY("failed to duplicate string"); vector_del(preproc, ret); ret = NULL; goto solve_done; } - tok2 = (preproc_token_t){.tokt = tok1->tokt, .tokv.sstr = dup, .tokv.sisstr = tok1->tokv.sisstr}; + tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.sstr = dup, .tokv.sisstr = tok1->tokv.sisstr}; break; } } if (!vector_push(preproc, ret, tok2)) { + LOG_MEMORY("failed to add token to output vector"); preproc_token_del(&tok2); vector_del(preproc, ret); ret = NULL; @@ -562,7 +586,12 @@ static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char VECTOR(preproc) *toks_to_add; if (!need_concat && !concat_cur) { if (!margs2[mtok->val.argid]) { - margs2[mtok->val.argid] = proc_do_expand(macros, vector_content(preprocs, margs)[mtok->val.argid], solved_macros, opt_used_macros); + margs2[mtok->val.argid] = preproc_do_expand(li, macros, vector_content(preprocs, margs)[mtok->val.argid], solved_macros, opt_used_macros); + if (!margs2[mtok->val.argid]) { + vector_del(preproc, ret); + ret = NULL; + goto solve_done; + } } toks_to_add = margs2[mtok->val.argid]; } else { @@ -572,20 +601,32 @@ static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char if (len && (concat_cur == 2)) { preproc_token_t *tok1 = &vector_last(preproc, ret); // Guaranteed to exist preproc_token_t *tok2 = vector_begin(preproc, toks_to_add); - if (((tok1->tokt == PPTOK_IDENT) || (tok1->tokt == PPTOK_IDENT_UNEXP) || (tok1->tokt == PPTOK_NUM)) - && ((tok2->tokt == PPTOK_IDENT) || (tok2->tokt == PPTOK_IDENT_UNEXP) || (tok2->tokt == PPTOK_NUM))) { +#define ISIDENT(tt) (((tt) == PPTOK_IDENT) || ((tt) == PPTOK_IDENT_UNEXP)) +#define FIND(s, c) strchr(string_content((s)), (c)) +#define ONLYDIGS(s) (!FIND((s), '.') && !FIND((s), '+') && !FIND((s), '-')) + if (ISIDENT(tok1->tokt) && (ISIDENT(tok2->tokt) || ((tok2->tokt == PPTOK_NUM) && ONLYDIGS(tok2->tokv.str)))) { + tta_start = 1; --len; + tok1->tokt = PPTOK_IDENT; + if (!string_add_string(tok1->tokv.str, tok2->tokv.str)) { + LOG_MEMORY("failed to concatenate identifiers"); + vector_del(preproc, ret); + ret = NULL; + goto solve_done; + } + } else if ((tok1->tokt == PPTOK_NUM) && (ISIDENT(tok2->tokt) || (tok2->tokt == PPTOK_NUM))) { tta_start = 1; --len; - // TODO: check if concat is possible, what behaviour should be in the case below - if ((tok2->tokt == PPTOK_IDENT_UNEXP) && (tok1->tokt == PPTOK_IDENT)) tok1->tokt = PPTOK_IDENT; if (!string_add_string(tok1->tokv.str, tok2->tokv.str)) { - printf("Memory error while expanding %s\n", mname); + LOG_MEMORY("failed to concatenate identifiers"); vector_del(preproc, ret); ret = NULL; goto solve_done; } } else { - printf("Warning: unsupported concatenation between token type %u and %u while expanding %s\n", tok1->tokt, tok2->tokt, mname); + log_warning(li, "unsupported concatenation between token type %u and %u while expanding %s\n", tok1->tokt, tok2->tokt, mname); } +#undef ISIDENT +#undef FIND +#undef ONLYDIGS } if (len) { preproc_token_t tok2; @@ -595,33 +636,34 @@ static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char case PPTOK_NEWLINE: case PPTOK_BLANK: case PPTOK_START_LINE_COMMENT: - case PPTOK_EOF: tok2 = (preproc_token_t){.tokt = tok1->tokt, .tokv.c = tok1->tokv.c}; break; - case PPTOK_SYM: tok2 = (preproc_token_t){.tokt = tok1->tokt, .tokv.sym = tok1->tokv.sym}; break; + case PPTOK_EOF: tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.c = tok1->tokv.c}; break; + case PPTOK_SYM: tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.sym = tok1->tokv.sym}; break; case PPTOK_IDENT: case PPTOK_IDENT_UNEXP: case PPTOK_NUM: { string_t *dup = string_dup(tok1->tokv.str); if (!dup) { - printf("Failed to duplicate string while expanding %s\n", mname); + LOG_MEMORY("failed to duplicate string"); vector_del(preproc, ret); ret = NULL; goto solve_done; } - tok2 = (preproc_token_t){.tokt = tok1->tokt, .tokv.str = dup}; + tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.str = dup}; break; } case PPTOK_INCL: case PPTOK_STRING: { string_t *dup = string_dup(tok1->tokv.sstr); if (!dup) { - printf("Failed to duplicate string while expanding %s\n", mname); + LOG_MEMORY("failed to duplicate string"); vector_del(preproc, ret); ret = NULL; goto solve_done; } - tok2 = (preproc_token_t){.tokt = tok1->tokt, .tokv.sstr = dup, .tokv.sisstr = tok1->tokv.sisstr}; + tok2 = (preproc_token_t){.tokt = tok1->tokt, .loginfo = *li, .tokv.sstr = dup, .tokv.sisstr = tok1->tokv.sisstr}; break; } } if (!vector_push(preproc, ret, tok2)) { + LOG_MEMORY("failed to add token to output vector"); preproc_token_del(&tok2); vector_del(preproc, ret); ret = NULL; @@ -637,15 +679,15 @@ static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char break; } case MTOK_STRINGIFY: - // TODO: better stringifier if (concat_cur == 2) { - printf("Warning: unsupported concatenation with strings while expanding %s\n", mname); + log_warning(li, "invalid concatenation with string while expanding %s\n", mname); } + // TODO: better stringifier preproc_token_t tok2; { string_t *dup = string_new_cap(15); if (!dup) { - printf("Failed to duplicate string while expanding %s\n", mname); + LOG_MEMORY("failed to allocate stringify string"); vector_del(preproc, ret); ret = NULL; goto solve_done; @@ -665,9 +707,10 @@ static VECTOR(preproc) *proc_solve_macro(const khash_t(macros_map) *macros, char string_add_char(dup, 'r'); string_add_char(dup, 'g'); string_add_char(dup, '>'); - tok2 = (preproc_token_t){.tokt = PPTOK_STRING, .tokv.sstr = dup, .tokv.sisstr = 1}; + tok2 = (preproc_token_t){.tokt = PPTOK_STRING, .loginfo = *li, .tokv.sstr = dup, .tokv.sisstr = 1}; } if (!vector_push(preproc, ret, tok2)) { + LOG_MEMORY("failed to add token to output vector"); preproc_token_del(&tok2); vector_del(preproc, ret); ret = NULL; @@ -698,7 +741,7 @@ solve_done: int iret; kh_put(string_set, solved_macros, mname, &iret); if (iret < 0) { - printf("Memory error while expanding %s\n", mname); + LOG_MEMORY("failed to add current macro to the set of expanded macros"); vector_del(preproc, ret); free(mname); return NULL; @@ -706,7 +749,7 @@ solve_done: // Next expand every remaining macros vector_trim(preproc, ret); - VECTOR(preproc) *ret2 = proc_do_expand(macros, ret, solved_macros, opt_used_macros); + VECTOR(preproc) *ret2 = preproc_do_expand(li, macros, ret, solved_macros, opt_used_macros); vector_del(preproc, ret); ret = ret2; if (!ret) return NULL; // There was an error, abort @@ -714,7 +757,7 @@ solve_done: // Finally pop mname (in case we are expanding an argument) khiter_t it = kh_get(string_set, solved_macros, mname); if (it == kh_end(solved_macros)) { - printf("Unknown error while expanding a macro\n"); + log_internal(li, "failed to find current macro in the set of expanded macros while expanding %s\n" , mname); vector_del(preproc, ret); return NULL; } @@ -724,13 +767,17 @@ solve_done: #pragma GCC diagnostic pop kh_del(string_set, solved_macros, it); } +#undef LOG_MEMORY return ret; } -static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const VECTOR(preproc) *toks, - khash_t(string_set) *solved_macros, khash_t(string_set) *opt_used_macros) { +static VECTOR(preproc) *preproc_do_expand(loginfo_t *li, const khash_t(macros_map) *macros, const VECTOR(preproc) *toks, + khash_t(string_set) *solved_macros, khash_t(string_set) *opt_used_macros) { VECTOR(preproc) *toks2 = vector_new_cap(preproc, vector_size(preproc, toks)); - if (!toks2) return NULL; + if (!toks2) { + log_memory("failed to allocate full macro expansion auxiliary vector\n"); + return NULL; + } vector_for(preproc, tok, toks) { preproc_token_t tok2; switch (tok->tokt) { @@ -738,35 +785,38 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const case PPTOK_NEWLINE: case PPTOK_BLANK: case PPTOK_START_LINE_COMMENT: - case PPTOK_EOF: tok2 = (preproc_token_t){.tokt = tok->tokt, .tokv.c = tok->tokv.c}; break; - case PPTOK_SYM: tok2 = (preproc_token_t){.tokt = tok->tokt, .tokv.sym = tok->tokv.sym}; break; + case PPTOK_EOF: tok2 = (preproc_token_t){.tokt = tok->tokt, .loginfo = tok->loginfo, .tokv.c = tok->tokv.c}; break; + case PPTOK_SYM: tok2 = (preproc_token_t){.tokt = tok->tokt, .loginfo = tok->loginfo, .tokv.sym = tok->tokv.sym}; break; case PPTOK_IDENT: case PPTOK_IDENT_UNEXP: case PPTOK_NUM: { string_t *dup = string_dup(tok->tokv.str); if (!dup) { - printf("Failed to duplicate string during full macro expansion\n"); + log_memory("failed to duplicate string during full macro expansion\n"); vector_del(preproc, toks2); return NULL; } - tok2 = (preproc_token_t){.tokt = tok->tokt, .tokv.str = dup}; + tok2 = (preproc_token_t){.tokt = tok->tokt, .loginfo = tok->loginfo, .tokv.str = dup}; break; } case PPTOK_INCL: case PPTOK_STRING: { string_t *dup = string_dup(tok->tokv.sstr); if (!dup) { - printf("Failed to duplicate string during full macro expansion\n"); + log_memory("failed to duplicate string during full macro expansion\n"); vector_del(preproc, toks2); return NULL; } - tok2 = (preproc_token_t){.tokt = tok->tokt, .tokv.sstr = dup, .tokv.sisstr = tok->tokv.sisstr}; + tok2 = (preproc_token_t){.tokt = tok->tokt, .loginfo = tok->loginfo, .tokv.sstr = dup, .tokv.sisstr = tok->tokv.sisstr}; break; } } vector_push(preproc, toks2, tok2); // cap > size, thus this always succeed } VECTOR(preproc) *ret = vector_new_cap(preproc, vector_size(preproc, toks)); - if (!ret) return NULL; + if (!ret) { + log_memory("failed to allocate full macro expansion result vector\n"); + return NULL; + } vector_for(preproc, tok, toks2) { switch (tok->tokt) { case PPTOK_IDENT: { @@ -792,14 +842,14 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const char *mname2 = strdup(string_content(mname)); if (!mname2) { // Abort - printf("Failed to add %s to the list of used macros (strdup returned NULL)\n", string_content(mname)); + log_memory("failed to add %s to the list of used macros (strdup returned NULL)\n", string_content(mname)); goto expand_done; } kh_put(string_set, opt_used_macros, mname2, &iret); if (iret < 0) { // Abort free(mname2); - printf("Failed to add %s to the list of used macros (kh_put ireturned %d)\n", string_content(mname), iret); + log_memory("failed to add %s to the list of used macros (kh_put ireturned %d)\n", string_content(mname), iret); goto expand_done; } else if (iret == 0) { // Just free mname2, it was already present @@ -810,13 +860,13 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const string_t *num_str = string_new_cap(1); if (!num_str) { // Abort - printf("Failed to create defined() output\n"); + log_memory("failed to create defined() output\n"); goto expand_done; } khiter_t it = kh_get(macros_map, macros, string_content(mname)); string_add_char(num_str, (it == kh_end(macros)) ? '0' : '1'); - if (!vector_push(preproc, ret, ((preproc_token_t){.tokt = PPTOK_NUM, .tokv.str = num_str}))) { - printf("Failed to add defined() to the output\n"); + if (!vector_push(preproc, ret, ((preproc_token_t){.tokt = PPTOK_NUM, .loginfo = *li, .tokv.str = num_str}))) { + log_memory("failed to add defined() result to the output\n"); string_del(num_str); goto expand_done; } @@ -842,7 +892,7 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const unsigned depth = 1; VECTOR(preprocs) *margs = vector_new(preprocs); if (!margs) { - printf("Memory error (parsing macro use %s)\n", string_content(tok->tokv.str)); + log_memory("failed to allocate macro arguments for macro %s during full macro expansion\n", string_content(tok->tokv.str)); if (margs) vector_del(preprocs, margs); goto expand_done; } @@ -853,7 +903,7 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const ++tok2; if ((depth == 1) && (tok2->tokt == PPTOK_SYM) && (tok2->tokv.sym == SYM_COMMA)) { // Possible optimization: emplace NULL if vector_size(marg) == 0 - // This would avoid allocating a new vector, but needs support in proc_solve_macro + // This would avoid allocating a new vector, but needs support in preproc_solve_macro vector_trim(preproc, marg); if (!vector_push(preprocs, margs, marg)) goto gather_args_err_mem; marg = vector_new(preproc); @@ -878,7 +928,7 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const if (0) { gather_args_err_mem: - printf("Memory error (parsing macro use %s)\n", string_content(tok->tokv.str)); + log_memory("failed to gather macro arguments for macro %s during full macro expansion\n", string_content(tok->tokv.str)); if (marg) vector_del(preproc, marg); vector_del(preprocs, margs); goto expand_done; @@ -888,14 +938,14 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const char *mname = string_steal(tok->tokv.str); tok = tok2; - VECTOR(preproc) *expanded = proc_solve_macro(macros, mname, m, margs, solved_macros, opt_used_macros); + VECTOR(preproc) *expanded = preproc_solve_macro(li, macros, mname, m, margs, solved_macros, opt_used_macros); vector_del(preprocs, margs); if (!expanded) { // Error expanding the macro goto expand_done; } if (!vector_push_vec(preproc, ret, expanded)) { - printf("Memory error (pushing expanded macro to expanded macro)\n"); + log_memory("pushing expanded macro to full macro expansion\n"); vector_del(preproc, expanded); goto expand_done; } @@ -904,13 +954,13 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const break; } } else { - VECTOR(preproc) *expanded = proc_solve_macro(macros, string_steal(tok->tokv.str), m, NULL, solved_macros, opt_used_macros); + VECTOR(preproc) *expanded = preproc_solve_macro(li, macros, string_steal(tok->tokv.str), m, NULL, solved_macros, opt_used_macros); if (!expanded) { ++tok; // Current token is already freed (string stolen) goto expand_done; } if (!vector_push_vec(preproc, ret, expanded)) { - printf("Failed to extend output for full macro expansion\n"); + log_memory("failed to add macro expansion in output vector of full macro expansion\n"); ++tok; // Current token is already freed (string stolen) goto expand_done; } @@ -933,7 +983,7 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const case PPTOK_START_LINE_COMMENT: case PPTOK_EOF: if (!vector_push(preproc, ret, *tok)) { - printf("Failed to duplicate token during full macro expansion\n"); + log_memory("failed to add token to output vector during full macro expansion\n"); goto expand_done; } break; @@ -969,6 +1019,8 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const #define OPLVL_AOR 9 // Bitwise (Arithmetic) #define OPLVL_BAN 10 // Boolean #define OPLVL_BOR 11 // Boolean +#define OPLVL_ALL 12 // Evaluate the entire stack +#define OPLVL_ALS 13 // Evaluate the entire stack, (don't update the states (ignored)) #define OPTYP_MUL 1 #define OPTYP_DIV 2 #define OPTYP_MOD 3 @@ -1003,22 +1055,242 @@ typedef struct preproc_eval_aux_s { int64_t v0; unsigned st1; const preproc_token_t *v1; - int64_t v2; - int64_t v3; - int64_t v4; - int64_t v5; - int64_t v6; - int64_t v7; - int64_t v8; - int64_t v9; + int64_t v2; loginfo_t li2; + int64_t v3; loginfo_t li3; + int64_t v4; loginfo_t li4; + int64_t v5; loginfo_t li5; + int64_t v6; loginfo_t li6; + int64_t v7; loginfo_t li7; + int64_t v8; loginfo_t li8; + int64_t v9; loginfo_t li9; + loginfo_t libool; unsigned n_colons; // Number of ':' expected (needs to skip to the end), ie number of ternary where the truth-y branch is taken } preproc_eval_aux_t; VECTOR_DECLARE_STATIC(ppeaux, preproc_eval_aux_t) VECTOR_IMPL_STATIC(ppeaux, (void)) +static int64_t eval_stack(preproc_eval_aux_t *st, loginfo_t li, int max_lv, int optype, _Bool is_unsigned, int *success) { + if (!li.lineno_end) { + li.lineno_end = li.lineno; + li.colno_end = li.colno; + } + + int64_t acc = st->v0; + st->st0 = 0; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wduplicated-cond" // For the else if (st->stX) + if (st->st2 == OPTYP_MUL) { + acc = st->v2 * acc; + st->st2 = 0; + li.lineno = st->li2.lineno; + li.colno = st->li2.colno; + } else if (st->st2 == OPTYP_DIV) { + if (!acc) { + log_error(&li, "division by zero during #if evaluation\n"); + *success = 0; + return 0; + } + acc = st->v2 / acc; + st->st2 = 0; + li.lineno = st->li2.lineno; + li.colno = st->li2.colno; + } else if (st->st2 == OPTYP_MOD) { + if (!acc) { + log_error(&li, "division by zero during #if evaluation\n"); + *success = 0; + return 0; + } + acc = st->v2 % acc; + st->st2 = 0; + li.lineno = st->li2.lineno; + li.colno = st->li2.colno; + } else if (st->st2) { + log_internal(&st->li2, "unknown st2 %d during #if evaluation\n", st->st2); + *success = 0; + return 0; + } + if (max_lv == 2) { + st->st2 = optype; + st->v2 = acc; + st->li2 = li; + return acc; + } + if (st->st3 == OPTYP_ADD) { + acc = st->v3 + acc; + st->st3 = 0; + li.lineno = st->li3.lineno; + li.colno = st->li3.colno; + } else if (st->st3 == OPTYP_SUB) { + acc = st->v3 - acc; + st->st3 = 0; + li.lineno = st->li3.lineno; + li.colno = st->li3.colno; + } else if (st->st3) { + log_internal(&st->li3, "unknown st3 %d during #if evaluation\n", st->st3); + *success = 0; + return 0; + } + if (max_lv == 3) { + st->st3 = optype; + st->v3 = acc; + st->li3 = li; + return acc; + } + if (st->st4 == OPTYP_LSL) { + acc = st->v4 << acc; + st->st4 = 0; + li.lineno = st->li4.lineno; + li.colno = st->li4.colno; + } else if (st->st4 == OPTYP_LSR) { + acc = is_unsigned ? (int64_t)((uint64_t)st->v4 >> (uint64_t)acc) : (st->v4 >> acc); + st->st4 = 0; + li.lineno = st->li4.lineno; + li.colno = st->li4.colno; + } else if (st->st4) { + log_internal(&st->li4, "unknown st4 %d during #if evaluation\n", st->st4); + *success = 0; + return 0; + } + if (max_lv == 4) { + st->st4 = optype; + st->v4 = acc; + st->li4 = li; + return acc; + } + if (st->st5 == OPTYP_LET) { + acc = is_unsigned ? ((uint64_t)st->v5 < (uint64_t)acc) : (st->v5 < acc); + is_unsigned = 0; + st->st5 = 0; + li.lineno = st->li5.lineno; + li.colno = st->li5.colno; + } else if (st->st5 == OPTYP_LEE) { + acc = is_unsigned ? ((uint64_t)st->v5 <= (uint64_t)acc) : (st->v5 <= acc); + is_unsigned = 0; + st->st5 = 0; + li.lineno = st->li5.lineno; + li.colno = st->li5.colno; + } else if (st->st5 == OPTYP_GRT) { + acc = is_unsigned ? ((uint64_t)st->v5 > (uint64_t)acc) : (st->v5 > acc); + is_unsigned = 0; + st->st5 = 0; + li.lineno = st->li5.lineno; + li.colno = st->li5.colno; + } else if (st->st5 == OPTYP_GRE) { + acc = is_unsigned ? ((uint64_t)st->v5 >= (uint64_t)acc) : (st->v5 >= acc); + is_unsigned = 0; + st->st5 = 0; + li.lineno = st->li5.lineno; + li.colno = st->li5.colno; + } else if (st->st5) { + log_internal(&st->li5, "unknown st5 %d during #if evaluation\n", st->st5); + *success = 0; + return 0; + } + if (max_lv == 5) { + st->st5 = optype; + st->v5 = acc; + st->li5 = li; + return acc; + } + if (st->st6 == OPTYP_EQU) { + acc = st->v6 == acc; + st->st6 = 0; + li.lineno = st->li6.lineno; + li.colno = st->li6.colno; + } else if (st->st6 == OPTYP_NEQ) { + acc = st->v6 != acc; + st->st6 = 0; + li.lineno = st->li6.lineno; + li.colno = st->li6.colno; + } else if (st->st6) { + log_internal(&st->li6, "unknown st6 %d during #if evaluation\n", st->st6); + *success = 0; + return 0; + } + if (max_lv == 6) { + st->st6 = optype; + st->v6 = acc; + st->li6 = li; + return acc; + } + if (st->st7 == OPTYP_AAN) { + acc = st->v7 & acc; + st->st7 = 0; + li.lineno = st->li7.lineno; + li.colno = st->li7.colno; + } else if (st->st7) { + log_internal(&st->li7, "unknown st7 %d during #if evaluation\n", st->st7); + *success = 0; + return 0; + } + if (max_lv == 7) { + st->st7 = optype; + st->v7 = acc; + st->li7 = li; + return acc; + } + if (st->st8 == OPTYP_XOR) { + acc = st->v8 ^ acc; + st->st8 = 0; + li.lineno = st->li8.lineno; + li.colno = st->li8.colno; + } else if (st->st8) { + log_internal(&st->li8, "unknown st8 %d during #if evaluation\n", st->st8); + *success = 0; + return 0; + } + if (max_lv == 8) { + st->st8 = optype; + st->v8 = acc; + st->li8 = li; + return acc; + } + if (st->st9 == OPTYP_AOR) { + acc = st->v9 | acc; + st->st9 = 0; + li.lineno = st->li9.lineno; + li.colno = st->li9.colno; + } else if (st->st9) { + log_internal(&st->li9, "unknown st9 %d during #if evaluation\n", st->st9); + *success = 0; + return 0; + } + if (max_lv == 9) { + st->st9 = optype; + st->v9 = acc; + st->li9 = li; + return acc; + } + if (max_lv == 10) { // OPLVL == OPLVL_BAN, OPTYP == OPTYP_BAN + li.lineno = st->libool.lineno; + li.colno = st->libool.colno; + st->libool = li; + return acc; + } + if (max_lv == 11) { // OPLVL == OPLVL_BOR, OPTYP == OPTYP_BOR + li.lineno = st->libool.lineno; + li.colno = st->libool.colno; + st->libool = li; + return acc; + } + if (st->st_bool) { + acc = !!acc; + st->st_bool = 0; + } + if ((max_lv == OPLVL_ALL) || (max_lv == OPLVL_ALS)) { + return acc; + } +#pragma GCC diagnostic pop + log_internal(&li, "invalid max level %d in preprocessor partial expression evaluation\n", max_lv); + *success = 0; + return acc; +} static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret, int ptr_is_32bits) { + int success; VECTOR(ppeaux) *stack = vector_new_cap(ppeaux, 1); if (!stack) { - printf("Failed to allocate #if evaluation stack vector\n"); + log_memory("failed to allocate #if evaluation stack vector\n"); *aux_ret = 0; return 0; } @@ -1029,13 +1301,13 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret, int ptr_i return 0; } vector_push(ppeaux, stack, (preproc_eval_aux_t){0}); // vector_cap >= 1 - int64_t acc; _Bool is_unsigned = 0; + int64_t acc; loginfo_t li0; _Bool is_unsigned = 0; vector_for(preproc, tok, cond) { if (tok->tokt == PPTOK_NUM) { // Evaluate token as an integer if st0 == 0, error otherwise if (vector_last(ppeaux, stack).st0 == 0) { num_constant_t cst; - if (!num_constant_convert(tok->tokv.str, &cst, ptr_is_32bits)) { + if (!num_constant_convert(&tok->loginfo, tok->tokv.str, &cst, ptr_is_32bits)) { goto eval_fail; } switch (cst.typ) { @@ -1047,21 +1319,23 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret, int ptr_i case NCT_DOUBLE: case NCT_LDOUBLE: default: - printf("Number '%s' is not a valid integer (during #if evaluation)\n", string_content(tok->tokv.str)); + log_error(&tok->loginfo, "number '%s' is not a valid integer (during #if evaluation)\n", string_content(tok->tokv.str)); goto eval_fail; } + li0 = tok->loginfo; goto push_acc_to_st0; } else { - printf("Invalid number during #if evaluation\n"); + log_error(&tok->loginfo, "unexpected number during #if evaluation\n"); goto eval_fail; } } else if ((tok->tokt == PPTOK_IDENT) || (tok->tokt == PPTOK_IDENT_UNEXP)) { // Evaluate token as 0 if st0 == 0, error otherwise if (vector_last(ppeaux, stack).st0 == 0) { acc = 0; + li0 = tok->loginfo; goto push_acc_to_st0; } else { - printf("Invalid ident '%s' during #if evaluation\n", string_content(tok->tokv.str)); + log_error(&tok->loginfo, "unexpected ident '%s' during #if evaluation\n", string_content(tok->tokv.str)); goto eval_fail; } } else if (tok->tokt == PPTOK_SYM) { @@ -1070,30 +1344,26 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret, int ptr_i switch (tok->tokv.sym) { case SYM_TILDE: // Unary (st0 == 0) - if (vector_last(ppeaux, stack).st0 == 0) { - // Unary, prepare lv1 then continue to the next token - if (!(vector_last(ppeaux, stack).st1++)) { - // Also update v1, since this is the first level 1 operator - vector_last(ppeaux, stack).v1 = tok; - } - goto done_partial_eval; - } else { - printf("Invalid %snary '%s' in #if expression\n", "u", sym2str[tok->tokv.sym]); + if (vector_last(ppeaux, stack).st0 != 0) { + log_error(&tok->loginfo, "unexpected unary '~' in #if expression\n"); goto eval_fail; } + if (!(vector_last(ppeaux, stack).st1++)) { + // Also update v1, since this is the first level 1 operator + vector_last(ppeaux, stack).v1 = tok; + } + goto done_partial_eval; case SYM_EXCL: // Unary (st0 == 0) - if (vector_last(ppeaux, stack).st0 == 0) { - // Unary, prepare lv1 then continue to the next token - if (!(vector_last(ppeaux, stack).st1++)) { - // Also update v1, since this is the first level 1 operator - vector_last(ppeaux, stack).v1 = tok; - } - goto done_partial_eval; - } else { - printf("Invalid %snary '%s' in #if expression\n", "u", sym2str[tok->tokv.sym]); + if (vector_last(ppeaux, stack).st0 != 0) { + log_error(&tok->loginfo, "unexpected unary '!' in #if expression\n"); goto eval_fail; } + if (!(vector_last(ppeaux, stack).st1++)) { + // Also update v1, since this is the first level 1 operator + vector_last(ppeaux, stack).v1 = tok; + } + goto done_partial_eval; case SYM_PLUS: // May be unary (st0 == 0) or binary (st0 != 0) if (vector_last(ppeaux, stack).st0 == 0) { @@ -1106,7 +1376,7 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret, int ptr_i } else { op_lvl = OPLVL_ADD; op_typ = OPTYP_ADD; - break; + goto add_binop; } case SYM_DASH: // May be unary (st0 == 0) or binary (st0 != 0) @@ -1120,363 +1390,222 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret, int ptr_i } else { op_lvl = OPLVL_SUB; op_typ = OPTYP_SUB; - break; + goto add_binop; } case SYM_STAR: // 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_MUL; - op_typ = OPTYP_MUL; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_MUL; + op_typ = OPTYP_MUL; + goto add_binop; case SYM_SLASH: // 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_DIV; - op_typ = OPTYP_DIV; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_DIV; + op_typ = OPTYP_DIV; + goto add_binop; 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; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_MOD; + op_typ = OPTYP_MOD; + goto add_binop; case SYM_HAT: // 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_XOR; - op_typ = OPTYP_XOR; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_XOR; + op_typ = OPTYP_XOR; + goto add_binop; case SYM_AMP: // 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_AAN; - op_typ = OPTYP_AAN; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_AAN; + op_typ = OPTYP_AAN; + goto add_binop; case SYM_PIPE: // 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_AOR; - op_typ = OPTYP_AOR; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_AOR; + op_typ = OPTYP_AOR; + goto add_binop; case SYM_EQEQ: // 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_EQU; - op_typ = OPTYP_EQU; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_EQU; + op_typ = OPTYP_EQU; + goto add_binop; case SYM_EXCLEQ: // 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_NEQ; - op_typ = OPTYP_NEQ; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_NEQ; + op_typ = OPTYP_NEQ; + goto add_binop; case SYM_LT: // 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_LET; - op_typ = OPTYP_LET; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_LET; + op_typ = OPTYP_LET; + goto add_binop; case SYM_GT: // 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_GRT; - op_typ = OPTYP_GRT; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_GRT; + op_typ = OPTYP_GRT; + goto add_binop; case SYM_LTEQ: // 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_LEE; - op_typ = OPTYP_LEE; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_LEE; + op_typ = OPTYP_LEE; + goto add_binop; case SYM_GTEQ: // 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_GRE; - op_typ = OPTYP_GRE; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_GRE; + op_typ = OPTYP_GRE; + goto add_binop; case SYM_AMPAMP: // 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_BAN; - op_typ = OPTYP_BAN; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_BAN; + op_typ = OPTYP_BAN; + goto add_binop; case SYM_PIPEPIPE: // 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_BOR; - op_typ = OPTYP_BOR; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_BOR; + op_typ = OPTYP_BOR; + goto add_binop; case SYM_LTLT: // 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_LSL; - op_typ = OPTYP_LSL; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_LSL; + op_typ = OPTYP_LSL; + goto add_binop; case SYM_GTGT: // 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_LSR; - op_typ = OPTYP_LSR; - break; - } + if (vector_last(ppeaux, stack).st0 == 0) goto invalid_binop; + op_lvl = OPLVL_LSR; + op_typ = OPTYP_LSR; + goto add_binop; case SYM_LPAREN: // May be placed anywhere a constant is expected (st0 == 0) and simply pushes a new stack - if (vector_last(ppeaux, stack).st0 == 0) { - if (!vector_push(ppeaux, stack, (preproc_eval_aux_t){0})) { - printf("Failed to push to the stack during #if evaluation\n"); - goto eval_fail; - } - goto done_partial_eval; - } else { - printf("Invalid opening parenthesis in #if expression\n"); - goto eval_fail; - } - case SYM_RPAREN: - case SYM_QUESTION: - // May be placed anywhere and simply pushes a new stack (paren) or more complex operation (ternary) - if ((tok->tokv.sym == SYM_RPAREN) && (vector_size(ppeaux, stack) == 1)) { - printf("Invalid closing parenthesis during #if evaluation\n"); - goto eval_fail; - } - if (!vector_last(ppeaux, stack).st0) { - printf("Invalid %s during #if evaluation\n", (tok->tokv.sym == SYM_RPAREN) ? "closing parenthesis" : "question mark"); - goto eval_fail; - } - - // Evaluate the top of the stack, then pop - acc = vector_last(ppeaux, stack).v0; - vector_last(ppeaux, stack).st0 = 0; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wduplicated-cond" // For the else if (.stX) - if (vector_last(ppeaux, stack).st2 == OPTYP_MUL) { - acc = vector_last(ppeaux, stack).v2 * acc; - vector_last(ppeaux, stack).st2 = 0; - } else if (vector_last(ppeaux, stack).st2 == OPTYP_DIV) { - 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 == 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); + if (vector_last(ppeaux, stack).st0 != 0) { + log_error(&tok->loginfo, "unexpected opening parenthesis in #if expression\n"); goto eval_fail; } - if (vector_last(ppeaux, stack).st3 == OPTYP_ADD) { - acc = vector_last(ppeaux, stack).v3 + acc; - vector_last(ppeaux, stack).st3 = 0; - } else if (vector_last(ppeaux, stack).st3 == OPTYP_SUB) { - acc = vector_last(ppeaux, stack).v3 - acc; - vector_last(ppeaux, stack).st3 = 0; - } else if (vector_last(ppeaux, stack).st3) { - printf("<internal error> Unknown st3 %d during #if evaluation\n", vector_last(ppeaux, stack).st3); + if (!vector_push(ppeaux, stack, (preproc_eval_aux_t){0})) { + log_memory("failed to push a new stack during #if evaluation\n"); goto eval_fail; } - if (vector_last(ppeaux, stack).st4 == OPTYP_LSL) { - acc = vector_last(ppeaux, stack).v4 << acc; - vector_last(ppeaux, stack).st4 = 0; - } else if (vector_last(ppeaux, stack).st4 == OPTYP_LSR) { - acc = is_unsigned ? (int64_t)((uint64_t)vector_last(ppeaux, stack).v4 >> (uint64_t)acc) : (vector_last(ppeaux, stack).v4 >> acc); - vector_last(ppeaux, stack).st4 = 0; - } else if (vector_last(ppeaux, stack).st4) { - printf("<internal error> Unknown st4 %d during #if evaluation\n", vector_last(ppeaux, stack).st4); + goto done_partial_eval; + case SYM_RPAREN: + // May be placed anywhere after a constant (st0 != 0) + if (vector_size(ppeaux, stack) == 1) { + log_error(&tok->loginfo, "unexpected symbol ')' (parenthesis not opened) during #if evaluation\n"); goto eval_fail; } - if (vector_last(ppeaux, stack).st5 == OPTYP_LET) { - acc = is_unsigned ? ((uint64_t)vector_last(ppeaux, stack).v5 < (uint64_t)acc) : (vector_last(ppeaux, stack).v5 < acc); - is_unsigned = 0; - vector_last(ppeaux, stack).st5 = 0; - } else if (vector_last(ppeaux, stack).st5 == OPTYP_LEE) { - acc = is_unsigned ? ((uint64_t)vector_last(ppeaux, stack).v5 <= (uint64_t)acc) : (vector_last(ppeaux, stack).v5 <= acc); - is_unsigned = 0; - vector_last(ppeaux, stack).st5 = 0; - } else if (vector_last(ppeaux, stack).st5 == OPTYP_GRT) { - acc = is_unsigned ? ((uint64_t)vector_last(ppeaux, stack).v5 > (uint64_t)acc) : (vector_last(ppeaux, stack).v5 > acc); - is_unsigned = 0; - vector_last(ppeaux, stack).st5 = 0; - } else if (vector_last(ppeaux, stack).st5 == OPTYP_GRE) { - acc = is_unsigned ? ((uint64_t)vector_last(ppeaux, stack).v5 >= (uint64_t)acc) : (vector_last(ppeaux, stack).v5 >= acc); - is_unsigned = 0; - vector_last(ppeaux, stack).st5 = 0; - } else if (vector_last(ppeaux, stack).st5) { - printf("<internal error> Unknown st5 %d during #if evaluation\n", vector_last(ppeaux, stack).st5); + if (vector_last(ppeaux, stack).n_colons) { + log_error(&tok->loginfo, "unexpected symbol ')', expected symbol ':' during #if evaluation\n"); goto eval_fail; } - if (vector_last(ppeaux, stack).st6 == OPTYP_EQU) { - acc = vector_last(ppeaux, stack).v6 == acc; - vector_last(ppeaux, stack).st6 = 0; - } else if (vector_last(ppeaux, stack).st6 == OPTYP_NEQ) { - acc = vector_last(ppeaux, stack).v6 != acc; - vector_last(ppeaux, stack).st6 = 0; - } else if (vector_last(ppeaux, stack).st6) { - printf("<internal error> Unknown st6 %d during #if evaluation\n", vector_last(ppeaux, stack).st6); + if (!vector_last(ppeaux, stack).st0) { + log_error(&tok->loginfo, "unexpected symbol ')' during #if evaluation\n"); goto eval_fail; } - if (vector_last(ppeaux, stack).st7 == OPTYP_AAN) { - acc = vector_last(ppeaux, stack).v7 & acc; - vector_last(ppeaux, stack).st7 = 0; - } else if (vector_last(ppeaux, stack).st7) { - printf("<internal error> Unknown st7 %d during #if evaluation\n", vector_last(ppeaux, stack).st7); + + eval_rparen: + // Evaluate the top of the stack, then pop + success = 1; + acc = eval_stack(&vector_last(ppeaux, stack), li0, OPLVL_ALS, 0, is_unsigned, &success); + if (!success) { goto eval_fail; } - if (vector_last(ppeaux, stack).st8 == OPTYP_XOR) { - acc = vector_last(ppeaux, stack).v8 ^ acc; - vector_last(ppeaux, stack).st8 = 0; - } else if (vector_last(ppeaux, stack).st8) { - printf("<internal error> Unknown st8 %d during #if evaluation\n", vector_last(ppeaux, stack).st8); + + eval_rparen_acc: + vector_pop(ppeaux, stack); + goto push_acc_to_st0; + + case SYM_QUESTION: { + // May be placed anywhere and may skip some tokens depending on acc + if (!vector_last(ppeaux, stack).st0) { + log_error(&tok->loginfo, "unexpected ternary operator during #if evaluation\n"); goto eval_fail; } - if (vector_last(ppeaux, stack).st9 == OPTYP_AOR) { - acc = vector_last(ppeaux, stack).v9 | acc; - vector_last(ppeaux, stack).st9 = 0; - } else if (vector_last(ppeaux, stack).st9) { - printf("<internal error> Unknown st9 %d during #if evaluation\n", vector_last(ppeaux, stack).st9); + + // Evaluate the top of the stack, then increase n_colons or skip tokens + success = 1; + acc = eval_stack(&vector_last(ppeaux, stack), li0, OPLVL_ALL, 0, is_unsigned, &success); + if (!success) { goto eval_fail; } - if (vector_last(ppeaux, stack).st_bool) { - acc = !!acc; - vector_last(ppeaux, stack).st_bool = 0; - } -#pragma GCC diagnostic pop - if (tok->tokv.sym == SYM_RPAREN) { - vector_pop(ppeaux, stack); - goto push_acc_to_st0; + eval_question_acc: + is_unsigned = 0; + if (acc) { + // Increase n_colons + ++vector_last(ppeaux, stack).n_colons; + goto done_partial_eval; } else { - eval_question_acc: - is_unsigned = 0; - if (acc) { - // Increase n_colons - ++vector_last(ppeaux, stack).n_colons; - goto done_partial_eval; - } else { - // Skip to the corresponding colon - unsigned nquestions = 0, nparens = 0; - // Note that we don't really care about the content of the ignored part; it may be syntaxically incorrect - for (++tok; tok < vector_end(preproc, cond); ++tok) { - if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_LPAREN)) { - ++nparens; - } else if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_RPAREN)) { - if (nparens) --nparens; - else { - printf("Unclosed parenthesis in #if evaluation\n"); - goto eval_fail; - } - } else if (!nparens && (tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_QUESTION)) { - ++nquestions; - } else if (!nparens && (tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_COLON)) { - if (nquestions) --nquestions; - else break; - } - } - if (tok == vector_end(preproc, cond)) { - printf("Unfinished ternary operator in #if evaluation\n"); - goto eval_fail; - } - goto done_partial_eval; - } - } - case SYM_COLON: - if (vector_last(ppeaux, stack).n_colons) { - // Decrease n_colons and skip to the rparen/end of vector - if (vector_size(ppeaux, stack) == 1) { - goto done_complete_stack; // No rparen, skip to the end of the vector - } - // Skip to the next rparen; also, we skip the correct count of ':' since we don't care about those anymore - // --vector_last(ppeaux, stack).n_colons; - unsigned nparens = 0; + // Skip to the corresponding colon + unsigned nquestions = 0, nparens = 0; // Note that we don't really care about the content of the ignored part; it may be syntaxically incorrect for (++tok; tok < vector_end(preproc, cond); ++tok) { if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_LPAREN)) { ++nparens; } else if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_RPAREN)) { if (nparens) --nparens; + else { + log_error(&tok->loginfo, "unexpected symbol ')', expected ':' during #if evaluation\n"); + goto eval_fail; + } + } else if (!nparens && (tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_QUESTION)) { + ++nquestions; + } else if (!nparens && (tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_COLON)) { + if (nquestions) --nquestions; else break; } } if (tok == vector_end(preproc, cond)) { - printf("Unfinished ternary operator in #if evaluation\n"); + log_error(&tok->loginfo, "ternary operator never finished during #if evaluation\n"); goto eval_fail; } - --tok; goto done_partial_eval; - } else { - printf("Invalid colon symbol during #if evaluation\n"); + } + } + case SYM_COLON: { + if (!vector_last(ppeaux, stack).n_colons) { + log_error(&tok->loginfo, "unexpected symbol ':' during #if evaluation\n"); + goto eval_fail; + } + if (!vector_last(ppeaux, stack).st0) { + log_error(&tok->loginfo, "unexpected symbol ':' during #if evaluation\n"); + goto eval_fail; + } + eval_colon_acc: + // Skip to the end of expression or to the corresponding rparen + if (vector_size(ppeaux, stack) == 1) { + goto done_complete_stack; // No parenthesis opened, skip to the end of the vector + } + // Skip to the next rparen; also, we skip correctly counting of ':' since we don't care about those anymore + unsigned nparens = 0; + // Note that we don't really care about the content of the ignored part; it may be syntaxically incorrect + for (++tok; tok < vector_end(preproc, cond); ++tok) { + if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_LPAREN)) { + ++nparens; + } else if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_RPAREN)) { + if (nparens) --nparens; + else break; + } + } + // We need to exit at a RPAREN + if (tok == vector_end(preproc, cond)) { + log_error(&vector_last(preproc, cond).loginfo, "missing closing parenthesis in #if expression\n"); goto eval_fail; } + vector_last(ppeaux, stack).n_colons = 0; + goto eval_rparen; } case SYM_LBRACKET: case SYM_RBRACKET: @@ -1504,228 +1633,165 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret, int ptr_i case SYM_DASHDASH: case SYM_COMMA: default: - printf("Invalid symbol ID %u during #if evaluation\n", tok->tokv.sym); + log_error(&tok->loginfo, "invalid symbol ID %u (%s) during #if evaluation\n", + tok->tokv.sym, (tok->tokv.sym <= LAST_SYM) ? sym2str[tok->tokv.sym] : "invalid"); goto eval_fail; } - acc = vector_last(ppeaux, stack).v0; - vector_last(ppeaux, stack).st0 = 0; - if (op_lvl < 2) { - printf("<internal error> Invalid op_lvl %d < 2 during #if evaluation\n", op_lvl); + // invalid_binop: unexpected binary operation + // add_binop: add a binary operation + if (0) { + invalid_binop: + log_error(&tok->loginfo, "unexpected binary operator '%s' in #if expression\n", sym2str[tok->tokv.sym]); goto eval_fail; - } - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wduplicated-cond" // For the else if (.stX) - if (vector_last(ppeaux, stack).st2 == OPTYP_MUL) { - acc = vector_last(ppeaux, stack).v2 * acc; - vector_last(ppeaux, stack).st2 = 0; - } else if (vector_last(ppeaux, stack).st2 == OPTYP_DIV) { - if (!acc) { - printf("Error: division by zero\n"); + add_binop: + if (op_lvl < 2) { + log_internal(&tok->loginfo, "invalid op_lvl %d < 2 during #if evaluation\n", op_lvl); goto eval_fail; } - 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"); + if (op_lvl >= OPLVL_ALL) { + log_internal(&tok->loginfo, "invalid op_lvl %d > OPLVL_ALL during #if evaluation\n", op_lvl); 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; - } - if (op_lvl == 2) { - vector_last(ppeaux, stack).st2 = op_typ; - vector_last(ppeaux, stack).v2 = acc; - goto done_partial_eval; - } - if (vector_last(ppeaux, stack).st3 == OPTYP_ADD) { - acc = vector_last(ppeaux, stack).v3 + acc; - vector_last(ppeaux, stack).st3 = 0; - } else if (vector_last(ppeaux, stack).st3 == OPTYP_SUB) { - acc = vector_last(ppeaux, stack).v3 - acc; - vector_last(ppeaux, stack).st3 = 0; - } else if (vector_last(ppeaux, stack).st3) { - printf("<internal error> Unknown st3 %d during #if evaluation\n", vector_last(ppeaux, stack).st3); - goto eval_fail; - } - if (op_lvl == 3) { - vector_last(ppeaux, stack).st3 = op_typ; - vector_last(ppeaux, stack).v3 = acc; - goto done_partial_eval; - } - if (vector_last(ppeaux, stack).st4 == OPTYP_LSL) { - acc = vector_last(ppeaux, stack).v4 << acc; - vector_last(ppeaux, stack).st4 = 0; - } else if (vector_last(ppeaux, stack).st4 == OPTYP_LSR) { - acc = is_unsigned ? (int64_t)((uint64_t)vector_last(ppeaux, stack).v4 >> (uint64_t)acc) : (vector_last(ppeaux, stack).v4 >> acc); - vector_last(ppeaux, stack).st4 = 0; - } else if (vector_last(ppeaux, stack).st4) { - printf("<internal error> Unknown st4 %d during #if evaluation\n", vector_last(ppeaux, stack).st4); - goto eval_fail; - } - if (op_lvl == 4) { - vector_last(ppeaux, stack).st4 = op_typ; - vector_last(ppeaux, stack).v4 = acc; - goto done_partial_eval; - } - if (vector_last(ppeaux, stack).st5 == OPTYP_LET) { - acc = is_unsigned ? ((uint64_t)vector_last(ppeaux, stack).v5 < (uint64_t)acc) : (vector_last(ppeaux, stack).v5 < acc); - is_unsigned = 0; - vector_last(ppeaux, stack).st5 = 0; - } else if (vector_last(ppeaux, stack).st5 == OPTYP_LEE) { - acc = is_unsigned ? ((uint64_t)vector_last(ppeaux, stack).v5 <= (uint64_t)acc) : (vector_last(ppeaux, stack).v5 <= acc); - is_unsigned = 0; - vector_last(ppeaux, stack).st5 = 0; - } else if (vector_last(ppeaux, stack).st5 == OPTYP_GRT) { - acc = is_unsigned ? ((uint64_t)vector_last(ppeaux, stack).v5 > (uint64_t)acc) : (vector_last(ppeaux, stack).v5 > acc); - is_unsigned = 0; - vector_last(ppeaux, stack).st5 = 0; - } else if (vector_last(ppeaux, stack).st5 == OPTYP_GRE) { - acc = is_unsigned ? ((uint64_t)vector_last(ppeaux, stack).v5 >= (uint64_t)acc) : (vector_last(ppeaux, stack).v5 >= acc); - is_unsigned = 0; - vector_last(ppeaux, stack).st5 = 0; - } else if (vector_last(ppeaux, stack).st5) { - printf("<internal error> Unknown st5 %d during #if evaluation\n", vector_last(ppeaux, stack).st5); - goto eval_fail; - } - if (op_lvl == 5) { - vector_last(ppeaux, stack).st5 = op_typ; - vector_last(ppeaux, stack).v5 = acc; - goto done_partial_eval; - } - if (vector_last(ppeaux, stack).st6 == OPTYP_EQU) { - acc = vector_last(ppeaux, stack).v6 == acc; - vector_last(ppeaux, stack).st6 = 0; - } else if (vector_last(ppeaux, stack).st6 == OPTYP_NEQ) { - acc = vector_last(ppeaux, stack).v6 != acc; - vector_last(ppeaux, stack).st6 = 0; - } else if (vector_last(ppeaux, stack).st6) { - printf("<internal error> Unknown st6 %d during #if evaluation\n", vector_last(ppeaux, stack).st6); - goto eval_fail; - } - if (op_lvl == 6) { - vector_last(ppeaux, stack).st6 = op_typ; - vector_last(ppeaux, stack).v6 = acc; - goto done_partial_eval; - } - if (vector_last(ppeaux, stack).st7 == OPTYP_AAN) { - acc = vector_last(ppeaux, stack).v7 & acc; - vector_last(ppeaux, stack).st7 = 0; - } else if (vector_last(ppeaux, stack).st7) { - printf("<internal error> Unknown st7 %d during #if evaluation\n", vector_last(ppeaux, stack).st7); - goto eval_fail; - } - if (op_lvl == 7) { - vector_last(ppeaux, stack).st7 = op_typ; - vector_last(ppeaux, stack).v7 = acc; - goto done_partial_eval; - } - if (vector_last(ppeaux, stack).st8 == OPTYP_XOR) { - acc = vector_last(ppeaux, stack).v8 ^ acc; - vector_last(ppeaux, stack).st8 = 0; - } else if (vector_last(ppeaux, stack).st8) { - printf("<internal error> Unknown st8 %d during #if evaluation\n", vector_last(ppeaux, stack).st8); - goto eval_fail; - } - if (op_lvl == 8) { - vector_last(ppeaux, stack).st8 = op_typ; - vector_last(ppeaux, stack).v8 = acc; - goto done_partial_eval; - } - if (vector_last(ppeaux, stack).st9 == OPTYP_AOR) { - acc = vector_last(ppeaux, stack).v9 | acc; - vector_last(ppeaux, stack).st9 = 0; - } else if (vector_last(ppeaux, stack).st9) { - printf("<internal error> Unknown st9 %d during #if evaluation\n", vector_last(ppeaux, stack).st9); - goto eval_fail; - } - if (op_lvl == 9) { - vector_last(ppeaux, stack).st9 = op_typ; - vector_last(ppeaux, stack).v9 = acc; - goto done_partial_eval; - } - if (op_lvl == 10) { - // We know that sym == SYM_AMPAMP, so we need to skip evaluating the remainder if it equals 0 - if (acc) goto done_partial_eval; - is_unsigned = 0; - unsigned nparens = 0; - // 0 && y ? z : w => w - // 0 && y || z => z - // Otherwise, keep skipping to the next token - for (++tok; tok < vector_end(preproc, cond); ++tok) { - if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_LPAREN)) { - ++nparens; - } else if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_RPAREN)) { - if (nparens) --nparens; - else { - vector_last(ppeaux, stack).v0 = acc; - vector_last(ppeaux, stack).st0 = 1; - --tok; - goto done_partial_eval; + + success = 1; + acc = eval_stack(&vector_last(ppeaux, stack), li0, op_lvl, op_typ, is_unsigned, &success); + if (!success) { + goto eval_fail; + } + + if (op_lvl < OPLVL_BAN) { + // No post-processing required + goto done_partial_eval; + } + if (op_lvl == OPLVL_BAN) { + // op_typ == OPLVL_BAN + vector_last(ppeaux, stack).st_bool = 1; + if (acc) goto done_partial_eval; + // We have five possibilities: + // [0] && x <EOL> ~> 0 + // [0] && x) ~> 0) + // [0] && x ? y : z ~> z + // [0] && x : y ~> 0 : y ~> 0 + // [0] && x || y ~> y + // We are at the '&&'; note that we know the top of the stack has no pending operation + unsigned nparens = 0; + for (++tok; tok < vector_end(preproc, cond); ++tok) { + if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_LPAREN)) { + ++nparens; + } else if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_RPAREN)) { + if (nparens) --nparens; + else { + if (vector_size(ppeaux, stack) == 1) { + log_error(&tok->loginfo, "unexpected symbol ')' (parenthesis not opened) during #if evaluation\n"); + goto eval_fail; + } + if (vector_last(ppeaux, stack).n_colons) { + log_error(&tok->loginfo, "unexpected symbol ')', expected symbol ':' during #if evaluation\n"); + goto eval_fail; + } + + goto eval_rparen_acc; + } + } else if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_QUESTION)) { + if (!nparens) { + goto eval_question_acc; + } + } else if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_COLON)) { + if (!nparens) { + if (!vector_last(ppeaux, stack).n_colons) { + log_error(&tok->loginfo, "unexpected symbol ':' during #if evaluation\n"); + goto eval_fail; + } + goto eval_colon_acc; + } + } else if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_PIPEPIPE)) { + if (!nparens) { + goto done_partial_eval; + } } - } else if (!nparens && (tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_QUESTION)) { - goto eval_question_acc; - } else if (!nparens && (tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_PIPEPIPE)) { - break; } - } - if (tok == vector_end(preproc, cond)) { - if (!nparens) goto done_complete_acc; - else { - printf("Unclosed parenthesis in #if evaluation\n"); + if (nparens) { + log_error(&vector_last(preproc, cond).loginfo, "expected symbol ')' during #if evaluation\n"); goto eval_fail; } - } - goto done_partial_eval; - } - if (op_lvl == 11) { - // We know that sym == SYM_PIPEPIPE, so we need to skip evaluating the remainder if it equals 1 - if (!acc) goto done_partial_eval; - is_unsigned = 0; - unsigned nparens = 0; - // 0 || y ? z : w => w - // Otherwise, keep skipping to the next token - for (++tok; tok < vector_end(preproc, cond); ++tok) { - if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_LPAREN)) { - ++nparens; - } else if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_RPAREN)) { - if (nparens) --nparens; - else { - vector_last(ppeaux, stack).v0 = acc; - vector_last(ppeaux, stack).st0 = 1; - --tok; - goto done_partial_eval; + if (vector_last(ppeaux, stack).n_colons) { + log_error(&vector_last(preproc, cond).loginfo, "expected symbol ':' during #if evaluation\n"); + goto eval_fail; + } + if (vector_size(ppeaux, stack) != 1) { + log_error(&vector_last(preproc, cond).loginfo, "expected symbol ')' during #if evaluation\n"); + goto eval_fail; + } + goto done_complete_acc; + } + if (op_lvl == OPLVL_BOR) { + // op_typ == OPLVL_BOR + vector_last(ppeaux, stack).st_bool = 1; + if (!acc) goto done_partial_eval; + // We have four possibilities: + // [!0] || x <EOL> ~> 1 + // [!0] || x) ~> 1) + // [!0] || x ? y : z ~> z + // [!0] || x : y ~> 1 : y ~> 1 + // We are at the '||'; note that we know the top of the stack has no pending operation + unsigned nparens = 0; + for (++tok; tok < vector_end(preproc, cond); ++tok) { + if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_LPAREN)) { + ++nparens; + } else if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_RPAREN)) { + if (nparens) --nparens; + else { + if (vector_size(ppeaux, stack) == 1) { + log_error(&tok->loginfo, "unexpected symbol ')' (parenthesis not opened) during #if evaluation\n"); + goto eval_fail; + } + if (vector_last(ppeaux, stack).n_colons) { + log_error(&tok->loginfo, "unexpected symbol ')', expected symbol ':' during #if evaluation\n"); + goto eval_fail; + } + + acc = 1; + goto eval_rparen_acc; + } + } else if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_QUESTION)) { + if (!nparens) { + acc = 1; + goto eval_question_acc; + } + } else if ((tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_COLON)) { + if (!nparens) { + if (!vector_last(ppeaux, stack).n_colons) { + log_error(&tok->loginfo, "unexpected symbol ':' during #if evaluation\n"); + goto eval_fail; + } + acc = 1; + goto eval_colon_acc; + } } - } else if (!nparens && (tok->tokt == PPTOK_SYM) && (tok->tokv.sym == SYM_QUESTION)) { - goto eval_question_acc; } - } - if (tok == vector_end(preproc, cond)) { - if (!nparens) goto done_complete_acc; - else { - printf("Unclosed parenthesis in #if evaluation\n"); + if (nparens) { + log_error(&vector_last(preproc, cond).loginfo, "expected symbol ')' during #if evaluation\n"); + goto eval_fail; + } + if (vector_last(ppeaux, stack).n_colons) { + log_error(&vector_last(preproc, cond).loginfo, "expected symbol ':' during #if evaluation\n"); + goto eval_fail; + } + if (vector_size(ppeaux, stack) != 1) { + log_error(&vector_last(preproc, cond).loginfo, "expected symbol ')' during #if evaluation\n"); goto eval_fail; } + acc = 1; + goto done_complete_acc; } - goto done_partial_eval; + log_internal(&li0, "invalid op_lvl %d during #if evaluation\n", op_lvl); + goto eval_fail; } - // if (vector_last(ppeaux, stack).st_bool) { - // acc = !!acc; - // vector_last(ppeaux, stack).st_bool = 0; - // } -#pragma GCC diagnostic pop - printf("<internal error> Invalid op_lvl %d > 11 during #if evaluation\n", op_lvl); - goto eval_fail; done_partial_eval: } else { - printf("Invalid token type %u during #if evaluation\n", tok->tokt); + log_error(&tok->loginfo, "invalid token type %u during #if evaluation\n", tok->tokt); goto eval_fail; } @@ -1740,7 +1806,8 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret, int ptr_i else if (sym == SYM_EXCL) acc = !acc; else if (sym == SYM_TILDE) acc = ~acc; else { - printf("<internal error> Unknown level 1 unary operator sym ID %u\n", sym); + log_internal(&vector_last(ppeaux, stack).v1[vector_last(ppeaux, stack).st1].loginfo, + "unknown level 1 unary operator sym ID %u\n", sym); } } vector_last(ppeaux, stack).v0 = acc; @@ -1749,114 +1816,16 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret, int ptr_i } if (vector_size(ppeaux, stack) != 1) { - printf("Opened parenthesis never closed in #if expression\n"); + log_error(&vector_last(preproc, cond).loginfo, "expected symbol ')' during #if evaluation\n"); goto eval_fail; } done_complete_stack: - acc = vector_last(ppeaux, stack).v0; - vector_last(ppeaux, stack).st0 = 0; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wduplicated-cond" // For the else if (.stX) - if (vector_last(ppeaux, stack).st2 == OPTYP_MUL) { - acc = vector_last(ppeaux, stack).v2 * acc; - vector_last(ppeaux, stack).st2 = 0; - } else if (vector_last(ppeaux, stack).st2 == OPTYP_DIV) { - 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 == 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; - } - if (vector_last(ppeaux, stack).st3 == OPTYP_ADD) { - acc = vector_last(ppeaux, stack).v3 + acc; - vector_last(ppeaux, stack).st3 = 0; - } else if (vector_last(ppeaux, stack).st3 == OPTYP_SUB) { - acc = vector_last(ppeaux, stack).v3 - acc; - vector_last(ppeaux, stack).st3 = 0; - } else if (vector_last(ppeaux, stack).st3) { - printf("<internal error> Unknown st3 %d during #if evaluation\n", vector_last(ppeaux, stack).st3); - goto eval_fail; - } - if (vector_last(ppeaux, stack).st4 == OPTYP_LSL) { - acc = vector_last(ppeaux, stack).v4 << acc; - vector_last(ppeaux, stack).st4 = 0; - } else if (vector_last(ppeaux, stack).st4 == OPTYP_LSR) { - acc = is_unsigned ? (int64_t)((uint64_t)vector_last(ppeaux, stack).v4 >> (uint64_t)acc) : (vector_last(ppeaux, stack).v4 >> acc); - vector_last(ppeaux, stack).st4 = 0; - } else if (vector_last(ppeaux, stack).st4) { - printf("<internal error> Unknown st4 %d during #if evaluation\n", vector_last(ppeaux, stack).st4); - goto eval_fail; - } - if (vector_last(ppeaux, stack).st5 == OPTYP_LET) { - acc = is_unsigned ? ((uint64_t)vector_last(ppeaux, stack).v5 < (uint64_t)acc) : (vector_last(ppeaux, stack).v5 < acc); - is_unsigned = 0; - vector_last(ppeaux, stack).st5 = 0; - } else if (vector_last(ppeaux, stack).st5 == OPTYP_LEE) { - acc = is_unsigned ? ((uint64_t)vector_last(ppeaux, stack).v5 <= (uint64_t)acc) : (vector_last(ppeaux, stack).v5 <= acc); - is_unsigned = 0; - vector_last(ppeaux, stack).st5 = 0; - } else if (vector_last(ppeaux, stack).st5 == OPTYP_GRT) { - acc = is_unsigned ? ((uint64_t)vector_last(ppeaux, stack).v5 > (uint64_t)acc) : (vector_last(ppeaux, stack).v5 > acc); - is_unsigned = 0; - vector_last(ppeaux, stack).st5 = 0; - } else if (vector_last(ppeaux, stack).st5 == OPTYP_GRE) { - acc = is_unsigned ? ((uint64_t)vector_last(ppeaux, stack).v5 >= (uint64_t)acc) : (vector_last(ppeaux, stack).v5 >= acc); - is_unsigned = 0; - vector_last(ppeaux, stack).st5 = 0; - } else if (vector_last(ppeaux, stack).st5) { - printf("<internal error> Unknown st5 %d during #if evaluation\n", vector_last(ppeaux, stack).st5); - goto eval_fail; - } - if (vector_last(ppeaux, stack).st6 == OPTYP_EQU) { - acc = vector_last(ppeaux, stack).v6 == acc; - vector_last(ppeaux, stack).st6 = 0; - } else if (vector_last(ppeaux, stack).st6 == OPTYP_NEQ) { - acc = vector_last(ppeaux, stack).v6 != acc; - vector_last(ppeaux, stack).st6 = 0; - } else if (vector_last(ppeaux, stack).st6) { - printf("<internal error> Unknown st6 %d during #if evaluation\n", vector_last(ppeaux, stack).st6); + success = 1; + acc = eval_stack(&vector_last(ppeaux, stack), li0, OPLVL_ALS, 0, is_unsigned, &success); + if (!success) { goto eval_fail; } - if (vector_last(ppeaux, stack).st7 == OPTYP_AAN) { - acc = vector_last(ppeaux, stack).v7 & acc; - vector_last(ppeaux, stack).st7 = 0; - } else if (vector_last(ppeaux, stack).st7) { - printf("<internal error> Unknown st7 %d during #if evaluation\n", vector_last(ppeaux, stack).st7); - goto eval_fail; - } - if (vector_last(ppeaux, stack).st8 == OPTYP_XOR) { - acc = vector_last(ppeaux, stack).v8 ^ acc; - vector_last(ppeaux, stack).st8 = 0; - } else if (vector_last(ppeaux, stack).st8) { - printf("<internal error> Unknown st8 %d during #if evaluation\n", vector_last(ppeaux, stack).st8); - goto eval_fail; - } - if (vector_last(ppeaux, stack).st9 == OPTYP_AOR) { - acc = vector_last(ppeaux, stack).v9 | acc; - vector_last(ppeaux, stack).st9 = 0; - } else if (vector_last(ppeaux, stack).st9) { - printf("<internal error> Unknown st9 %d during #if evaluation\n", vector_last(ppeaux, stack).st9); - goto eval_fail; - } - if (vector_last(ppeaux, stack).st_bool) { - acc = !!acc; - vector_last(ppeaux, stack).st_bool = 0; - } -#pragma GCC diagnostic pop done_complete_acc: vector_del(ppeaux, stack); @@ -1869,7 +1838,7 @@ int proc_unget_token(preproc_t *src, proc_token_t *tok) { } static proc_token_t proc_next_token_aux(preproc_t *src) { if (!vector_size(ppsource, src->prep)) { - return (proc_token_t){ .tokt = PTOK_EOF, .tokv = {.c = (char)EOF} }; + return (proc_token_t){ .tokt = PTOK_EOF, .loginfo = { 0 }, .tokv = {.c = (char)EOF} }; } if (vector_last(ppsource, src->prep).srct == PPSRC_PTOKEN) { proc_token_t ret = vector_last(ppsource, src->prep).srcv.ptok; @@ -1879,7 +1848,7 @@ static proc_token_t proc_next_token_aux(preproc_t *src) { check_if_depth: { if (!vector_size(ppsource, src->prep)) { - return (proc_token_t){ .tokt = PTOK_EOF, .tokv = {.c = (char)EOF} }; + return (proc_token_t){ .tokt = PTOK_EOF, .loginfo = { 0 }, .tokv = {.c = (char)EOF} }; } ppsource_t *ppsrc = &vector_last(ppsource, src->prep); if ((ppsrc->srct == PPSRC_PREPARE) && (ppsrc->srcv.prep.ok_depth != ppsrc->srcv.prep.cond_depth)) { @@ -1896,12 +1865,13 @@ check_if_depth: src->st = PPST_NONE; proc_token_t ret; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = tok.tokv.c; return ret; } else if (tok.tokt == PPTOK_NEWLINE) { src->st = PPST_NL; } else if (tok.tokt == PPTOK_EOF) { - printf("Error: file ended before closing all conditionals (ignoring)\n"); + log_warning(&tok.loginfo, "file ended before closing all conditionals (ignoring)\n"); vector_pop(ppsource, src->prep); goto check_if_depth; } else if ((tok.tokt == PPTOK_SYM) && (src->st == PPST_NL) && (tok.tokv.sym == SYM_HASH)) { @@ -1938,36 +1908,40 @@ check_if_depth: string_del(tok.tokv.str); VECTOR(preproc) *cond = vector_new(preproc); if (!cond) { - printf("Error: failed to allocate #elif condition vector\n"); + log_memory("failed to allocate #elif condition vector\n"); src->st = PPST_NONE; - return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = {.c = '\0'} }; + return (proc_token_t){ .tokt = PTOK_INVALID, .loginfo = tok.loginfo, .tokv = {.c = '\0'} }; } tok = ppsrc_next_token(src); + loginfo_t li = tok.loginfo; while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { + li.lineno_end = tok.loginfo.lineno_end ? tok.loginfo.lineno_end : tok.loginfo.lineno; + li.colno_end = tok.loginfo.colno_end ? tok.loginfo.colno_end : tok.loginfo.colno; if (!vector_push(preproc, cond, tok)) { - printf("Error: failed to add token to #elif condition vector\n"); + log_memory("failed to add token to #elif condition vector\n"); vector_del(preproc, cond); src->st = PPST_NONE; - return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = {.c = '\0'} }; + return (proc_token_t){ .tokt = PTOK_INVALID, .loginfo = tok.loginfo, .tokv = {.c = '\0'} }; } tok = ppsrc_next_token(src); } vector_trim(preproc, cond); khash_t(string_set) *solved_macros = kh_init(string_set); if (!solved_macros) { - printf("Error: failed to allocate #elif solved_macros set\n"); + log_memory("failed to allocate #elif solved_macros set\n"); vector_del(preproc, cond); src->st = PPST_NONE; - return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = {.c = '\0'} }; + return (proc_token_t){ .tokt = PTOK_INVALID, .loginfo = tok.loginfo, .tokv = {.c = '\0'} }; } - VECTOR(preproc) *expanded = proc_do_expand(src->macros_map, cond, solved_macros, src->macros_used); + VECTOR(preproc) *expanded = preproc_do_expand(&li, src->macros_map, cond, solved_macros, src->macros_used); vector_del(preproc, cond); macros_set_del(solved_macros); if (!expanded) { - printf("Error: failed to expand #elif condition\n"); + // Not required as preproc_do_expand already prints an error, but this can be useful + log_error(&li, "failed to expand #elif condition\n"); src->st = PPST_NONE; - return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = {.c = '\0'} }; + return (proc_token_t){ .tokt = PTOK_INVALID, .loginfo = tok.loginfo, .tokv = {.c = '\0'} }; } // Now we need to compute what is pointed by expanded, and increase cond_depth and ok_depth as needed @@ -1975,7 +1949,8 @@ check_if_depth: int64_t res = preproc_eval(expanded, &st, src->target->size_long == 4); vector_del(preproc, expanded); if (!st) { - printf("Error: failed to evaluate #elif condition in (%s)\n", src->cur_file); + // Not required as preproc_eval already prints an error, but this can be useful + log_error(&li, "failed to evaluate #elif condition\n"); src->st = PPST_NONE; return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = {.c = '\0'} }; } @@ -1992,7 +1967,7 @@ check_if_depth: } } if (tok.tokt == PPTOK_EOF) { - printf("Error: file ended before closing all conditionals (ignoring)\n"); + log_warning(&tok.loginfo, "file ended before closing all conditionals (ignoring)\n"); vector_pop(ppsource, src->prep); src->st = PPST_NL; // Should be redundant since TOK_NEWLINE is added before TOK_EOF if required // EOF has an empty destructor @@ -2007,7 +1982,7 @@ check_if_depth: string_del(tok.tokv.str); tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { - printf("Invalid token type %u after '#elifdef' preprocessor command\n", tok.tokt); + log_error(&tok.loginfo, "invalid token type %u after '#elifdef' preprocessor command\n", tok.tokt); goto preproc_ignore_remaining; } if ((ppsrc->srcv.prep.ok_depth == ppsrc->srcv.prep.cond_depth - 1) && !ppsrc->srcv.prep.entered_next_ok_cond) { @@ -2023,7 +1998,7 @@ check_if_depth: string_del(tok.tokv.str); tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { - printf("Invalid token type %u after '#elifdef' preprocessor command\n", tok.tokt); + log_error(&tok.loginfo, "invalid token type %u after '#elifdef' preprocessor command\n", tok.tokt); goto preproc_ignore_remaining; } if ((ppsrc->srcv.prep.ok_depth == ppsrc->srcv.prep.cond_depth - 1) && !ppsrc->srcv.prep.entered_next_ok_cond) { @@ -2061,7 +2036,7 @@ check_if_depth: goto preproc_ignore_remaining_goto; } - printf("Unknown ignored pp command %s (%s), skipping until EOL\n", string_content(tok.tokv.str), src->cur_file); + log_warning(&tok.loginfo, "Unknown ignored pp command %s, skipping until EOL\n", string_content(tok.tokv.str)); preproc_ignore_remaining: while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { preproc_token_del(&tok); @@ -2092,6 +2067,7 @@ check_if_depth: check_next_token: if (!vector_size(ppsource, src->prep)) { ret.tokt = PTOK_EOF; + ret.loginfo = (loginfo_t){0}; ret.tokv.c = (char)EOF; return ret; } @@ -2102,6 +2078,7 @@ start_cur_token: case PPTOK_INVALID: src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = tok.tokv.c; return ret; case PPTOK_IDENT: @@ -2112,6 +2089,7 @@ start_cur_token: macro_t *m = &kh_val(src->macros_map, it); int need_solve = !m->is_funlike; VECTOR(preprocs) *margs = NULL; + loginfo_t li = tok.loginfo; if (m->is_funlike) { preproc_token_t tok2 = ppsrc_next_token(src); size_t nnls = 0; @@ -2146,13 +2124,16 @@ start_cur_token: if ((tok2.tokt == PPTOK_SYM) && (tok2.tokv.sym == SYM_LPAREN)) ++need_solve; else if ((tok2.tokt == PPTOK_SYM) && (tok2.tokv.sym == SYM_RPAREN)) --need_solve; } + li.lineno_end = tok2.loginfo.lineno_end ? tok2.loginfo.lineno_end : tok2.loginfo.lineno; + li.colno_end = tok2.loginfo.colno_end ? tok2.loginfo.colno_end : tok2.loginfo.colno; if (need_solve) { - printf("Unfinished fun-like macro %s\n", string_content(tok.tokv.str)); + log_error(&li, "unfinished function-like macro %s\n", string_content(tok.tokv.str)); vector_del(preprocs, margs); vector_del(preproc, marg); string_del(tok.tokv.str); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok2.loginfo; ret.tokv.c = tok.tokv.c; return ret; } @@ -2166,11 +2147,12 @@ start_cur_token: need_solve = 1; } else { if (!vector_reserve(ppsource, src->prep, vector_size(ppsource, src->prep) + nnls + 1)) { - printf("Memory error (undoing lookahead for macro use %s)\n", string_content(tok.tokv.str)); + log_memory("undoing lookahead for macro use %s\n", string_content(tok.tokv.str)); string_del(tok.tokv.str); preproc_token_del(&tok2); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = li; ret.tokv.c = '\0'; return ret; } @@ -2189,22 +2171,24 @@ start_cur_token: char *mname = string_steal(tok.tokv.str); - VECTOR(preproc) *solved = proc_solve_macro(src->macros_map, mname, m, margs, solved_macros, NULL); + VECTOR(preproc) *solved = preproc_solve_macro(&li, src->macros_map, mname, m, margs, solved_macros, NULL); if (margs) vector_del(preprocs, margs); macros_set_del(solved_macros); if (!solved) { src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = li; ret.tokv.c = '\0'; return ret; } // If the expansion is empty, don't push it if (vector_size(preproc, solved)) { if (!vector_push(ppsource, src->prep, ((ppsource_t){.srct = PPSRC_PPTOKENS, .srcv.pptoks = {.idx = 0, .toks = solved}}))) { - printf("Memory error (pushing expanded macro)\n"); + log_memory("pushing expanded macro\n"); vector_del(preproc, solved); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = li; ret.tokv.c = '\0'; return ret; } @@ -2219,11 +2203,12 @@ start_cur_token: if (0) { solve_err_mem: - printf("Memory error (parsing macro use %s)\n", string_content(tok.tokv.str)); + log_memory("parsing macro use %s\n", string_content(tok.tokv.str)); if (margs) vector_del(preprocs, margs); string_del(tok.tokv.str); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = li; ret.tokv.c = '\0'; return ret; } @@ -2240,20 +2225,24 @@ start_cur_token: ret.tokt = PTOK_KEYWORD; ret.tokv.kw = kh_val(str2kw, it); } + ret.loginfo = tok.loginfo; return ret; } case PPTOK_NUM: src->st = (src->st == PPST_PRAGMA_EXPLICIT) ? PPST_PRAGMA_EXPLICIT : PPST_NONE; ret.tokt = PTOK_NUM; + ret.loginfo = tok.loginfo; ret.tokv.str = tok.tokv.str; return ret; case PPTOK_STRING: src->st = (src->st == PPST_PRAGMA_EXPLICIT) ? PPST_PRAGMA_EXPLICIT : PPST_NONE; ret.tokt = PTOK_STRING; + ret.loginfo = tok.loginfo; ret.tokv = (union proc_token_val_u){.sstr = tok.tokv.sstr, .sisstr = tok.tokv.sisstr}; return ret; case PPTOK_INCL: src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = tok.tokv.sisstr ? '<' : '"'; string_del(tok.tokv.sstr); return ret; @@ -2262,19 +2251,14 @@ start_cur_token: tok = ppsrc_next_token(src); if ((tok.tokt == PPTOK_NEWLINE) || (tok.tokt == PPTOK_EOF)) { // Empty preprocessor command - if (tok.tokt == PPTOK_NEWLINE) { - ret.tokt = PTOK_EOF; - ret.tokv.c = tok.tokv.c; - return ret; - } else { - goto check_next_token; - } + goto start_cur_token; } if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) goto preproc_hash_err; if (!strcmp(string_content(tok.tokv.str), "include") || !strcmp(string_content(tok.tokv.str), "include_next")) { int is_next = string_content(tok.tokv.str)[7] == '_'; string_del(tok.tokv.str); tok = ppsrc_next_token(src); + loginfo_t li = tok.loginfo; string_t *incl_file; int is_sys; if (tok.tokt == PPTOK_INCL) { @@ -2282,48 +2266,59 @@ start_cur_token: // Assume we only have one #include "..." path, so include_next is always a system include is_sys = is_next || !tok.tokv.sisstr; tok = ppsrc_next_token(src); // Token was moved + loginfo_t ignored_infos = tok.loginfo; int has_ignored = 0; 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); + has_ignored = 1; + ignored_infos.lineno_end = tok.loginfo.lineno_end ? tok.loginfo.lineno_end : tok.loginfo.lineno; + ignored_infos.colno_end = tok.loginfo.colno_end ? tok.loginfo.colno_end : tok.loginfo.colno; preproc_token_del(&tok); tok = ppsrc_next_token(src); } + if (has_ignored) { + log_warning(&ignored_infos, "ignored tokens after #include%s directive\n", is_next ? "_next" : ""); + } } else { // Expand macro, then try again VECTOR(preproc) *incl = vector_new(preproc); if (!incl) { - printf("Error: failed to allocate #include tokens vector (%s)\n", src->cur_file); + log_memory("failed to allocate #include tokens vector\n"); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { if (!vector_push(preproc, incl, tok)) { - printf("Error: failed to add token to #include tokens vector (%s)\n", src->cur_file); + log_memory("failed to add token to #include tokens vector\n"); vector_del(preproc, incl); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } + li.lineno_end = tok.loginfo.lineno_end ? tok.loginfo.lineno_end : tok.loginfo.lineno; + li.colno_end = tok.loginfo.colno_end ? tok.loginfo.colno_end : tok.loginfo.colno; tok = ppsrc_next_token(src); } vector_trim(preproc, incl); khash_t(string_set) *solved_macros = kh_init(string_set); if (!solved_macros) { - printf("Error: failed to allocate #include solved_macros set (%s)\n", src->cur_file); + log_memory("failed to allocate #include solved_macros set\n"); vector_del(preproc, incl); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } - VECTOR(preproc) *expanded = proc_do_expand(src->macros_map, incl, solved_macros, src->macros_used); + VECTOR(preproc) *expanded = preproc_do_expand(&li, src->macros_map, incl, solved_macros, src->macros_used); vector_del(preproc, incl); macros_set_del(solved_macros); if (!expanded) { - printf("Error: failed to expand #include tokens (%s)\n", src->cur_file); + log_error(&li, "failed to expand #include tokens\n"); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; ret.tokv.c = '\0'; @@ -2332,27 +2327,27 @@ start_cur_token: // Now we need to check what is pointed by expanded if (!vector_size(preproc, expanded)) { - printf("Error: missing #include name (%s)\n", src->cur_file); + log_error(&li, "missing #include name\n"); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } if (vector_content(preproc, expanded)[0].tokt == PPTOK_STRING) { is_sys = is_next || src->is_sys; preproc_token_t *exp = vector_content(preproc, expanded); - // TODO - printf("Error: TODO: #include <expanded, first is string '%s' (%d)> (%s)\n", - string_content(exp->tokv.sstr), exp->tokv.sisstr, src->cur_file); + log_error(&li, "TODO: #include <expanded, first is string '%s' (%d)>\n", string_content(exp->tokv.sstr), exp->tokv.sisstr); vector_del(preproc, expanded); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } else if ((vector_content(preproc, expanded)[0].tokt == PPTOK_SYM) && (vector_content(preproc, expanded)[0].tokv.sym == SYM_LT) && (vector_last(preproc, expanded).tokt == PPTOK_SYM) && (vector_last(preproc, expanded).tokv.sym == SYM_GT) && (vector_size(preproc, expanded) >= 3)) { - printf("Warning: #include command with macro expansion, assuming no space is present in the file name\n"); + log_warning(&li, "#include command with macro expansion, assuming no space is present in the file name\n"); is_sys = 0; incl_file = string_new(); for (vector_preproc_elem *tok2 = expanded->content + 1; tok2 < expanded->content + expanded->vsize - 1; ++tok2) { @@ -2360,26 +2355,26 @@ start_cur_token: case PPTOK_IDENT: case PPTOK_IDENT_UNEXP: if (!string_add_string(incl_file, tok2->tokv.str)) { - printf("Error: failed to add ident to include string (%s)\n", src->cur_file); + log_memory("failed to add ident to include string\n"); vector_del(preproc, expanded); string_del(incl_file); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } break; case PPTOK_SYM: - for (const char *s = sym2str[tok2->tokv.sym]; *s; ++s) { - if (!string_add_char(incl_file, *s)) { - printf("Error: failed to add symbol to include string (%s)\n", src->cur_file); - vector_del(preproc, expanded); - string_del(incl_file); - src->st = PPST_NONE; - ret.tokt = PTOK_INVALID; - ret.tokv.c = '\0'; - return ret; - } + if (!string_add_cstr(incl_file, sym2str[tok2->tokv.sym])) { + log_memory("failed to add symbol to include string\n"); + vector_del(preproc, expanded); + string_del(incl_file); + src->st = PPST_NONE; + ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; + ret.tokv.c = '\0'; + return ret; } break; @@ -2392,32 +2387,39 @@ start_cur_token: case PPTOK_START_LINE_COMMENT: case PPTOK_EOF: default: - printf("Error: TODO: add token type %u to include string (%s)\n", tok2->tokt, src->cur_file); + log_error(&li, "TODO: add token type %u to include string\n", tok2->tokt); vector_del(preproc, expanded); string_del(incl_file); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } } vector_del(preproc, expanded); } else { - printf("Error: invalid #include command (macro expansion does not result in string or <...>) (%s)\n", src->cur_file); + log_error(&li, "invalid #include command (macro expansion does not result in string or <...>)\n"); vector_del(preproc, expanded); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } } // cur_pathno == 0 if cur_file was from an #include "...", otherwise idx + 1 +#ifdef LOG_INCLUDE + printf("Opening %s as %s from system path %zu\n", string_content(incl_file), + is_sys ? "system header" : "cur header", is_next ? src->cur_pathno : 0); +#endif if ((is_sys || !try_open_dir(src, incl_file)) && !try_open_sys(src, incl_file, is_next ? src->cur_pathno : 0)) { - printf("Failed to open %s\n", string_content(incl_file)); + log_error(&li, "failed to open %s\n", string_content(incl_file)); string_del(incl_file); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; - ret.tokv.c = tok.tokv.sisstr ? '<' : '"'; + ret.loginfo = li; + ret.tokv.c = is_sys ? '<' : '"'; return ret; } string_del(incl_file); @@ -2427,16 +2429,17 @@ start_cur_token: string_del(tok.tokv.str); tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { - printf("Invalid token type %u after '#define' preprocessor command\n", tok.tokt); + log_error(&tok.loginfo, "invalid token type %u after '#define' preprocessor command\n", tok.tokt); goto preproc_hash_err; } string_t *defname = tok.tokv.str; macro_t m = (macro_t){ .is_funlike = 0, .has_varargs = 0, .nargs = 0, .toks = vector_new(mtoken) }; if (!m.toks) { - printf("Failed to allocate token vector for macro %s, returning EOF\n", string_content(defname)); + log_memory("failed to allocate token vector for macro %s\n", string_content(defname)); string_del(defname); // Token is now freed - ret.tokt = PTOK_EOF; - ret.tokv.c = (char)EOF; + ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; + ret.tokv.c = '\0'; return ret; } khash_t(argid_map) *args = NULL; @@ -2445,11 +2448,12 @@ start_cur_token: m.is_funlike = 1; args = kh_init(argid_map); if (!args) { - printf("Failed to allocate args map for macro %s, returning EOF\n", string_content(defname)); + log_memory("failed to allocate args map for macro %s\n", string_content(defname)); string_del(defname); // Token is now freed vector_del(mtoken, m.toks); - ret.tokt = PTOK_EOF; - ret.tokv.c = (char)EOF; + ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; + ret.tokv.c = '\0'; return ret; } m.nargs = 0; @@ -2466,17 +2470,18 @@ start_cur_token: char *tok_str = strdup("__VA_ARGS__"); khiter_t kh_k = kh_put(argid_map, args, tok_str, &kh_ret); // Moves the string content if (kh_ret < 0) { // Failed to move, needs to free here - printf("Failed to push arg %s for macro %s, returning EOF\n", tok_str, string_content(defname)); + log_memory("failed to push arg %s for macro %s\n", tok_str, string_content(defname)); string_del(defname); free(tok_str); vector_del(mtoken, m.toks); argid_map_del(args); - ret.tokt = PTOK_EOF; - ret.tokv.c = (char)EOF; + ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; + ret.tokv.c = '\0'; return ret; } if (kh_ret == 0) { - printf("Duplicate arg %s defining macro %s\n", tok_str, string_content(defname)); + log_error(&tok.loginfo, "duplicate argument name %s defining macro %s\n", tok_str, string_content(defname)); string_del(defname); vector_del(mtoken, m.toks); argid_map_del(args); @@ -2486,7 +2491,7 @@ start_cur_token: // Empty token destructor tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_RPAREN)) { - printf("Invalid token type %u after variadic macro arguments definition\n", tok.tokt); + log_error(&tok.loginfo, "invalid token type %u after variadic macro arguments definition\n", tok.tokt); string_del(defname); vector_del(mtoken, m.toks); argid_map_del(args); @@ -2499,17 +2504,18 @@ start_cur_token: char *tok_str = string_steal(tok.tokv.str); khiter_t kh_k = kh_put(argid_map, args, tok_str, &kh_ret); // Moves the string content if (kh_ret < 0) { // Failed to move, needs to free here - printf("Failed to push arg %s for macro %s, returning EOF\n", tok_str, string_content(defname)); + log_memory("failed to push arg %s for macro %s\n", tok_str, string_content(defname)); string_del(defname); free(tok_str); vector_del(mtoken, m.toks); argid_map_del(args); - ret.tokt = PTOK_EOF; - ret.tokv.c = (char)EOF; + ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; + ret.tokv.c = '\0'; return ret; } if (kh_ret == 0) { - printf("Duplicate arg %s defining macro %s\n", tok_str, string_content(defname)); + log_error(&tok.loginfo, "duplicate argument name %s defining macro %s\n", tok_str, string_content(defname)); string_del(defname); vector_del(mtoken, m.toks); argid_map_del(args); @@ -2534,7 +2540,7 @@ start_cur_token: // Empty token destructor tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_RPAREN)) { - printf("Invalid token type %u after variadic macro arguments definition\n", tok.tokt); + log_error(&tok.loginfo, "invalid token type %u after variadic macro arguments definition\n", tok.tokt); string_del(defname); vector_del(mtoken, m.toks); argid_map_del(args); @@ -2543,7 +2549,7 @@ start_cur_token: ok = 1; break; } else { - printf("Invalid %s type %u during variadic macro arguments definition\n", + log_error(&tok.loginfo, "invalid %s type %u in macro arguments definition\n", (tok.tokt == PPTOK_SYM) ? "symbol" : "token", (tok.tokt == PPTOK_SYM) ? tok.tokv.sym : tok.tokt); string_del(defname); @@ -2552,7 +2558,7 @@ start_cur_token: goto preproc_hash_err; } } else { - printf("Invalid %s type %u as macro arguments definition name\n", + log_error(&tok.loginfo, "invalid %s type %u as macro arguments definition name\n", (tok.tokt == PPTOK_SYM) ? "symbol" : "token", (tok.tokt == PPTOK_SYM) ? tok.tokv.sym : tok.tokt); string_del(defname); vector_del(mtoken, m.toks); @@ -2562,7 +2568,7 @@ start_cur_token: } } if (!ok) { - printf("Invalid macro definition for %s\n", string_content(defname)); + log_error(&tok.loginfo, "invalid macro definition for %s\n", string_content(defname)); string_del(defname); vector_del(mtoken, m.toks); argid_map_del(args); @@ -2582,7 +2588,7 @@ start_cur_token: while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { if ((tok.tokt == PPTOK_SYM) && (tok.tokv.sym == SYM_HASH)) { if (state & ST_STR) { - printf("Warning: duplicated stringify in macro definition (defining %s)\n", string_content(defname)); + log_warning(&tok.loginfo, "duplicated stringify in macro definition (defining %s)\n", string_content(defname)); } else { state |= ST_STR; } @@ -2592,9 +2598,9 @@ start_cur_token: } if ((tok.tokt == PPTOK_SYM) && (tok.tokv.sym == SYM_HASHHASH)) { if (state & ST_CONCAT) { - printf("Warning: duplicated concatenation in macro definition (defining %s)\n", string_content(defname)); + log_warning(&tok.loginfo, "duplicated concatenation in macro definition (defining %s)\n", string_content(defname)); } else if (!vector_size(mtoken, m.toks)) { - printf("Warning: invalid concatenation at start of macro definition (defining %s)\n", string_content(defname)); + log_warning(&tok.loginfo, "invalid concatenation at start of macro definition (defining %s)\n", string_content(defname)); } else { state |= ST_CONCAT; } @@ -2612,23 +2618,59 @@ start_cur_token: } } if (argid != -1u) { - mtok = mtoken_new_arg(argid, state & ST_STR); // TODO: check for != NULL + mtok = mtoken_new_arg(argid, state & ST_STR); + if (!mtok) { + log_memory("failed to allocate new m-token (defining %s)\n", string_content(defname)); + string_del(defname); + macro_del(&m); + src->st = PPST_NONE; + ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; + ret.tokv.c = tok.tokv.c; + return ret; + } state &= ~ST_STR; } else { - mtok = mtoken_new_token(tok); // Token moved // TODO: check for != NULL + mtok = mtoken_new_token(tok); // Token moved + if (!mtok) { + log_memory("failed to allocate new m-token (defining %s)\n", string_content(defname)); + string_del(defname); + macro_del(&m); + if (tok.tokt == PPTOK_NEWLINE) goto check_next_token; + else goto start_cur_token; + } if (state & ST_STR) { - printf("Warning: invalid stringify before token (defining %s)\n", string_content(defname)); + log_warning(&tok.loginfo, "invalid stringify before token (defining %s)\n", string_content(defname)); state &= ~ST_STR; } } if (state & ST_CONCAT) { mtoken_t *mtok2 = vector_last(mtoken, m.toks); // Guaranteed to exist before setting ST_CONCAT - mtok = mtoken_new_concat(mtok2, mtok); // TODO: check for != NULL + mtok = mtoken_new_concat(mtok2, mtok); + if (!mtok) { + log_memory("failed to allocate new m-token concatenation (defining %s)\n", string_content(defname)); + string_del(defname); + macro_del(&m); + vector_pop_nodel(mtoken, m.toks); + src->st = PPST_NONE; + ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; + ret.tokv.c = tok.tokv.c; + return ret; + } vector_last(mtoken, m.toks) = mtok; state &= ~ST_CONCAT; } else { - // TODO: check for error - vector_push(mtoken, m.toks, mtok); + if (!vector_push(mtoken, m.toks, mtok)) { + log_memory("failed to add m-token (defining %s)\n", string_content(defname)); + string_del(defname); + macro_del(&m); + src->st = PPST_NONE; + ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; + ret.tokv.c = tok.tokv.c; + return ret; + } } // mtok moved to the vector tok = ppsrc_next_token(src); @@ -2638,41 +2680,47 @@ start_cur_token: if (args) argid_map_del(args); if (tok.tokt == PPTOK_INVALID) { // Abort + log_error(&tok.loginfo, "unexpected invalid input token\n"); string_del(defname); macro_del(&m); - if (tok.tokt == PPTOK_NEWLINE) goto check_next_token; - else goto start_cur_token; + src->st = PPST_NONE; + ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; + ret.tokv.c = tok.tokv.c; + return ret; } else { // NL and EOF have empty destructors khiter_t kh_k; int iret; char *mname_dup = string_steal(defname); - // if (m.is_funlike) printf("OK for %s: %u args", mname_dup, m.nargs); - // else printf("OK for %s: no arg", mname_dup); - // printf("\n"); - // vector_for(mtoken, it, m.toks) { - // printf("Macro token: "); - // print_macro_tok(*it); - // printf("\n"); - // } kh_k = kh_put(string_set, src->macros_defined, mname_dup, &iret); - // TODO: check iret? - if (iret >= 1) { + if (iret < 0) { + // Abort + log_memory("failed to remember macro %s as defined, aborting\n", mname_dup); + free(mname_dup); + macro_del(&m); + src->st = PPST_NONE; + ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; + ret.tokv.c = tok.tokv.c; + return ret; + } else if (iret > 0) { mname_dup = strdup(mname_dup); } kh_k = kh_put(macros_map, src->macros_map, mname_dup, &iret); if (iret < 0) { // Abort - printf("Failed to remember macro %s, aborting\n", mname_dup); + log_memory("failed to remember macro %s, aborting\n", mname_dup); free(mname_dup); macro_del(&m); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = tok.tokv.c; return ret; } else if (iret == 0) { // Ignore - // Too noisy printf("Duplicated macro %s\n", mname_dup); + // Too noisy log_warning(&tok.loginfo, "Duplicated macro %s\n", mname_dup); free(mname_dup); macro_del(&m); } else { @@ -2685,7 +2733,7 @@ start_cur_token: string_del(tok.tokv.str); tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { - printf("Invalid token type %u after '#undef' preprocessor command\n", tok.tokt); + log_error(&tok.loginfo, "invalid token type %u after '#undef' preprocessor command\n", tok.tokt); goto preproc_hash_err; } string_t *mname = tok.tokv.str; @@ -2708,7 +2756,7 @@ start_cur_token: if (tok.tokt == PPTOK_NEWLINE) goto check_next_token; else goto start_cur_token; } else if (!strcmp(string_content(tok.tokv.str), "error")) { - printf("Error: #error command (%s):", src->cur_file); + log_error(&tok.loginfo, "#error command:"); string_del(tok.tokv.str); tok = ppsrc_next_token(src); while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { @@ -2740,10 +2788,11 @@ start_cur_token: printf("\n"); vector_clear(ppsource, src->prep); ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = (char)EOF; return ret; } else if (!strcmp(string_content(tok.tokv.str), "warning")) { - printf("Warning: #warning command (%s):", src->cur_file); + log_warning(&tok.loginfo, "#warning command:"); tok = ppsrc_next_token(src); while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { switch (tok.tokt) { @@ -2754,10 +2803,12 @@ start_cur_token: case PPTOK_SYM: printf("%s%s", (tok.tokv.sym == SYM_COMMA) ? "" : " ", sym2str[tok.tokv.sym]); break; + case PPTOK_STRING: + printf(" %c%s%c", tok.tokv.sisstr ? '"' : '\'', string_content(tok.tokv.sstr), tok.tokv.sisstr ? '"' : '\''); + break; case PPTOK_INVALID: case PPTOK_NUM: - case PPTOK_STRING: case PPTOK_INCL: case PPTOK_NEWLINE: case PPTOK_BLANK: @@ -2775,15 +2826,16 @@ start_cur_token: string_del(tok.tokv.str); tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { - printf("Unknown pragma directive, skipping until EOL\n"); + log_error(&tok.loginfo, "unknown pragma directive, skipping until EOL\n"); goto preproc_hash_err; } else if (!strcmp(string_content(tok.tokv.str), "wrappers")) { string_del(tok.tokv.str); tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { - printf("Unknown pragma wrappers directive, skipping until EOL\n"); + log_error(&tok.loginfo, "unknown pragma wrappers directive, skipping until EOL\n"); goto preproc_hash_err; } else if (!strcmp(string_content(tok.tokv.str), "allow_ints_ext")) { + ret.loginfo = tok.loginfo; while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { preproc_token_del(&tok); tok = ppsrc_next_token(src); @@ -2798,11 +2850,12 @@ start_cur_token: string_del(tok.tokv.str); tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { - printf("Invalid pragma wrappers explicit_simple directive, skipping until EOL\n"); + log_error(&tok.loginfo, "invalid pragma wrappers explicit_simple directive, skipping until EOL\n"); goto preproc_hash_err; } src->st = PPST_NL; ret.tokt = PTOK_PRAGMA; + ret.loginfo = tok.loginfo; ret.tokv.pragma.typ = PRAGMA_SIMPLE_SU; ret.tokv.pragma.val = tok.tokv.str; tok = ppsrc_next_token(src); @@ -2820,11 +2873,12 @@ start_cur_token: string_del(tok.tokv.str); tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { - printf("Invalid pragma wrappers explicit_simple directive, skipping until EOL\n"); + log_error(&tok.loginfo, "invalid pragma wrappers explicit_simple directive, skipping until EOL\n"); goto preproc_hash_err; } src->st = PPST_PRAGMA_EXPLICIT; ret.tokt = PTOK_PRAGMA; + ret.loginfo = tok.loginfo; ret.tokv.pragma.typ = PRAGMA_EXPLICIT_CONV; ret.tokv.pragma.val = tok.tokv.str; return ret; @@ -2832,69 +2886,78 @@ start_cur_token: string_del(tok.tokv.str); tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { - printf("Invalid pragma wrappers explicit_simple directive, skipping until EOL\n"); + log_error(&tok.loginfo, "invalid pragma wrappers explicit_simple directive, skipping until EOL\n"); goto preproc_hash_err; } src->st = PPST_PRAGMA_EXPLICIT; ret.tokt = PTOK_PRAGMA; + ret.loginfo = tok.loginfo; ret.tokv.pragma.typ = PRAGMA_EXPLICIT_CONV_STRICT; ret.tokv.pragma.val = tok.tokv.str; return ret; } else { - printf("Unknown pragma wrappers directive '%s', skipping until EOL\n", string_content(tok.tokv.str)); + log_error(&tok.loginfo, "unknown pragma wrappers directive '%s', skipping until EOL\n", string_content(tok.tokv.str)); goto preproc_hash_err; } } else { - printf("Unknown pragma directive '%s', skipping until EOL\n", string_content(tok.tokv.str)); + log_error(&tok.loginfo, "unknown pragma directive '%s', skipping until EOL\n", string_content(tok.tokv.str)); goto preproc_hash_err; } } else if (!strcmp(string_content(tok.tokv.str), "if")) { if (vector_last(ppsource, src->prep).srct != PPSRC_PREPARE) { - printf("Error: invalid #if source type %u\n", vector_last(ppsource, src->prep).srct); + log_error(&tok.loginfo, "invalid #if source type %u\n", vector_last(ppsource, src->prep).srct); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } string_del(tok.tokv.str); VECTOR(preproc) *cond = vector_new(preproc); if (!cond) { - printf("Error: failed to allocate #if condition vector\n"); + log_memory("failed to allocate #if condition vector\n"); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } tok = ppsrc_next_token(src); + loginfo_t li = tok.loginfo; while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { if (!vector_push(preproc, cond, tok)) { - printf("Error: failed to add token to #if condition vector\n"); + log_memory("failed to add token to #if condition vector\n"); vector_del(preproc, cond); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } + li.lineno_end = tok.loginfo.lineno_end ? tok.loginfo.lineno_end : tok.loginfo.lineno; + li.colno_end = tok.loginfo.colno_end ? tok.loginfo.colno_end : tok.loginfo.colno; tok = ppsrc_next_token(src); } vector_trim(preproc, cond); khash_t(string_set) *solved_macros = kh_init(string_set); if (!solved_macros) { - printf("Error: failed to allocate #if solved_macros set\n"); + log_memory("failed to allocate #if solved_macros set\n"); vector_del(preproc, cond); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } - VECTOR(preproc) *expanded = proc_do_expand(src->macros_map, cond, solved_macros, src->macros_used); + VECTOR(preproc) *expanded = preproc_do_expand(&li, src->macros_map, cond, solved_macros, src->macros_used); vector_del(preproc, cond); macros_set_del(solved_macros); if (!expanded) { - printf("Error: failed to expand #if condition\n"); + log_error(&li, "Error: failed to expand #if condition\n"); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } @@ -2904,9 +2967,10 @@ start_cur_token: int64_t res = preproc_eval(expanded, &st, src->target->size_long == 4); vector_del(preproc, expanded); if (!st) { - printf("Error: failed to evaluate #if condition (%s)\n", src->cur_file); + log_error(&li, "Error: failed to evaluate #if condition\n"); src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = '\0'; return ret; } @@ -2922,13 +2986,13 @@ start_cur_token: } } else if (!strcmp(string_content(tok.tokv.str), "ifdef")) { if (vector_last(ppsource, src->prep).srct != PPSRC_PREPARE) { - printf("Error: invalid #ifdef source type %u\n", vector_last(ppsource, src->prep).srct); + log_error(&tok.loginfo, "invalid #ifdef source type %u\n", vector_last(ppsource, src->prep).srct); goto preproc_hash_err; } string_del(tok.tokv.str); tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { - printf("Invalid token type %u after '#ifdef' preprocessor command\n", tok.tokt); + log_error(&tok.loginfo, "invalid token type %u after '#ifdef' preprocessor command\n", tok.tokt); goto preproc_hash_err; } khiter_t it = kh_get(macros_map, src->macros_map, string_content(tok.tokv.str)); @@ -2952,13 +3016,13 @@ start_cur_token: } } else if (!strcmp(string_content(tok.tokv.str), "ifndef")) { if (vector_last(ppsource, src->prep).srct != PPSRC_PREPARE) { - printf("Error: invalid #ifndef source type %u\n", vector_last(ppsource, src->prep).srct); + log_error(&tok.loginfo, "invalid #ifndef source type %u\n", vector_last(ppsource, src->prep).srct); goto preproc_hash_err; } string_del(tok.tokv.str); tok = ppsrc_next_token(src); if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { - printf("Invalid token type %u after '#ifndef' preprocessor command\n", tok.tokt); + log_error(&tok.loginfo, "invalid token type %u after '#ifndef' preprocessor command\n", tok.tokt); goto preproc_hash_err; } khiter_t it = kh_get(macros_map, src->macros_map, string_content(tok.tokv.str)); @@ -2983,7 +3047,7 @@ start_cur_token: } else if (!strcmp(string_content(tok.tokv.str), "elif")) { // We are already in an #if or #elif (or #else) with a match, so we need to leave it and go to the very top if (vector_last(ppsource, src->prep).srct != PPSRC_PREPARE) { - printf("Error: invalid #elif source type %u\n", vector_last(ppsource, src->prep).srct); + log_error(&tok.loginfo, "invalid #elif source type %u\n", vector_last(ppsource, src->prep).srct); goto preproc_hash_err; } if (vector_last(ppsource, src->prep).srcv.prep.ok_depth) { @@ -2991,13 +3055,13 @@ start_cur_token: --vector_last(ppsource, src->prep).srcv.prep.ok_depth; goto preproc_hash_err_goto; } else { - printf("Warning: unexpected #elif preprocessor command\n"); + log_warning(&tok.loginfo, "unexpected #elif preprocessor command\n"); goto preproc_hash_err; } } else if (!strcmp(string_content(tok.tokv.str), "elifdef")) { // We are already in an #if or #elif (or #else) with a match, so we need to leave it and go to the very top if (vector_last(ppsource, src->prep).srct != PPSRC_PREPARE) { - printf("Error: invalid #elifdef source type %u\n", vector_last(ppsource, src->prep).srct); + log_error(&tok.loginfo, "invalid #elifdef source type %u\n", vector_last(ppsource, src->prep).srct); goto preproc_hash_err; } string_del(tok.tokv.str); @@ -3017,13 +3081,13 @@ start_cur_token: --vector_last(ppsource, src->prep).srcv.prep.ok_depth; goto preproc_hash_err_goto; } else { - printf("Warning: unexpected #elifdef preprocessor command\n"); + log_warning(&tok.loginfo, "unexpected #elifdef preprocessor command\n"); goto preproc_hash_err; } } else if (!strcmp(string_content(tok.tokv.str), "elifndef")) { // We are already in an #if or #elif (or #else) with a match, so we need to leave it and go to the very top if (vector_last(ppsource, src->prep).srct != PPSRC_PREPARE) { - printf("Error: invalid #elifndef source type %u\n", vector_last(ppsource, src->prep).srct); + log_error(&tok.loginfo, "invalid #elifndef source type %u\n", vector_last(ppsource, src->prep).srct); goto preproc_hash_err; } string_del(tok.tokv.str); @@ -3043,13 +3107,13 @@ start_cur_token: --vector_last(ppsource, src->prep).srcv.prep.ok_depth; goto preproc_hash_err_goto; } else { - printf("Warning: unexpected #elifndef preprocessor command\n"); + log_warning(&tok.loginfo, "unexpected #elifndef preprocessor command\n"); goto preproc_hash_err; } } else if (!strcmp(string_content(tok.tokv.str), "else")) { // We are already in an #if or #elif (or #else) with a match, so we need to leave it and go to the very top if (vector_last(ppsource, src->prep).srct != PPSRC_PREPARE) { - printf("Error: invalid #else source type %u\n", vector_last(ppsource, src->prep).srct); + log_error(&tok.loginfo, "invalid #else source type %u\n", vector_last(ppsource, src->prep).srct); goto preproc_hash_err; } if (vector_last(ppsource, src->prep).srcv.prep.ok_depth) { @@ -3057,24 +3121,24 @@ start_cur_token: --vector_last(ppsource, src->prep).srcv.prep.ok_depth; goto preproc_hash_err_goto; } else { - printf("Warning: unexpected #else preprocessor command\n"); + log_warning(&tok.loginfo, "unexpected #else preprocessor command\n"); goto preproc_hash_err; } } else if (!strcmp(string_content(tok.tokv.str), "endif")) { if (vector_last(ppsource, src->prep).srct != PPSRC_PREPARE) { - printf("Error: invalid #endif source type %u\n", vector_last(ppsource, src->prep).srct); + log_error(&tok.loginfo, "invalid #endif source type %u\n", vector_last(ppsource, src->prep).srct); goto preproc_hash_err; } if (vector_last(ppsource, src->prep).srcv.prep.ok_depth) { --vector_last(ppsource, src->prep).srcv.prep.ok_depth; --vector_last(ppsource, src->prep).srcv.prep.cond_depth; } else { - printf("Warning: unexpected #endif preprocessor command\n"); + log_warning(&tok.loginfo, "unexpected #endif preprocessor command\n"); } goto preproc_hash_err; } - printf("Unknown pp command %s (%s), skipping until EOL\n", string_content(tok.tokv.str), src->cur_file); + log_warning(&tok.loginfo, "Unknown preprocessor command %s, skipping until EOL\n", string_content(tok.tokv.str)); preproc_hash_err: while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { preproc_token_del(&tok); @@ -3093,12 +3157,14 @@ start_cur_token: } src->st = (src->st == PPST_PRAGMA_EXPLICIT) ? PPST_PRAGMA_EXPLICIT : PPST_NONE; ret.tokt = PTOK_SYM; + ret.loginfo = tok.loginfo; ret.tokv.sym = tok.tokv.sym; return ret; case PPTOK_NEWLINE: if (src->st == PPST_PRAGMA_EXPLICIT) { src->st = PPST_NL; ret.tokt = PTOK_SYM; + ret.loginfo = tok.loginfo; ret.tokv.sym = SYM_SEMICOLON; return ret; } @@ -3107,18 +3173,22 @@ start_cur_token: case PPTOK_BLANK: src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = tok.tokv.c; return ret; case PPTOK_START_LINE_COMMENT: src->st = PPST_NONE; ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; ret.tokv.c = tok.tokv.c; return ret; case PPTOK_EOF: if ((vector_last(ppsource, src->prep).srct == PPSRC_PREPARE) && vector_last(ppsource, src->prep).srcv.prep.cond_depth) { - printf("Error: file ended before closing all conditionals (ignoring)\n"); + log_warning(&tok.loginfo, "file ended before closing all conditionals (ignoring)\n"); } - // printf("Closing %s\n", src->cur_file); +#ifdef LOG_CLOSE + printf("Closing %s\n", src->cur_file); +#endif if (vector_last(ppsource, src->prep).srct == PPSRC_PREPARE) { if (src->dirname) free(src->dirname); if (src->cur_file) free(src->cur_file); @@ -3133,7 +3203,9 @@ start_cur_token: if (src->st == PPST_PRAGMA_EXPLICIT) { src->st = PPST_NL; ret.tokt = PTOK_SYM; + ret.loginfo = (loginfo_t){0}; // The token's loginfo may have been deleted by the vector_pop above ret.tokv.sym = SYM_SEMICOLON; + // Empty destructor return ret; } src->st = PPST_NL; // Should be redundant since TOK_NEWLINE is added before TOK_EOF if required @@ -3142,9 +3214,10 @@ start_cur_token: goto check_next_token; default: - printf("Unknown next pp token type %u, sending EOF\n", tok.tokt); - ret.tokt = PTOK_EOF; - ret.tokv.c = (char)EOF; + log_error(&tok.loginfo, "unknown preprocessor token type %u, sending INVALID\n", tok.tokt); + ret.tokt = PTOK_INVALID; + ret.loginfo = tok.loginfo; + ret.tokv.c = '\0'; return ret; } } @@ -3155,7 +3228,7 @@ proc_token_t proc_next_token(preproc_t *src) { proc_token_t ret2 = proc_next_token_aux(src); 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"); + log_memory("failed to concatenate adjacent strings\n"); string_del(ret.tokv.sstr); string_del(ret2.tokv.sstr); src->st = PPST_NONE; @@ -3164,9 +3237,11 @@ proc_token_t proc_next_token(preproc_t *src) { return ret; } string_del(ret2.tokv.sstr); + ret.loginfo.lineno_end = ret2.loginfo.lineno_end ? ret2.loginfo.lineno_end : ret2.loginfo.lineno; + ret.loginfo.colno_end = ret2.loginfo.colno_end ? ret2.loginfo.colno_end : ret2.loginfo.colno; } else { if (!proc_unget_token(src, &ret2)) { - printf("Error: failed to unget token next to string token\n"); + log_memory("failed to unget token next to string token\n"); string_del(ret.tokv.sstr); proc_token_del(&ret2); src->st = PPST_NONE; |