avoid memory leaks with lost CStrings on stack after errors. tccpp.c: - use/abuse static Cstring tokcstr where possible tccgen.c: - use/abuse static Cstring initstr where possible tcc.h/libtcc.a: - add 'stk_data' array to track memory pointer on stack - add macros stk_push/pop() and cstr_new/free_s() tccasm.c: - use that - use char[16] instead of char* for op.constraint
Unified · Split
| @@ -68,6 +68,9 @@ · 67 unmodified lines | |||
| 68 | /* XXX: get rid of this ASAP (or maybe not) */ | 68 | /* XXX: get rid of this ASAP (or maybe not) */ |
| 69 | ST_DATA struct TCCState *tcc_state; | 69 | ST_DATA struct TCCState *tcc_state; |
| 70 | TCC_SEM(static tcc_compile_sem); | 70 | TCC_SEM(static tcc_compile_sem); |
| 71 | /* an array of pointers to memory to be free'd after errors */ | ||
| 72 | ST_DATA void** stk_data; | ||
| 73 | ST_DATA int nb_stk_data; | ||
| 71 | 74 | ||
| 72 | /********************************************************/ | 75 | /********************************************************/ |
| 73 | #ifdef _WIN32 | 76 | #ifdef _WIN32 |
| @@ -609,8 +612,11 @@ static void error1(int mode, const char *fmt, va_list ap) · 535 unmodified lines | |||
| 609 | cstr_free(&cs); | 612 | cstr_free(&cs); |
| 610 | if (mode != ERROR_WARN) | 613 | if (mode != ERROR_WARN) |
| 611 | s1->nb_errors++; | 614 | s1->nb_errors++; |
| 612 | if (mode == ERROR_ERROR && s1->error_set_jmp_enabled) | 615 | if (mode == ERROR_ERROR && s1->error_set_jmp_enabled) { |
| 616 | while (nb_stk_data) | ||
| 617 | tcc_free(*(void**)stk_data[--nb_stk_data]); | ||
| 613 | longjmp(s1->error_jmp_buf, 1); | 618 | longjmp(s1->error_jmp_buf, 1); |
| 619 | } | ||
| 614 | } | 620 | } |
| 615 | 621 | ||
| 616 | LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func) | 622 | LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func) |
| @@ -495,6 +495,7 @@ typedef struct CString { · 494 unmodified lines | |||
| 495 | int size; /* size in bytes */ | 495 | int size; /* size in bytes */ |
| 496 | int size_allocated; | 496 | int size_allocated; |
| 497 | void *data; /* either 'char *' or 'nwchar_t *' */ | 497 | void *data; /* either 'char *' or 'nwchar_t *' */ |
| 498 | struct CString *prev; | ||
| 498 | } CString; | 499 | } CString; |
| 499 | 500 | ||
| 500 | /* type definition */ | 501 | /* type definition */ |
| @@ -733,7 +734,7 @@ typedef struct ExprValue { · 232 unmodified lines | |||
| 733 | #define MAX_ASM_OPERANDS 30 | 734 | #define MAX_ASM_OPERANDS 30 |
| 734 | typedef struct ASMOperand { | 735 | typedef struct ASMOperand { |
| 735 | int id; /* GCC 3 optional identifier (0 if number only supported) */ | 736 | int id; /* GCC 3 optional identifier (0 if number only supported) */ |
| 736 | char *constraint; | 737 | char constraint[16]; |
| 737 | char asm_str[16]; /* computed asm string for operand */ | 738 | char asm_str[16]; /* computed asm string for operand */ |
| 738 | SValue *vt; /* C value of the expression */ | 739 | SValue *vt; /* C value of the expression */ |
| 739 | int ref_index; /* if >= 0, gives reference to a output constraint */ | 740 | int ref_index; /* if >= 0, gives reference to a output constraint */ |
| @@ -1208,6 +1209,8 @@ enum tcc_token { · 468 unmodified lines | |||
| 1208 | /* ------------ libtcc.c ------------ */ | 1209 | /* ------------ libtcc.c ------------ */ |
| 1209 | 1210 | ||
| 1210 | ST_DATA struct TCCState *tcc_state; | 1211 | ST_DATA struct TCCState *tcc_state; |
| 1212 | ST_DATA void** stk_data; | ||
| 1213 | ST_DATA int nb_stk_data; | ||
| 1211 | 1214 | ||
| 1212 | /* public functions currently used by the tcc main function */ | 1215 | /* public functions currently used by the tcc main function */ |
| 1213 | ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s); | 1216 | ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s); |
| @@ -1257,11 +1260,17 @@ ST_FUNC void cstr_free(CString *cstr); · 43 unmodified lines | |||
| 1257 | ST_FUNC int cstr_printf(CString *cs, const char *fmt, ...) PRINTF_LIKE(2,3); | 1260 | ST_FUNC int cstr_printf(CString *cs, const char *fmt, ...) PRINTF_LIKE(2,3); |
| 1258 | ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap); | 1261 | ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap); |
| 1259 | ST_FUNC void cstr_reset(CString *cstr); | 1262 | ST_FUNC void cstr_reset(CString *cstr); |
| 1260 | |||
| 1261 | ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen); | 1263 | ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen); |
| 1262 | ST_FUNC int tcc_open(TCCState *s1, const char *filename); | 1264 | ST_FUNC int tcc_open(TCCState *s1, const char *filename); |
| 1263 | ST_FUNC void tcc_close(void); | 1265 | ST_FUNC void tcc_close(void); |
| 1264 | 1266 | ||
| 1267 | /* mark a memory pointer on stack for cleanup after errors */ | ||
| 1268 | #define stk_push(p) dynarray_add(&stk_data, &nb_stk_data, p) | ||
| 1269 | #define stk_pop() (--nb_stk_data) | ||
| 1270 | /* mark CString on stack for cleanup errors */ | ||
| 1271 | #define cstr_new_s(cstr) (cstr_new(cstr), stk_push(&(cstr)->data)) | ||
| 1272 | #define cstr_free_s(cstr) (cstr_free(cstr), stk_pop()) | ||
| 1273 | |||
| 1265 | ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags); | 1274 | ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags); |
| 1266 | /* flags: */ | 1275 | /* flags: */ |
| 1267 | #define AFF_PRINT_ERROR 0x10 /* print error if file not found */ | 1276 | #define AFF_PRINT_ERROR 0x10 /* print error if file not found */ |
| @@ -1483,8 +1492,8 @@ ST_FUNC int type_size(CType *type, int *a); · 215 unmodified lines | |||
| 1483 | ST_FUNC void mk_pointer(CType *type); | 1492 | ST_FUNC void mk_pointer(CType *type); |
| 1484 | ST_FUNC void vstore(void); | 1493 | ST_FUNC void vstore(void); |
| 1485 | ST_FUNC void inc(int post, int c); | 1494 | ST_FUNC void inc(int post, int c); |
| 1486 | ST_FUNC void parse_mult_str (CString *astr, const char *msg); | 1495 | ST_FUNC CString* parse_mult_str(const char *msg); |
| 1487 | ST_FUNC void parse_asm_str(CString *astr); | 1496 | ST_FUNC CString* parse_asm_str(void); |
| 1488 | ST_FUNC void indir(void); | 1497 | ST_FUNC void indir(void); |
| 1489 | ST_FUNC void unary(void); | 1498 | ST_FUNC void unary(void); |
| 1490 | ST_FUNC void gexpr(void); | 1499 | ST_FUNC void gexpr(void); |
| @@ -1064,15 +1064,12 @@ ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, · 1063 unmodified lines | |||
| 1064 | } | 1064 | } |
| 1065 | 1065 | ||
| 1066 | static void subst_asm_operands(ASMOperand *operands, int nb_operands, | 1066 | static void subst_asm_operands(ASMOperand *operands, int nb_operands, |
| 1067 | CString *out_str, CString *in_str) | 1067 | CString *out_str, const char *str) |
| 1068 | { | 1068 | { |
| 1069 | int c, index, modifier; | 1069 | int c, index, modifier; |
| 1070 | const char *str; | ||
| 1071 | ASMOperand *op; | 1070 | ASMOperand *op; |
| 1072 | SValue sv; | 1071 | SValue sv; |
| 1073 | 1072 | ||
| 1074 | cstr_new(out_str); | ||
| 1075 | str = in_str->data; | ||
| 1076 | for(;;) { | 1073 | for(;;) { |
| 1077 | c = *str++; | 1074 | c = *str++; |
| 1078 | if (c == '%') { | 1075 | if (c == '%') { |
| @@ -1118,11 +1115,11 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr, · 39 unmodified lines | |||
| 1118 | { | 1115 | { |
| 1119 | ASMOperand *op; | 1116 | ASMOperand *op; |
| 1120 | int nb_operands; | 1117 | int nb_operands; |
| 1118 | char* astr; | ||
| 1121 | 1119 | ||
| 1122 | if (tok != ':') { | 1120 | if (tok != ':') { |
| 1123 | nb_operands = *nb_operands_ptr; | 1121 | nb_operands = *nb_operands_ptr; |
| 1124 | for(;;) { | 1122 | for(;;) { |
| 1125 | CString astr; | ||
| 1126 | if (nb_operands >= MAX_ASM_OPERANDS) | 1123 | if (nb_operands >= MAX_ASM_OPERANDS) |
| 1127 | tcc_error("too many asm operands"); | 1124 | tcc_error("too many asm operands"); |
| 1128 | op = &operands[nb_operands++]; | 1125 | op = &operands[nb_operands++]; |
| @@ -1135,10 +1132,8 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr, · 6 unmodified lines | |||
| 1135 | next(); | 1132 | next(); |
| 1136 | skip(']'); | 1133 | skip(']'); |
| 1137 | } | 1134 | } |
| 1138 | parse_mult_str(&astr, "string constant"); | 1135 | astr = parse_mult_str("string constant")->data; |
| 1139 | op->constraint = tcc_malloc(astr.size); | 1136 | pstrcpy(op->constraint, sizeof op->constraint, astr); |
| 1140 | strcpy(op->constraint, astr.data); | ||
| 1141 | cstr_free(&astr); | ||
| 1142 | skip('('); | 1137 | skip('('); |
| 1143 | gexpr(); | 1138 | gexpr(); |
| 1144 | if (is_output) { | 1139 | if (is_output) { |
| @@ -1171,7 +1166,8 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr, · 26 unmodified lines | |||
| 1171 | /* parse the GCC asm() instruction */ | 1166 | /* parse the GCC asm() instruction */ |
| 1172 | ST_FUNC void asm_instr(void) | 1167 | ST_FUNC void asm_instr(void) |
| 1173 | { | 1168 | { |
| 1174 | CString astr, astr1; | 1169 | CString astr, *astr1; |
| 1170 | |||
| 1175 | ASMOperand operands[MAX_ASM_OPERANDS]; | 1171 | ASMOperand operands[MAX_ASM_OPERANDS]; |
| 1176 | int nb_outputs, nb_operands, i, must_subst, out_reg, nb_labels; | 1172 | int nb_outputs, nb_operands, i, must_subst, out_reg, nb_labels; |
| 1177 | uint8_t clobber_regs[NB_ASM_REGS]; | 1173 | uint8_t clobber_regs[NB_ASM_REGS]; |
| @@ -1183,7 +1179,11 @@ ST_FUNC void asm_instr(void) · 5 unmodified lines | |||
| 1183 | || tok == TOK_GOTO) { | 1179 | || tok == TOK_GOTO) { |
| 1184 | next(); | 1180 | next(); |
| 1185 | } | 1181 | } |
| 1186 | parse_asm_str(&astr); | 1182 | |
| 1183 | astr1 = parse_asm_str(); | ||
| 1184 | cstr_new_s(&astr); | ||
| 1185 | cstr_cat(&astr, astr1->data, astr1->size); | ||
| 1186 | |||
| 1187 | nb_operands = 0; | 1187 | nb_operands = 0; |
| 1188 | nb_outputs = 0; | 1188 | nb_outputs = 0; |
| 1189 | nb_labels = 0; | 1189 | nb_labels = 0; |
| @@ -1273,13 +1273,14 @@ ST_FUNC void asm_instr(void) · 83 unmodified lines | |||
| 1273 | printf("asm: \"%s\"\n", (char *)astr.data); | 1273 | printf("asm: \"%s\"\n", (char *)astr.data); |
| 1274 | #endif | 1274 | #endif |
| 1275 | if (must_subst) { | 1275 | if (must_subst) { |
| 1276 | subst_asm_operands(operands, nb_operands + nb_labels, &astr1, &astr); | 1276 | cstr_reset(astr1); |
| 1277 | cstr_free(&astr); | 1277 | cstr_cat(astr1, astr.data, astr.size); |
| 1278 | } else { | 1278 | cstr_reset(&astr); |
| 1279 | astr1 = astr; | 1279 | subst_asm_operands(operands, nb_operands + nb_labels, &astr, astr1->data); |
| 1280 | } | 1280 | } |
| 1281 | |||
| 1281 | #ifdef ASM_DEBUG | 1282 | #ifdef ASM_DEBUG |
| 1282 | printf("subst_asm: \"%s\"\n", (char *)astr1.data); | 1283 | printf("subst_asm: \"%s\"\n", (char *)astr.data); |
| 1283 | #endif | 1284 | #endif |
| 1284 | 1285 | ||
| 1285 | /* generate loads */ | 1286 | /* generate loads */ |
| @@ -1290,7 +1291,8 @@ ST_FUNC void asm_instr(void) · 4 unmodified lines | |||
| 1290 | bleed out to surrounding code. */ | 1291 | bleed out to surrounding code. */ |
| 1291 | sec = cur_text_section; | 1292 | sec = cur_text_section; |
| 1292 | /* assemble the string with tcc internal assembler */ | 1293 | /* assemble the string with tcc internal assembler */ |
| 1293 | tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1, 0); | 1294 | tcc_assemble_inline(tcc_state, astr.data, astr.size - 1, 0); |
| 1295 | cstr_free_s(&astr); | ||
| 1294 | if (sec != cur_text_section) { | 1296 | if (sec != cur_text_section) { |
| 1295 | tcc_warning("inline asm tries to change current section"); | 1297 | tcc_warning("inline asm tries to change current section"); |
| 1296 | use_section1(tcc_state, sec); | 1298 | use_section1(tcc_state, sec); |
| @@ -1305,23 +1307,20 @@ ST_FUNC void asm_instr(void) · 8 unmodified lines | |||
| 1305 | 1307 | ||
| 1306 | /* free everything */ | 1308 | /* free everything */ |
| 1307 | for(i=0;i<nb_operands;i++) { | 1309 | for(i=0;i<nb_operands;i++) { |
| 1308 | ASMOperand *op; | ||
| 1309 | op = &operands[i]; | ||
| 1310 | tcc_free(op->constraint); | ||
| 1311 | vpop(); | 1310 | vpop(); |
| 1312 | } | 1311 | } |
| 1313 | cstr_free(&astr1); | 1312 | |
| 1314 | } | 1313 | } |
| 1315 | 1314 | ||
| 1316 | ST_FUNC void asm_global_instr(void) | 1315 | ST_FUNC void asm_global_instr(void) |
| 1317 | { | 1316 | { |
| 1318 | CString astr; | 1317 | CString *astr; |
| 1319 | int saved_nocode_wanted = nocode_wanted; | 1318 | int saved_nocode_wanted = nocode_wanted; |
| 1320 | 1319 | ||
| 1321 | /* Global asm blocks are always emitted. */ | 1320 | /* Global asm blocks are always emitted. */ |
| 1322 | nocode_wanted = 0; | 1321 | nocode_wanted = 0; |
| 1323 | next(); | 1322 | next(); |
| 1324 | parse_asm_str(&astr); | 1323 | astr = parse_asm_str(); |
| 1325 | skip(')'); | 1324 | skip(')'); |
| 1326 | /* NOTE: we do not eat the ';' so that we can restore the current | 1325 | /* NOTE: we do not eat the ';' so that we can restore the current |
| 1327 | token after the assembler parsing */ | 1326 | token after the assembler parsing */ |
| @@ -1335,14 +1334,13 @@ ST_FUNC void asm_global_instr(void) · 7 unmodified lines | |||
| 1335 | ind = cur_text_section->data_offset; | 1334 | ind = cur_text_section->data_offset; |
| 1336 | 1335 | ||
| 1337 | /* assemble the string with tcc internal assembler */ | 1336 | /* assemble the string with tcc internal assembler */ |
| 1338 | tcc_assemble_inline(tcc_state, astr.data, astr.size - 1, 1); | 1337 | tcc_assemble_inline(tcc_state, astr->data, astr->size - 1, 1); |
| 1339 | 1338 | ||
| 1340 | cur_text_section->data_offset = ind; | 1339 | cur_text_section->data_offset = ind; |
| 1341 | 1340 | ||
| 1342 | /* restore the current C token */ | 1341 | /* restore the current C token */ |
| 1343 | next(); | 1342 | next(); |
| 1344 | 1343 | ||
| 1345 | cstr_free(&astr); | ||
| 1346 | nocode_wanted = saved_nocode_wanted; | 1344 | nocode_wanted = saved_nocode_wanted; |
| 1347 | } | 1345 | } |
| 1348 | 1346 | ||
| @@ -402,7 +402,6 @@ ST_FUNC int tccgen_compile(TCCState *s1) · 401 unmodified lines | |||
| 402 | ST_FUNC void tccgen_finish(TCCState *s1) | 402 | ST_FUNC void tccgen_finish(TCCState *s1) |
| 403 | { | 403 | { |
| 404 | tcc_debug_end(s1); /* just in case of errors: free memory */ | 404 | tcc_debug_end(s1); /* just in case of errors: free memory */ |
| 405 | cstr_free(&initstr); | ||
| 406 | free_inline_functions(s1); | 405 | free_inline_functions(s1); |
| 407 | sym_pop(&global_stack, NULL, 0); | 406 | sym_pop(&global_stack, NULL, 0); |
| 408 | sym_pop(&local_stack, NULL, 0); | 407 | sym_pop(&local_stack, NULL, 0); |
| @@ -412,6 +411,8 @@ ST_FUNC void tccgen_finish(TCCState *s1) · 3 unmodified lines | |||
| 412 | dynarray_reset(&sym_pools, &nb_sym_pools); | 411 | dynarray_reset(&sym_pools, &nb_sym_pools); |
| 413 | sym_free_first = NULL; | 412 | sym_free_first = NULL; |
| 414 | global_label_stack = local_label_stack = NULL; | 413 | global_label_stack = local_label_stack = NULL; |
| 414 | cstr_free(&initstr); | ||
| 415 | dynarray_reset(&stk_data, &nb_stk_data); | ||
| 415 | } | 416 | } |
| 416 | 417 | ||
| 417 | /* ------------------------------------------------------------------------- */ | 418 | /* ------------------------------------------------------------------------- */ |
| @@ -3756,18 +3757,19 @@ ST_FUNC void inc(int post, int c) · 3338 unmodified lines | |||
| 3756 | vpop(); /* if post op, return saved value */ | 3757 | vpop(); /* if post op, return saved value */ |
| 3757 | } | 3758 | } |
| 3758 | 3759 | ||
| 3759 | ST_FUNC void parse_mult_str (CString *astr, const char *msg) | 3760 | ST_FUNC CString* parse_mult_str (const char *msg) |
| 3760 | { | 3761 | { |
| 3761 | /* read the string */ | 3762 | /* read the string */ |
| 3762 | if (tok != TOK_STR) | 3763 | if (tok != TOK_STR) |
| 3763 | expect(msg); | 3764 | expect(msg); |
| 3764 | cstr_new(astr); | 3765 | cstr_reset(&initstr); |
| 3765 | while (tok == TOK_STR) { | 3766 | while (tok == TOK_STR) { |
| 3766 | /* XXX: add \0 handling too ? */ | 3767 | /* XXX: add \0 handling too ? */ |
| 3767 | cstr_cat(astr, tokc.str.data, -1); | 3768 | cstr_cat(&initstr, tokc.str.data, -1); |
| 3768 | next(); | 3769 | next(); |
| 3769 | } | 3770 | } |
| 3770 | cstr_ccat(astr, '\0'); | 3771 | cstr_ccat(&initstr, '\0'); |
| 3772 | return &initstr; | ||
| 3771 | } | 3773 | } |
| 3772 | 3774 | ||
| 3773 | /* If I is >= 1 and a power of two, returns log2(i)+1. | 3775 | /* If I is >= 1 and a power of two, returns log2(i)+1. |
| @@ -3792,7 +3794,7 @@ ST_FUNC int exact_log2p1(int i) · 18 unmodified lines | |||
| 3792 | static void parse_attribute(AttributeDef *ad) | 3794 | static void parse_attribute(AttributeDef *ad) |
| 3793 | { | 3795 | { |
| 3794 | int t, n; | 3796 | int t, n; |
| 3795 | CString astr; | 3797 | char *astr; |
| 3796 | 3798 | ||
| 3797 | redo: | 3799 | redo: |
| 3798 | if (tok != TOK_ATTRIBUTE1 && tok != TOK_ATTRIBUTE2) | 3800 | if (tok != TOK_ATTRIBUTE1 && tok != TOK_ATTRIBUTE2) |
| @@ -3839,37 +3841,33 @@ redo: · 40 unmodified lines | |||
| 3839 | case TOK_SECTION1: | 3841 | case TOK_SECTION1: |
| 3840 | case TOK_SECTION2: | 3842 | case TOK_SECTION2: |
| 3841 | skip('('); | 3843 | skip('('); |
| 3842 | parse_mult_str(&astr, "section name"); | 3844 | astr = parse_mult_str("section name")->data; |
| 3843 | ad->section = find_section(tcc_state, (char *)astr.data); | 3845 | ad->section = find_section(tcc_state, astr); |
| 3844 | skip(')'); | 3846 | skip(')'); |
| 3845 | cstr_free(&astr); | ||
| 3846 | break; | 3847 | break; |
| 3847 | case TOK_ALIAS1: | 3848 | case TOK_ALIAS1: |
| 3848 | case TOK_ALIAS2: | 3849 | case TOK_ALIAS2: |
| 3849 | skip('('); | 3850 | skip('('); |
| 3850 | parse_mult_str(&astr, "alias(\"target\")"); | 3851 | astr = parse_mult_str("alias(\"target\")")->data; |
| 3851 | ad->alias_target = /* save string as token, for later */ | 3852 | /* save string as token, for later */ |
| 3852 | tok_alloc((char*)astr.data, astr.size-1)->tok; | 3853 | ad->alias_target = tok_alloc_const(astr); |
| 3853 | skip(')'); | 3854 | skip(')'); |
| 3854 | cstr_free(&astr); | ||
| 3855 | break; | 3855 | break; |
| 3856 | case TOK_VISIBILITY1: | 3856 | case TOK_VISIBILITY1: |
| 3857 | case TOK_VISIBILITY2: | 3857 | case TOK_VISIBILITY2: |
| 3858 | skip('('); | 3858 | skip('('); |
| 3859 | parse_mult_str(&astr, | 3859 | astr = parse_mult_str("visibility(\"default|hidden|internal|protected\")")->data; |
| 3860 | "visibility(\"default|hidden|internal|protected\")"); | 3860 | if (!strcmp (astr, "default")) |
| 3861 | if (!strcmp (astr.data, "default")) | ||
| 3862 | ad->a.visibility = STV_DEFAULT; | 3861 | ad->a.visibility = STV_DEFAULT; |
| 3863 | else if (!strcmp (astr.data, "hidden")) | 3862 | else if (!strcmp (astr, "hidden")) |
| 3864 | ad->a.visibility = STV_HIDDEN; | 3863 | ad->a.visibility = STV_HIDDEN; |
| 3865 | else if (!strcmp (astr.data, "internal")) | 3864 | else if (!strcmp (astr, "internal")) |
| 3866 | ad->a.visibility = STV_INTERNAL; | 3865 | ad->a.visibility = STV_INTERNAL; |
| 3867 | else if (!strcmp (astr.data, "protected")) | 3866 | else if (!strcmp (astr, "protected")) |
| 3868 | ad->a.visibility = STV_PROTECTED; | 3867 | ad->a.visibility = STV_PROTECTED; |
| 3869 | else | 3868 | else |
| 3870 | expect("visibility(\"default|hidden|internal|protected\")"); | 3869 | expect("visibility(\"default|hidden|internal|protected\")"); |
| 3871 | skip(')'); | 3870 | skip(')'); |
| 3872 | cstr_free(&astr); | ||
| 3873 | break; | 3871 | break; |
| 3874 | case TOK_ALIGNED1: | 3872 | case TOK_ALIGNED1: |
| 3875 | case TOK_ALIGNED2: | 3873 | case TOK_ALIGNED2: |
| @@ -4818,26 +4816,25 @@ static inline void convert_parameter_type(CType *pt) · 942 unmodified lines | |||
| 4818 | } | 4816 | } |
| 4819 | } | 4817 | } |
| 4820 | 4818 | ||
| 4821 | ST_FUNC void parse_asm_str(CString *astr) | 4819 | ST_FUNC CString* parse_asm_str(void) |
| 4822 | { | 4820 | { |
| 4823 | skip('('); | 4821 | skip('('); |
| 4824 | parse_mult_str(astr, "string constant"); | 4822 | return parse_mult_str("string constant"); |
| 4825 | } | 4823 | } |
| 4826 | 4824 | ||
| 4827 | /* Parse an asm label and return the token */ | 4825 | /* Parse an asm label and return the token */ |
| 4828 | static int asm_label_instr(void) | 4826 | static int asm_label_instr(void) |
| 4829 | { | 4827 | { |
| 4830 | int v; | 4828 | int v; |
| 4831 | CString astr; | 4829 | char *astr; |
| 4832 | 4830 | ||
| 4833 | next(); | 4831 | next(); |
| 4834 | parse_asm_str(&astr); | 4832 | astr = parse_asm_str()->data; |
| 4835 | skip(')'); | 4833 | skip(')'); |
| 4836 | #ifdef ASM_DEBUG | 4834 | #ifdef ASM_DEBUG |
| 4837 | printf("asm_alias: \"%s\"\n", (char *)astr.data); | 4835 | printf("asm_alias: \"%s\"\n", astr); |
| 4838 | #endif | 4836 | #endif |
| 4839 | v = tok_alloc(astr.data, astr.size - 1)->tok; | 4837 | v = tok_alloc_const(astr); |
| 4840 | cstr_free(&astr); | ||
| 4841 | return v; | 4838 | return v; |
| 4842 | } | 4839 | } |
| 4843 | 4840 | ||
| @@ -8357,29 +8354,23 @@ static void free_inline_functions(TCCState *s) · 3513 unmodified lines | |||
| 8357 | dynarray_reset(&s->inline_fns, &s->nb_inline_fns); | 8354 | dynarray_reset(&s->inline_fns, &s->nb_inline_fns); |
| 8358 | } | 8355 | } |
| 8359 | 8356 | ||
| 8360 | static void do_Static_assert(void){ | 8357 | static void do_Static_assert(void) |
| 8361 | CString error_str; | 8358 | { |
| 8362 | int c; | 8359 | int c; |
| 8360 | const char *msg; | ||
| 8363 | 8361 | ||
| 8364 | next(); | 8362 | next(); |
| 8365 | skip('('); | 8363 | skip('('); |
| 8366 | c = expr_const(); | 8364 | c = expr_const(); |
| 8367 | 8365 | msg = "_Static_assert fail"; | |
| 8368 | if (tok == ')') { | 8366 | if (tok == ',') { |
| 8369 | if (!c) | 8367 | next(); |
| 8370 | tcc_error("_Static_assert fail"); | 8368 | msg = parse_mult_str("string constant")->data; |
| 8371 | next(); | ||
| 8372 | goto static_assert_out; | ||
| 8373 | } | 8369 | } |
| 8374 | |||
| 8375 | skip(','); | ||
| 8376 | parse_mult_str(&error_str, "string constant"); | ||
| 8377 | if (c == 0) | ||
| 8378 | tcc_error("%s", (char *)error_str.data); | ||
| 8379 | cstr_free(&error_str); | ||
| 8380 | skip(')'); | 8370 | skip(')'); |
| 8381 | static_assert_out: | 8371 | if (c == 0) |
| 8382 | skip(';'); | 8372 | tcc_error("%s", msg); |
| 8373 | skip(';'); | ||
| 8383 | } | 8374 | } |
| 8384 | 8375 | ||
| 8385 | /* 'l' is VT_LOCAL or VT_CONST to define default storage type | 8376 | /* 'l' is VT_LOCAL or VT_CONST to define default storage type |
| @@ -8393,10 +8384,11 @@ static int decl(int l) · 7 unmodified lines | |||
| 8393 | AttributeDef ad, adbase; | 8384 | AttributeDef ad, adbase; |
| 8394 | 8385 | ||
| 8395 | while (1) { | 8386 | while (1) { |
| 8396 | if (tok == TOK_STATIC_ASSERT) { | 8387 | |
| 8397 | do_Static_assert(); | 8388 | if (tok == TOK_STATIC_ASSERT) { |
| 8398 | continue; | 8389 | do_Static_assert(); |
| 8399 | } | 8390 | continue; |
| 8391 | } | ||
| 8400 | 8392 | ||
| 8401 | oldint = 0; | 8393 | oldint = 0; |
| 8402 | if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) { | 8394 | if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) { |
| @@ -45,7 +45,6 @@ ST_DATA TokenSym **table_ident; · 44 unmodified lines | |||
| 45 | static TokenSym *hash_ident[TOK_HASH_SIZE]; | 45 | static TokenSym *hash_ident[TOK_HASH_SIZE]; |
| 46 | static char token_buf[STRING_MAX_SIZE + 1]; | 46 | static char token_buf[STRING_MAX_SIZE + 1]; |
| 47 | static CString cstr_buf; | 47 | static CString cstr_buf; |
| 48 | static CString macro_equal_buf; | ||
| 49 | static TokenString tokstr_buf; | 48 | static TokenString tokstr_buf; |
| 50 | static unsigned char isidnum_table[256 - CH_EOF]; | 49 | static unsigned char isidnum_table[256 - CH_EOF]; |
| 51 | static int pp_debug_tok, pp_debug_symv; | 50 | static int pp_debug_tok, pp_debug_symv; |
| @@ -399,7 +398,6 @@ ST_FUNC void cstr_new(CString *cstr) · 347 unmodified lines | |||
| 399 | ST_FUNC void cstr_free(CString *cstr) | 398 | ST_FUNC void cstr_free(CString *cstr) |
| 400 | { | 399 | { |
| 401 | tcc_free(cstr->data); | 400 | tcc_free(cstr->data); |
| 402 | cstr_new(cstr); | ||
| 403 | } | 401 | } |
| 404 | 402 | ||
| 405 | /* reset string to empty */ | 403 | /* reset string to empty */ |
| @@ -1273,12 +1271,11 @@ static int macro_is_equal(const int *a, const int *b) · 867 unmodified lines | |||
| 1273 | return 1; | 1271 | return 1; |
| 1274 | 1272 | ||
| 1275 | while (*a && *b) { | 1273 | while (*a && *b) { |
| 1276 | /* first time preallocate macro_equal_buf, next time only reset position to start */ | 1274 | cstr_reset(&tokcstr); |
| 1277 | cstr_reset(¯o_equal_buf); | ||
| 1278 | TOK_GET(&t, &a, &cv); | 1275 | TOK_GET(&t, &a, &cv); |
| 1279 | cstr_cat(¯o_equal_buf, get_tok_str(t, &cv), 0); | 1276 | cstr_cat(&tokcstr, get_tok_str(t, &cv), 0); |
| 1280 | TOK_GET(&t, &b, &cv); | 1277 | TOK_GET(&t, &b, &cv); |
| 1281 | if (strcmp(macro_equal_buf.data, get_tok_str(t, &cv))) | 1278 | if (strcmp(tokcstr.data, get_tok_str(t, &cv))) |
| 1282 | return 0; | 1279 | return 0; |
| 1283 | } | 1280 | } |
| 1284 | return !(*a || *b); | 1281 | return !(*a || *b); |
| @@ -1348,14 +1345,15 @@ search_cached_include(TCCState *s1, const char *filename, int add); · 63 unmodified lines | |||
| 1348 | static int parse_include(TCCState *s1, int do_next, int test) | 1345 | static int parse_include(TCCState *s1, int do_next, int test) |
| 1349 | { | 1346 | { |
| 1350 | int c, i; | 1347 | int c, i; |
| 1351 | CString cs; | ||
| 1352 | char name[1024], buf[1024], *p; | 1348 | char name[1024], buf[1024], *p; |
| 1353 | CachedInclude *e; | 1349 | CachedInclude *e; |
| 1354 | 1350 | ||
| 1355 | cstr_new(&cs); | ||
| 1356 | c = skip_spaces(); | 1351 | c = skip_spaces(); |
| 1357 | if (c == '<' || c == '\"') { | 1352 | if (c == '<' || c == '\"') { |
| 1358 | file->buf_ptr = parse_pp_string(file->buf_ptr, c == '<' ? '>' : c, &cs); | 1353 | cstr_reset(&tokcstr); |
| 1354 | file->buf_ptr = parse_pp_string(file->buf_ptr, c == '<' ? '>' : c, &tokcstr); | ||
| 1355 | i = tokcstr.size; | ||
| 1356 | pstrncpy(name, tokcstr.data, i >= sizeof name ? sizeof name - 1 : i); | ||
| 1359 | next_nomacro(); | 1357 | next_nomacro(); |
| 1360 | } else { | 1358 | } else { |
| 1361 | /* computed #include : concatenate tokens until result is one of | 1359 | /* computed #include : concatenate tokens until result is one of |
| @@ -1363,24 +1361,22 @@ static int parse_include(TCCState *s1, int do_next, int test) · 1 unmodified line | |||
| 1363 | parse_flags = PARSE_FLAG_PREPROCESS | 1361 | parse_flags = PARSE_FLAG_PREPROCESS |
| 1364 | | PARSE_FLAG_LINEFEED | 1362 | | PARSE_FLAG_LINEFEED |
| 1365 | | (parse_flags & PARSE_FLAG_ASM_FILE); | 1363 | | (parse_flags & PARSE_FLAG_ASM_FILE); |
| 1364 | name[0] = 0; | ||
| 1366 | for (;;) { | 1365 | for (;;) { |
| 1367 | next(); | 1366 | next(); |
| 1368 | p = cs.data, i = cs.size - 1; | 1367 | p = name, i = strlen(p) - 1; |
| 1369 | if (i > 0 | 1368 | if (i > 0 |
| 1370 | && ((p[0] == '"' && p[i] == '"') | 1369 | && ((p[0] == '"' && p[i] == '"') |
| 1371 | || (p[0] == '<' && p[i] == '>'))) | 1370 | || (p[0] == '<' && p[i] == '>'))) |
| 1372 | break; | 1371 | break; |
| 1373 | if (tok == TOK_LINEFEED) | 1372 | if (tok == TOK_LINEFEED) |
| 1374 | tcc_error("'#include' expects \"FILENAME\" or <FILENAME>"); | 1373 | tcc_error("'#include' expects \"FILENAME\" or <FILENAME>"); |
| 1375 | cstr_cat(&cs, get_tok_str(tok, &tokc), -1); | 1374 | pstrcat(name, sizeof name, get_tok_str(tok, &tokc)); |
| 1376 | } | 1375 | } |
| 1377 | c = p[0]; | 1376 | c = p[0]; |
| 1378 | /* remove '<>|""' */ | 1377 | /* remove '<>|""' */ |
| 1379 | memmove(p, p + 1, cs.size -= 2); | 1378 | memmove(p, p + 1, i - 1), p[i - 1] = 0; |
| 1380 | } | 1379 | } |
| 1381 | cstr_ccat(&cs, '\0'); | ||
| 1382 | pstrcpy(name, sizeof name, cs.data); | ||
| 1383 | cstr_free(&cs); | ||
| 1384 | 1380 | ||
| 1385 | i = do_next ? file->include_next_index : -1; | 1381 | i = do_next ? file->include_next_index : -1; |
| 1386 | for (;;) { | 1382 | for (;;) { |
| @@ -2934,7 +2930,6 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) · 1547 unmodified lines | |||
| 2934 | Sym *s; | 2930 | Sym *s; |
| 2935 | CValue cval; | 2931 | CValue cval; |
| 2936 | TokenString str; | 2932 | TokenString str; |
| 2937 | CString cstr; | ||
| 2938 | 2933 | ||
| 2939 | tok_str_new(&str); | 2934 | tok_str_new(&str); |
| 2940 | t0 = t1 = 0; | 2935 | t0 = t1 = 0; |
| @@ -2949,8 +2944,8 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) · 8 unmodified lines | |||
| 2949 | goto bad_stringy; | 2944 | goto bad_stringy; |
| 2950 | s = sym_find2(args, t); | 2945 | s = sym_find2(args, t); |
| 2951 | if (s) { | 2946 | if (s) { |
| 2952 | cstr_new(&cstr); | 2947 | cstr_reset(&tokcstr); |
| 2953 | cstr_ccat(&cstr, '\"'); | 2948 | cstr_ccat(&tokcstr, '\"'); |
| 2954 | st = s->d; | 2949 | st = s->d; |
| 2955 | spc = 0; | 2950 | spc = 0; |
| 2956 | while (*st >= 0) { | 2951 | while (*st >= 0) { |
| @@ -2961,24 +2956,23 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) · 4 unmodified lines | |||
| 2961 | const char *s = get_tok_str(t, &cval); | 2956 | const char *s = get_tok_str(t, &cval); |
| 2962 | while (*s) { | 2957 | while (*s) { |
| 2963 | if (t == TOK_PPSTR && *s != '\'') | 2958 | if (t == TOK_PPSTR && *s != '\'') |
| 2964 | add_char(&cstr, *s); | 2959 | add_char(&tokcstr, *s); |
| 2965 | else | 2960 | else |
| 2966 | cstr_ccat(&cstr, *s); | 2961 | cstr_ccat(&tokcstr, *s); |
| 2967 | ++s; | 2962 | ++s; |
| 2968 | } | 2963 | } |
| 2969 | } | 2964 | } |
| 2970 | } | 2965 | } |
| 2971 | cstr.size -= spc; | 2966 | tokcstr.size -= spc; |
| 2972 | cstr_ccat(&cstr, '\"'); | 2967 | cstr_ccat(&tokcstr, '\"'); |
| 2973 | cstr_ccat(&cstr, '\0'); | 2968 | cstr_ccat(&tokcstr, '\0'); |
| 2974 | #ifdef PP_DEBUG | 2969 | #ifdef PP_DEBUG |
| 2975 | printf("\nstringize: <%s>\n", (char *)cstr.data); | 2970 | printf("\nstringize: <%s>\n", (char *)tokcstr.data); |
| 2976 | #endif | 2971 | #endif |
| 2977 | /* add string */ | 2972 | /* add string */ |
| 2978 | cval.str.size = cstr.size; | 2973 | cval.str.size = tokcstr.size; |
| 2979 | cval.str.data = cstr.data; | 2974 | cval.str.data = tokcstr.data; |
| 2980 | tok_str_add2(&str, TOK_PPSTR, &cval); | 2975 | tok_str_add2(&str, TOK_PPSTR, &cval); |
| 2981 | cstr_free(&cstr); | ||
| 2982 | } else { | 2976 | } else { |
| 2983 | bad_stringy: | 2977 | bad_stringy: |
| 2984 | expect("macro parameter after '#'"); | 2978 | expect("macro parameter after '#'"); |
| @@ -3047,19 +3041,19 @@ static char const ab_month_name[12][4] = · 62 unmodified lines | |||
| 3047 | 3041 | ||
| 3048 | static int paste_tokens(int t1, CValue *v1, int t2, CValue *v2) | 3042 | static int paste_tokens(int t1, CValue *v1, int t2, CValue *v2) |
| 3049 | { | 3043 | { |
| 3050 | CString cstr; | ||
| 3051 | int n, ret = 1; | 3044 | int n, ret = 1; |
| 3052 | 3045 | ||
| 3053 | cstr_new(&cstr); | 3046 | cstr_reset(&tokcstr); |
| 3054 | if (t1 != TOK_PLCHLDR) | 3047 | if (t1 != TOK_PLCHLDR) |
| 3055 | cstr_cat(&cstr, get_tok_str(t1, v1), -1); | 3048 | cstr_cat(&tokcstr, get_tok_str(t1, v1), -1); |
| 3056 | n = cstr.size; | 3049 | n = tokcstr.size; |
| 3057 | if (t2 != TOK_PLCHLDR) | 3050 | if (t2 != TOK_PLCHLDR) |
| 3058 | cstr_cat(&cstr, get_tok_str(t2, v2), -1); | 3051 | cstr_cat(&tokcstr, get_tok_str(t2, v2), -1); |
| 3059 | cstr_ccat(&cstr, '\0'); | 3052 | cstr_ccat(&tokcstr, '\0'); |
| 3053 | //printf("paste <%s>\n", (char*)tokcstr.data); | ||
| 3060 | 3054 | ||
| 3061 | tcc_open_bf(tcc_state, ":paste:", cstr.size); | 3055 | tcc_open_bf(tcc_state, ":paste:", tokcstr.size); |
| 3062 | memcpy(file->buffer, cstr.data, cstr.size); | 3056 | memcpy(file->buffer, tokcstr.data, tokcstr.size); |
| 3063 | tok_flags = 0; | 3057 | tok_flags = 0; |
| 3064 | for (;;) { | 3058 | for (;;) { |
| 3065 | next_nomacro1(); | 3059 | next_nomacro1(); |
| @@ -3068,13 +3062,11 @@ static int paste_tokens(int t1, CValue *v1, int t2, CValue *v2) · 2 unmodified lines | |||
| 3068 | if (is_space(tok)) | 3062 | if (is_space(tok)) |
| 3069 | continue; | 3063 | continue; |
| 3070 | tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid" | 3064 | tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid" |
| 3071 | " preprocessing token", n, (char *)cstr.data, (char*)cstr.data + n); | 3065 | " preprocessing token", n, file->buffer, file->buffer + n); |
| 3072 | ret = 0; | 3066 | ret = 0; |
| 3073 | break; | 3067 | break; |
| 3074 | } | 3068 | } |
| 3075 | tcc_close(); | 3069 | tcc_close(); |
| 3076 | //printf("paste <%s>\n", (char*)cstr.data); | ||
| 3077 | cstr_free(&cstr); | ||
| 3078 | return ret; | 3070 | return ret; |
| 3079 | } | 3071 | } |
| 3080 | 3072 | ||
| @@ -3214,7 +3206,6 @@ static int macro_subst_tok( · 133 unmodified lines | |||
| 3214 | TokenString str; | 3206 | TokenString str; |
| 3215 | char *cstrval; | 3207 | char *cstrval; |
| 3216 | CValue cval; | 3208 | CValue cval; |
| 3217 | CString cstr; | ||
| 3218 | char buf[32]; | 3209 | char buf[32]; |
| 3219 | 3210 | ||
| 3220 | /* if symbol is a macro, prepare substitution */ | 3211 | /* if symbol is a macro, prepare substitution */ |
| @@ -3245,12 +3236,11 @@ static int macro_subst_tok( · 24 unmodified lines | |||
| 3245 | add_cstr: | 3236 | add_cstr: |
| 3246 | t1 = TOK_STR; | 3237 | t1 = TOK_STR; |
| 3247 | add_cstr1: | 3238 | add_cstr1: |
| 3248 | cstr_new(&cstr); | 3239 | cstr_reset(&tokcstr); |
| 3249 | cstr_cat(&cstr, cstrval, 0); | 3240 | cstr_cat(&tokcstr, cstrval, 0); |
| 3250 | cval.str.size = cstr.size; | 3241 | cval.str.size = tokcstr.size; |
| 3251 | cval.str.data = cstr.data; | 3242 | cval.str.data = tokcstr.data; |
| 3252 | tok_str_add2(tok_str, t1, &cval); | 3243 | tok_str_add2(tok_str, t1, &cval); |
| 3253 | cstr_free(&cstr); | ||
| 3254 | } else if (s->d) { | 3244 | } else if (s->d) { |
| 3255 | int saved_parse_flags = parse_flags; | 3245 | int saved_parse_flags = parse_flags; |
| 3256 | int *joined_str = NULL; | 3246 | int *joined_str = NULL; |
| @@ -3634,7 +3624,6 @@ static void tcc_predefs(TCCState *s1, CString *cs, int is_asm) · 377 unmodified lines | |||
| 3634 | ST_FUNC void preprocess_start(TCCState *s1, int filetype) | 3624 | ST_FUNC void preprocess_start(TCCState *s1, int filetype) |
| 3635 | { | 3625 | { |
| 3636 | int is_asm = !!(filetype & (AFF_TYPE_ASM|AFF_TYPE_ASMPP)); | 3626 | int is_asm = !!(filetype & (AFF_TYPE_ASM|AFF_TYPE_ASMPP)); |
| 3637 | CString cstr; | ||
| 3638 | 3627 | ||
| 3639 | tccpp_new(s1); | 3628 | tccpp_new(s1); |
| 3640 | 3629 | ||
| @@ -3652,6 +3641,7 @@ ST_FUNC void preprocess_start(TCCState *s1, int filetype) · 11 unmodified lines | |||
| 3652 | set_idnum('.', is_asm ? IS_ID : 0); | 3641 | set_idnum('.', is_asm ? IS_ID : 0); |
| 3653 | 3642 | ||
| 3654 | if (!(filetype & AFF_TYPE_ASM)) { | 3643 | if (!(filetype & AFF_TYPE_ASM)) { |
| 3644 | CString cstr; | ||
| 3655 | cstr_new(&cstr); | 3645 | cstr_new(&cstr); |
| 3656 | tcc_predefs(s1, &cstr, is_asm); | 3646 | tcc_predefs(s1, &cstr, is_asm); |
| 3657 | if (s1->cmdline_defs.size) | 3647 | if (s1->cmdline_defs.size) |
| @@ -3710,6 +3700,7 @@ ST_FUNC void tccpp_new(TCCState *s) · 52 unmodified lines | |||
| 3710 | memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *)); | 3700 | memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *)); |
| 3711 | memset(s->cached_includes_hash, 0, sizeof s->cached_includes_hash); | 3701 | memset(s->cached_includes_hash, 0, sizeof s->cached_includes_hash); |
| 3712 | 3702 | ||
| 3703 | cstr_new(&tokcstr); | ||
| 3713 | cstr_new(&cstr_buf); | 3704 | cstr_new(&cstr_buf); |
| 3714 | cstr_realloc(&cstr_buf, STRING_MAX_SIZE); | 3705 | cstr_realloc(&cstr_buf, STRING_MAX_SIZE); |
| 3715 | tok_str_new(&tokstr_buf); | 3706 | tok_str_new(&tokstr_buf); |
| @@ -3755,7 +3746,6 @@ ST_FUNC void tccpp_delete(TCCState *s) · 39 unmodified lines | |||
| 3755 | /* free static buffers */ | 3746 | /* free static buffers */ |
| 3756 | cstr_free(&tokcstr); | 3747 | cstr_free(&tokcstr); |
| 3757 | cstr_free(&cstr_buf); | 3748 | cstr_free(&cstr_buf); |
| 3758 | cstr_free(¯o_equal_buf); | ||
| 3759 | tok_str_free_str(tokstr_buf.str); | 3749 | tok_str_free_str(tokstr_buf.str); |
| 3760 | 3750 | ||
| 3761 | /* free allocators */ | 3751 | /* free allocators */ |