From 0c8447db7970813292a8be74ee50e49091be5d15 Mon Sep 17 00:00:00 2001 From: seyko Date: Tue, 21 Apr 2015 06:34:35 +0300 Subject: [PATCH] * and #pragma pop_macro("macro_name") * give warning if pragma is unknown for tcc * don't free asm_label in sym_free(), it's a job of the asm_free_labels(). The above pragmas are used in the mingw headers. Thise pragmas are implemented in gcc-4.5+ and current clang. --- tcc.h | 1 + tccasm.c | 5 +++- tccgen.c | 1 - tccpp.c | 34 +++++++++++++++++++++++++++ tcctok.h | 2 ++ tests/tests2/77_push_pop_macro.c | 23 ++++++++++++++++++ tests/tests2/77_push_pop_macro.expect | 5 ++++ tests/tests2/Makefile | 3 ++- 8 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 tests/tests2/77_push_pop_macro.c create mode 100644 tests/tests2/77_push_pop_macro.expect diff --git a/tcc.h b/tcc.h index a0b4894..52baf58 100644 --- a/tcc.h +++ b/tcc.h @@ -326,6 +326,7 @@ typedef struct TokenSym { struct TokenSym *hash_next; struct Sym *sym_define; /* direct pointer to define */ + struct Sym *sym_define_stack; /* direct pointer to a push_macro stack */ struct Sym *sym_label; /* direct pointer to label */ struct Sym *sym_struct; /* direct pointer to structure */ struct Sym *sym_identifier; /* direct pointer to identifier */ diff --git a/tccasm.c b/tccasm.c index 3fa6f07..f67c1a6 100644 --- a/tccasm.c +++ b/tccasm.c @@ -292,7 +292,7 @@ static void asm_free_labels(TCCState *st) { Sym *s, *s1; Section *sec; - + for(s = st->asm_labels; s != NULL; s = s1) { s1 = s->prev; /* define symbol value in object file */ @@ -305,6 +305,9 @@ static void asm_free_labels(TCCState *st) } /* remove label */ table_ident[s->v - TOK_IDENT]->sym_label = NULL; + if (s->asm_label) { + tcc_free(s->asm_label); + } sym_free(s); } st->asm_labels = NULL; diff --git a/tccgen.c b/tccgen.c index 5275b47..103c955 100644 --- a/tccgen.c +++ b/tccgen.c @@ -152,7 +152,6 @@ static inline Sym *sym_malloc(void) ST_INLN void sym_free(Sym *sym) { sym->next = sym_free_first; - tcc_free(sym->asm_label); sym_free_first = sym; } diff --git a/tccpp.c b/tccpp.c index 42ebf48..4d9430d 100644 --- a/tccpp.c +++ b/tccpp.c @@ -222,6 +222,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) table_ident[i] = ts; ts->tok = tok_ident++; ts->sym_define = NULL; + ts->sym_define_stack = NULL; ts->sym_label = NULL; ts->sym_struct = NULL; ts->sym_identifier = NULL; @@ -1446,6 +1447,39 @@ static void pragma_parse(TCCState *s1) } else { tcc_warning("#pragma comment(lib) is ignored"); } + } else if ((tok == TOK_push_macro) || (tok == TOK_pop_macro)) { + int push_macro = (tok == TOK_push_macro); + next(); + skip('('); + if (tok != TOK_STR) { + expect("\""); + } else { + int len = strlen((char *)tokc.cstr->data); + tcc_open_bf(s1, "", len); + memcpy(file->buffer, tokc.cstr->data, len); + ch = file->buf_ptr[0]; + next_nomacro(); + if (tok >= TOK_IDENT) { + Sym *s = table_ident[tok - TOK_IDENT]->sym_define; + Sym *ss = table_ident[tok - TOK_IDENT]->sym_define_stack; + if (push_macro) { + if (s) { + s->prev_tok = ss; + table_ident[tok - TOK_IDENT]->sym_define_stack = s; + } + } else { + if (ss) { + table_ident[tok - TOK_IDENT]->sym_define = ss; + table_ident[tok - TOK_IDENT]->sym_define_stack = ss->prev_tok; + } + } + } + tcc_close(); + } + next(); + skip(')'); + } else { + tcc_warning("unknown #pragma %s", get_tok_str(tok, &tokc)); } } diff --git a/tcctok.h b/tcctok.h index 5e1cf07..ace81dc 100644 --- a/tcctok.h +++ b/tcctok.h @@ -155,6 +155,8 @@ #endif DEF(TOK_comment, "comment") DEF(TOK_lib, "lib") + DEF(TOK_push_macro, "push_macro") + DEF(TOK_pop_macro, "pop_macro") /* builtin functions or variables */ #ifndef TCC_ARM_EABI diff --git a/tests/tests2/77_push_pop_macro.c b/tests/tests2/77_push_pop_macro.c new file mode 100644 index 0000000..1f0b1bc --- /dev/null +++ b/tests/tests2/77_push_pop_macro.c @@ -0,0 +1,23 @@ +#include + +int main() +{ + #define abort "111" + printf("abort = %s\n", abort); + + #pragma push_macro("abort") + #undef abort + #define abort "222" + printf("abort = %s\n", abort); + + #pragma push_macro("abort") + #undef abort + #define abort "333" + printf("abort = %s\n", abort); + + #pragma pop_macro("abort") + printf("abort = %s\n", abort); + + #pragma pop_macro("abort") + printf("abort = %s\n", abort); +} diff --git a/tests/tests2/77_push_pop_macro.expect b/tests/tests2/77_push_pop_macro.expect new file mode 100644 index 0000000..d8a5530 --- /dev/null +++ b/tests/tests2/77_push_pop_macro.expect @@ -0,0 +1,5 @@ +abort = 111 +abort = 222 +abort = 333 +abort = 222 +abort = 111 diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index a5a18fb..87daf7b 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -95,7 +95,8 @@ TESTS = \ 73_arm64.test \ 74_nocode_wanted.test \ 75_array_in_struct_init.test \ - 76_dollars_in_identifiers.test + 76_dollars_in_identifiers.test \ + 77_push_pop_macro.test # 34_array_assignment.test -- array assignment is not in C standard