summaryrefslogtreecommitdiff
path: root/libcpp/directives.c
diff options
context:
space:
mode:
authorKai Tietz <kai.tietz@onevision.com>2009-11-11 18:37:19 +0000
committerKai Tietz <ktietz@gcc.gnu.org>2009-11-11 19:37:19 +0100
commit17e7cb855000baa6598005571d7dd49cfac5282a (patch)
treee54ead3691775dbb1e9d31588966d79cac024672 /libcpp/directives.c
parent110532c838d2302c88de13ad88f81ec975ed4b1e (diff)
downloadgcc-17e7cb855000baa6598005571d7dd49cfac5282a.tar.gz
ChangeLog for libcpp
2009-11-11 Kai Tietz <kai.tietz@onevision.com> * directives.c (do_pragma_push_macro): New pragma handler. (do_pragma_pop_macro): Likewise. (_cpp_init_internal_pragmas): Add push_macro and pop_macro handler to internal pragmas. (lex_macro_node_from_str): Removed. (cpp_push_definition): Replace lex_macro_node_from_str by _cpp_lex_identifier. (cpp_pop_definition): Likewise. * internal.h (_cpp_lex_identifier): New prototype. (def_pragma_macro): New structure. (cpp_reader): New member pushed_macros. * lex.c (_cpp_lex_identifier): New function. (lex_identifier_intern): New function. * init.c (cpp_create_reader): Initialize pushed_macros member. (cpp_destroy): Free elements in pushed_macros member. * pch.c (_cpp_save_pushed_macros): New function. (_cpp_restore_pushed_macros): Likewise. (_cpp_restore_pushed_macros): Use _cpp_save_pushed_macros. (cpp_read_state): Use _cpp_restore_pushed_macros. ChangeLog for gcc 2009-11-11 Kai Tietz <kai.tietz@onevision.com> * config/i386/cygming.h (HANDLE_PRAGMA_PUSH_POP_MACRO): Removed. * c-pragma.c (def_pragma_macro_value): Likewise. (def_pragma_macro): Likewise. (pushed_macro_table): Likewise. (HANDLE_PRAGMA_PUSH_POP_MACRO): Remove guarded code. * doc/tm.texi (HANDLE_PRAGMA_PUSH_POP_MACRO): Removed. ChangeLog for gcc/testsuite 2009-11-11 Kai Tietz <kai.tietz@onevision.com> * g++.dg/torture/pushpop_macro.C: New testcase. * gcc.c-torture/execute/pushpop_macro.c: New testcase. * gcc.dg/cpp/pragma-pop_macro-1.c: Allow test for all targets. From-SVN: r154098
Diffstat (limited to 'libcpp/directives.c')
-rw-r--r--libcpp/directives.c115
1 files changed, 96 insertions, 19 deletions
diff --git a/libcpp/directives.c b/libcpp/directives.c
index 01bb599e266..aed940e56e1 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -126,6 +126,8 @@ static int parse_answer (cpp_reader *, struct answer **, int, source_location);
static cpp_hashnode *parse_assertion (cpp_reader *, struct answer **, int);
static struct answer ** find_answer (cpp_hashnode *, const struct answer *);
static void handle_assertion (cpp_reader *, const char *, int);
+static void do_pragma_push_macro (cpp_reader *);
+static void do_pragma_pop_macro (cpp_reader *);
/* This is the table of directive handlers. It is ordered by
frequency of occurrence; the numbers at the end are directive
@@ -1244,6 +1246,8 @@ _cpp_init_internal_pragmas (cpp_reader *pfile)
{
/* Pragmas in the global namespace. */
register_pragma_internal (pfile, 0, "once", do_pragma_once);
+ register_pragma_internal (pfile, 0, "push_macro", do_pragma_push_macro);
+ register_pragma_internal (pfile, 0, "pop_macro", do_pragma_pop_macro);
/* New GCC-specific pragmas should be put in the GCC namespace. */
register_pragma_internal (pfile, "GCC", "poison", do_pragma_poison);
@@ -1423,6 +1427,96 @@ do_pragma_once (cpp_reader *pfile)
_cpp_mark_file_once_only (pfile, pfile->buffer->file);
}
+/* Handle #pragma push_macro(STRING). */
+static void
+do_pragma_push_macro (cpp_reader *pfile)
+{
+ char *macroname, *dest;
+ const char *limit, *src;
+ const cpp_token *txt;
+ struct def_pragma_macro *c;
+
+ txt = get__Pragma_string (pfile);
+ if (!txt)
+ {
+ source_location src_loc = pfile->cur_token[-1].src_loc;
+ cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0,
+ "invalid #pragma push_macro directive");
+ check_eol (pfile, false);
+ skip_rest_of_line (pfile);
+ return;
+ }
+ dest = macroname = (char *) alloca (txt->val.str.len + 2);
+ src = (const char *) (txt->val.str.text + 1 + (txt->val.str.text[0] == 'L'));
+ limit = (const char *) (txt->val.str.text + txt->val.str.len - 1);
+ while (src < limit)
+ {
+ /* We know there is a character following the backslash. */
+ if (*src == '\\' && (src[1] == '\\' || src[1] == '"'))
+ src++;
+ *dest++ = *src++;
+ }
+ *dest = 0;
+ check_eol (pfile, false);
+ skip_rest_of_line (pfile);
+ c = XNEW (struct def_pragma_macro);
+ c->name = XNEWVAR (char, strlen (macroname) + 1);
+ strcpy (c->name, macroname);
+ c->next = pfile->pushed_macros;
+ c->value = cpp_push_definition (pfile, c->name);
+ pfile->pushed_macros = c;
+}
+
+/* Handle #pragma pop_macro(STRING). */
+static void
+do_pragma_pop_macro (cpp_reader *pfile)
+{
+ char *macroname, *dest;
+ const char *limit, *src;
+ const cpp_token *txt;
+ struct def_pragma_macro *l = NULL, *c = pfile->pushed_macros;
+ txt = get__Pragma_string (pfile);
+ if (!txt)
+ {
+ source_location src_loc = pfile->cur_token[-1].src_loc;
+ cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0,
+ "invalid #pragma pop_macro directive");
+ check_eol (pfile, false);
+ skip_rest_of_line (pfile);
+ return;
+ }
+ dest = macroname = (char *) alloca (txt->val.str.len + 2);
+ src = (const char *) (txt->val.str.text + 1 + (txt->val.str.text[0] == 'L'));
+ limit = (const char *) (txt->val.str.text + txt->val.str.len - 1);
+ while (src < limit)
+ {
+ /* We know there is a character following the backslash. */
+ if (*src == '\\' && (src[1] == '\\' || src[1] == '"'))
+ src++;
+ *dest++ = *src++;
+ }
+ *dest = 0;
+ check_eol (pfile, false);
+ skip_rest_of_line (pfile);
+
+ while (c != NULL)
+ {
+ if (!strcmp (c->name, macroname))
+ {
+ if (!l)
+ pfile->pushed_macros = c->next;
+ else
+ l->next = c->next;
+ cpp_pop_definition (pfile, c->name, c->value);
+ free (c->name);
+ free (c);
+ break;
+ }
+ l = c;
+ c = c->next;
+ }
+}
+
/* Handle #pragma GCC poison, to poison one or more identifiers so
that the lexer produces a hard error for each subsequent usage. */
static void
@@ -2225,28 +2319,11 @@ 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 = (uchar *) 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);
+ cpp_hashnode *node = _cpp_lex_identifier (pfile, str);
if (node && node->type == NT_MACRO)
return node->value.macro;
else
@@ -2258,7 +2335,7 @@ cpp_push_definition (cpp_reader *pfile, const char *str)
void
cpp_pop_definition (cpp_reader *pfile, const char *str, cpp_macro *dfn)
{
- cpp_hashnode *node = lex_macro_node_from_str (pfile, str);
+ cpp_hashnode *node = _cpp_lex_identifier (pfile, str);
if (node == NULL)
return;