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/parse.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/parse.c')
| -rw-r--r-- | wrapperhelper/src/parse.c | 1064 |
1 files changed, 571 insertions, 493 deletions
diff --git a/wrapperhelper/src/parse.c b/wrapperhelper/src/parse.c index 0254d8df..8f593f22 100644 --- a/wrapperhelper/src/parse.c +++ b/wrapperhelper/src/parse.c @@ -12,7 +12,7 @@ void dump_prepare(const char *filename, FILE *file) { prepare_t *prep = prepare_new_file(file, filename); if (!prep) { - printf("Failed to create the prepare structure\n"); + log_memory("failed to create the prepare structure\n"); return; } while (1) { @@ -30,7 +30,7 @@ void dump_preproc(machine_t *target, const char *filename, FILE *file) { char *dirname = strchr(filename, '/') ? strndup(filename, (size_t)(strrchr(filename, '/') - filename)) : NULL; preproc_t *prep = preproc_new_file(target, file, dirname, filename); if (!prep) { - printf("Failed to create the preproc structure\n"); + log_memory("failed to create the preproc structure\n"); if (dirname) free(dirname); return; } @@ -90,29 +90,31 @@ VECTOR_IMPL_STATIC(size_t, (void)) #define VALIDATION_DECL 1 #define VALIDATION_LAST_DECL 2 #define VALIDATION_FUN 3 -static int validate_storage_type(machine_t *target, enum decl_storage storage, +static int validate_storage_type(loginfo_t *loginfo, machine_t *target, enum decl_storage storage, type_t *typ, enum token_sym_type_e sym) { // We may still do adjustments here - if (!validate_type(target, typ)) return 0; + if (!validate_type(loginfo, target, typ)) return 0; if (typ->typ == TYPE_FUNCTION) { if ((storage == TMPSTO_TLS) || (storage == TMPSTO_TLS_EXTERN) || (storage == TMPSTO_TLS_STATIC)) { - printf("Error: functions cannot be thread local\n"); + log_error(loginfo, "functions cannot be thread local\n"); return 0; } if ((sym == SYM_COMMA) || (sym == SYM_RPAREN) || (sym == SYM_SEMICOLON)) { return (sym == SYM_SEMICOLON) ? VALIDATION_LAST_DECL : VALIDATION_DECL; } else if (sym == SYM_LBRACKET) { return VALIDATION_FUN; + } else { + log_error(loginfo, "unexpected symbol %s (%u) after function declaration\n", sym2str[sym], sym); + return 0; } } else { if ((sym == SYM_COMMA) || (sym == SYM_RPAREN) || (sym == SYM_SEMICOLON) || ((storage != TMPSTO_TYPEDEF) && (sym == SYM_EQ))) { return (sym == SYM_SEMICOLON) ? VALIDATION_LAST_DECL : VALIDATION_DECL; + } else { + log_error(loginfo, "unexpected symbol %s (%u) after %s declaration\n", sym2str[sym], sym, (storage == TMPSTO_TYPEDEF) ? "type" : "variable"); + return 0; } } - printf("TODO: validate_storage_type on storage %u, sym %s (%u), valid type ", storage, sym2str[sym], sym); - type_print(typ); - printf("\n"); - return 0; } static void promote_csts(num_constant_t *v1, num_constant_t *v2) { @@ -197,6 +199,8 @@ static void promote_csts(num_constant_t *v1, num_constant_t *v2) { } } +#define TOKEN_MATCH_ATTR(attr) (!strcmp(string_content(tok->tokv.str), #attr) || !strcmp(string_content(tok->tokv.str), "__" #attr "__")) + VECTOR_DECLARE_STATIC(exprs, expr_t*) #define expr_del_ptr(p) expr_del(*(p)) VECTOR_IMPL_STATIC(exprs, expr_del_ptr) @@ -310,95 +314,6 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s type_t *(*builtins)[LAST_BUILTIN + 1], khash_t(const_map) *const_map, khash_t(type_set) *type_set, preproc_t *prep, proc_token_t *tok, enum decl_storage *storage, enum fun_spec *fspec, enum decl_spec *spec, type_t *typ); - -void expr_print(expr_t *e) { - switch (e->typ) { - case ETY_VAR: printf("%s", string_content(e->val.var)); break; - case ETY_CONST: - switch (e->val.cst.typ) { - case NCT_FLOAT: printf("%ff", e->val.cst.val.f); break; - case NCT_DOUBLE: printf("%f", e->val.cst.val.d); break; - case NCT_LDOUBLE: printf("%Lfl", e->val.cst.val.l); break; - case NCT_INT32: printf("%d", e->val.cst.val.i32); break; - case NCT_UINT32: printf("%uu", e->val.cst.val.u32); break; - case NCT_INT64: printf("%ldll", e->val.cst.val.i64); break; - case NCT_UINT64: printf("%lullu", e->val.cst.val.u64); break; - } - break; - case ETY_CALL: printf("(call)"); break; - case ETY_ACCESS: printf("(.)"); break; - case ETY_PTRACCESS: printf("(->)"); break; - case ETY_UNARY: - switch (e->val.unary.typ) { - case UOT_POSTINCR: printf("(++)"); expr_print(e->val.unary.e); break; - case UOT_POSTDECR: printf("(--)"); expr_print(e->val.unary.e); break; - case UOT_PREINCR: printf("++"); expr_print(e->val.unary.e); break; - case UOT_PREDECR: printf("--"); expr_print(e->val.unary.e); break; - case UOT_REF: printf("&"); expr_print(e->val.unary.e); break; - case UOT_POS: printf("(+)"); expr_print(e->val.unary.e); break; - case UOT_NEG: printf("(-)"); expr_print(e->val.unary.e); break; - case UOT_DEREF: printf("(*)"); expr_print(e->val.unary.e); break; - case UOT_ANOT: printf("~"); expr_print(e->val.unary.e); break; - case UOT_BNOT: printf("!"); expr_print(e->val.unary.e); break; - } - break; - case ETY_BINARY: { - printf("("); - expr_print(e->val.binary.e1); - switch (e->val.binary.typ) { - case BOT_ADD: printf(") + ("); break; - case BOT_SUB: printf(") - ("); break; - case BOT_MUL: printf(") * ("); break; - case BOT_DIV: printf(") / ("); break; - case BOT_MOD: printf(") %% ("); break; - case BOT_LSH: printf(") << ("); break; - case BOT_RSH: printf(") >> ("); break; - case BOT_LT: printf(") < ("); break; - case BOT_GT: printf(") > ("); break; - case BOT_LE: printf(") <= ("); break; - case BOT_GE: printf(") >= ("); break; - case BOT_EQ: printf(") == ("); break; - case BOT_NE: printf(") != ("); break; - case BOT_AAND: printf(") & ("); break; - case BOT_AXOR: printf(") ^ ("); break; - case BOT_AOR: printf(") | ("); break; - case BOT_BAND: printf(") && ("); break; - case BOT_BOR: printf(") || ("); break; - case BOT_ASSGN_EQ: printf(") = ("); break; - case BOT_ASSGN_ADD: printf(") += ("); break; - case BOT_ASSGN_SUB: printf(") -= ("); break; - case BOT_ASSGN_MUL: printf(") *= ("); break; - case BOT_ASSGN_DIV: printf(") /= ("); break; - case BOT_ASSGN_MOD: printf(") %%= ("); break; - case BOT_ASSGN_LSH: printf(") <<= ("); break; - case BOT_ASSGN_RSH: printf(") >>= ("); break; - case BOT_ASSGN_AAND: printf(") &= ("); break; - case BOT_ASSGN_AXOR: printf(") ^= ("); break; - case BOT_ASSGN_AOR: printf(") |= ("); break; - case BOT_COMMA: printf("), ("); break; - case BOT_ARRAY: printf(")["); break; - } - expr_print(e->val.binary.e2); - printf(e->val.binary.typ == BOT_ARRAY ? "]" : ")"); - break; } - case ETY_TERNARY: { - printf("("); - expr_print(e->val.ternary.e1); - switch (e->val.ternary.typ) { - case TOT_COND: printf(") ? "); break; - } - expr_print(e->val.ternary.e2); - switch (e->val.ternary.typ) { - case TOT_COND: printf(" : ("); break; - } - expr_print(e->val.ternary.e3); - printf(")"); - break; } - case ETY_CAST: printf("("); type_print(e->val.cast.typ); printf(")"); expr_print(e->val.cast.e); break; - } -} - - static int is_type_spec_qual_kw(enum token_keyword_type_e kw) { return (kw == KW_ATOMIC) || @@ -437,7 +352,7 @@ static int parse_type_name(machine_t *target, khash_t(struct_map) *struct_map, k } *typ = type_try_merge(*typ, type_set); if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == end_sym)) { - return validate_type(target, *typ); + return validate_type(&tok->loginfo, target, *typ); } struct parse_declarator_dest_s dest2; dest2.argt.dest = NULL; @@ -454,18 +369,20 @@ static int parse_type_name(machine_t *target, khash_t(struct_map) *struct_map, k } type_del(*typ); if (!dest2.argt.dest) { - printf("Internal error: argument type is NULL\n"); + log_internal(&tok->loginfo, "parse_type_name: argument type is NULL\n"); // Empty destructor goto failed; } if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != end_sym)) { + log_error(&tok->loginfo, "invalid token %s %u after type name\n", + (tok->tokt == PTOK_SYM) ? "symbol" : "type", (tok->tokt == PTOK_SYM) ? tok->tokv.sym : tok->tokt); type_del(dest2.argt.dest); proc_token_del(tok); goto failed; } *typ = dest2.argt.dest; *typ = type_try_merge(*typ, type_set); - return validate_type(target, *typ); + return validate_type(&tok->loginfo, target, *typ); failed: return 0; @@ -476,13 +393,13 @@ static expr_t *parse_expression(machine_t *target, khash_t(struct_map) *struct_m khash_t(type_set) *type_set, preproc_t *prep, proc_token_t *tok, int expr_level) { // Note that expr_level >= 1; expr_level = 0 doesn't appear in the grammar if ((expr_level < 1) || (expr_level > 16)) { - printf("Internal error: invalid expression level %d\n", expr_level); + log_internal(&tok->loginfo, "Internal error: invalid expression level %d\n", expr_level); return NULL; } VECTOR(expr_pops) *op_stack = vector_new(expr_pops); if (!op_stack) { - printf("Error: failed to create operation stack"); + log_memory("failed to create operation stack"); proc_token_del(tok); return NULL; } @@ -494,18 +411,16 @@ pushed_expr: e = NULL; expr_new_token: - // printf("expr_new_token with level %d / %d\n", has_level, expr_level); - // proc_token_print(tok); if (tok->tokt == PTOK_IDENT) { if (has_level != -1) { - printf("Error: invalid expression: unexpected identifier '%s'\n", string_content(tok->tokv.str)); + log_error(&tok->loginfo, "invalid expression: unexpected identifier '%s'\n", string_content(tok->tokv.str)); string_del(tok->tokv.str); goto failed; } has_level = 0; e = malloc(sizeof *e); if (!e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); string_del(tok->tokv.str); goto failed; } @@ -515,19 +430,19 @@ expr_new_token: goto expr_new_token; } else if (tok->tokt == PTOK_NUM) { if (has_level != -1) { - printf("Error: invalid expression: unexpected number '%s'\n", string_content(tok->tokv.str)); + log_error(&tok->loginfo, "invalid expression: unexpected number '%s'\n", string_content(tok->tokv.str)); string_del(tok->tokv.str); goto failed; } has_level = 0; e = malloc(sizeof *e); if (!e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); string_del(tok->tokv.str); goto failed; } e->typ = ETY_CONST; - if (!num_constant_convert(tok->tokv.str, &e->val.cst, target->size_long == 4)) { + if (!num_constant_convert(&tok->loginfo, tok->tokv.str, &e->val.cst, target->size_long == 4)) { string_del(tok->tokv.str); goto failed; } @@ -536,19 +451,19 @@ expr_new_token: goto expr_new_token; } else if ((tok->tokt == PTOK_STRING) && !tok->tokv.sisstr) { if (has_level != -1) { - printf("Error: invalid expression: unexpected character constant '%s'\n", string_content(tok->tokv.sstr)); + log_error(&tok->loginfo, "invalid expression: unexpected character constant '%s'\n", string_content(tok->tokv.sstr)); string_del(tok->tokv.sstr); goto failed; } if (string_len(tok->tokv.sstr) != 1) { - printf("Error: TODO: invalid expression: multibyte character constant '%s'\n", string_content(tok->tokv.sstr)); + log_TODO(&tok->loginfo, "invalid expression: multibyte character constant '%s'\n", string_content(tok->tokv.sstr)); string_del(tok->tokv.sstr); goto failed; } has_level = 0; e = malloc(sizeof *e); if (!e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); string_del(tok->tokv.sstr); goto failed; } @@ -570,7 +485,7 @@ expr_new_token: .val.unop = opt \ }; \ if (!vector_push(expr_pops, op_stack, pop)) { \ - printf("Error: failed to add partial operation to operation stack\n"); \ + log_memory("failed to add partial operation to operation stack\n"); \ /* Empty destructor */ \ goto failed; \ } \ @@ -589,7 +504,7 @@ expr_new_token: .val.binop = {.op = opt, .e1 = e} \ }; \ if (!vector_push(expr_pops, op_stack, pop)) { \ - printf("Error: failed to add partial operation to operation stack\n"); \ + log_memory("failed to add partial operation to operation stack\n"); \ /* Empty destructor */ \ goto failed; \ } \ @@ -598,12 +513,13 @@ expr_new_token: goto pushed_expr; \ } \ } + if ((expr_level >= 1) && (tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_PLUSPLUS)) { if ((has_level != -1) && (has_level <= 1)) { has_level = 1; expr_t *new_e = malloc(sizeof *new_e); if (!new_e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); string_del(tok->tokv.str); goto failed; } @@ -620,7 +536,7 @@ expr_new_token: has_level = 1; expr_t *new_e = malloc(sizeof *new_e); if (!new_e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); string_del(tok->tokv.str); goto failed; } @@ -641,7 +557,7 @@ expr_new_token: .val.binop = {.last_sym = SYM_RSQBRACKET, .op = BOT_ARRAY, .e1 = e} }; if (!vector_push(expr_pops, op_stack, pop)) { - printf("Error: failed to add partial operation to operation stack\n"); + log_memory("failed to add partial operation to operation stack\n"); /* Empty destructor */ goto failed; } @@ -657,13 +573,13 @@ expr_new_token: *tok = proc_next_token(prep); if (tok->tokt != PTOK_IDENT) { - printf("Error: invalid expression: unexpected token after access symbol\n"); + log_error(&tok->loginfo, "invalid expression: unexpected token after access symbol\n"); proc_token_del(tok); goto failed; } expr_t *new_e = malloc(sizeof *new_e); if (!new_e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); string_del(tok->tokv.str); goto failed; } @@ -683,24 +599,24 @@ expr_new_token: UNOP(SYM_STAR, UOT_DEREF, 2, 3) UNOP(SYM_TILDE, UOT_ANOT, 2, 3) UNOP(SYM_EXCL, UOT_BNOT, 2, 3) - BINOP(SYM_STAR, BOT_MUL, 4, 4, 3) - BINOP(SYM_SLASH, BOT_DIV, 4, 4, 3) - BINOP(SYM_PERCENT, BOT_MOD, 4, 4, 3) - BINOP(SYM_PLUS, BOT_ADD, 5, 5, 4) - BINOP(SYM_DASH, BOT_SUB, 5, 5, 4) - BINOP(SYM_LTLT, BOT_LSH, 6, 6, 5) - BINOP(SYM_GTGT, BOT_RSH, 6, 6, 5) - BINOP(SYM_LT, BOT_LT, 7, 7, 6) - BINOP(SYM_GT, BOT_GT, 7, 7, 6) - BINOP(SYM_LTEQ, BOT_LE, 7, 7, 6) - BINOP(SYM_GTEQ, BOT_GE, 7, 7, 6) - BINOP(SYM_EQEQ, BOT_EQ, 8, 8, 7) - BINOP(SYM_EXCLEQ, BOT_NE, 8, 8, 7) - BINOP(SYM_AMP, BOT_AAND, 9, 9, 8) - BINOP(SYM_HAT, BOT_AXOR, 10, 10, 9) - BINOP(SYM_PIPE, BOT_AOR, 11, 11, 10) - BINOP(SYM_AMPAMP, BOT_BAND, 12, 12, 11) - BINOP(SYM_PIPEPIPE, BOT_BOR, 13, 13, 12) + BINOP(SYM_STAR, BOT_MUL, 4, 4, 3) + BINOP(SYM_SLASH, BOT_DIV, 4, 4, 3) + BINOP(SYM_PERCENT, BOT_MOD, 4, 4, 3) + BINOP(SYM_PLUS, BOT_ADD, 5, 5, 4) + BINOP(SYM_DASH, BOT_SUB, 5, 5, 4) + BINOP(SYM_LTLT, BOT_LSH, 6, 6, 5) + BINOP(SYM_GTGT, BOT_RSH, 6, 6, 5) + BINOP(SYM_LT, BOT_LT, 7, 7, 6) + BINOP(SYM_GT, BOT_GT, 7, 7, 6) + BINOP(SYM_LTEQ, BOT_LE, 7, 7, 6) + BINOP(SYM_GTEQ, BOT_GE, 7, 7, 6) + BINOP(SYM_EQEQ, BOT_EQ, 8, 8, 7) + BINOP(SYM_EXCLEQ, BOT_NE, 8, 8, 7) + BINOP(SYM_AMP, BOT_AAND, 9, 9, 8) + BINOP(SYM_HAT, BOT_AXOR, 10, 10, 9) + BINOP(SYM_PIPE, BOT_AOR, 11, 11, 10) + BINOP(SYM_AMPAMP, BOT_BAND, 12, 12, 11) + BINOP(SYM_PIPEPIPE, BOT_BOR, 13, 13, 12) if ((expr_level >= 14) && (tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_QUESTION)) { if ((has_level != -1) && (has_level <= 13)) { struct expr_partial_op pop = { @@ -710,7 +626,7 @@ expr_new_token: .val.ternop = {.arg23_sep = SYM_COLON, .once_done2_want_level = 14, .op = TOT_COND, .e1 = e} }; if (!vector_push(expr_pops, op_stack, pop)) { - printf("Error: failed to add partial operation to operation stack\n"); + log_memory("failed to add partial operation to operation stack\n"); // Empty destructor goto failed; } @@ -719,18 +635,18 @@ expr_new_token: goto pushed_expr; } } - BINOP(SYM_EQ, BOT_ASSGN_EQ, 15, 2, 15) - BINOP(SYM_STAREQ, BOT_ASSGN_MUL, 15, 2, 15) - BINOP(SYM_SLASHEQ, BOT_ASSGN_DIV, 15, 2, 15) - BINOP(SYM_PERCENTEQ, BOT_ASSGN_MOD, 15, 2, 15) - BINOP(SYM_PLUSEQ, BOT_ASSGN_ADD, 15, 2, 15) - BINOP(SYM_DASHEQ, BOT_ASSGN_SUB, 15, 2, 15) - BINOP(SYM_LTLTEQ, BOT_ASSGN_LSH, 15, 2, 15) - BINOP(SYM_GTGTEQ, BOT_ASSGN_RSH, 15, 2, 15) - BINOP(SYM_AMPEQ, BOT_ASSGN_AAND, 15, 2, 15) - BINOP(SYM_HATEQ, BOT_ASSGN_AXOR, 15, 2, 15) - BINOP(SYM_PIPEEQ, BOT_ASSGN_AOR, 15, 2, 15) - BINOP(SYM_COMMA, BOT_COMMA, 16, 16, 15) + BINOP(SYM_EQ, BOT_ASSGN_EQ, 15, 2, 15) + BINOP(SYM_STAREQ, BOT_ASSGN_MUL, 15, 2, 15) + BINOP(SYM_SLASHEQ, BOT_ASSGN_DIV, 15, 2, 15) + BINOP(SYM_PERCENTEQ, BOT_ASSGN_MOD, 15, 2, 15) + BINOP(SYM_PLUSEQ, BOT_ASSGN_ADD, 15, 2, 15) + BINOP(SYM_DASHEQ, BOT_ASSGN_SUB, 15, 2, 15) + BINOP(SYM_LTLTEQ, BOT_ASSGN_LSH, 15, 2, 15) + BINOP(SYM_GTGTEQ, BOT_ASSGN_RSH, 15, 2, 15) + BINOP(SYM_AMPEQ, BOT_ASSGN_AAND, 15, 2, 15) + BINOP(SYM_HATEQ, BOT_ASSGN_AXOR, 15, 2, 15) + BINOP(SYM_PIPEEQ, BOT_ASSGN_AOR, 15, 2, 15) + BINOP(SYM_COMMA, BOT_COMMA, 16, 16, 15) // expr2 ::= sizeof expr2 // which includes expr2 ::= sizeof ( expr16 ) @@ -745,7 +661,7 @@ expr_new_token: .val.c = '\0' }; if (!vector_push(expr_pops, op_stack, pop)) { - printf("Error: failed to add partial operation to operation stack\n"); + log_memory("failed to add partial operation to operation stack\n"); proc_token_del(tok); goto failed; } @@ -758,7 +674,7 @@ expr_new_token: if (IS_BEGIN_TYPE_NAME) { type_t *typ = type_new(); if (!typ) { - printf("Error: failed to create new type info structure\n"); + log_memory("failed to create new type info structure\n"); proc_token_del(tok); goto failed; } @@ -766,14 +682,14 @@ expr_new_token: goto failed; } if (!typ->is_validated || typ->is_incomplete || (typ->typ == TYPE_FUNCTION)) { - printf("Error: cannot get the size of a function or incomplete type\n"); + log_error(&tok->loginfo, "cannot get the size of a function or incomplete type\n"); type_del(typ); proc_token_del(tok); goto failed; } e = malloc(sizeof *e); if (!e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); type_del(typ); proc_token_del(tok); goto failed; @@ -784,6 +700,7 @@ expr_new_token: has_level = 2; type_del(typ); if (!e->val.cst.val.u64) { + log_internal(&tok->loginfo, "size of type is 0\n"); proc_token_del(tok); goto failed; } @@ -798,7 +715,7 @@ expr_new_token: .val.c = 0 }; if (!vector_push(expr_pops, op_stack, pop)) { - printf("Error: failed to add partial operation to operation stack\n"); + log_memory("failed to add partial operation to operation stack\n"); proc_token_del(tok); goto failed; } @@ -809,7 +726,7 @@ expr_new_token: .val.c = 0 }; if (!vector_push(expr_pops, op_stack, pop)) { - printf("Error: failed to add partial operation to operation stack\n"); + log_memory("failed to add partial operation to operation stack\n"); proc_token_del(tok); goto failed; } @@ -821,7 +738,7 @@ expr_new_token: if ((has_level == -1) && (expr_level >= 2) && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_ALIGNOF)) { *tok = proc_next_token(prep); if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_LPAREN)) { - printf("Error: invalid _Alignof expression\n"); + log_error(&tok->loginfo, "unexpected token, expected symbol '('\n"); proc_token_del(tok); goto failed; } @@ -829,7 +746,7 @@ expr_new_token: *tok = proc_next_token(prep); type_t *typ = type_new(); if (!typ) { - printf("Error: failed to create new type info structure\n"); + log_memory("failed to create new type info structure\n"); proc_token_del(tok); goto failed; } @@ -837,14 +754,14 @@ expr_new_token: goto failed; } if (!typ->is_validated || typ->is_incomplete || (typ->typ == TYPE_FUNCTION)) { - printf("Error: cannot get the alignment of a function or incomplete type\n"); + log_error(&tok->loginfo, "cannot get the alignment of a function or incomplete type\n"); type_del(typ); proc_token_del(tok); goto failed; } e = malloc(sizeof *e); if (!e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); type_del(typ); proc_token_del(tok); goto failed; @@ -855,6 +772,7 @@ expr_new_token: has_level = 2; type_del(typ); if (!e->val.cst.val.u64) { + log_internal(&tok->loginfo, "alignment of type is 0\n"); proc_token_del(tok); goto failed; } @@ -876,7 +794,7 @@ expr_new_token: expr_t *new_e = malloc(sizeof *new_e); new_e = malloc(sizeof *new_e); if (!new_e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); // Empty destructor goto failed; } @@ -891,7 +809,7 @@ expr_new_token: // We want a function call with at least one argument VECTOR(exprs) *exprs = vector_new_cap(exprs, 1); if (!exprs) { - printf("Error: failed to add partial operation to operation stack\n"); + log_memory("failed to add partial operation to operation stack\n"); proc_token_del(tok); goto failed; } @@ -902,7 +820,7 @@ expr_new_token: .val.funcall = {.f = e, .exprs = exprs} }; if (!vector_push(expr_pops, op_stack, pop)) { - printf("Error: failed to add partial operation to operation stack\n"); + log_memory("failed to add partial operation to operation stack\n"); vector_del(exprs, exprs); proc_token_del(tok); goto failed; @@ -916,7 +834,7 @@ expr_new_token: if ((expr_level >= 1) && IS_BEGIN_TYPE_NAME) { type_t *typ = type_new(); if (!typ) { - printf("Error: failed to create new type info structure\n"); + log_memory("failed to create new type info structure\n"); proc_token_del(tok); goto failed; } @@ -926,12 +844,12 @@ expr_new_token: goto failed; } if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_LBRACKET)) { - printf("Error: TODO: initializer-list\n"); + log_TODO(&tok->loginfo, "initializer-list\n"); type_del(typ); proc_token_del(tok); goto failed; } else if (expr_level < 3) { - printf("Error: cast expression (level 3) but the expression level is at most 2\n"); + log_error(&tok->loginfo, "cast expression (level 3) but the required expression level is 1 or 2 (expected symbol '{')\n"); type_del(typ); proc_token_del(tok); goto failed; @@ -943,7 +861,7 @@ expr_new_token: .val.typ = typ }; if (!vector_push(expr_pops, op_stack, pop)) { - printf("Error: failed to add partial operation to operation stack\n"); + log_memory("failed to add partial operation to operation stack\n"); /* Empty destructor */ goto failed; } @@ -959,7 +877,7 @@ expr_new_token: .val.c = 0 }; if (!vector_push(expr_pops, op_stack, pop)) { - printf("Error: failed to add partial operation to operation stack\n"); + log_memory("failed to add partial operation to operation stack\n"); proc_token_del(tok); goto failed; } @@ -985,13 +903,13 @@ expr_new_token: } break; case EPO_SIZEOF: - printf("Error: TODO: find type of expression\n"); + log_TODO(&tok->loginfo, "find type of expression\n"); proc_token_del(tok); goto failed; case EPO_CAST: new_e = malloc(sizeof *new_e); if (!new_e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); proc_token_del(tok); goto failed; } @@ -1009,13 +927,13 @@ expr_new_token: has_level = pop->once_done_is_level; expr_level = pop->once_done_want_level; if (!vector_push(exprs, pop->val.funcall.exprs, e)) { - printf("Error: failed to add argument to argument stack\n"); + log_memory("failed to add argument to argument stack\n"); // Empty destructor goto failed; } e = malloc(sizeof *e); if (!e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); // Empty destructor goto failed; } @@ -1029,7 +947,7 @@ expr_new_token: goto expr_new_token; } else if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_COMMA)) { if (!vector_push(exprs, pop->val.funcall.exprs, e)) { - printf("Error: failed to add argument to argument stack\n"); + log_memory("failed to add argument to argument stack\n"); // Empty destructor goto failed; } @@ -1042,7 +960,7 @@ expr_new_token: case EPO_UNARY: new_e = malloc(sizeof *new_e); if (!new_e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); proc_token_del(tok); goto failed; } @@ -1063,7 +981,7 @@ expr_new_token: case EPO_BINARY_ARG: new_e = malloc(sizeof *new_e); if (!new_e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); proc_token_del(tok); goto failed; } @@ -1090,7 +1008,7 @@ expr_new_token: case EPO_TERNARY_ARG2: new_e = malloc(sizeof *new_e); if (!new_e) { - printf("Error: failed to create new expression atom\n"); + log_memory("failed to create new expression atom\n"); proc_token_del(tok); goto failed; } @@ -1113,15 +1031,14 @@ expr_new_token: vector_del(expr_pops, op_stack); return e; } - printf("Error: invalid expression: unexpected token\n"); - proc_token_print(tok); + log_error(&tok->loginfo, "invalid expression: unexpected token\n"); proc_token_del(tok); failed: vector_del(expr_pops, op_stack); if (e) expr_del(e); return NULL; } -static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constant_t *dest, int fatal) { +static int eval_expression(loginfo_t *li, machine_t *target, expr_t *e, khash_t(const_map) *const_map, num_constant_t *dest, int fatal) { // Evaluate the expression (we suppose it is constant) switch (e->typ) { case ETY_VAR: { @@ -1130,7 +1047,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan *dest = kh_val(const_map, it); return 1; } - if (fatal) printf("Error: failed to evaluate expression: expression is not constant (variable)\n"); + if (fatal) log_error(li, "failed to evaluate expression: expression is not constant (variable)\n"); return 0; } case ETY_CONST: @@ -1140,18 +1057,16 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan // case ETY_GENERIC: case ETY_CALL: - if (fatal) printf("Error: failed to evaluate expression: expression is not constant (function call)\n"); + if (fatal) log_error(li, "failed to evaluate expression: expression is not constant (function call)\n"); return 0; case ETY_ACCESS: case ETY_PTRACCESS: - if (fatal) printf("Error: failed to evaluate expression: expression is not constant (member access)\n"); + if (fatal) log_error(li, "failed to evaluate expression: expression is not constant (member access)\n"); return 0; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wfloat-equal" case ETY_UNARY: - if (!eval_expression(e->val.unary.e, const_map, dest, fatal)) return 0; + if (!eval_expression(li, target, e->val.unary.e, const_map, dest, fatal)) return 0; switch (e->val.unary.typ) { case UOT_POSTINCR: @@ -1160,7 +1075,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case UOT_PREDECR: case UOT_REF: case UOT_DEREF: - if (fatal) printf("Error: failed to evaluate expression: expression is not constant (assignment or memory accesses)\n"); + if (fatal) log_error(li, "failed to evaluate expression: expression is not constant (assignment or memory accesses)\n"); return 0; case UOT_POS: return 1; // Nothing to do @@ -1180,7 +1095,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case NCT_FLOAT: case NCT_DOUBLE: case NCT_LDOUBLE: - if (fatal) printf("Error: failed to evaluate expression: cannot bitwise-negate a floating point number\n"); + if (fatal) log_error(li, "failed to evaluate expression: cannot bitwise-negate a floating point number\n"); return 0; case NCT_INT32: dest->val.i32 = ~dest->val.i32; return 1; case NCT_UINT32: dest->val.u32 = ~dest->val.u32; return 1; @@ -1190,9 +1105,12 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan } case UOT_BNOT: switch (dest->typ) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" case NCT_FLOAT: dest->typ = NCT_INT32; dest->val.i32 = !dest->val.f; return 1; case NCT_DOUBLE: dest->typ = NCT_INT32; dest->val.i32 = !dest->val.d; return 1; case NCT_LDOUBLE: dest->typ = NCT_INT32; dest->val.i32 = !dest->val.l; return 1; +#pragma GCC diagnostic pop case NCT_INT32: dest->typ = NCT_INT32; dest->val.i32 = !dest->val.i32; return 1; case NCT_UINT32: dest->typ = NCT_INT32; dest->val.i32 = !dest->val.u32; return 1; case NCT_INT64: dest->typ = NCT_INT32; dest->val.i32 = !dest->val.i64; return 1; @@ -1204,8 +1122,8 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case ETY_BINARY: { num_constant_t dest1, dest2; - if (!eval_expression(e->val.binary.e1, const_map, &dest1, fatal)) return 0; - if (!eval_expression(e->val.binary.e2, const_map, &dest2, fatal)) return 0; + if (!eval_expression(li, target, e->val.binary.e1, const_map, &dest1, fatal)) return 0; + if (!eval_expression(li, target, e->val.binary.e2, const_map, &dest2, fatal)) return 0; switch (e->val.binary.typ) { case BOT_ASSGN_EQ: @@ -1220,7 +1138,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case BOT_ASSGN_AXOR: case BOT_ASSGN_AOR: case BOT_ARRAY: // Is this possible? - if (fatal) printf("Error: failed to evaluate expression: expression is not constant (assignments)\n"); + if (fatal) log_error(li, "failed to evaluate expression: expression is not constant (assignments)\n"); return 0; #define DOIT(op) \ promote_csts(&dest1, &dest2); \ @@ -1240,7 +1158,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case NCT_FLOAT: \ case NCT_DOUBLE: \ case NCT_LDOUBLE: \ - if (fatal) printf("Error: failed to evaluate expression: binary operation %u incompatible with floating point numbers\n", e->val.binary.typ); \ + if (fatal) log_error(li, "failed to evaluate expression: binary operation %u incompatible with floating point numbers\n", e->val.binary.typ); \ return 0; \ case NCT_INT32: dest->val.i32 = dest1.val.i32 op dest2.val.i32; return 1; \ case NCT_UINT32: dest->val.u32 = dest1.val.u32 op dest2.val.u32; return 1; \ @@ -1251,14 +1169,14 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan #define DOIT_BOOL(op) \ promote_csts(&dest1, &dest2); \ switch (dest1.typ) { \ - case NCT_FLOAT: dest->typ = NCT_INT32; dest->val.i32 = dest1.val.f op dest2.val.f ; return 1; \ - case NCT_DOUBLE: dest->typ = NCT_INT32; dest->val.i32 = dest1.val.d op dest2.val.d ; return 1; \ - case NCT_LDOUBLE: dest->typ = NCT_INT32; dest->val.i32 = dest1.val.l op dest2.val.l ; return 1; \ - case NCT_INT32: dest->typ = NCT_INT32; dest->val.i32 = dest1.val.i32 op dest2.val.i32; return 1; \ - case NCT_UINT32: dest->typ = NCT_INT32; dest->val.i32 = dest1.val.u32 op dest2.val.u32; return 1; \ - case NCT_INT64: dest->typ = NCT_INT32; dest->val.i32 = dest1.val.i64 op dest2.val.i64; return 1; \ - case NCT_UINT64: dest->typ = NCT_INT32; dest->val.i32 = dest1.val.u64 op dest2.val.u64; return 1; \ - default: return 0; \ + case NCT_FLOAT: dest->typ = NCT_UINT32; dest->val.u32 = dest1.val.f op dest2.val.f ; return 1; \ + case NCT_DOUBLE: dest->typ = NCT_UINT32; dest->val.u32 = dest1.val.d op dest2.val.d ; return 1; \ + case NCT_LDOUBLE: dest->typ = NCT_UINT32; dest->val.u32 = dest1.val.l op dest2.val.l ; return 1; \ + case NCT_INT32: dest->typ = NCT_UINT32; dest->val.u32 = dest1.val.i32 op dest2.val.i32; return 1; \ + case NCT_UINT32: dest->typ = NCT_UINT32; dest->val.u32 = dest1.val.u32 op dest2.val.u32; return 1; \ + case NCT_INT64: dest->typ = NCT_UINT32; dest->val.u32 = dest1.val.i64 op dest2.val.i64; return 1; \ + case NCT_UINT64: dest->typ = NCT_UINT32; dest->val.u32 = dest1.val.u64 op dest2.val.u64; return 1; \ + default: return 0; \ } case BOT_ADD: DOIT(+) case BOT_SUB: DOIT(-) @@ -1271,13 +1189,19 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case BOT_GT: DOIT_BOOL(>) case BOT_LE: DOIT_BOOL(<=) case BOT_GE: DOIT_BOOL(>=) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" case BOT_EQ: DOIT_BOOL(==) case BOT_NE: DOIT_BOOL(!=) +#pragma GCC diagnostic pop case BOT_AAND: DOIT_INT(&) case BOT_AXOR: DOIT_INT(^) case BOT_AOR: DOIT_INT(|) - case BOT_BAND: DOIT(&&) - case BOT_BOR: DOIT(||) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" + case BOT_BAND: DOIT_BOOL(&&) + case BOT_BOR: DOIT_BOOL(||) +#pragma GCC diagnostic pop case BOT_COMMA: *dest = dest2; return 1; #undef DOIT_BOOL #undef DOIT_INT @@ -1287,17 +1211,20 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case ETY_TERNARY: { num_constant_t dest1, dest2, dest3; - if (!eval_expression(e->val.ternary.e1, const_map, &dest1, fatal)) return 0; - if (!eval_expression(e->val.ternary.e2, const_map, &dest2, fatal)) return 0; - if (!eval_expression(e->val.ternary.e3, const_map, &dest3, fatal)) return 0; + if (!eval_expression(li, target, e->val.ternary.e1, const_map, &dest1, fatal)) return 0; + if (!eval_expression(li, target, e->val.ternary.e2, const_map, &dest2, fatal)) return 0; + if (!eval_expression(li, target, e->val.ternary.e3, const_map, &dest3, fatal)) return 0; switch (e->val.ternary.typ) { case TOT_COND: promote_csts(&dest2, &dest3); switch (dest1.typ) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" case NCT_FLOAT: *dest = dest1.val.f ? dest2 : dest3; return 1; case NCT_DOUBLE: *dest = dest1.val.d ? dest2 : dest3; return 1; case NCT_LDOUBLE: *dest = dest1.val.l ? dest2 : dest3; return 1; +#pragma GCC diagnostic pop case NCT_INT32: *dest = dest1.val.i32 ? dest2 : dest3; return 1; case NCT_UINT32: *dest = dest1.val.u32 ? dest2 : dest3; return 1; case NCT_INT64: *dest = dest1.val.i64 ? dest2 : dest3; return 1; @@ -1306,17 +1233,49 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan } default: return 0; } } -#pragma GCC diagnostic pop // case ETY_INIT_LIST: case ETY_CAST: - if (!eval_expression(e->val.cast.e, const_map, dest, fatal)) return 0; + if (!eval_expression(li, target, e->val.cast.e, const_map, dest, fatal)) return 0; if (e->val.cast.typ->typ == TYPE_BUILTIN) { switch (e->val.cast.typ->val.builtin) { + case BTT_VOID: + if (fatal) log_error(li, "invalid cast to void\n"); + return 0; + case BTT_BOOL: + switch (dest->typ) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" + case NCT_FLOAT: dest->val.u32 = (_Bool)dest->val.f; break; + case NCT_DOUBLE: dest->val.u32 = (_Bool)dest->val.d; break; + case NCT_LDOUBLE: dest->val.u32 = (_Bool)dest->val.l; break; +#pragma GCC diagnostic pop + case NCT_INT32: dest->val.u32 = (_Bool)dest->val.i32; break; + case NCT_UINT32: dest->val.u32 = (_Bool)dest->val.u32; break; + case NCT_INT64: dest->val.u32 = (_Bool)dest->val.i64; break; + case NCT_UINT64: dest->val.u32 = (_Bool)dest->val.u64; break; + } + dest->typ = NCT_UINT32; + return 1; + case BTT_SCHAR: + case BTT_S8: + cast_s8: + switch (dest->typ) { + case NCT_FLOAT: dest->val.i32 = (int8_t)dest->val.f; break; + case NCT_DOUBLE: dest->val.i32 = (int8_t)dest->val.d; break; + case NCT_LDOUBLE: dest->val.i32 = (int8_t)dest->val.l; break; + case NCT_INT32: dest->val.i32 = (int8_t)dest->val.i32; break; + case NCT_UINT32: dest->val.i32 = (int8_t)dest->val.u32; break; + case NCT_INT64: dest->val.i32 = (int8_t)dest->val.i64; break; + case NCT_UINT64: dest->val.i32 = (int8_t)dest->val.u64; break; + } + dest->typ = NCT_INT32; + return 1; case BTT_UCHAR: case BTT_U8: + cast_u8: switch (dest->typ) { case NCT_FLOAT: dest->val.u32 = (uint8_t)dest->val.f; break; case NCT_DOUBLE: dest->val.u32 = (uint8_t)dest->val.d; break; @@ -1328,9 +1287,37 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan } dest->typ = NCT_UINT32; return 1; + case BTT_SHORT: + case BTT_SSHORT: + case BTT_S16: + switch (dest->typ) { + case NCT_FLOAT: dest->val.i32 = (int16_t)dest->val.f; break; + case NCT_DOUBLE: dest->val.i32 = (int16_t)dest->val.d; break; + case NCT_LDOUBLE: dest->val.i32 = (int16_t)dest->val.l; break; + case NCT_INT32: dest->val.i32 = (int16_t)dest->val.i32; break; + case NCT_UINT32: dest->val.i32 = (int16_t)dest->val.u32; break; + case NCT_INT64: dest->val.i32 = (int16_t)dest->val.i64; break; + case NCT_UINT64: dest->val.i32 = (int16_t)dest->val.u64; break; + } + dest->typ = NCT_INT32; + return 1; + case BTT_USHORT: + case BTT_U16: + switch (dest->typ) { + case NCT_FLOAT: dest->val.u32 = (uint16_t)dest->val.f; break; + case NCT_DOUBLE: dest->val.u32 = (uint16_t)dest->val.d; break; + case NCT_LDOUBLE: dest->val.u32 = (uint16_t)dest->val.l; break; + case NCT_INT32: dest->val.u32 = (uint16_t)dest->val.i32; break; + case NCT_UINT32: dest->val.u32 = (uint16_t)dest->val.u32; break; + case NCT_INT64: dest->val.u32 = (uint16_t)dest->val.i64; break; + case NCT_UINT64: dest->val.u32 = (uint16_t)dest->val.u64; break; + } + dest->typ = NCT_UINT32; + return 1; case BTT_INT: case BTT_SINT: case BTT_S32: + cast_s32: switch (dest->typ) { case NCT_FLOAT: dest->val.i32 = (int32_t)dest->val.f; break; case NCT_DOUBLE: dest->val.i32 = (int32_t)dest->val.d; break; @@ -1344,6 +1331,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan return 1; case BTT_UINT: case BTT_U32: + cast_u32: switch (dest->typ) { case NCT_FLOAT: dest->val.u32 = (uint32_t)dest->val.f; break; case NCT_DOUBLE: dest->val.u32 = (uint32_t)dest->val.d; break; @@ -1355,10 +1343,24 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan } dest->typ = NCT_UINT32; return 1; - case BTT_ULONG: - // Warning: assuming sizeof(long) == 8 on the current target - // TODO: use machine to select between U32 and U64 + case BTT_LONGLONG: + case BTT_SLONGLONG: + case BTT_S64: + cast_s64: + switch (dest->typ) { + case NCT_FLOAT: dest->val.i64 = (int64_t)dest->val.f; break; + case NCT_DOUBLE: dest->val.i64 = (int64_t)dest->val.d; break; + case NCT_LDOUBLE: dest->val.i64 = (int64_t)dest->val.l; break; + case NCT_INT32: dest->val.i64 = (int64_t)dest->val.i32; break; + case NCT_UINT32: dest->val.i64 = (int64_t)dest->val.u32; break; + case NCT_INT64: break; + case NCT_UINT64: dest->val.i64 = (int64_t)dest->val.u64; break; + } + dest->typ = NCT_INT64; + return 1; + case BTT_ULONGLONG: case BTT_U64: + cast_u64: switch (dest->typ) { case NCT_FLOAT: dest->val.u64 = (uint64_t)dest->val.f; break; case NCT_DOUBLE: dest->val.u64 = (uint64_t)dest->val.d; break; @@ -1370,25 +1372,31 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan } dest->typ = NCT_UINT64; return 1; - case BTT_VOID: - case BTT_BOOL: - case BTT_CHAR: // May be signed or unsigned depending on the machine - case BTT_SCHAR: - case BTT_SHORT: - case BTT_SSHORT: - case BTT_USHORT: + case BTT_CHAR: + if (target->unsigned_char) goto cast_u8; + else goto cast_s8; case BTT_LONG: case BTT_SLONG: - case BTT_LONGLONG: - case BTT_SLONGLONG: - case BTT_ULONGLONG: + if (target->size_long == 4) { + goto cast_s32; + } else if (target->size_long == 8) { + goto cast_s64; + } else { + log_internal(li, "unsupported cast to long with target sizeof(long) == %zu\n", target->size_long); + return 0; + } + case BTT_ULONG: + if (target->size_long == 4) { + goto cast_u32; + } else if (target->size_long == 8) { + goto cast_u64; + } else { + log_internal(li, "unsupported cast to unsigned long with target sizeof(long) == %zu\n", target->size_long); + return 0; + } case BTT_INT128: case BTT_SINT128: case BTT_UINT128: - case BTT_S8: - case BTT_S16: - case BTT_U16: - case BTT_S64: case BTT_FLOAT: case BTT_CFLOAT: case BTT_IFLOAT: @@ -1403,11 +1411,11 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case BTT_IFLOAT128: case BTT_VA_LIST: default: - if (fatal) printf("Error: TODO: cast to builtin %s in constant expression\n", builtin2str[e->val.cast.typ->val.builtin]); + if (fatal) log_TODO(li, "unsupported cast to builtin %s in constant expression\n", builtin2str[e->val.cast.typ->val.builtin]); return 0; } } else { - if (fatal) printf("Error: cast in constant expression\n"); + if (fatal) log_TODO(li, "unsupported cast in constant expression\n"); return 0; } @@ -1426,7 +1434,7 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s // Empty destructor *tok = proc_next_token(prep); if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_LPAREN)) { - printf("Error: unexpected token in static assertion declaration\n"); + log_error(&tok->loginfo, "unexpected token in static assertion declaration\n"); proc_token_del(tok); goto failed; } @@ -1437,13 +1445,13 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s goto failed; } if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_COMMA)) { - printf("Error: unexpected token in static assertion expression\n"); + log_error(&tok->loginfo, "unexpected token in static assertion expression\n"); expr_del(e); proc_token_del(tok); goto failed; } num_constant_t eval; - if (!eval_expression(e, const_map, &eval, 1)) { + if (!eval_expression(&tok->loginfo, target, e, const_map, &eval, 1)) { expr_del(e); // Empty destructor goto failed; @@ -1451,37 +1459,40 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s expr_del(e); *tok = proc_next_token(prep); if ((tok->tokt != PTOK_STRING) || !tok->tokv.sisstr) { - printf("Error: unexpected token in static assertion message\n"); + log_error(&tok->loginfo, "unexpected token in static assertion message\n"); proc_token_del(tok); goto failed; } string_t *errmsg = tok->tokv.str; *tok = proc_next_token(prep); if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_RPAREN)) { - printf("Error: unexpected token in static assertion message\n"); + log_error(&tok->loginfo, "unexpected token in static assertion message\n"); proc_token_del(tok); goto failed; } *tok = proc_next_token(prep); if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_SEMICOLON)) { - printf("Error: unexpected token after static assertion\n"); + log_error(&tok->loginfo, "unexpected token after static assertion\n"); proc_token_del(tok); goto failed; } int iserror; switch (eval.typ) { - case NCT_FLOAT: iserror = (int)eval.val.f == 0; break; - case NCT_DOUBLE: iserror = (int)eval.val.d == 0; break; - case NCT_LDOUBLE: iserror = (int)eval.val.l == 0; break; - case NCT_INT32: iserror = eval.val.i32 == 0; break; - case NCT_UINT32: iserror = eval.val.u32 == 0; break; - case NCT_INT64: iserror = eval.val.i64 == 0; break; - case NCT_UINT64: iserror = eval.val.u64 == 0; break; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" + case NCT_FLOAT: iserror = !eval.val.f; break; + case NCT_DOUBLE: iserror = !eval.val.d; break; + case NCT_LDOUBLE: iserror = !eval.val.l; break; +#pragma GCC diagnostic pop + case NCT_INT32: iserror = !eval.val.i32; break; + case NCT_UINT32: iserror = !eval.val.u32; break; + case NCT_INT64: iserror = !eval.val.i64; break; + case NCT_UINT64: iserror = !eval.val.u64; break; default: iserror = 1; } if (iserror) { - printf("Error: static assertion failed: %s\n", string_content(errmsg)); + log_error(&tok->loginfo, "static assertion failed: %s\n", string_content(errmsg)); string_del(errmsg); // Empty destructor goto failed; @@ -1493,15 +1504,14 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s parse_cur_token_decl: if (tok->tokt == PTOK_EOF) { - printf("Error: unexpected end of file in declaration\n"); - proc_token_print(tok); + log_error(&tok->loginfo, "unexpected end of file in declaration\n"); goto failed; } // Storage if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_AUTO)) { if (*storage == TMPSTO_NONE) *storage = TMPSTO_AUTO; else { - printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1510,7 +1520,7 @@ parse_cur_token_decl: if (*storage == TMPSTO_NONE) *storage = TMPSTO_EXTERN; else if (*storage == TMPSTO_TLS) *storage = TMPSTO_TLS_EXTERN; else { - printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1518,7 +1528,7 @@ parse_cur_token_decl: } else if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_REGISTER)) { if (*storage == TMPSTO_NONE) *storage = TMPSTO_REG; else { - printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1527,7 +1537,7 @@ parse_cur_token_decl: if (*storage == TMPSTO_NONE) *storage = TMPSTO_STATIC; else if (*storage == TMPSTO_TLS) *storage = TMPSTO_TLS_STATIC; else { - printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1537,7 +1547,7 @@ parse_cur_token_decl: else if (*storage == TMPSTO_EXTERN) *storage = TMPSTO_TLS_EXTERN; else if (*storage == TMPSTO_STATIC) *storage = TMPSTO_TLS_STATIC; else { - printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1545,7 +1555,7 @@ parse_cur_token_decl: } else if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_TYPEDEF)) { if (*storage == TMPSTO_NONE) *storage = TMPSTO_TYPEDEF; else { - printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1568,9 +1578,30 @@ parse_cur_token_decl: // Empty destructor *tok = proc_next_token(prep); if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_LPAREN)) { - printf("Error: TODO: _Atomic(type-name)\n"); + if (*spec != SPEC_NONE) { + log_error(&tok->loginfo, "unexpected symbol '('\n"); + // Empty destructor + goto failed; + } + *spec = SPEC_TYPE; + if (!parse_type_name(target, struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, SYM_RPAREN, &typ)) { + goto failed; + } + if (!typ->is_validated) { + log_internal(&tok->loginfo, "_Atomic() type is not validated\n"); + type_del(typ); + // Empty destructor + goto failed; + } + if ((typ->typ == TYPE_ARRAY) || (typ->typ == TYPE_FUNCTION) || typ->is_atomic || typ->is_const || typ->is_restrict || typ->is_volatile) { + log_error(&tok->loginfo, "the type name in an _Atomic() may not be an array, a function, atomic, or qualified\n"); + type_del(typ); + // Empty destructor + goto failed; + } // Empty destructor - goto failed; + *tok = proc_next_token(prep); + goto parse_cur_token_decl; } else { typ->is_atomic = 1; goto parse_cur_token_decl; @@ -1591,16 +1622,16 @@ parse_cur_token_decl: // Specifier #define SPEC(bt,post) \ - if (*spec == SPEC_NONE) { \ - *spec = SPEC_BUILTIN; \ - typ->typ = TYPE_BUILTIN; \ - typ->val.builtin = BTT_ ## bt; \ - post \ - } else { \ - printf("Error: unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); \ - goto failed; \ - } \ - *tok = proc_next_token(prep); \ + if (*spec == SPEC_NONE) { \ + *spec = SPEC_BUILTIN; \ + typ->typ = TYPE_BUILTIN; \ + typ->val.builtin = BTT_ ## bt; \ + post \ + } else { \ + log_error(&tok->loginfo, "unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); \ + goto failed; \ + } \ + *tok = proc_next_token(prep); \ goto parse_cur_token_decl; #define SPEC_SIGNED(bt, allow_int) \ if ((*spec == SPEC_NONE) || (allow_int && (*spec == SPEC_BUILTIN) && (typ->val.builtin == BTT_INT))) { \ @@ -1614,7 +1645,7 @@ parse_cur_token_decl: *spec = allow_int ? *spec : SPEC_BUILTIN; \ typ->val.builtin = BTT_U ## bt; \ } else { \ - printf("Error: unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); \ + log_error(&tok->loginfo, "unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); \ goto failed; \ } \ *tok = proc_next_token(prep); \ @@ -1635,7 +1666,7 @@ parse_cur_token_decl: } else if ((*spec == SPEC_BUILTIN) && (typ->val.builtin == BTT_LONGDOUBLE)) { typ->val.builtin = BTT_CLONGDOUBLE; } else { - printf("Error: unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1654,7 +1685,7 @@ parse_cur_token_decl: } else if ((*spec == SPEC_BUILTIN) && (typ->val.builtin == BTT_LONGDOUBLE)) { typ->val.builtin = BTT_ILONGDOUBLE; } else { - printf("Error: unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1684,7 +1715,7 @@ parse_cur_token_decl: *spec = SPEC_BUILTIN; typ->val.builtin = BTT_LONGDOUBLE; } else { - printf("Error: unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1703,7 +1734,7 @@ parse_cur_token_decl: typ->typ = TYPE_BUILTIN; typ->val.builtin = BTT_IFLOAT; } else { - printf("Error: unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1722,7 +1753,7 @@ parse_cur_token_decl: typ->typ = TYPE_BUILTIN; typ->val.builtin = BTT_IFLOAT128; } else { - printf("Error: unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1737,7 +1768,7 @@ parse_cur_token_decl: } else if (*spec == SPEC_BUILTIN_NOINT) { *spec = SPEC_BUILTIN; } else { - printf("Error: unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1770,7 +1801,7 @@ parse_cur_token_decl: } else if (*spec == SPEC_IMAGINARY) { *spec = SPEC_LONGIMAGINARY; } else { - printf("Error: unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1793,7 +1824,7 @@ parse_cur_token_decl: } else if (((*spec == SPEC_BUILTIN_NOINT) || (*spec == SPEC_BUILTIN)) && (typ->val.builtin == BTT_SHORT)) { typ->val.builtin = BTT_SSHORT; } else { - printf("Error: unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1814,7 +1845,7 @@ parse_cur_token_decl: } else if (((*spec == SPEC_BUILTIN_NOINT) || (*spec == SPEC_BUILTIN)) && (typ->val.builtin == BTT_SHORT)) { typ->val.builtin = BTT_USHORT; } else { - printf("Error: unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); + log_error(&tok->loginfo, "unexpected type specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; } *tok = proc_next_token(prep); @@ -1828,19 +1859,13 @@ parse_cur_token_decl: // The ident is the type-specifier khiter_t it = kh_get(type_map, type_map, string_content(tok->tokv.str)); if (it == kh_end(type_map)) { - printf("Error: invalid type '%s' (ident is not a typedef)\n" - "Current state:\n" - " storage: %p/%u\n" - " spec: %u\n" - " type: ", string_content(tok->tokv.str), storage, storage ? *storage : TMPSTO_NONE, *spec); - type_print(typ); - printf("\n"); + log_error(&tok->loginfo, "invalid type '%s' (ident is not a typedef)\n", string_content(tok->tokv.str)); string_del(tok->tokv.str); goto failed; } else { *spec = SPEC_TYPE; if (!type_copy_into(typ, kh_val(type_map, it))) { - printf("Failed to duplicate type infos\n"); + log_memory("failed to duplicate type infos\n"); string_del(tok->tokv.str); goto failed; } @@ -1855,32 +1880,34 @@ parse_cur_token_decl: // Empty destructor *tok = proc_next_token(prep); - khiter_t it = kh_end(struct_map); // Iterator into the struct_map + string_t *tag; if (tok->tokt == PTOK_IDENT) { - string_t *tag = tok->tokv.str; + tag = tok->tokv.str; // Token moved *tok = proc_next_token(prep); + khiter_t it; // Iterator into the struct_map int iret; it = kh_put(struct_map, struct_map, string_content(tag), &iret); if (iret < 0) { - printf("Error: failed to add structure to struct map\n"); + log_memory("failed to add structure to struct map\n"); proc_token_del(tok); goto failed; } else if (iret == 0) { // Structure already declared or defined if (kh_val(struct_map, it)->is_struct != is_struct) { - printf("Error: incoherent struct/union tagging of %s\n", string_content(tag)); + log_error(&tok->loginfo, "incoherent struct/union tagging of %s\n", string_content(tag)); string_del(tag); proc_token_del(tok); goto failed; } ++kh_val(struct_map, it)->nrefs; string_del(tag); + tag = kh_val(struct_map, it)->tag; } else { kh_val(struct_map, it) = struct_new(is_struct, tag); if (!kh_val(struct_map, it)) { - printf("Error: failed to create new structure metadata structure\n"); + log_memory("failed to create new structure metadata structure\n"); string_del(tag); proc_token_del(tok); goto failed; @@ -1890,10 +1917,11 @@ parse_cur_token_decl: typ->val.st = kh_val(struct_map, it); typ->is_incomplete = !typ->val.st->is_defined; } else { + tag = NULL; typ->typ = TYPE_STRUCT_UNION; typ->val.st = struct_new(is_struct, NULL); if (!typ->val.st) { - printf("Error: failed to create new structure metadata structure\n"); + log_memory("failed to create new structure metadata structure\n"); proc_token_del(tok); goto failed; } @@ -1901,24 +1929,18 @@ parse_cur_token_decl: } if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_LBRACKET)) { if (typ->val.st->is_defined) { - printf("Error: TODO: struct redefinition\n" - "Current state:\n" - " storage: %p/%u\n" - " spec: %u\n" - " type: ", storage, storage ? *storage : TMPSTO_NONE, *spec); - type_print(typ); - printf("\n"); + log_TODO(&tok->loginfo, "struct redefinition (tag is %s)\n", typ->val.st->tag ? string_content(typ->val.st->tag) : "<no tag>"); goto failed; } VECTOR(st_members) *members = vector_new(st_members); if (!members) { - printf("Failed to create a members vector\n"); + log_memory("failed to create a members vector\n"); goto failed; } type_t *typ2 = type_new(); if (!typ2) { - printf("Failed to create a type info structure\n"); + log_memory("failed to create a type info structure\n"); vector_del(st_members, members); goto failed; } @@ -1941,13 +1963,13 @@ parse_cur_token_decl: // A struct-declaration that does not declare an anonymous structure or anonymous union // shall contain a struct-declarator-list. if ((typ2->typ != TYPE_STRUCT_UNION) || typ2->val.st->tag) { - printf("Error: missing struct-declarator-list\n"); + log_error(&tok->loginfo, "missing struct-declarator-list\n"); vector_del(st_members, members); type_del(typ2); goto failed; } if (!vector_push(st_members, members, ((st_member_t){.name = NULL, .typ = typ2, .is_bitfield = 0}))) { - printf("Error: failed to add anonymous structure member\n"); + log_memory("failed to add anonymous structure member\n"); vector_del(st_members, members); type_del(typ2); // Empty destructor @@ -1955,7 +1977,7 @@ parse_cur_token_decl: } typ2 = type_new(); if (!typ2) { - printf("Failed to create a type info structure\n"); + log_memory("failed to create a type info structure\n"); vector_del(st_members, members); // Empty destructor goto failed; @@ -1974,7 +1996,7 @@ parse_cur_token_decl: dest2.structms.const_map = const_map; dest2.structms.dest = members; if (!parse_declarator(target, &dest2, prep, tok, TMPSTO_NONE, FSPEC_NONE, typ2, 0, 1, 1, 1)) { - printf("Error parsing struct-declarator-list\n"); + log_error(&tok->loginfo, "error parsing struct-declarator-list\n"); vector_del(st_members, members); type_del(typ2); // Token is deleted @@ -1982,14 +2004,14 @@ parse_cur_token_decl: } type_del(typ2); if ((tok->tokt != PTOK_SYM) && (tok->tokv.sym != SYM_SEMICOLON)) { - printf("Error parsing struct-declarator-list (invalid next token)\n"); + log_error(&tok->loginfo, "error parsing struct-declarator-list (invalid next token)\n"); vector_del(st_members, members); proc_token_del(tok); goto failed; } typ2 = type_new(); if (!typ2) { - printf("Failed to create a type info structure\n"); + log_memory("failed to create a type info structure\n"); vector_del(st_members, members); // Empty destructor goto failed; @@ -1998,7 +2020,7 @@ parse_cur_token_decl: } type_del(typ2); if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_RBRACKET)) { - printf("Error parsing struct-declarator-list (invalid next token)\n"); + log_error(&tok->loginfo, "error parsing struct-declarator-list (invalid next token)\n"); vector_del(st_members, members); proc_token_del(tok); goto failed; @@ -2006,6 +2028,13 @@ parse_cur_token_decl: typ->is_incomplete = 0; typ->is_validated = 0; + if (tag) { + khiter_t it = kh_get(type_set, type_set, typ); + if (it != kh_end(type_set)) { + kh_key(type_set, it)->is_incomplete = 0; + kh_key(type_set, it)->is_validated = 0; + } + } typ->val.st->has_incomplete = 0; // Filled by the validate_type step typ->val.st->nmembers = vector_size(st_members, members); typ->val.st->members = vector_steal(st_members, members); @@ -2013,8 +2042,8 @@ parse_cur_token_decl: *tok = proc_next_token(prep); goto parse_cur_token_decl; } else { - if (it == kh_end(struct_map)) { - printf("Error: invalid structure declaration: missing tag and/or definition\n"); + if (!tag) { + log_error(&tok->loginfo, "invalid structure declaration: missing tag and/or definition\n"); proc_token_del(tok); goto failed; } @@ -2033,19 +2062,19 @@ parse_cur_token_decl: } if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_LBRACKET)) { if (!tag) { - printf("Error: unexpected token after keyword 'enum'\n"); + log_error(&tok->loginfo, "unexpected token after keyword 'enum'\n"); proc_token_del(tok); goto failed; } khiter_t it = kh_get(type_map, enum_map, string_content(tag)); if (it == kh_end(enum_map)) { - printf("Error: enumeration %s has not been defined yet\n", string_content(tag)); // TODO? + log_error(&tok->loginfo, "enumeration %s has not been defined yet\n", string_content(tag)); // TODO? string_del(tag); proc_token_del(tok); goto failed; } if (!type_copy_into(typ, kh_val(enum_map, it))) { - printf("Failed to duplicate enum type infos\n"); + log_memory("failed to duplicate enum type infos\n"); string_del(tag); proc_token_del(tok); goto failed; @@ -2068,25 +2097,93 @@ parse_cur_token_decl: num_constant_t cst = { .typ = NCT_INT32, .val.i32 = -1 }; // Empty destructor *tok = proc_next_token(prep); + if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_RBRACKET)) { + log_error(&tok->loginfo, "expected enum constant name before '}'\n"); + proc_token_del(tok); + goto failed; + } int iret; while ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_RBRACKET)) { if (tok->tokt != PTOK_IDENT) { - printf("Error: invalid token in enumeration definition\n"); + log_error(&tok->loginfo, "unexpected token in enumeration definition\n"); if (tag) string_del(tag); proc_token_del(tok); goto failed; } char *ident = string_steal(tok->tokv.str); *tok = proc_next_token(prep); + while ((tok->tokt == PTOK_IDENT) && !strcmp(string_content(tok->tokv.str), "__attribute__")) { + // Attribute + string_del(tok->tokv.str); + *tok = proc_next_token(prep); + if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_LPAREN)) { + log_error(&tok->loginfo, "unexpected token, expected '('\n"); + free(ident); + if (tag) string_del(tag); + proc_token_del(tok); + goto failed; + } + // Empty destructor + *tok = proc_next_token(prep); + if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_LPAREN)) { + log_error(&tok->loginfo, "unexpected token, expected '('\n"); + free(ident); + if (tag) string_del(tag); + // Empty destructor + goto failed; + } + // Empty destructor + *tok = proc_next_token(prep); + enum_attribute_list: + if ((tok->tokt == PTOK_IDENT) && TOKEN_MATCH_ATTR(deprecated)) { + log_warning(&tok->loginfo, "ignoring enum constant attribute 'deprecated'\n"); + string_del(tok->tokv.str); + *tok = proc_next_token(prep); + if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_COMMA)) { + // Empty destructor + *tok = proc_next_token(prep); + goto enum_attribute_list; + } else goto enum_attribute_list_end; + } + if ((tok->tokt == PTOK_IDENT) && TOKEN_MATCH_ATTR(unavailable)) { + log_warning(&tok->loginfo, "ignoring enum constant attribute 'unavailable'\n"); + string_del(tok->tokv.str); + *tok = proc_next_token(prep); + if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_COMMA)) { + // Empty destructor + *tok = proc_next_token(prep); + goto enum_attribute_list; + } else goto enum_attribute_list_end; + } + enum_attribute_list_end: + if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_RPAREN)) { + log_error(&tok->loginfo, "unexpected token, expected ident or ')'\n"); + free(ident); + if (tag) string_del(tag); + // Empty destructor + goto failed; + } + // Empty destructor + *tok = proc_next_token(prep); + if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_RPAREN)) { + log_error(&tok->loginfo, "unexpected token, expected ')'\n"); + free(ident); + if (tag) string_del(tag); + // Empty destructor + goto failed; + } + // Empty destructor + *tok = proc_next_token(prep); + } khiter_t it = kh_put(const_map, const_map, ident, &iret); if (iret < 0) { - printf("Error: failed to add constant %s to the constants map\n", ident); + log_memory("failed to add constant %s to the constants map\n", ident); free(ident); if (tag) string_del(tag); proc_token_del(tok); goto failed; } else if (iret == 0) { - printf("Error: constant %s is already in the constants map\n", ident); + log_error(&tok->loginfo, "constant %s is already defined\n", ident); free(ident); if (tag) string_del(tag); proc_token_del(tok); @@ -2114,7 +2211,7 @@ parse_cur_token_decl: break; case NCT_UINT64: if (cst.val.u64 == UINT64_MAX) { - printf("Error: enum constant is too big\n"); + log_error(&tok->loginfo, "enum constant is too big\n"); if (tag) string_del(tag); proc_token_del(tok); goto failed; @@ -2124,7 +2221,7 @@ parse_cur_token_decl: case NCT_DOUBLE: case NCT_LDOUBLE: default: - printf("Internal error: enum constant is a float/double/ldouble\n"); + log_internal(&tok->loginfo, "enum constant is a float/double/ldouble\n"); if (tag) string_del(tag); proc_token_del(tok); goto failed; @@ -2137,13 +2234,13 @@ parse_cur_token_decl: goto failed; } if ((tok->tokt != PTOK_SYM) || ((tok->tokv.sym != SYM_COMMA) && (tok->tokv.sym != SYM_RBRACKET))) { - printf("Error: unexpected token during enumeration declaration\n"); + log_error(&tok->loginfo, "unexpected token during enumeration declaration\n"); expr_del(e); if (tag) string_del(tag); proc_token_del(tok); goto failed; } - if (!eval_expression(e, const_map, &cst, 1)) { + if (!eval_expression(&tok->loginfo, target, e, const_map, &cst, 1)) { expr_del(e); if (tag) string_del(tag); // Empty destructor @@ -2156,7 +2253,7 @@ parse_cur_token_decl: if (cst.val.i32 < 0) { has_neg = 1; if (btt == BTT_U64) { - printf("Error: enum constant is too big\n"); + log_error(&tok->loginfo, "enum constant is too big\n"); if (tag) string_del(tag); // Empty destructor goto failed; @@ -2177,7 +2274,7 @@ parse_cur_token_decl: not_in_i32 = 1; } if (btt == BTT_U64) { - printf("Error: enum constant is too big\n"); + log_error(&tok->loginfo, "enum constant is too big\n"); if (tag) string_del(tag); // Empty destructor goto failed; @@ -2198,7 +2295,7 @@ parse_cur_token_decl: if (cst.val.u64 > (uint32_t)INT32_MAX) { not_in_i32 = 1; if (has_neg && (cst.val.u64 > (uint64_t)INT64_MAX)) { - printf("Error: enum constant is too big\n"); + log_error(&tok->loginfo, "enum constant is too big\n"); if (tag) string_del(tag); // Empty destructor goto failed; @@ -2210,7 +2307,7 @@ parse_cur_token_decl: case NCT_DOUBLE: case NCT_LDOUBLE: default: - printf("Error: invalid floating-point enumeration constant\n"); + log_error(&tok->loginfo, "invalid floating-point enumeration constant\n"); if (tag) string_del(tag); // Empty destructor goto failed; @@ -2224,19 +2321,19 @@ parse_cur_token_decl: char *ctag = string_steal(tag); khiter_t it = kh_put(type_map, enum_map, ctag, &iret); if (iret < 0) { - printf("Error: failed to add enumeration %s to the type map\n", ctag); + log_memory("failed to add enumeration %s to the type map\n", ctag); free(ctag); // Empty destructor goto failed; } else if (iret == 0) { - printf("Error: enumeration %s already exists\n", ctag); + log_error(&tok->loginfo, "enumeration %s already exists\n", ctag); free(ctag); // Empty destructor goto failed; } type_t *new_typ = type_new(); if (!new_typ) { - printf("Error: failed to create type info for enumeration %s\n", ctag); + log_memory("failed to create type info for enumeration %s\n", ctag); free(ctag); kh_del(type_map, enum_map, it); // Empty destructor @@ -2247,7 +2344,7 @@ parse_cur_token_decl: typ->val.typ = new_typ->val.typ = (*builtins)[btt]; typ->val.typ->nrefs += 2; new_typ = type_try_merge(new_typ, type_set); - validate_type(target, new_typ); // Assume it returns 1 + validate_type(&tok->loginfo, target, new_typ); // Assume it returns 1 kh_val(enum_map, it) = new_typ; } else { typ->typ = TYPE_ENUM; @@ -2269,14 +2366,7 @@ parse_cur_token_decl: return 1; invalid_token: - printf("Error: unexpected token (parse_declaration_specifier)\n" - "Current state:\n" - " storage: %p/%u\n" - " spec: %u\n" - " type: ", storage, storage ? *storage : TMPSTO_NONE, *spec); - type_print(typ); - printf("\n"); - proc_token_print(tok); + log_error(&tok->loginfo, "unexpected token (parse_declaration_specifier)\n"); proc_token_del(tok); failed: @@ -2294,7 +2384,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d type_t *cur_bottom = NULL; VECTOR(size_t) *nptr_stack = vector_new_cap(size_t, 1); if (!nptr_stack) { - printf("Failed to parse init_declarator_list (allocate nptr_stack)\n"); + log_memory("failed to allocate nptr stack\n"); proc_token_del(tok); goto failed0; } @@ -2302,31 +2392,13 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d while (1) { switch (tok->tokt) { case PTOK_IDENT: - if (!has_ident) { - if (allow_decl) { - cur_ident = tok->tokv.str; - has_ident = 1; - *tok = proc_next_token(prep); - break; - } else { - printf("Error: unexpected identifier: abstract declarator do not contain a name\n" - "Current state:\n" - " storage: %u\n" - " type: ", storage); - type_print(typ); - printf("\n"); - proc_token_print(tok); - proc_token_del(tok); - goto failed; - } + if (!has_ident && allow_decl) { + cur_ident = tok->tokv.str; + has_ident = 1; + *tok = proc_next_token(prep); + break; } else { - printf("Error: unexpected identifier\n" - "Current state:\n" - " storage: %u\n" - " type: ", storage); - type_print(typ); - printf("\n"); - proc_token_print(tok); + log_error(&tok->loginfo, "unexpected identifier\n"); proc_token_del(tok); goto failed; } @@ -2337,7 +2409,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d VECTOR(types) *args = vector_new(types); if (!args) { - printf("Error: failed to create new type (function argument)\n"); + log_memory("failed to create new type (function argument)\n"); // Empty destructor goto failed; } @@ -2350,7 +2422,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d vector_del(types, args); new_typ = type_new(); if (!new_typ) { - printf("Error: failed to create new function type\n"); + log_memory("failed to create new function type\n"); // Empty destructor goto failed; } @@ -2362,7 +2434,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d goto end_fun; } if (!proc_unget_token(prep, tok)) { - printf("Error: failed to unget processor token\n"); + log_memory("failed to unget processor token\n"); // Empty destructor vector_del(types, args); goto failed; @@ -2378,7 +2450,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d // Empty destructor *tok = proc_next_token(prep); if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_RPAREN)) { - printf("Error: invalid token after function variadic argument\n"); + log_error(&tok->loginfo, "invalid token after function variadic argument\n"); proc_token_del(tok); vector_del(types, args); goto failed; @@ -2387,7 +2459,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } else { type_t *typ2 = type_new(); if (!typ2) { - printf("Error: failed to create new type (function argument)\n"); + log_memory("failed to create new type (function argument)\n"); // Empty destructor vector_del(types, args); goto failed; @@ -2403,7 +2475,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } if (spec2 == SPEC_NONE) { // _Static_assert declaration; empty destructor - printf("Invalid _Static_assert declaration\n"); + log_error(&tok->loginfo, "unexpected _Static_assert declaration\n"); vector_del(types, args); type_del(typ2); goto failed; @@ -2414,13 +2486,13 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d // Need to convert type to a pointer type_t *typ3 = type_new(); if (!typ3) { - printf("Error: failed to allocate new type\n"); + log_memory("failed to allocate new type\n"); type_del(typ2); // Empty destructor goto failed; } if (!type_copy_into(typ3, typ2)) { - printf("Error: failed to duplicate array type to temporary type\n"); + log_memory("failed to duplicate array type to temporary type\n"); type_del(typ3); type_del(typ2); // Empty destructor @@ -2432,7 +2504,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d typ2 = type_try_merge(typ3, PDECL_TYPE_SET); } if (!vector_push(types, args, typ2)) { - printf("Error: failed to add argument to argument vector\n"); + log_memory("failed to add argument to argument vector\n"); vector_del(types, args); type_del(typ2); // Empty destructor @@ -2445,13 +2517,13 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d // Need to convert type to a pointer type_t *typ3 = type_new(); if (!typ3) { - printf("Error: failed to allocate new type\n"); + log_memory("failed to allocate new type\n"); type_del(typ2); // Empty destructor goto failed; } if (!type_copy_into(typ3, typ2)) { - printf("Error: failed to duplicate array type to temporary type\n"); + log_memory("failed to duplicate array type to temporary type\n"); type_del(typ3); type_del(typ2); // Empty destructor @@ -2463,7 +2535,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d typ2 = type_try_merge(typ3, PDECL_TYPE_SET); } if (!vector_push(types, args, typ2)) { - printf("Error: failed to add argument to argument vector\n"); + log_memory("failed to add argument to argument vector\n"); vector_del(types, args); type_del(typ2); // Empty destructor @@ -2490,13 +2562,13 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } type_del(typ2); if (!dest2.argt.dest) { - printf("Internal error: argument type is NULL\n"); + log_internal(&tok->loginfo, "argument type is NULL\n"); vector_del(types, args); // Empty destructor goto failed; } if (!vector_push(types, args, dest2.argt.dest)) { - printf("Error: failed to add argument to argument vector\n"); + log_memory("failed to add argument to argument vector\n"); vector_del(types, args); type_del(dest2.argt.dest); // Empty destructor @@ -2509,7 +2581,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d *tok = proc_next_token(prep); continue; } - printf("Error: invalid token after function argument\n"); + log_error(&tok->loginfo, "invalid token after function argument\n"); vector_del(types, args); proc_token_del(tok); goto failed; @@ -2518,7 +2590,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d no_arg: new_typ = type_new(); if (!new_typ) { - printf("Error: failed to create new function type\n"); + log_memory("failed to create new function type\n"); // Empty destructor goto failed; } @@ -2547,7 +2619,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d break; } else { if (!vector_push(size_t, nptr_stack, 0)) { - printf("Failed to parse init_declarator_list (open parenthesis)\n"); + log_memory("Failed to push 0 to the nptr stack for opening a parenthesis\n"); // Empty destructor goto failed; } @@ -2556,13 +2628,13 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } } else if (tok->tokv.sym == SYM_STAR) { if (has_ident) { - printf("Error: invalid token '*' after identifier in declaration\n"); + log_error(&tok->loginfo, "invalid token '*' after identifier in declaration\n"); // Empty destructor goto failed; } else { type_t *new_typ = type_new_ptr(typ); if (!new_typ) { - printf("Failed to parse init_declarator_list (create new pointer typ)\n"); + log_memory("failed to create a new pointer type info structure\n"); // Empty destructor goto failed; } @@ -2574,14 +2646,14 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } else if (tok->tokv.sym == SYM_LSQBRACKET) { if (!has_ident) { if (!allow_abstract) { - printf("Error: invalid token '[' before identifier in declaration\n"); + log_error(&tok->loginfo, "invalid token '[' before identifier in declaration\n"); // Empty destructor goto failed; } has_ident = 1; } if (array_atomic || array_const || array_restrict || array_static || array_volatile) { - printf("Error: invalid array after array with type qualifier(s) and/or 'static'\n"); + log_error(&tok->loginfo, "invalid array after array with type qualifier(s) and/or 'static'\n"); // Empty destructor goto failed; } @@ -2598,10 +2670,10 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d size_t nelems; _Bool is_incomplete; while (1) { #define DO_CHECKS \ - if (is_init || is_list || !allow_decl || (cur_bottom && (typ->typ != TYPE_ARRAY))) { \ - printf("Error: type qualifiers and 'static' may only appear in function argument array declarations\n"); \ - /* Empty destructor */ \ - goto failed; \ + if (is_init || is_list || !allow_decl || (cur_bottom && (typ->typ != TYPE_ARRAY))) { \ + log_error(&tok->loginfo, "type qualifiers and 'static' may only appear in function argument array declarations\n"); \ + /* Empty destructor */ \ + goto failed; \ } if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_ATOMIC)) { DO_CHECKS @@ -2629,7 +2701,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_RSQBRACKET)) { if (array_static) { // Missing expression - printf("Error: unexpected token ']' in static length array declaration\n"); + log_error(&tok->loginfo, "unexpected token ']' in static length array declaration\n"); // Empty destructor goto failed; } @@ -2639,7 +2711,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } else if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_STAR)) { if (array_static) { // Missing expression - printf("Error: unexpected token '*' in static length array declaration\n"); + log_error(&tok->loginfo, "unexpected token '*' in static length array declaration\n"); // Empty destructor goto failed; } @@ -2650,7 +2722,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d *tok = proc_next_token(prep); if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_RSQBRACKET)) { // TODO: ...[*expr] - printf("Error: unexpected token during variable length array declaration\n"); + log_error(&tok->loginfo, "unexpected token during variable length array declaration\n"); proc_token_del(tok); goto failed; } @@ -2663,13 +2735,13 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d goto failed; } if ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_RSQBRACKET)) { - printf("Error: unexpected token during array declaration\n"); + log_error(&tok->loginfo, "unexpected token during array declaration\n"); expr_del(e); proc_token_del(tok); goto failed; } num_constant_t cst; - if (eval_expression(e, PDECL_CONST_MAP, &cst, is_init || is_list || !allow_decl)) { + if (eval_expression(&tok->loginfo, target, e, PDECL_CONST_MAP, &cst, is_init || is_list || !allow_decl)) { expr_del(e); int is_neg; switch (cst.typ) { @@ -2683,7 +2755,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d default: is_neg = 1; } if (is_neg) { - printf("Error: the size of an array must be nonnegative"); + log_error(&tok->loginfo, "the size of an array must be nonnegative"); // Empty destructor goto failed; } @@ -2702,7 +2774,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d if (cur_bottom) { type_t *tmp = type_new(); if (!tmp) { - printf("Failed to parse init_declarator_list (create new array type)\n"); + log_memory("failed to create new array type info\n"); // Empty destructor goto failed; } @@ -2721,7 +2793,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } else { type_t *new_typ = type_new(); if (!new_typ) { - printf("Failed to parse init_declarator_list (create new array type)\n"); + log_memory("failed to create new array type info\n"); // Empty destructor goto failed; } @@ -2737,7 +2809,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } else if (tok->tokv.sym == SYM_RPAREN) { if (!has_ident) { if (!allow_abstract) { - printf("Error: invalid token ')' before identifier in declaration\n"); + log_error(&tok->loginfo, "invalid token ')' before identifier in declaration\n"); // Empty destructor goto failed; } @@ -2745,7 +2817,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } if (vector_size(size_t, nptr_stack) == 1) { if (!is_init && !is_list) goto rparen_ok_ret; - printf("Error: closing unopened parenthesis in declaration\n"); + log_error(&tok->loginfo, "closing unopened parenthesis in declaration\n"); // Empty destructor goto failed; } @@ -2773,12 +2845,12 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d || (is_init && (tok->tokv.sym == SYM_LBRACKET))) { rparen_ok_ret: // Last function argument if (!allow_abstract && !has_ident) { - printf("Error: invalid symbol '%s' before identifier\n", sym2str[tok->tokv.sym]); + log_error(&tok->loginfo, "invalid symbol '%s' before identifier\n", sym2str[tok->tokv.sym]); // Empty destructor goto failed; } if (vector_size(size_t, nptr_stack) != 1) { - printf("Error: invalid symbol '%s' (missing parenthesis?)\n", sym2str[tok->tokv.sym]); + log_error(&tok->loginfo, "invalid symbol '%s' (missing parenthesis?)\n", sym2str[tok->tokv.sym]); // Empty destructor goto failed; } @@ -2786,7 +2858,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d // Try to free some redundant types typ = type_try_merge(typ, PDECL_TYPE_SET); - int validation = validate_storage_type(target, storage, typ, tok->tokv.sym); + int validation = validate_storage_type(&tok->loginfo, target, storage, typ, tok->tokv.sym); if (!validation) { // Empty destructor goto failed; @@ -2796,7 +2868,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d // Function definition; tok is '{' if (!is_init || !is_list || has_list) { // We are not at the top-level or we have an initialization list - printf("Error: invalid function definition\n"); + log_error(&tok->loginfo, "invalid function definition\n"); // Empty destructor goto failed; } @@ -2807,7 +2879,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d declaration_t *decl = malloc(sizeof *decl); if (!decl) { - printf("Failed to create new declaration\n"); + log_memory("failed to create new declaration\n"); // Empty destructor goto failed; } @@ -2819,7 +2891,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d char *cident = string_steal(cur_ident); cur_ident = NULL; khiter_t it = kh_put(decl_map, dest->f->decl_map, cident, &iret); if (iret < 0) { - printf("Failed to add function '%s' to the declaration map\n", cident); + log_memory("failed to add function '%s' to the declaration map\n", cident); free(cident); free(decl); // Empty destructor @@ -2827,7 +2899,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } else if (iret == 0) { free(decl); if (kh_val(dest->f->decl_map, it)->defined) { - printf("Error: function '%s' is already in the declaration map\n", cident); + log_error(&tok->loginfo, "function '%s' is already in the declaration map\n", cident); free(cident); // Empty destructor goto failed; @@ -2850,11 +2922,11 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d else goto success; } } while (!proc_token_isend(tok)); - printf("Error: unexpected token in function body\n"); + log_error(&tok->loginfo, "unexpected token in function body\n"); goto failed; } if ((fspec != FSPEC_NONE) && (typ->typ != TYPE_FUNCTION)) { - printf("Error: unexpected function specifier\n"); + log_error(&tok->loginfo, "unexpected function specifier\n"); // Empty destructor goto failed; } @@ -2863,7 +2935,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d if (storage == TMPSTO_TYPEDEF) { if (!is_init || !is_list) { // We are not at the top-level (note that storage is set to NONE in function arguments) - printf("Error: invalid function definition\n"); + log_error(&tok->loginfo, "invalid function definition\n"); // Empty destructor goto failed; } @@ -2872,13 +2944,13 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d char *cident = string_steal(cur_ident); cur_ident = NULL; khiter_t it = kh_put(type_map, dest->f->type_map, cident, &iret); if (iret < 0) { - printf("Failed to add '%s' to the type map\n", cident); + log_memory("failed to add '%s' to the type map\n", cident); free(cident); // Empty destructor goto failed; } else if (iret == 0) { if (!type_t_equal(typ, kh_val(dest->f->type_map, it))) { - printf("Error: '%s' is already in the type map with a different type\n", cident); + log_error(&tok->loginfo, "'%s' is already in the type map with a different type\n", cident); free(cident); type_del(typ); // Empty destructor @@ -2894,7 +2966,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d if (is_init && is_list) { decl = malloc(sizeof *decl); if (!decl) { - printf("Failed to create new declaration\n"); + log_memory("failed to create new declaration\n"); // Empty destructor goto failed; } @@ -2908,7 +2980,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d char *cident = string_steal(cur_ident); cur_ident = NULL; khiter_t it = kh_put(decl_map, dest->f->decl_map, cident, &iret); if (iret < 0) { - printf("Failed to add '%s' to the declaration map\n", cident); + log_memory("failed to add '%s' to the declaration map\n", cident); free(cident); free(decl); // Empty destructor @@ -2916,7 +2988,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } else if (iret == 0) { if (!type_t_equal(typ, kh_val(dest->f->decl_map, it)->typ) || ((storage == TMPSTO_NONE) && (kh_val(dest->f->decl_map, it)->storage == STORAGE_NONE))) { - printf("Error: '%s' is already in the declaration map (storage=%u)\n", cident, storage); + log_error(&tok->loginfo, "'%s' is already in the declaration map\n", cident); free(cident); free(decl); type_del(typ); @@ -2939,12 +3011,12 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d if (typ == base_type) { typ = type_new(); if (!typ) { - printf("Error: failed to allocate new type\n"); + log_memory("failed to allocate new type\n"); // Empty destructor goto failed; } if (!type_copy_into(typ, base_type)) { - printf("Error: failed to allocate new type\n"); + log_memory("failed to allocate new type\n"); // Empty destructor goto failed; } @@ -2963,13 +3035,13 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d goto success; } else if (!is_init && is_list) { if (!vector_push(st_members, dest->structms.dest, ((st_member_t){.name = cur_ident, .typ = typ, .is_bitfield = 0}))) { - printf("Error: failed to add structure member %s\n", string_content(cur_ident)); + log_memory("failed to add structure member %s\n", string_content(cur_ident)); string_del(cur_ident); // Empty destructor goto failed; } } else { - printf("Internal error: unknown is_init/is_list combination %d%d\n", is_init, is_list); + log_internal(&tok->loginfo, "unknown is_init/is_list combination %d%d\n", is_init, is_list); // Empty destructor goto failed; } @@ -2977,12 +3049,12 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_EQ)) { // Initialization if (!is_init) { - printf("Error: unexpected initializer\n"); + log_error(&tok->loginfo, "unexpected initializer\n"); goto failed; } if (decl) { if (decl->defined) { - printf("Error: invalid declaration initializer: variable was already declared\n"); + log_error(&tok->loginfo, "invalid declaration initializer: variable was already declared\n"); goto failed; } decl->defined = 1; @@ -3001,7 +3073,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } } while (!proc_token_isend(tok)); if (proc_token_isend(tok)) { - printf("Error: unexpected token in declaration initializer\n"); + log_error(&tok->loginfo, "unexpected token in declaration initializer\n"); proc_token_del(tok); goto failed; } @@ -3009,13 +3081,13 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d expr_t *e = parse_expression(target, PDECL_STRUCT_MAP, PDECL_TYPE_MAP, PDECL_ENUM_MAP, PDECL_BUILTINS, PDECL_CONST_MAP, PDECL_TYPE_SET, prep, tok, 15); if (!e) { - printf("Error: invalid declaration initializer\n"); + log_error(&tok->loginfo, "invalid declaration initializer\n"); goto failed; } expr_del(e); } if ((tok->tokt != PTOK_SYM) || ((tok->tokv.sym != SYM_COMMA) && (tok->tokv.sym != SYM_SEMICOLON))) { - printf("Error: unexpected token in declaration initializer\n"); + log_error(&tok->loginfo, "unexpected token in declaration initializer\n"); proc_token_del(tok); goto failed; } @@ -3032,7 +3104,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } } else if (!is_init && is_list && (tok->tokv.sym == SYM_COLON)) { if (vector_size(size_t, nptr_stack) != 1) { - printf("Error: invalid symbol '%s' (missing parenthesis?)\n", sym2str[tok->tokv.sym]); + log_error(&tok->loginfo, "invalid symbol '%s' (missing parenthesis?)\n", sym2str[tok->tokv.sym]); // Empty destructor goto failed; } @@ -3048,20 +3120,20 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d goto failed; } if ((tok->tokt != PTOK_SYM) || ((tok->tokv.sym != SYM_COMMA) && (tok->tokv.sym != SYM_SEMICOLON))) { - printf("Error: unexpected token in bitfield width\n"); + log_error(&tok->loginfo, "unexpected token in bitfield width\n"); expr_del(e); proc_token_del(tok); goto failed; } num_constant_t eval; - if (!eval_expression(e, dest->structms.const_map, &eval, 1)) { + if (!eval_expression(&tok->loginfo, target, e, dest->structms.const_map, &eval, 1)) { expr_del(e); // Empty destructor goto failed; } expr_del(e); - int validation = validate_storage_type(target, storage, typ, tok->tokv.sym); + int validation = validate_storage_type(&tok->loginfo, target, storage, typ, tok->tokv.sym); if (!validation) { // Empty destructor goto failed; @@ -3070,12 +3142,12 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d if (validation == VALIDATION_FUN) { // We are not at the top-level or we have an initialization list // Should never happen - printf("Error: invalid function definition in structure definition\n"); + log_error(&tok->loginfo, "invalid function definition in structure definition\n"); // Empty destructor goto failed; } if ((fspec != FSPEC_NONE) && (typ->typ != TYPE_FUNCTION)) { - printf("Error: unexpected function specifier\n"); + log_error(&tok->loginfo, "unexpected function specifier\n"); // Empty destructor goto failed; } @@ -3084,7 +3156,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d switch (eval.typ) { case NCT_INT32: if (eval.val.i32 < 0) { - printf("Error: invalid negative bitfield width\n"); + log_error(&tok->loginfo, "invalid negative bitfield width\n"); goto failed; } width = (size_t)eval.val.i32; @@ -3094,7 +3166,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d break; case NCT_INT64: if (eval.val.i64 < 0) { - printf("Error: invalid negative bitfield width\n"); + log_error(&tok->loginfo, "invalid negative bitfield width\n"); goto failed; } width = (size_t)eval.val.i64; @@ -3106,13 +3178,13 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d case NCT_DOUBLE: case NCT_LDOUBLE: default: - printf("Error: invalid non-integer bitfield width\n"); + log_error(&tok->loginfo, "invalid non-integer bitfield width\n"); goto failed; } if (!vector_push(st_members, dest->structms.dest, ((st_member_t){.name = cur_ident, .typ = typ, .is_bitfield = 1, .bitfield_width = width}))) { - printf("Error: failed to add structure member %s\n", string_content(cur_ident)); + log_memory("failed to add structure member %s\n", string_content(cur_ident)); string_del(cur_ident); // Empty destructor goto failed; @@ -3131,12 +3203,12 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d case PTOK_KEYWORD: if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_ATOMIC)) { if (has_ident) { - printf("Error: invalid keyword '_Atomic' after identifier\n"); + log_error(&tok->loginfo, "invalid keyword '_Atomic' after identifier\n"); proc_token_print(tok); // Empty destructor goto failed; } else if (!vector_last(size_t, nptr_stack)) { - printf("Error: invalid keyword '_Atomic' before symbol '*'\n"); + log_error(&tok->loginfo, "invalid keyword '_Atomic' before symbol '*'\n"); proc_token_print(tok); // Empty destructor goto failed; @@ -3147,12 +3219,12 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } } else if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_CONST)) { if (has_ident) { - printf("Error: invalid keyword 'const' after identifier\n"); + log_error(&tok->loginfo, "invalid keyword 'const' after identifier\n"); proc_token_print(tok); // Empty destructor goto failed; } else if (!vector_last(size_t, nptr_stack)) { - printf("Error: invalid keyword 'const' before symbol '*'\n"); + log_error(&tok->loginfo, "invalid keyword 'const' before symbol '*'\n"); proc_token_print(tok); // Empty destructor goto failed; @@ -3163,12 +3235,12 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } } else if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_RESTRICT)) { if (has_ident) { - printf("Error: invalid keyword 'restrict' after identifier\n"); + log_error(&tok->loginfo, "invalid keyword 'restrict' after identifier\n"); proc_token_print(tok); // Empty destructor goto failed; } else if (!vector_last(size_t, nptr_stack)) { - printf("Error: invalid keyword 'restrict' before symbol '*'\n"); + log_error(&tok->loginfo, "invalid keyword 'restrict' before symbol '*'\n"); proc_token_print(tok); // Empty destructor goto failed; @@ -3179,12 +3251,12 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } } else if ((tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_VOLATILE)) { if (has_ident) { - printf("Error: invalid keyword 'volatile' after identifier\n"); + log_error(&tok->loginfo, "invalid keyword 'volatile' after identifier\n"); proc_token_print(tok); // Empty destructor goto failed; } else if (!vector_last(size_t, nptr_stack)) { - printf("Error: invalid keyword 'volatile' before symbol '*'\n"); + log_error(&tok->loginfo, "invalid keyword 'volatile' before symbol '*'\n"); proc_token_print(tok); // Empty destructor goto failed; @@ -3200,13 +3272,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d case PTOK_STRING: case PTOK_PRAGMA: case PTOK_EOF: - printf("Error: unexpected token (parse_declarator %d%d%d%d)\n" - "Current state:\n" - " storage: %u\n" - " type: ", is_init, is_list, allow_decl, allow_abstract, storage); - type_print(typ); - printf("\n"); - proc_token_print(tok); + log_error(&tok->loginfo, "unexpected token (in parse_declarator %d%d%d%d)\n", is_init, is_list, allow_decl, allow_abstract); proc_token_del(tok); goto failed; } @@ -3226,44 +3292,44 @@ failed0: static int finalize_file(machine_t *target, file_t *file) { #define MARK_SIMPLE(sname) \ - it = kh_get(struct_map, file->struct_map, #sname); \ - if (it != kh_end(file->struct_map)) { \ - kh_val(file->struct_map, it)->is_simple = 1; \ - } else { \ - it = kh_get(type_map, file->type_map, #sname); \ - if (it != kh_end(file->type_map)) { \ - type_t *typ2 = kh_val(file->type_map, it); \ - if (typ2->typ != TYPE_STRUCT_UNION) { \ - printf("Error: invalid typedef " #sname ": not a structure\n"); \ - return 0; \ - } \ - typ2->val.st->is_simple = 1; \ - } \ + it = kh_get(struct_map, file->struct_map, #sname); \ + if (it != kh_end(file->struct_map)) { \ + kh_val(file->struct_map, it)->is_simple = 1; \ + } else { \ + it = kh_get(type_map, file->type_map, #sname); \ + if (it != kh_end(file->type_map)) { \ + type_t *typ2 = kh_val(file->type_map, it); \ + if (typ2->typ != TYPE_STRUCT_UNION) { \ + log_error_nopos("invalid typedef " #sname ": not a structure\n"); \ + return 0; \ + } \ + typ2->val.st->is_simple = 1; \ + } \ } #define SET_WEAK(converted) \ - validate_type(target, typ); \ - typ = type_try_merge(typ, file->type_set); \ - it = kh_put(conv_map, file->relaxed_type_conversion, typ, &iret); \ - if (iret < 0) { \ - printf("Error: failed to add relaxed conversion to type map\n"); \ - type_del(typ); \ - return 0; \ - } else if (iret == 0) { \ - printf("Error: type already has a relaxed conversion\n"); \ - type_del(typ); \ - return 0; \ - } \ + validate_type(&(loginfo_t){0}, target, typ); \ + typ = type_try_merge(typ, file->type_set); \ + it = kh_put(conv_map, file->relaxed_type_conversion, typ, &iret); \ + if (iret < 0) { \ + log_memory("failed to add relaxed conversion to type map\n"); \ + type_del(typ); \ + return 0; \ + } else if (iret == 0) { \ + log_error_nopos("type already has a relaxed conversion\n"); \ + type_del(typ); \ + return 0; \ + } \ kh_val(file->relaxed_type_conversion, it) = string_new_cstr(#converted); #define SET_WEAK_PTR_TO(to_typ, converted) \ - it = kh_get(type_map, file->type_map, #to_typ); \ - if (it != kh_end(file->type_map)) { \ - typ = type_new_ptr(kh_val(file->type_map, it)); \ - if (!typ) { \ - printf("Failed to create type " #to_typ "*\n"); \ - return 0; \ - } \ - ++kh_val(file->type_map, it)->nrefs; \ - SET_WEAK(converted) \ + it = kh_get(type_map, file->type_map, #to_typ); \ + if (it != kh_end(file->type_map)) { \ + typ = type_new_ptr(kh_val(file->type_map, it)); \ + if (!typ) { \ + log_memory("failed to create type " #to_typ "*\n"); \ + return 0; \ + } \ + ++kh_val(file->type_map, it)->nrefs; \ + SET_WEAK(converted) \ } type_t *typ; @@ -3273,13 +3339,25 @@ static int finalize_file(machine_t *target, file_t *file) { SET_WEAK_PTR_TO(FILE, S) // #pragma type_letters b xcb_connection_t* SET_WEAK_PTR_TO(xcb_connection_t, S) + if (target->size_long == 4) { + // Only on x86, not on x86_64 + it = kh_get(type_map, file->type_map, "locale_t"); + if (it != kh_end(file->type_map)) { + typ = kh_val(file->type_map, it); + SET_WEAK(a) + } + } // #pragma mark_simple ... - MARK_SIMPLE(FTS) - MARK_SIMPLE(FTS64) - MARK_SIMPLE(glob_t) - MARK_SIMPLE(glob64_t) + if (target->size_long == 8) { + // Only on x86_64, not on x86 + MARK_SIMPLE(FTS) + MARK_SIMPLE(FTS64) + MARK_SIMPLE(glob_t) + MARK_SIMPLE(glob64_t) + } #undef MARK_SIMPLE #undef SET_WEAK +#undef SET_WEAK_PTR_TO return 1; } @@ -3287,20 +3365,20 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { char *dirname = strchr(filename, '/') ? strndup(filename, (size_t)(strrchr(filename, '/') - filename)) : NULL; preproc_t *prep = preproc_new_file(target, file, dirname, filename); if (!prep) { - printf("Failed to create the preproc structure\n"); + log_memory("failed to create the preproc structure\n"); if (dirname) free(dirname); return NULL; } file_t *ret = file_new(target); if (!ret) { - printf("Failed to create the file structure\n"); + log_memory("failed to create the file structure\n"); preproc_del(prep); return NULL; } type_t *typ = type_new(); if (!typ) { - printf("Failed to create a type info structure\n"); + log_memory("failed to create a type info structure\n"); goto failed; } while (1) { @@ -3315,17 +3393,17 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { int iret; char *dup = strdup(typenames[i]); if (!dup) { - printf("Failed to create a type info structure\n"); + log_memory("failed to create a type info structure\n"); goto failed; } type_t *t = ret->builtins[BTT_START_INT_EXT + i]; khiter_t it = kh_put(type_map, ret->type_map, dup, &iret); if (iret < 0) { - printf("Failed to add an intrinsic to the type map\n"); + log_memory("failed to add an intrinsic to the type map\n"); goto failed; } else if (iret == 0) { if (!type_t_equal(t, kh_val(ret->type_map, it))) { - printf("Error: %s is already defined\n", dup); + log_error(&tok.loginfo, "%s is already defined\n", dup); free(dup); goto failed; } @@ -3347,13 +3425,13 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { if (it != kh_end(ret->struct_map)) { type_t *typ2 = kh_val(ret->type_map, it); if (typ2->typ != TYPE_STRUCT_UNION) { - printf("Error: failed to find struct/union named %s\n", string_content(sutag)); + log_error(&tok.loginfo, "failed to find struct/union named %s\n", string_content(sutag)); string_del(sutag); goto failed; } su = typ2->val.st; } else { - printf("Error: failed to find struct/union named %s\n", string_content(sutag)); + log_error(&tok.loginfo, "failed to find struct/union named %s\n", string_content(sutag)); string_del(sutag); goto failed; } @@ -3366,7 +3444,7 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { string_t *converted = tok.tokv.pragma.val; type_t *typ2 = type_new(); if (!typ2) { - printf("Error: failed to create new type info structure\n"); + log_memory("failed to create new type info structure\n"); string_del(converted); type_del(typ2); goto failed; @@ -3380,13 +3458,13 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { int iret; khiter_t it = kh_put(conv_map, ret->relaxed_type_conversion, typ2, &iret); if (iret < 0) { - printf("Error: failed to add relaxed conversion to type map\n"); + log_memory("failed to add relaxed conversion to type map\n"); string_del(converted); type_del(typ2); // Empty destructor goto failed; } else if (iret == 0) { - printf("Error: type already has a relaxed conversion\n"); + log_error(&tok.loginfo, "type already has a relaxed conversion\n"); string_del(converted); type_del(typ2); // Empty destructor @@ -3400,7 +3478,7 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { string_t *converted = tok.tokv.pragma.val; type_t *typ2 = type_new(); if (!typ2) { - printf("Error: failed to create new type info structure\n"); + log_memory("failed to create new type info structure\n"); string_del(converted); type_del(typ2); goto failed; @@ -3413,7 +3491,7 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { } type_del(typ2); // typ2 is in the type set, so it is already used if (typ2->converted) { - printf("Error: type already has a strict conversion\n"); + log_error(&tok.loginfo, "type already has a strict conversion\n"); string_del(converted); // Empty destructor goto failed; @@ -3424,7 +3502,7 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { break; } } } else if (proc_token_iserror(&tok)) { - printf("Error: unexpected error token\n"); + log_error(&tok.loginfo, "unexpected error token\n"); proc_token_del(&tok); goto failed; } else { @@ -3442,11 +3520,11 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { goto failed; } } else { - if (validate_storage_type(target, storage, typ, tok.tokv.sym) != VALIDATION_LAST_DECL) { + if (validate_storage_type(&tok.loginfo, target, storage, typ, tok.tokv.sym) != VALIDATION_LAST_DECL) { goto failed; } if (fspec != FSPEC_NONE) { - printf("Error: unexpected function specifier\n"); + log_error(&tok.loginfo, "unexpected function specifier\n"); // Empty destructor goto failed; } @@ -3455,7 +3533,7 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { type_del(typ); typ = type_new(); if (!typ) { - printf("Failed to create a type info structure\n"); + log_memory("failed to create a type info structure\n"); goto failed; } } @@ -3465,7 +3543,7 @@ success: preproc_del(prep); type_del(typ); if (!finalize_file(target, ret)) { - printf("Error: failed to add builtin aliases\n"); + log_memory("failed to add builtin aliases\n"); file_del(ret); return NULL; } |