OSDN Git Service

libcpp/
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 30 Mar 2007 21:12:53 +0000 (21:12 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 30 Mar 2007 21:12:53 +0000 (21:12 +0000)
        * 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@123370 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-pragma.c
gcc/doc/tm.texi
gcc/testsuite/gcc.dg/pragma-push_macro-1.c [new file with mode: 0644]
libcpp/ChangeLog
libcpp/directives.c
libcpp/include/cpplib.h

index e426c4d..1f01dac 100644 (file)
@@ -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 
 2007-03-30  Anatoly Sokolov <aesok@post.ru>
 
        * config/avr/avr.c (avr_override_options): Clear 
index b2712ac..65da618 100644 (file)
@@ -245,6 +245,144 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
 }
 #endif  /* HANDLE_PRAGMA_PACK */
 
 }
 #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
 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
   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
 #ifdef HANDLE_PRAGMA_WEAK
   c_register_pragma (0, "weak", handle_pragma_weak);
 #endif
index 9cdc869..0d4185d 100644 (file)
@@ -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
 
 @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
 @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 (file)
index 0000000..ac5d059
--- /dev/null
@@ -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;
+}
index 1da9b3f..a8be346 100644 (file)
@@ -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.
 2007-03-01  Brooks Moses  <brooks.moses@codesourcery.com>
 
        * Makefile.in: Add dummy install-pdf target.
index d67cb5f..d9cf9d2 100644 (file)
@@ -2078,6 +2078,65 @@ cpp_undef (cpp_reader *pfile, const char *macro)
   run_directive (pfile, T_UNDEF, buf, len);
 }
 
   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)
 /* Process the string STR as if it appeared as the body of a #assert.  */
 void
 cpp_assert (cpp_reader *pfile, const char *str)
index c15c8f5..b293998 100644 (file)
@@ -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 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 *);
 
 /* Undefine all macros and assertions.  */
 extern void cpp_undef_all (cpp_reader *);