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
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 @@
   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_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 *);