diff options
author | Richard Henderson <rth@redhat.com> | 2007-03-30 14:12:53 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2007-03-30 14:12:53 -0700 |
commit | 121de39fc0ebadfbf9ef9f1721aa3cac42ac92e1 (patch) | |
tree | f8ad58ad599c110a4cb386319a9c1e0f7f184b64 | |
parent | 6c7ac15dc63e3435b7cec32baa37e48d86c381e3 (diff) | |
download | gcc-121de39fc0ebadfbf9ef9f1721aa3cac42ac92e1.zip gcc-121de39fc0ebadfbf9ef9f1721aa3cac42ac92e1.tar.gz gcc-121de39fc0ebadfbf9ef9f1721aa3cac42ac92e1.tar.bz2 |
directives.c (lex_macro_node_from_str): New.
libcpp/
* directives.c (lex_macro_node_from_str): New.
(cpp_push_definition, cpp_pop_definition): New.
* include/cpplib.h (cpp_push_definition, cpp_pop_definition): Declare.
gcc/
* c-pragma.c (struct def_pragma_macro_value): New.
(struct def_pragma_macro): New.
(pushed_macro_table): New.
(dpm_hash, dpm_eq): New.
(handle_pragma_push_macro, handle_pragma_pop_macro): New.
(init_pragma): Install them.
* doc/tm.texi (HANDLE_PRAGMA_PUSH_POP_MACRO): New.
Co-Authored-By: Kai Tietz <kai.tietz@onevision.com>
From-SVN: r123370
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/c-pragma.c | 142 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pragma-push_macro-1.c | 26 | ||||
-rw-r--r-- | libcpp/ChangeLog | 6 | ||||
-rw-r--r-- | libcpp/directives.c | 59 | ||||
-rw-r--r-- | libcpp/include/cpplib.h | 3 |
7 files changed, 259 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e426c4d..1f01dac 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2007-03-30 Richard Henderson <rth@redhat.com> + Kai Tietz <kai.tietz@onevision.com> + + * c-pragma.c (struct def_pragma_macro_value): New. + (struct def_pragma_macro): New. + (pushed_macro_table): New. + (dpm_hash, dpm_eq): New. + (handle_pragma_push_macro, handle_pragma_pop_macro): New. + (init_pragma): Install them. + * doc/tm.texi (HANDLE_PRAGMA_PUSH_POP_MACRO): New. + 2007-03-30 Anatoly Sokolov <aesok@post.ru> * config/avr/avr.c (avr_override_options): Clear diff --git a/gcc/c-pragma.c b/gcc/c-pragma.c index b2712ac..65da618 100644 --- a/gcc/c-pragma.c +++ b/gcc/c-pragma.c @@ -245,6 +245,144 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy)) } #endif /* HANDLE_PRAGMA_PACK */ +struct def_pragma_macro_value GTY(()) +{ + struct def_pragma_macro_value *prev; + cpp_macro *value; +}; + +struct def_pragma_macro GTY(()) +{ + hashval_t hash; + const char *name; + struct def_pragma_macro_value value; +}; + +static GTY((param_is (struct def_pragma_macro))) htab_t pushed_macro_table; + +#ifdef HANDLE_PRAGMA_PUSH_POP_MACRO +/* Hash table control functions for pushed_macro_table. */ +static hashval_t +dpm_hash (const void *p) +{ + return ((const struct def_pragma_macro *)p)->hash; +} + +static int +dpm_eq (const void *pa, const void *pb) +{ + const struct def_pragma_macro *a = pa, *b = pb; + return a->hash == b->hash && strcmp (a->name, b->name) == 0; +} + +/* #pragma push_macro("MACRO_NAME") + #pragma pop_macro("MACRO_NAME") */ + +static void +handle_pragma_push_macro (cpp_reader *reader) +{ + tree x, id = 0; + enum cpp_ttype token; + struct def_pragma_macro dummy, *c; + const char *macroname; + void **slot; + + if (pragma_lex (&x) != CPP_OPEN_PAREN) + GCC_BAD ("missing %<(%> after %<#pragma push_macro%> - ignored"); + + token = pragma_lex (&id); + + /* Silently ignore */ + if (token == CPP_CLOSE_PAREN) + return; + if (token != CPP_STRING) + GCC_BAD ("invalid constant in %<#pragma push_macro%> - ignored"); + + if (pragma_lex (&x) != CPP_CLOSE_PAREN) + GCC_BAD ("missing %<)%> after %<#pragma push_macro%> - ignored"); + + if (pragma_lex (&x) != CPP_EOF) + warning (OPT_Wpragmas, "junk at end of %<#pragma push_macro%>"); + + /* Check for empty string, and silently ignore. */ + if (TREE_STRING_LENGTH (id) < 1) + return; + macroname = TREE_STRING_POINTER (id); + + if (pushed_macro_table == NULL) + pushed_macro_table = htab_create_ggc (15, dpm_hash, dpm_eq, 0); + + dummy.hash = htab_hash_string (macroname); + dummy.name = macroname; + slot = htab_find_slot_with_hash (pushed_macro_table, &dummy, + dummy.hash, INSERT); + c = *slot; + if (c == NULL) + { + *slot = c = ggc_alloc (sizeof (struct def_pragma_macro)); + c->hash = dummy.hash; + c->name = ggc_alloc_string (macroname, TREE_STRING_LENGTH (id) - 1); + c->value.prev = NULL; + } + else + { + struct def_pragma_macro_value *v; + v = ggc_alloc (sizeof (struct def_pragma_macro_value)); + *v = c->value; + c->value.prev = v; + } + + c->value.value = cpp_push_definition (reader, macroname); +} + +static void +handle_pragma_pop_macro (cpp_reader *reader) +{ + tree x, id = 0; + enum cpp_ttype token; + struct def_pragma_macro dummy, *c; + const char *macroname; + void **slot; + + if (pragma_lex (&x) != CPP_OPEN_PAREN) + GCC_BAD ("missing %<(%> after %<#pragma pop_macro%> - ignored"); + + token = pragma_lex (&id); + + /* Silently ignore */ + if (token == CPP_CLOSE_PAREN) + return; + if (token != CPP_STRING) + GCC_BAD ("invalid constant in %<#pragma pop_macro%> - ignored"); + + if (pragma_lex (&x) != CPP_CLOSE_PAREN) + GCC_BAD ("missing %<)%> after %<#pragma pop_macro%> - ignored"); + + if (pragma_lex (&x) != CPP_EOF) + warning (OPT_Wpragmas, "junk at end of %<#pragma pop_macro%>"); + + /* Check for empty string, and silently ignore. */ + if (TREE_STRING_LENGTH (id) < 1) + return; + macroname = TREE_STRING_POINTER (id); + + dummy.hash = htab_hash_string (macroname); + dummy.name = macroname; + slot = htab_find_slot_with_hash (pushed_macro_table, &dummy, + dummy.hash, NO_INSERT); + if (slot == NULL) + return; + c = *slot; + + cpp_pop_definition (reader, c->name, c->value.value); + + if (c->value.prev) + c->value = *c->value.prev; + else + htab_clear_slot (pushed_macro_table, slot); +} +#endif /* HANDLE_PRAGMA_PUSH_POP_MACRO */ + static GTY(()) tree pending_weaks; #ifdef HANDLE_PRAGMA_WEAK @@ -819,6 +957,10 @@ init_pragma (void) c_register_pragma (0, "pack", handle_pragma_pack); #endif #endif +#ifdef HANDLE_PRAGMA_PUSH_POP_MACRO + c_register_pragma (0 ,"push_macro", handle_pragma_push_macro); + c_register_pragma (0 ,"pop_macro", handle_pragma_pop_macro); +#endif #ifdef HANDLE_PRAGMA_WEAK c_register_pragma (0, "weak", handle_pragma_weak); #endif diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 9cdc869..0d4185d 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -9719,6 +9719,18 @@ This must be a value that would also be valid to use with @samp{#pragma pack()} (that is, a small power of two). @end defmac +@findex #pragma +@findex pragma +@defmac HANDLE_PRAGMA_PUSH_POP_MACRO +Define this macro if you want to support the Win32 style pragmas +@samp{#pragma push_macro(macro-name-as-string)} and @samp{#pragma +pop_macro(macro-name-as-string)}. The @samp{#pragma push_macro( +macro-name-as-string)} pragma saves the named macro and via +@samp{#pragma pop_macro(macro-name-as-string)} it will return to the +previous value. +@end defmac + + @defmac DOLLARS_IN_IDENTIFIERS Define this macro to control use of the character @samp{$} in identifier names for the C family of languages. 0 means @samp{$} is diff --git a/gcc/testsuite/gcc.dg/pragma-push_macro-1.c b/gcc/testsuite/gcc.dg/pragma-push_macro-1.c new file mode 100644 index 0000000..ac5d059 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pragma-push_macro-1.c @@ -0,0 +1,26 @@ +/* Prove that HANDLE_PRAGMA_PUSH_POP_MACRO handling works somewhat. */ + +/* { dg-do link { target *-*-mingw* } } */ + +#define TEXT1 "ABC" +#define TEXT2 "DEF" + +int main() +{ + if (__builtin_strcmp (TEXT1 TEXT2, "ABCDEF") != 0) + link_error (); + +#pragma push_macro("TEXT1") +#undef TEXT1 +#define TEXT1 "XYZ" + + if (__builtin_strcmp (TEXT1 TEXT2, "XYZDEF") != 0) + link_error (); + +#pragma pop_macro("TEXT1") + + if (__builtin_strcmp (TEXT1 TEXT2, "ABCDEF") != 0) + link_error (); + + return 0; +} diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 1da9b3f..a8be346 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,9 @@ +2007-03-30 Richard Henderson <rth@redhat.com> + + * directives.c (lex_macro_node_from_str): New. + (cpp_push_definition, cpp_pop_definition): New. + * include/cpplib.h (cpp_push_definition, cpp_pop_definition): Declare. + 2007-03-01 Brooks Moses <brooks.moses@codesourcery.com> * Makefile.in: Add dummy install-pdf target. diff --git a/libcpp/directives.c b/libcpp/directives.c index d67cb5f..d9cf9d2 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -2078,6 +2078,65 @@ cpp_undef (cpp_reader *pfile, const char *macro) run_directive (pfile, T_UNDEF, buf, len); } +/* Like lex_macro_node, but read the input from STR. */ +static cpp_hashnode * +lex_macro_node_from_str (cpp_reader *pfile, const char *str) +{ + size_t len = strlen (str); + uchar *buf = (char *) alloca (len + 1); + cpp_hashnode *node; + + memcpy (buf, str, len); + buf[len] = '\n'; + cpp_push_buffer (pfile, buf, len, true); + node = lex_macro_node (pfile, true); + _cpp_pop_buffer (pfile); + + return node; +} + +/* If STR is a defined macro, return its definition node, else return NULL. */ +cpp_macro * +cpp_push_definition (cpp_reader *pfile, const char *str) +{ + cpp_hashnode *node = lex_macro_node_from_str (pfile, str); + if (node && node->type == NT_MACRO) + return node->value.macro; + else + return NULL; +} + +/* Replace a previous definition DFN of the macro STR. If DFN is NULL, + then the macro should be undefined. */ +void +cpp_pop_definition (cpp_reader *pfile, const char *str, cpp_macro *dfn) +{ + cpp_hashnode *node = lex_macro_node_from_str (pfile, str); + if (node == NULL) + return; + + if (node->type == NT_MACRO) + { + if (pfile->cb.undef) + pfile->cb.undef (pfile, pfile->directive_line, node); + if (CPP_OPTION (pfile, warn_unused_macros)) + _cpp_warn_if_unused_macro (pfile, node, NULL); + } + if (node->type != NT_VOID) + _cpp_free_definition (node); + + if (dfn) + { + node->type = NT_MACRO; + node->value.macro = dfn; + if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_"))) + node->flags |= NODE_WARN; + + if (pfile->cb.define) + pfile->cb.define (pfile, pfile->directive_line, node); + } +} + /* Process the string STR as if it appeared as the body of a #assert. */ void cpp_assert (cpp_reader *pfile, const char *str) diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index c15c8f5..b293998 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -704,6 +704,9 @@ extern void cpp_assert (cpp_reader *, const char *); extern void cpp_undef (cpp_reader *, const char *); extern void cpp_unassert (cpp_reader *, const char *); +extern cpp_macro *cpp_push_definition (cpp_reader *, const char *); +extern void cpp_pop_definition (cpp_reader *, const char *, cpp_macro *); + /* Undefine all macros and assertions. */ extern void cpp_undef_all (cpp_reader *); |