mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-21 19:35:28 -05:00
Index: gcc/ChangeLog
2004-06-09 Geoffrey Keating <geoffk@apple.com> * Makefile.in (CPPLIB_H): Put files in order of inclusion. (CPP_ID_DATA_H): New. (gtype-desc.o): Update dependencies. (GTFILES): Use CPP_ID_DATA_H. Index: gcc/testsuite/ChangeLog 2004-06-09 Geoffrey Keating <geoffk@apple.com> * gcc.dg/pch/macro-4.c: New. * gcc.dg/pch/macro-4.hs: New. Index: libcpp/ChangeLog 2004-06-09 Geoffrey Keating <geoffk@apple.com> * traditional.c (push_replacement_text): Set macro->traditional. (save_replacement_text): Likewise. * pch.c (cpp_write_pch_state): Don't write list of defined macros. (struct save_macro_item): Delete. (struct save_macro_data): Use a character array not the previous structured format. (save_macros): Save macro as text not as internal structures. (cpp_prepare_state): Update for changes to save_macro_data. (cpp_read_state): Don't read macros defined in PCH. Restore -D macros as text. * macro.c (create_iso_definition): Honour alloc_subobject. Clear traditional flag. (_cpp_create_definition): Honour alloc_subobject. * lex.c (cpp_token_val_index): New. * internal.h: Include cpp-id-data.h. (uchar): Move definition to cpp-id-data.h. (U): Likewise. (cpp_macro): Likewise. * directives.c (struct answer): Move to cpp-id-data.h. (do_assert): Honour alloc_subobject. Index: libcpp/include/ChangeLog 2004-06-09 Geoffrey Keating <geoffk@apple.com> * symtab.h (struct ht): Add field 'alloc_subobject'. * cpplib.h (struct cpp_string): Add GTY marker. (enum cpp_token_fld_kind): New. (struct cpp_token): Add GTY markers. (cpp_token_val_index): Prototype. (CPP_HASHNODE_VALUE_IDX): New. (struct cpp_hashnode): Don't skip fields of 'value' when marking. * cpp-id-data.h: New file. From-SVN: r82851
This commit is contained in:
committed by
Geoffrey Keating
parent
293155b099
commit
d8044160b7
@@ -1,3 +1,27 @@
|
||||
2004-06-09 Geoffrey Keating <geoffk@apple.com>
|
||||
|
||||
* traditional.c (push_replacement_text): Set macro->traditional.
|
||||
(save_replacement_text): Likewise.
|
||||
* pch.c (cpp_write_pch_state): Don't write list of defined macros.
|
||||
(struct save_macro_item): Delete.
|
||||
(struct save_macro_data): Use a character array not the previous
|
||||
structured format.
|
||||
(save_macros): Save macro as text not as internal structures.
|
||||
(cpp_prepare_state): Update for changes to save_macro_data.
|
||||
(cpp_read_state): Don't read macros defined in PCH. Restore
|
||||
-D macros as text.
|
||||
* macro.c (create_iso_definition): Honour alloc_subobject.
|
||||
Clear traditional flag.
|
||||
(_cpp_create_definition): Honour alloc_subobject.
|
||||
* lex.c (cpp_token_val_index): New.
|
||||
* internal.h: Include cpp-id-data.h.
|
||||
(uchar): Move definition to cpp-id-data.h.
|
||||
(U): Likewise.
|
||||
(cpp_macro): Likewise.
|
||||
* directives.c (struct answer): Move to cpp-id-data.h.
|
||||
(do_assert): Honour alloc_subobject.
|
||||
|
||||
|
||||
2004-06-09 Paolo Bonzini <bonzini@gnu.org>
|
||||
|
||||
* Makefile.am (all-local): New.
|
||||
|
||||
@@ -26,14 +26,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
#include "mkdeps.h"
|
||||
#include "obstack.h"
|
||||
|
||||
/* Chained list of answers to an assertion. */
|
||||
struct answer
|
||||
{
|
||||
struct answer *next;
|
||||
unsigned int count;
|
||||
cpp_token first[1];
|
||||
};
|
||||
|
||||
/* Stack of conditionals currently in progress
|
||||
(including both successful and failing conditionals). */
|
||||
struct if_stack
|
||||
@@ -1727,6 +1719,8 @@ do_assert (cpp_reader *pfile)
|
||||
node = parse_assertion (pfile, &new_answer, T_ASSERT);
|
||||
if (node)
|
||||
{
|
||||
size_t answer_size;
|
||||
|
||||
/* Place the new answer in the answer list. First check there
|
||||
is not a duplicate. */
|
||||
new_answer->next = 0;
|
||||
@@ -1741,11 +1735,20 @@ do_assert (cpp_reader *pfile)
|
||||
new_answer->next = node->value.answers;
|
||||
}
|
||||
|
||||
answer_size = sizeof (struct answer) + ((new_answer->count - 1)
|
||||
* sizeof (cpp_token));
|
||||
/* Commit or allocate storage for the object. */
|
||||
if (pfile->hash_table->alloc_subobject)
|
||||
{
|
||||
struct answer *temp_answer = new_answer;
|
||||
new_answer = pfile->hash_table->alloc_subobject (answer_size);
|
||||
memcpy (new_answer, temp_answer, answer_size);
|
||||
}
|
||||
else
|
||||
BUFF_FRONT (pfile->a_buff) += answer_size;
|
||||
|
||||
node->type = NT_ASSERTION;
|
||||
node->value.answers = new_answer;
|
||||
BUFF_FRONT (pfile->a_buff) += (sizeof (struct answer)
|
||||
+ (new_answer->count - 1)
|
||||
* sizeof (cpp_token));
|
||||
check_eol (pfile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
2004-06-09 Geoffrey Keating <geoffk@apple.com>
|
||||
|
||||
* symtab.h (struct ht): Add field 'alloc_subobject'.
|
||||
* cpplib.h (struct cpp_string): Add GTY marker.
|
||||
(enum cpp_token_fld_kind): New.
|
||||
(struct cpp_token): Add GTY markers.
|
||||
(cpp_token_val_index): Prototype.
|
||||
(CPP_HASHNODE_VALUE_IDX): New.
|
||||
(struct cpp_hashnode): Don't skip fields of 'value' when marking.
|
||||
* cpp-id-data.h: New file.
|
||||
|
||||
2004-05-29 Geoffrey Keating <geoffk@apple.com>
|
||||
|
||||
* symtab.h (struct ht): New field 'entries_owned'
|
||||
|
||||
77
libcpp/include/cpp-id-data.h
Normal file
77
libcpp/include/cpp-id-data.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* Structures that hang off cpp_identifier, for PCH.
|
||||
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "cpplib.h"
|
||||
|
||||
#ifndef HAVE_UCHAR
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
#define U (const uchar *) /* Intended use: U"string" */
|
||||
|
||||
/* Chained list of answers to an assertion. */
|
||||
struct answer GTY(())
|
||||
{
|
||||
struct answer *next;
|
||||
unsigned int count;
|
||||
cpp_token GTY ((length ("%h.count"))) first[1];
|
||||
};
|
||||
|
||||
/* Each macro definition is recorded in a cpp_macro structure.
|
||||
Variadic macros cannot occur with traditional cpp. */
|
||||
struct cpp_macro GTY(())
|
||||
{
|
||||
/* Parameters, if any. */
|
||||
cpp_hashnode ** GTY ((nested_ptr (union tree_node,
|
||||
"%h ? CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (%h)) : NULL",
|
||||
"%h ? HT_IDENT_TO_GCC_IDENT (HT_NODE (%h)) : NULL"),
|
||||
length ("%h.paramc")))
|
||||
params;
|
||||
|
||||
/* Replacement tokens (ISO) or replacement text (traditional). See
|
||||
comment at top of cpptrad.c for how traditional function-like
|
||||
macros are encoded. */
|
||||
union cpp_macro_u
|
||||
{
|
||||
cpp_token * GTY ((tag ("0"), length ("%0.count"))) tokens;
|
||||
const uchar * GTY ((tag ("1"))) text;
|
||||
} GTY ((desc ("%1.traditional"))) exp;
|
||||
|
||||
/* Definition line number. */
|
||||
source_location line;
|
||||
|
||||
/* Number of tokens in expansion, or bytes for traditional macros. */
|
||||
unsigned int count;
|
||||
|
||||
/* Number of parameters. */
|
||||
unsigned short paramc;
|
||||
|
||||
/* If a function-like macro. */
|
||||
unsigned int fun_like : 1;
|
||||
|
||||
/* If a variadic macro. */
|
||||
unsigned int variadic : 1;
|
||||
|
||||
/* If macro defined in system header. */
|
||||
unsigned int syshdr : 1;
|
||||
|
||||
/* Nonzero if it has been expanded or had its existence tested. */
|
||||
unsigned int used : 1;
|
||||
|
||||
/* Indicate which field of 'exp' is in use. */
|
||||
unsigned int traditional : 1;
|
||||
};
|
||||
@@ -156,7 +156,7 @@ enum c_lang {CLK_GNUC89 = 0, CLK_GNUC99, CLK_STDC89, CLK_STDC94, CLK_STDC99,
|
||||
CLK_GNUCXX, CLK_CXX98, CLK_ASM};
|
||||
|
||||
/* Payload of a NUMBER, STRING, CHAR or COMMENT token. */
|
||||
struct cpp_string
|
||||
struct cpp_string GTY(())
|
||||
{
|
||||
unsigned int len;
|
||||
const unsigned char *text;
|
||||
@@ -171,23 +171,48 @@ struct cpp_string
|
||||
#define NO_EXPAND (1 << 5) /* Do not macro-expand this token. */
|
||||
#define BOL (1 << 6) /* Token at beginning of line. */
|
||||
|
||||
/* Specify which field, if any, of the cpp_token union is used. */
|
||||
|
||||
enum cpp_token_fld_kind {
|
||||
CPP_TOKEN_FLD_NODE,
|
||||
CPP_TOKEN_FLD_SOURCE,
|
||||
CPP_TOKEN_FLD_STR,
|
||||
CPP_TOKEN_FLD_ARG_NO,
|
||||
CPP_TOKEN_FLD_NONE
|
||||
};
|
||||
|
||||
/* A preprocessing token. This has been carefully packed and should
|
||||
occupy 16 bytes on 32-bit hosts and 24 bytes on 64-bit hosts. */
|
||||
struct cpp_token
|
||||
struct cpp_token GTY(())
|
||||
{
|
||||
source_location src_loc; /* Location of first char of token. */
|
||||
ENUM_BITFIELD(cpp_ttype) type : CHAR_BIT; /* token type */
|
||||
unsigned char flags; /* flags - see above */
|
||||
|
||||
union
|
||||
union cpp_token_u
|
||||
{
|
||||
cpp_hashnode *node; /* An identifier. */
|
||||
const cpp_token *source; /* Inherit padding from this token. */
|
||||
struct cpp_string str; /* A string, or number. */
|
||||
unsigned int arg_no; /* Argument no. for a CPP_MACRO_ARG. */
|
||||
} val;
|
||||
/* An identifier. */
|
||||
cpp_hashnode *
|
||||
GTY ((nested_ptr (union tree_node,
|
||||
"%h ? CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (%h)) : NULL",
|
||||
"%h ? HT_IDENT_TO_GCC_IDENT (HT_NODE (%h)) : NULL"),
|
||||
tag ("CPP_TOKEN_FLD_NODE")))
|
||||
node;
|
||||
|
||||
/* Inherit padding from this token. */
|
||||
cpp_token * GTY ((tag ("CPP_TOKEN_FLD_SOURCE"))) source;
|
||||
|
||||
/* A string, or number. */
|
||||
struct cpp_string GTY ((tag ("CPP_TOKEN_FLD_STR"))) str;
|
||||
|
||||
/* Argument no. for a CPP_MACRO_ARG. */
|
||||
unsigned int GTY ((tag ("CPP_TOKEN_FLD_ARG_NO"))) arg_no;
|
||||
} GTY ((desc ("cpp_token_val_index (&%1)"))) val;
|
||||
};
|
||||
|
||||
/* Say which field is in use. */
|
||||
extern enum cpp_token_fld_kind cpp_token_val_index (cpp_token *tok);
|
||||
|
||||
/* A type wide enough to hold any multibyte source character.
|
||||
cpplib's character constant interpreter requires an unsigned type.
|
||||
Also, a typedef for the signed equivalent.
|
||||
@@ -498,6 +523,23 @@ enum builtin_type
|
||||
#define NODE_LEN(NODE) HT_LEN (&(NODE)->ident)
|
||||
#define NODE_NAME(NODE) HT_STR (&(NODE)->ident)
|
||||
|
||||
/* Specify which field, if any, of the union is used. */
|
||||
|
||||
enum {
|
||||
NTV_MACRO,
|
||||
NTV_ANSWER,
|
||||
NTV_BUILTIN,
|
||||
NTV_ARGUMENT,
|
||||
NTV_NONE
|
||||
};
|
||||
|
||||
#define CPP_HASHNODE_VALUE_IDX(HNODE) \
|
||||
((HNODE.flags & NODE_MACRO_ARG) ? NTV_ARGUMENT \
|
||||
: HNODE.type == NT_MACRO ? ((HNODE.flags & NODE_BUILTIN) \
|
||||
? NTV_BUILTIN : NTV_MACRO) \
|
||||
: HNODE.type == NT_ASSERTION ? NTV_ANSWER \
|
||||
: NTV_NONE)
|
||||
|
||||
/* The common part of an identifier node shared amongst all 3 C front
|
||||
ends. Also used to store CPP identifiers, which are a superset of
|
||||
identifiers in the grammatical sense. */
|
||||
@@ -515,14 +557,14 @@ struct cpp_hashnode GTY(())
|
||||
union _cpp_hashnode_value
|
||||
{
|
||||
/* If a macro. */
|
||||
cpp_macro * GTY((skip)) macro;
|
||||
cpp_macro * GTY((tag ("NTV_MACRO"))) macro;
|
||||
/* Answers to an assertion. */
|
||||
struct answer * GTY ((skip)) answers;
|
||||
struct answer * GTY ((tag ("NTV_ANSWER"))) answers;
|
||||
/* Code for a builtin macro. */
|
||||
enum builtin_type GTY ((tag ("1"))) builtin;
|
||||
enum builtin_type GTY ((tag ("NTV_BUILTIN"))) builtin;
|
||||
/* Macro argument index. */
|
||||
unsigned short GTY ((tag ("0"))) arg_index;
|
||||
} GTY ((desc ("0"))) value;
|
||||
unsigned short GTY ((tag ("NTV_ARGUMENT"))) arg_index;
|
||||
} GTY ((desc ("CPP_HASHNODE_VALUE_IDX (%1)"))) value;
|
||||
};
|
||||
|
||||
/* Call this first to get a handle to pass to other functions.
|
||||
|
||||
@@ -46,8 +46,11 @@ struct ht
|
||||
struct obstack stack;
|
||||
|
||||
hashnode *entries;
|
||||
/* Call back. */
|
||||
/* Call back, allocate a node. */
|
||||
hashnode (*alloc_node) (hash_table *);
|
||||
/* Call back, allocate something that hangs off a node like a cpp_macro.
|
||||
NULL means use the usual allocator. */
|
||||
void * (*alloc_subobject) (size_t);
|
||||
|
||||
unsigned int nslots; /* Total slots in the entries array. */
|
||||
unsigned int nelements; /* Number of live elements. */
|
||||
|
||||
@@ -24,6 +24,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
#define LIBCPP_INTERNAL_H
|
||||
|
||||
#include "symtab.h"
|
||||
#include "cpp-id-data.h"
|
||||
|
||||
#if defined HAVE_ICONV_H && defined HAVE_ICONV
|
||||
#include <iconv.h>
|
||||
@@ -45,11 +46,6 @@ struct cset_converter
|
||||
iconv_t cd;
|
||||
};
|
||||
|
||||
#ifndef HAVE_UCHAR
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
#define U (const uchar *) /* Intended use: U"string" */
|
||||
|
||||
#define BITS_PER_CPPCHAR_T (CHAR_BIT * sizeof (cppchar_t))
|
||||
|
||||
/* Test if a sign is valid within a preprocessing number. */
|
||||
@@ -90,44 +86,6 @@ struct dummy
|
||||
#define CPP_ALIGN2(size, align) (((size) + ((align) - 1)) & ~((align) - 1))
|
||||
#define CPP_ALIGN(size) CPP_ALIGN2 (size, DEFAULT_ALIGNMENT)
|
||||
|
||||
/* Each macro definition is recorded in a cpp_macro structure.
|
||||
Variadic macros cannot occur with traditional cpp. */
|
||||
struct cpp_macro
|
||||
{
|
||||
/* Parameters, if any. */
|
||||
cpp_hashnode **params;
|
||||
|
||||
/* Replacement tokens (ISO) or replacement text (traditional). See
|
||||
comment at top of cpptrad.c for how traditional function-like
|
||||
macros are encoded. */
|
||||
union
|
||||
{
|
||||
cpp_token *tokens;
|
||||
const uchar *text;
|
||||
} exp;
|
||||
|
||||
/* Definition line number. */
|
||||
fileline line;
|
||||
|
||||
/* Number of tokens in expansion, or bytes for traditional macros. */
|
||||
unsigned int count;
|
||||
|
||||
/* Number of parameters. */
|
||||
unsigned short paramc;
|
||||
|
||||
/* If a function-like macro. */
|
||||
unsigned int fun_like : 1;
|
||||
|
||||
/* If a variadic macro. */
|
||||
unsigned int variadic : 1;
|
||||
|
||||
/* If macro defined in system header. */
|
||||
unsigned int syshdr : 1;
|
||||
|
||||
/* Nonzero if it has been expanded or had its existence tested. */
|
||||
unsigned int used : 1;
|
||||
};
|
||||
|
||||
#define _cpp_mark_macro_used(NODE) do { \
|
||||
if ((NODE)->type == NT_MACRO && !((NODE)->flags & NODE_BUILTIN)) \
|
||||
(NODE)->value.macro->used = 1; } while (0)
|
||||
|
||||
22
libcpp/lex.c
22
libcpp/lex.c
@@ -1556,3 +1556,25 @@ _cpp_aligned_alloc (cpp_reader *pfile, size_t len)
|
||||
buff->cur = result + len;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Say which field of TOK is in use. */
|
||||
|
||||
enum cpp_token_fld_kind
|
||||
cpp_token_val_index (cpp_token *tok)
|
||||
{
|
||||
switch (TOKEN_SPELL (tok))
|
||||
{
|
||||
case SPELL_IDENT:
|
||||
return CPP_TOKEN_FLD_NODE;
|
||||
case SPELL_LITERAL:
|
||||
return CPP_TOKEN_FLD_STR;
|
||||
case SPELL_NONE:
|
||||
if (tok->type == CPP_MACRO_ARG)
|
||||
return CPP_TOKEN_FLD_ARG_NO;
|
||||
else if (tok->type == CPP_PADDING)
|
||||
return CPP_TOKEN_FLD_SOURCE;
|
||||
/* else fall through */
|
||||
default:
|
||||
return CPP_TOKEN_FLD_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1408,8 +1408,16 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
/* Success. Commit the parameter array. */
|
||||
BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->params[macro->paramc];
|
||||
/* Success. Commit or allocate the parameter array. */
|
||||
if (pfile->hash_table->alloc_subobject)
|
||||
{
|
||||
cpp_token *tokns = pfile->hash_table->alloc_subobject
|
||||
(sizeof (cpp_token) * macro->paramc);
|
||||
memcpy (tokns, macro->params, sizeof (cpp_token) * macro->paramc);
|
||||
macro->params = tokns;
|
||||
}
|
||||
else
|
||||
BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->params[macro->paramc];
|
||||
macro->fun_like = 1;
|
||||
}
|
||||
else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE))
|
||||
@@ -1472,6 +1480,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
}
|
||||
|
||||
macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff);
|
||||
macro->traditional = 0;
|
||||
|
||||
/* Don't count the CPP_EOF. */
|
||||
macro->count--;
|
||||
@@ -1480,8 +1489,16 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
if (macro->count)
|
||||
macro->exp.tokens[0].flags &= ~PREV_WHITE;
|
||||
|
||||
/* Commit the memory. */
|
||||
BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->exp.tokens[macro->count];
|
||||
/* Commit or allocate the memory. */
|
||||
if (pfile->hash_table->alloc_subobject)
|
||||
{
|
||||
cpp_token *tokns = pfile->hash_table->alloc_subobject (sizeof (cpp_token)
|
||||
* macro->count);
|
||||
memcpy (tokns, macro->exp.tokens, sizeof (cpp_token) * macro->count);
|
||||
macro->exp.tokens = tokns;
|
||||
}
|
||||
else
|
||||
BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->exp.tokens[macro->count];
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1494,7 +1511,10 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
|
||||
unsigned int i;
|
||||
bool ok;
|
||||
|
||||
macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro));
|
||||
if (pfile->hash_table->alloc_subobject)
|
||||
macro = pfile->hash_table->alloc_subobject (sizeof (cpp_macro));
|
||||
else
|
||||
macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro));
|
||||
macro->line = pfile->directive_line;
|
||||
macro->params = 0;
|
||||
macro->paramc = 0;
|
||||
|
||||
159
libcpp/pch.c
159
libcpp/pch.c
@@ -347,15 +347,6 @@ cpp_write_pch_state (cpp_reader *r, FILE *f)
|
||||
{
|
||||
struct macrodef_struct z;
|
||||
|
||||
/* Write out the list of defined identifiers. */
|
||||
cpp_forall_identifiers (r, write_macdef, f);
|
||||
memset (&z, 0, sizeof (z));
|
||||
if (fwrite (&z, sizeof (z), 1, f) != 1)
|
||||
{
|
||||
cpp_errno (r, CPP_DL_ERROR, "while writing precompiled header");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!r->deps)
|
||||
r->deps = deps_init ();
|
||||
|
||||
@@ -544,46 +535,64 @@ cpp_valid_state (cpp_reader *r, const char *name, int fd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Save all the existing macros and assertions.
|
||||
This code assumes that there might be hundreds, but not thousands of
|
||||
existing definitions. */
|
||||
|
||||
struct save_macro_item {
|
||||
struct save_macro_item *next;
|
||||
struct cpp_hashnode macs[64];
|
||||
};
|
||||
/* Save all the existing macros. */
|
||||
|
||||
struct save_macro_data
|
||||
{
|
||||
struct save_macro_item *macros;
|
||||
uchar **defns;
|
||||
size_t count;
|
||||
size_t array_size;
|
||||
char **saved_pragmas;
|
||||
};
|
||||
|
||||
/* Save the definition of a single macro, so that it will persist across
|
||||
a PCH restore. */
|
||||
/* Save the definition of a single macro, so that it will persist
|
||||
across a PCH restore. Because macro data is in GCed memory, which
|
||||
will be blown away by PCH, it must be temporarily copied to
|
||||
malloced memory. (The macros will refer to identifier nodes which
|
||||
are also GCed and so on, so the copying is done by turning them
|
||||
into self-contained strings.) The assumption is that most macro
|
||||
definitions will come from the PCH file, not from the compilation
|
||||
before the PCH file is loaded, so it doesn't matter that this is
|
||||
a little expensive.
|
||||
|
||||
It would reduce the cost even further if macros defined in the PCH
|
||||
file were not saved in this way, but this is not done (yet), except
|
||||
for builtins, and for #assert by default. */
|
||||
|
||||
static int
|
||||
save_macros (cpp_reader *r ATTRIBUTE_UNUSED, cpp_hashnode *h, void *data_p)
|
||||
save_macros (cpp_reader *r, cpp_hashnode *h, void *data_p)
|
||||
{
|
||||
struct save_macro_data *data = (struct save_macro_data *)data_p;
|
||||
if (h->type != NT_VOID
|
||||
&& (h->flags & NODE_BUILTIN) == 0)
|
||||
{
|
||||
cpp_hashnode *save;
|
||||
if (data->count == ARRAY_SIZE (data->macros->macs))
|
||||
if (data->count == data->array_size)
|
||||
{
|
||||
struct save_macro_item *d = data->macros;
|
||||
data->macros = xmalloc (sizeof (struct save_macro_item));
|
||||
data->macros->next = d;
|
||||
data->count = 0;
|
||||
data->array_size *= 2;
|
||||
data->defns = xrealloc (data->defns, (data->array_size
|
||||
* sizeof (uchar *)));
|
||||
}
|
||||
|
||||
switch (h->type)
|
||||
{
|
||||
case NT_ASSERTION:
|
||||
/* Not currently implemented. */
|
||||
return 1;
|
||||
|
||||
case NT_MACRO:
|
||||
{
|
||||
const uchar * defn = cpp_macro_definition (r, h);
|
||||
size_t defnlen = ustrlen (defn);
|
||||
|
||||
data->defns[data->count] = xmemdup (defn, defnlen, defnlen + 2);
|
||||
data->defns[data->count][defnlen] = '\n';
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
save = data->macros->macs + data->count;
|
||||
data->count++;
|
||||
memcpy (save, h, sizeof (struct cpp_hashnode));
|
||||
HT_STR (&save->ident) = xmemdup (HT_STR (HT_NODE (save)),
|
||||
HT_LEN (HT_NODE (save)),
|
||||
HT_LEN (HT_NODE (save)) + 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -596,8 +605,9 @@ cpp_prepare_state (cpp_reader *r, struct save_macro_data **data)
|
||||
{
|
||||
struct save_macro_data *d = xmalloc (sizeof (struct save_macro_data));
|
||||
|
||||
d->macros = NULL;
|
||||
d->count = ARRAY_SIZE (d->macros->macs);
|
||||
d->array_size = 512;
|
||||
d->defns = xmalloc (d->array_size * sizeof (d->defns[0]));
|
||||
d->count = 0;
|
||||
cpp_forall_identifiers (r, save_macros, d);
|
||||
d->saved_pragmas = _cpp_save_pragma_names (r);
|
||||
*data = d;
|
||||
@@ -612,11 +622,9 @@ cpp_read_state (cpp_reader *r, const char *name, FILE *f,
|
||||
struct save_macro_data *data)
|
||||
{
|
||||
struct macrodef_struct m;
|
||||
size_t defnlen = 256;
|
||||
unsigned char *defn = xmalloc (defnlen);
|
||||
struct lexer_state old_state;
|
||||
struct save_macro_item *d;
|
||||
size_t i, mac_count;
|
||||
struct lexer_state old_state;
|
||||
|
||||
/* Restore spec_nodes, which will be full of references to the old
|
||||
hashtable entries and so will now be invalid. */
|
||||
@@ -628,70 +636,28 @@ cpp_read_state (cpp_reader *r, const char *name, FILE *f,
|
||||
s->n__VA_ARGS__ = cpp_lookup (r, DSC("__VA_ARGS__"));
|
||||
}
|
||||
|
||||
/* Run through the carefully-saved macros, insert them. */
|
||||
d = data->macros;
|
||||
mac_count = data->count;
|
||||
while (d)
|
||||
{
|
||||
struct save_macro_item *nextd;
|
||||
for (i = 0; i < mac_count; i++)
|
||||
{
|
||||
cpp_hashnode *h;
|
||||
|
||||
h = cpp_lookup (r, HT_STR (HT_NODE (&d->macs[i])),
|
||||
HT_LEN (HT_NODE (&d->macs[i])));
|
||||
h->type = d->macs[i].type;
|
||||
h->flags = d->macs[i].flags;
|
||||
h->value = d->macs[i].value;
|
||||
free ((void *)HT_STR (HT_NODE (&d->macs[i])));
|
||||
}
|
||||
nextd = d->next;
|
||||
free (d);
|
||||
d = nextd;
|
||||
mac_count = ARRAY_SIZE (d->macs);
|
||||
}
|
||||
|
||||
_cpp_restore_pragma_names (r, data->saved_pragmas);
|
||||
|
||||
free (data);
|
||||
|
||||
old_state = r->state;
|
||||
|
||||
r->state.in_directive = 1;
|
||||
r->state.prevent_expansion = 1;
|
||||
r->state.angled_headers = 0;
|
||||
|
||||
/* Read in the identifiers that must be defined. */
|
||||
for (;;)
|
||||
/* Run through the carefully-saved macros, insert them. */
|
||||
for (i = 0; i < data->count; i++)
|
||||
{
|
||||
cpp_hashnode *h;
|
||||
|
||||
if (fread (&m, sizeof (m), 1, f) != 1)
|
||||
goto error;
|
||||
|
||||
if (m.name_length == 0)
|
||||
break;
|
||||
size_t namelen;
|
||||
uchar *defn;
|
||||
|
||||
if (defnlen < m.definition_length + 1)
|
||||
namelen = strcspn (data->defns[i], "( \n");
|
||||
h = cpp_lookup (r, data->defns[i], namelen);
|
||||
defn = data->defns[i] + namelen;
|
||||
|
||||
/* The PCH file is valid, so we know that if there is a definition
|
||||
from the PCH file it must be the same as the one we had
|
||||
originally, and so do not need to restore it. */
|
||||
if (h->type == NT_VOID)
|
||||
{
|
||||
defnlen = m.definition_length + 256;
|
||||
defn = xrealloc (defn, defnlen);
|
||||
}
|
||||
|
||||
if (fread (defn, 1, m.definition_length, f) != m.definition_length)
|
||||
goto error;
|
||||
defn[m.definition_length] = '\n';
|
||||
|
||||
h = cpp_lookup (r, defn, m.name_length);
|
||||
|
||||
if (h->type == NT_MACRO)
|
||||
_cpp_free_definition (h);
|
||||
if (m.flags & NODE_POISONED)
|
||||
h->flags |= NODE_POISONED | NODE_DIAGNOSTIC;
|
||||
else if (m.name_length != m.definition_length)
|
||||
{
|
||||
if (cpp_push_buffer (r, defn + m.name_length,
|
||||
m.definition_length - m.name_length, true)
|
||||
if (cpp_push_buffer (r, defn, ustrchr (defn, '\n') - defn, true)
|
||||
!= NULL)
|
||||
{
|
||||
_cpp_clean_line (r);
|
||||
@@ -702,11 +668,14 @@ cpp_read_state (cpp_reader *r, const char *name, FILE *f,
|
||||
else
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
free (data->defns[i]);
|
||||
}
|
||||
r->state = old_state;
|
||||
free (defn);
|
||||
defn = NULL;
|
||||
|
||||
_cpp_restore_pragma_names (r, data->saved_pragmas);
|
||||
|
||||
free (data);
|
||||
|
||||
if (deps_restore (r->deps, f, CPP_OPTION (r, restore_pch_deps) ? name : NULL)
|
||||
!= 0)
|
||||
|
||||
@@ -701,6 +701,7 @@ push_replacement_text (cpp_reader *pfile, cpp_hashnode *node)
|
||||
cpp_macro *macro = node->value.macro;
|
||||
macro->used = 1;
|
||||
text = macro->exp.text;
|
||||
macro->traditional = 1;
|
||||
len = macro->count;
|
||||
}
|
||||
|
||||
@@ -934,6 +935,7 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro,
|
||||
memcpy (exp, pfile->out.base, len);
|
||||
exp[len] = '\n';
|
||||
macro->exp.text = exp;
|
||||
macro->traditional = 1;
|
||||
macro->count = len;
|
||||
}
|
||||
else
|
||||
@@ -949,6 +951,7 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro,
|
||||
exp = BUFF_FRONT (pfile->a_buff);
|
||||
block = (struct block *) (exp + macro->count);
|
||||
macro->exp.text = exp;
|
||||
macro->traditional = 1;
|
||||
|
||||
/* Write out the block information. */
|
||||
block->text_len = len;
|
||||
|
||||
Reference in New Issue
Block a user