The above pragmas are used in the mingw headers. Thise pragmas are implemented in gcc-4.5+ and current clang.
Unified · Split
| @@ -326,6 +326,7 @@ · 325 unmodified lines | ||
| 326 | 326 | typedef struct TokenSym { |
| 327 | 327 | struct TokenSym *hash_next; |
| 328 | 328 | struct Sym *sym_define; /* direct pointer to define */ |
| 329 | + struct Sym *sym_define_stack; /* direct pointer to a push_macro stack */ | |
| 329 | 330 | struct Sym *sym_label; /* direct pointer to label */ |
| 330 | 331 | struct Sym *sym_struct; /* direct pointer to structure */ |
| 331 | 332 | struct Sym *sym_identifier; /* direct pointer to identifier */ |
| @@ -292,7 +292,7 @@ static void asm_free_labels(TCCState *st) · 291 unmodified lines | ||
| 292 | 292 | { |
| 293 | 293 | Sym *s, *s1; |
| 294 | 294 | Section *sec; |
| 295 | − | |
| 295 | + | |
| 296 | 296 | for(s = st->asm_labels; s != NULL; s = s1) { |
| 297 | 297 | s1 = s->prev; |
| 298 | 298 | /* define symbol value in object file */ |
| @@ -305,6 +305,9 @@ static void asm_free_labels(TCCState *st) · 6 unmodified lines | ||
| 305 | 305 | } |
| 306 | 306 | /* remove label */ |
| 307 | 307 | table_ident[s->v - TOK_IDENT]->sym_label = NULL; |
| 308 | + if (s->asm_label) { | |
| 309 | + tcc_free(s->asm_label); | |
| 310 | + } | |
| 308 | 311 | sym_free(s); |
| 309 | 312 | } |
| 310 | 313 | st->asm_labels = NULL; |
| @@ -152,7 +152,6 @@ static inline Sym *sym_malloc(void) · 151 unmodified lines | ||
| 152 | 152 | ST_INLN void sym_free(Sym *sym) |
| 153 | 153 | { |
| 154 | 154 | sym->next = sym_free_first; |
| 155 | − tcc_free(sym->asm_label); | |
| 156 | 155 | sym_free_first = sym; |
| 157 | 156 | } |
| 158 | 157 | |
| @@ -222,6 +222,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) · 221 unmodified lines | ||
| 222 | 222 | table_ident[i] = ts; |
| 223 | 223 | ts->tok = tok_ident++; |
| 224 | 224 | ts->sym_define = NULL; |
| 225 | + ts->sym_define_stack = NULL; | |
| 225 | 226 | ts->sym_label = NULL; |
| 226 | 227 | ts->sym_struct = NULL; |
| 227 | 228 | ts->sym_identifier = NULL; |
| @@ -1446,6 +1447,39 @@ static void pragma_parse(TCCState *s1) · 1218 unmodified lines | ||
| 1446 | 1447 | } else { |
| 1447 | 1448 | tcc_warning("#pragma comment(lib) is ignored"); |
| 1448 | 1449 | } |
| 1450 | + } else if ((tok == TOK_push_macro) || (tok == TOK_pop_macro)) { | |
| 1451 | + int push_macro = (tok == TOK_push_macro); | |
| 1452 | + next(); | |
| 1453 | + skip('('); | |
| 1454 | + if (tok != TOK_STR) { | |
| 1455 | + expect("\""); | |
| 1456 | + } else { | |
| 1457 | + int len = strlen((char *)tokc.cstr->data); | |
| 1458 | + tcc_open_bf(s1, "<push_pop_macro>", len); | |
| 1459 | + memcpy(file->buffer, tokc.cstr->data, len); | |
| 1460 | + ch = file->buf_ptr[0]; | |
| 1461 | + next_nomacro(); | |
| 1462 | + if (tok >= TOK_IDENT) { | |
| 1463 | + Sym *s = table_ident[tok - TOK_IDENT]->sym_define; | |
| 1464 | + Sym *ss = table_ident[tok - TOK_IDENT]->sym_define_stack; | |
| 1465 | + if (push_macro) { | |
| 1466 | + if (s) { | |
| 1467 | + s->prev_tok = ss; | |
| 1468 | + table_ident[tok - TOK_IDENT]->sym_define_stack = s; | |
| 1469 | + } | |
| 1470 | + } else { | |
| 1471 | + if (ss) { | |
| 1472 | + table_ident[tok - TOK_IDENT]->sym_define = ss; | |
| 1473 | + table_ident[tok - TOK_IDENT]->sym_define_stack = ss->prev_tok; | |
| 1474 | + } | |
| 1475 | + } | |
| 1476 | + } | |
| 1477 | + tcc_close(); | |
| 1478 | + } | |
| 1479 | + next(); | |
| 1480 | + skip(')'); | |
| 1481 | + } else { | |
| 1482 | + tcc_warning("unknown #pragma %s", get_tok_str(tok, &tokc)); | |
| 1449 | 1483 | } |
| 1450 | 1484 | } |
| 1451 | 1485 | |
| @@ -155,6 +155,8 @@ · 154 unmodified lines | ||
| 155 | 155 | #endif |
| 156 | 156 | DEF(TOK_comment, "comment") |
| 157 | 157 | DEF(TOK_lib, "lib") |
| 158 | + DEF(TOK_push_macro, "push_macro") | |
| 159 | + DEF(TOK_pop_macro, "pop_macro") | |
| 158 | 160 | |
| 159 | 161 | /* builtin functions or variables */ |
| 160 | 162 | #ifndef TCC_ARM_EABI |
| @@ -0,0 +1,23 @@ | ||
| 1 | +#include <stdio.h> | |
| 2 | + | |
| 3 | +int main() | |
| 4 | +{ | |
| 5 | + #define abort "111" | |
| 6 | + printf("abort = %s\n", abort); | |
| 7 | + | |
| 8 | + #pragma push_macro("abort") | |
| 9 | + #undef abort | |
| 10 | + #define abort "222" | |
| 11 | + printf("abort = %s\n", abort); | |
| 12 | + | |
| 13 | + #pragma push_macro("abort") | |
| 14 | + #undef abort | |
| 15 | + #define abort "333" | |
| 16 | + printf("abort = %s\n", abort); | |
| 17 | + | |
| 18 | + #pragma pop_macro("abort") | |
| 19 | + printf("abort = %s\n", abort); | |
| 20 | + | |
| 21 | + #pragma pop_macro("abort") | |
| 22 | + printf("abort = %s\n", abort); | |
| 23 | +} | |
| @@ -0,0 +1,5 @@ | ||
| 1 | +abort = 111 | |
| 2 | +abort = 222 | |
| 3 | +abort = 333 | |
| 4 | +abort = 222 | |
| 5 | +abort = 111 | |
| @@ -95,7 +95,8 @@ TESTS = \ · 94 unmodified lines | ||
| 95 | 95 | 73_arm64.test \ |
| 96 | 96 | 74_nocode_wanted.test \ |
| 97 | 97 | 75_array_in_struct_init.test \ |
| 98 | − 76_dollars_in_identifiers.test | |
| 98 | + 76_dollars_in_identifiers.test \ | |
| 99 | + 77_push_pop_macro.test | |
| 99 | 100 | |
| 100 | 101 | # 34_array_assignment.test -- array assignment is not in C standard |
| 101 | 102 | |