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
This commit is contained in:
Kai Tietz 2009-11-11 18:37:19 +00:00 committed by Kai Tietz
parent 110532c838
commit 17e7cb8550
16 changed files with 411 additions and 177 deletions

View File

@ -1,3 +1,15 @@
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.
2009-11-11 Basile Starynkevitch <basile@starynkevitch.net>
* doc/plugins.texi (Registering custom attributes): section
renamed as (Registering custom attributes or pragmas).

View File

@ -244,144 +244,6 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
}
#endif /* HANDLE_PRAGMA_PACK */
struct GTY(()) def_pragma_macro_value {
struct def_pragma_macro_value *prev;
cpp_macro *value;
};
struct GTY(()) def_pragma_macro {
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 *const a = (const struct def_pragma_macro *) pa,
*const b = (const struct def_pragma_macro *) 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 = (struct def_pragma_macro *) *slot;
if (c == NULL)
{
*slot = c = GGC_NEW (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_NEW (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 = NULL;
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;
if (pushed_macro_table)
slot = htab_find_slot_with_hash (pushed_macro_table, &dummy,
dummy.hash, NO_INSERT);
if (slot == NULL)
return;
c = (struct def_pragma_macro *) *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
@ -1422,10 +1284,6 @@ 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

View File

@ -127,8 +127,6 @@ along with GCC; see the file COPYING3. If not see
/* Enable parsing of #pragma pack(push,<n>) and #pragma pack(pop). */
#define HANDLE_PRAGMA_PACK_PUSH_POP 1
/* Enable push_macro & pop_macro */
#define HANDLE_PRAGMA_PUSH_POP_MACRO 1
union tree_node;
#define TREE union tree_node *

View File

@ -10476,18 +10476,6 @@ 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

View File

@ -1,4 +1,10 @@
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.
2009-11-11 Jon Beniston <jon@beniston.com>
* lib/target-supports.exp (check_profiling_available): lm32 target

View File

@ -0,0 +1,19 @@
/* Do the preprocessor push_macro/pop_macro test. */
/* { dg-do run } */
extern "C" void abort ();
#define _ 2
#pragma push_macro("_")
#undef _
#define _ 1
#pragma pop_macro("_")
int main ()
{
if (_ != 2)
abort ();
return 0;
}

View File

@ -0,0 +1,15 @@
extern void abort ();
#define _ 2
#pragma push_macro("_")
#undef _
#define _ 1
#pragma pop_macro("_")
int main ()
{
if (_ != 2)
abort ();
return 0;
}

View File

@ -1,7 +1,7 @@
/* PR preprocessor/35061 */
/* Do nothing if there is nothing on the macro stack to pop. */
/* { dg-do preprocess { target *-*-mingw* *-*-cygwin* } } */
/* { dg-do preprocess } */
#define X 1
/* # pragma push_macro("X") */

View File

@ -0,0 +1,11 @@
#include "pushpop-1.hs"
#if FOO != 2
#error FOO != 2
#endif
#pragma pop_macro("FOO")
#if FOO != 1
#error FOR != 1
#endif

View File

@ -0,0 +1,5 @@
#define FOO 1
#pragma push_macro ("FOO")
#undef FOO
#define FOO 2

View File

@ -1,3 +1,26 @@
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.
2009-10-19 Jakub Jelinek <jakub@redhat.com>
* charset.c (cpp_init_iconv): Initialize utf8_cset_desc.

View File

@ -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;

View File

@ -216,6 +216,9 @@ cpp_create_reader (enum c_lang lang, hash_table *table,
pfile->a_buff = _cpp_get_buff (pfile, 0);
pfile->u_buff = _cpp_get_buff (pfile, 0);
/* Initialize table for push_macro/pop_macro. */
pfile->pushed_macros = 0;
/* The expression parser stack. */
_cpp_expand_op_stack (pfile);
@ -245,6 +248,7 @@ void
cpp_destroy (cpp_reader *pfile)
{
cpp_context *context, *contextn;
struct def_pragma_macro *pmacro;
tokenrun *run, *runn;
int i;
@ -296,6 +300,17 @@ cpp_destroy (cpp_reader *pfile)
free (pfile->comments.entries);
}
if (pfile->pushed_macros)
{
do
{
pmacro = pfile->pushed_macros;
pfile->pushed_macros = pmacro->next;
free (pmacro->name);
free (pmacro);
}
while (pfile->pushed_macros);
}
free (pfile);
}

View File

@ -305,6 +305,16 @@ struct cpp_buffer
struct cset_converter input_cset_desc;
};
/* The list of saved macros by push_macro pragma. */
struct def_pragma_macro {
/* Chain element to previous saved macro. */
struct def_pragma_macro *next;
/* Name of the macro. */
char *name;
/* The stored macro content. */
cpp_macro *value;
};
/* A cpp_reader encapsulates the "state" of a pre-processor run.
Applying cpp_get_token repeatedly yields a stream of pre-processor
tokens. Usually, there is only one cpp_reader object active. */
@ -475,6 +485,9 @@ struct cpp_reader
/* Table of comments, when state.save_comments is true. */
cpp_comment_table comments;
/* List of saved macros by push_macro. */
struct def_pragma_macro *pushed_macros;
};
/* Character classes. Based on the more primitive macros in safe-ctype.h.
@ -575,6 +588,7 @@ extern const cpp_token *_cpp_lex_token (cpp_reader *);
extern cpp_token *_cpp_lex_direct (cpp_reader *);
extern int _cpp_equiv_tokens (const cpp_token *, const cpp_token *);
extern void _cpp_init_tokenrun (tokenrun *, unsigned int);
extern cpp_hashnode *_cpp_lex_identifier (cpp_reader *, const char *);
/* In init.c. */
extern void _cpp_maybe_push_include_file (cpp_reader *);

View File

@ -504,6 +504,63 @@ forms_identifier_p (cpp_reader *pfile, int first,
return false;
}
/* Helper function to get the cpp_hashnode of the identifier BASE. */
static cpp_hashnode *
lex_identifier_intern (cpp_reader *pfile, const uchar *base)
{
cpp_hashnode *result;
const uchar *cur;
unsigned int len;
unsigned int hash = HT_HASHSTEP (0, *base);
cur = base + 1;
while (ISIDNUM (*cur))
{
hash = HT_HASHSTEP (hash, *cur);
cur++;
}
len = cur - base;
hash = HT_HASHFINISH (hash, len);
result = CPP_HASHNODE (ht_lookup_with_hash (pfile->hash_table,
base, len, hash, HT_ALLOC));
/* Rarely, identifiers require diagnostics when lexed. */
if (__builtin_expect ((result->flags & NODE_DIAGNOSTIC)
&& !pfile->state.skipping, 0))
{
/* It is allowed to poison the same identifier twice. */
if ((result->flags & NODE_POISONED) && !pfile->state.poisoned_ok)
cpp_error (pfile, CPP_DL_ERROR, "attempt to use poisoned \"%s\"",
NODE_NAME (result));
/* Constraint 6.10.3.5: __VA_ARGS__ should only appear in the
replacement list of a variadic macro. */
if (result == pfile->spec_nodes.n__VA_ARGS__
&& !pfile->state.va_args_ok)
cpp_error (pfile, CPP_DL_PEDWARN,
"__VA_ARGS__ can only appear in the expansion"
" of a C99 variadic macro");
/* For -Wc++-compat, warn about use of C++ named operators. */
if (result->flags & NODE_WARN_OPERATOR)
cpp_error (pfile, CPP_DL_WARNING,
"identifier \"%s\" is a special operator name in C++",
NODE_NAME (result));
}
return result;
}
/* Get the cpp_hashnode of an identifier specified by NAME in
the current cpp_reader object. If none is found, NULL is returned. */
cpp_hashnode *
_cpp_lex_identifier (cpp_reader *pfile, const char *name)
{
cpp_hashnode *result;
result = lex_identifier_intern (pfile, (uchar *) name);
return result;
}
/* Lex an identifier starting at BUFFER->CUR - 1. */
static cpp_hashnode *
lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn,

View File

@ -33,6 +33,8 @@ static int comp_hashnodes (const void *, const void *);
static int collect_ht_nodes (cpp_reader *, cpp_hashnode *, void *);
static int write_defs (cpp_reader *, cpp_hashnode *, void *);
static int save_macros (cpp_reader *, cpp_hashnode *, void *);
static int _cpp_save_pushed_macros (cpp_reader *, FILE *);
static int _cpp_restore_pushed_macros (cpp_reader *, FILE *);
/* This structure represents a macro definition on disk. */
struct macrodef_struct
@ -378,9 +380,140 @@ cpp_write_pch_state (cpp_reader *r, FILE *f)
return -1;
}
/* Write saved macros. */
if (! _cpp_save_pushed_macros (r, f))
{
cpp_errno (r, CPP_DL_ERROR, "while writing precompiled header");
return -1;
}
return 0;
}
static int
_cpp_restore_pushed_macros (cpp_reader *r, FILE *f)
{
size_t count_saved = 0;
size_t i;
struct def_pragma_macro *p;
size_t nlen;
cpp_hashnode *h = NULL;
cpp_macro *m;
uchar *defn;
size_t defnlen;
if (fread (&count_saved, sizeof (count_saved), 1, f) != 1)
return 0;
if (! count_saved)
return 1;
for (i = 0; i < count_saved; i++)
{
if (fread (&nlen, sizeof (nlen), 1, f) != 1)
return 0;
p = XNEW (struct def_pragma_macro);
p->name = XNEWVAR (char, nlen + 1);
p->name[nlen] = 0;
if (fread (p->name, nlen, 1, f) != 1)
return 0;
/* Save old state. */
m = cpp_push_definition (r, p->name);
if (fread (&defnlen, sizeof (defnlen), 1, f) != 1)
return 0;
defn = XNEWVAR (uchar, defnlen + 2);
defn[defnlen] = '\n';
defn[defnlen + 1] = 0;
if (fread (defn, defnlen, 1, f) != 1)
return 0;
cpp_pop_definition (r, p->name, NULL);
{
size_t namelen;
uchar *dn;
namelen = ustrcspn (defn, "( \n");
h = cpp_lookup (r, defn, namelen);
dn = defn + namelen;
h->type = NT_VOID;
h->flags &= ~(NODE_POISONED|NODE_BUILTIN|NODE_DISABLED|NODE_USED);
if (cpp_push_buffer (r, dn, ustrchr (dn, '\n') - dn, true)
!= NULL)
{
_cpp_clean_line (r);
if (!_cpp_create_definition (r, h))
abort ();
_cpp_pop_buffer (r);
}
else
abort ();
}
p->value = cpp_push_definition (r, p->name);
free (defn);
p->next = r->pushed_macros;
r->pushed_macros = p;
/* Restore current state. */
cpp_pop_definition (r, p->name, m);
}
return 1;
}
static int
_cpp_save_pushed_macros (cpp_reader *r, FILE *f)
{
size_t count_saved = 0;
size_t i;
struct def_pragma_macro *p,**pp;
cpp_hashnode *node;
cpp_macro *m;
size_t defnlen;
const uchar *defn;
/* Get count. */
p = r->pushed_macros;
while (p != NULL)
{
count_saved++;
p = p->next;
}
if (fwrite (&count_saved, sizeof (count_saved), 1, f) != 1)
return 0;
if (!count_saved)
return 1;
pp = (struct def_pragma_macro **) alloca (sizeof (struct def_pragma_macro *)
* count_saved);
/* Store them in reverse order. */
p = r->pushed_macros;
i = count_saved;
while (p != NULL)
{
--i;
pp[i] = p;
p = p->next;
}
for (i = 0; i < count_saved; i++)
{
/* Save old state. */
m = cpp_push_definition (r, pp[i]->name);
/* Set temporary macro name to saved state. */
cpp_pop_definition (r, pp[i]->name, pp[i]->value);
node = _cpp_lex_identifier (r, pp[i]->name);
defnlen = strlen (pp[i]->name);
if (fwrite (&defnlen, sizeof (size_t), 1, f) != 1
|| fwrite (pp[i]->name, defnlen, 1, f) != 1)
return 0;
defn = cpp_macro_definition (r, node);
defnlen = ustrlen (defn);
if (fwrite (&defnlen, sizeof (size_t), 1, f) != 1
|| fwrite (defn, defnlen, 1, f) != 1)
return 0;
/* Restore current state. */
cpp_pop_definition (r, pp[i]->name, m);
}
return 1;
}
/* Data structure to transform hash table nodes into a sorted list */
@ -752,6 +885,9 @@ cpp_read_state (cpp_reader *r, const char *name, FILE *f,
if (!r->counter)
r->counter = counter;
/* Read pushed macros. */
if (! _cpp_restore_pushed_macros (r, f))
goto error;
return 0;
error: