mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-23 19:03:59 +08:00
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
This commit is contained in:
parent
6c7ac15dc6
commit
121de39fc0
@ -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
|
||||
|
142
gcc/c-pragma.c
142
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
|
||||
|
@ -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
|
||||
|
26
gcc/testsuite/gcc.dg/pragma-push_macro-1.c
Normal file
26
gcc/testsuite/gcc.dg/pragma-push_macro-1.c
Normal file
@ -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;
|
||||
}
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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 *);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user