|  | /* Part of CPP library.  (Precompiled header reading/writing.) | 
|  | Copyright (C) 2000-2020 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 3, 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; see the file COPYING3.  If not see | 
|  | <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #include "config.h" | 
|  | #include "system.h" | 
|  | #include "cpplib.h" | 
|  | #include "internal.h" | 
|  | #include "hashtab.h" | 
|  | #include "mkdeps.h" | 
|  |  | 
|  | static int write_macdef (cpp_reader *, cpp_hashnode *, void *); | 
|  | static int save_idents (cpp_reader *, cpp_hashnode *, void *); | 
|  | static hashval_t hashmem (const void *, size_t); | 
|  | static hashval_t cpp_string_hash (const void *); | 
|  | static int cpp_string_eq (const void *, const void *); | 
|  | static int count_defs (cpp_reader *, cpp_hashnode *, void *); | 
|  | 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 | 
|  | { | 
|  | unsigned int definition_length; | 
|  | unsigned short name_length; | 
|  | unsigned short flags; | 
|  | }; | 
|  |  | 
|  | /* This is how we write out a macro definition. | 
|  | Suitable for being called by cpp_forall_identifiers.  */ | 
|  |  | 
|  | static int | 
|  | write_macdef (cpp_reader *pfile, cpp_hashnode *hn, void *file_p) | 
|  | { | 
|  | FILE *f = (FILE *) file_p; | 
|  | bool is_void = false; | 
|  | switch (hn->type) | 
|  | { | 
|  | case NT_VOID: | 
|  | if (! (hn->flags & NODE_POISONED)) | 
|  | return 1; | 
|  | is_void = true; | 
|  | goto poisoned; | 
|  |  | 
|  | case NT_BUILTIN_MACRO: | 
|  | return 1; | 
|  |  | 
|  | case NT_USER_MACRO: | 
|  | if (hn->value.macro->kind != cmk_assert) | 
|  | { | 
|  | poisoned: | 
|  | struct macrodef_struct s; | 
|  | const unsigned char *defn; | 
|  |  | 
|  | s.name_length = NODE_LEN (hn); | 
|  | s.flags = hn->flags & NODE_POISONED; | 
|  |  | 
|  | if (is_void) | 
|  | { | 
|  | defn = NODE_NAME (hn); | 
|  | s.definition_length = s.name_length; | 
|  | } | 
|  | else | 
|  | { | 
|  | defn = cpp_macro_definition (pfile, hn); | 
|  | s.definition_length = ustrlen (defn); | 
|  | } | 
|  |  | 
|  | if (fwrite (&s, sizeof (s), 1, f) != 1 | 
|  | || fwrite (defn, 1, s.definition_length, f) != s.definition_length) | 
|  | { | 
|  | cpp_errno (pfile, CPP_DL_ERROR, | 
|  | "while writing precompiled header"); | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | return 1; | 
|  |  | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* This structure records the names of the defined macros. | 
|  | It's also used as a callback structure for size_initial_idents | 
|  | and save_idents.  */ | 
|  |  | 
|  | struct cpp_savedstate | 
|  | { | 
|  | /* A hash table of the defined identifiers.  */ | 
|  | htab_t definedhash; | 
|  | /* The size of the definitions of those identifiers (the size of | 
|  | 'definedstrs').  */ | 
|  | size_t hashsize; | 
|  | /* Number of definitions */ | 
|  | size_t n_defs; | 
|  | /* Array of definitions.  In cpp_write_pch_deps it is used for sorting.  */ | 
|  | cpp_hashnode **defs; | 
|  | /* Space for the next definition.  Definitions are null-terminated | 
|  | strings.  */ | 
|  | unsigned char *definedstrs; | 
|  | }; | 
|  |  | 
|  | /* Save this identifier into the state: put it in the hash table, | 
|  | put the definition in 'definedstrs'.  */ | 
|  |  | 
|  | static int | 
|  | save_idents (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p) | 
|  | { | 
|  | struct cpp_savedstate *const ss = (struct cpp_savedstate *)ss_p; | 
|  |  | 
|  | if (hn->type != NT_VOID) | 
|  | { | 
|  | struct cpp_string news; | 
|  | void **slot; | 
|  |  | 
|  | news.len = NODE_LEN (hn); | 
|  | news.text= NODE_NAME (hn); | 
|  | slot = htab_find_slot (ss->definedhash, &news, INSERT); | 
|  | if (*slot == NULL) | 
|  | { | 
|  | struct cpp_string *sp; | 
|  | unsigned char *text; | 
|  |  | 
|  | sp = XNEW (struct cpp_string); | 
|  | *slot = sp; | 
|  |  | 
|  | sp->len = NODE_LEN (hn); | 
|  | sp->text = text = XNEWVEC (unsigned char, NODE_LEN (hn)); | 
|  | memcpy (text, NODE_NAME (hn), NODE_LEN (hn)); | 
|  | } | 
|  | } | 
|  |  | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | /* Hash some memory in a generic way.  */ | 
|  |  | 
|  | static hashval_t | 
|  | hashmem (const void *p_p, size_t sz) | 
|  | { | 
|  | const unsigned char *p = (const unsigned char *)p_p; | 
|  | size_t i; | 
|  | hashval_t h; | 
|  |  | 
|  | h = 0; | 
|  | for (i = 0; i < sz; i++) | 
|  | h = h * 67 - (*p++ - 113); | 
|  | return h; | 
|  | } | 
|  |  | 
|  | /* Hash a cpp string for the hashtable machinery.  */ | 
|  |  | 
|  | static hashval_t | 
|  | cpp_string_hash (const void *a_p) | 
|  | { | 
|  | const struct cpp_string *a = (const struct cpp_string *) a_p; | 
|  | return hashmem (a->text, a->len); | 
|  | } | 
|  |  | 
|  | /* Compare two cpp strings for the hashtable machinery.  */ | 
|  |  | 
|  | static int | 
|  | cpp_string_eq (const void *a_p, const void *b_p) | 
|  | { | 
|  | const struct cpp_string *a = (const struct cpp_string *) a_p; | 
|  | const struct cpp_string *b = (const struct cpp_string *) b_p; | 
|  | return (a->len == b->len | 
|  | && memcmp (a->text, b->text, a->len) == 0); | 
|  | } | 
|  |  | 
|  | /* Free memory associated with cpp_string.  */ | 
|  |  | 
|  | static void | 
|  | cpp_string_free (void *a_p) | 
|  | { | 
|  | struct cpp_string *a = (struct cpp_string *) a_p; | 
|  | free ((void *) a->text); | 
|  | free (a); | 
|  | } | 
|  |  | 
|  | /* Save the current definitions of the cpp_reader for dependency | 
|  | checking purposes.  When writing a precompiled header, this should | 
|  | be called at the same point in the compilation as cpp_valid_state | 
|  | would be called when reading the precompiled header back in.  */ | 
|  |  | 
|  | int | 
|  | cpp_save_state (cpp_reader *r, FILE *f) | 
|  | { | 
|  | /* Save the list of non-void identifiers for the dependency checking.  */ | 
|  | r->savedstate = XNEW (struct cpp_savedstate); | 
|  | r->savedstate->definedhash = htab_create (100, cpp_string_hash, | 
|  | cpp_string_eq, cpp_string_free); | 
|  | cpp_forall_identifiers (r, save_idents, r->savedstate); | 
|  |  | 
|  | /* Write out the list of defined identifiers.  */ | 
|  | cpp_forall_identifiers (r, write_macdef, f); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Calculate the 'hashsize' field of the saved state.  */ | 
|  |  | 
|  | static int | 
|  | count_defs (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p) | 
|  | { | 
|  | struct cpp_savedstate *const ss = (struct cpp_savedstate *)ss_p; | 
|  |  | 
|  | switch (hn->type) | 
|  | { | 
|  | case NT_BUILTIN_MACRO: | 
|  | return 1; | 
|  |  | 
|  | case NT_USER_MACRO: | 
|  | if (hn->value.macro->kind == cmk_assert) | 
|  | return 1; | 
|  |  | 
|  | /* fall through.  */ | 
|  |  | 
|  | case NT_VOID: | 
|  | { | 
|  | struct cpp_string news; | 
|  | void **slot; | 
|  |  | 
|  | news.len = NODE_LEN (hn); | 
|  | news.text = NODE_NAME (hn); | 
|  | slot = (void **) htab_find (ss->definedhash, &news); | 
|  | if (slot == NULL) | 
|  | { | 
|  | ss->hashsize += NODE_LEN (hn) + 1; | 
|  | ss->n_defs += 1; | 
|  | } | 
|  | } | 
|  | return 1; | 
|  |  | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Collect the identifiers into the state's string table.  */ | 
|  | static int | 
|  | write_defs (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p) | 
|  | { | 
|  | struct cpp_savedstate *const ss = (struct cpp_savedstate *)ss_p; | 
|  |  | 
|  | switch (hn->type) | 
|  | { | 
|  | case NT_BUILTIN_MACRO: | 
|  | return 1; | 
|  |  | 
|  | case NT_USER_MACRO: | 
|  | if (hn->value.macro->kind == cmk_assert) | 
|  | return 1; | 
|  |  | 
|  | /* fall through.  */ | 
|  |  | 
|  | case NT_VOID: | 
|  | { | 
|  | struct cpp_string news; | 
|  | void **slot; | 
|  |  | 
|  | news.len = NODE_LEN (hn); | 
|  | news.text = NODE_NAME (hn); | 
|  | slot = (void **) htab_find (ss->definedhash, &news); | 
|  | if (slot == NULL) | 
|  | { | 
|  | ss->defs[ss->n_defs] = hn; | 
|  | ss->n_defs += 1; | 
|  | } | 
|  | } | 
|  | return 1; | 
|  |  | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Comparison function for qsort.  The arguments point to pointers of | 
|  | type ht_hashnode *.  */ | 
|  | static int | 
|  | comp_hashnodes (const void *px, const void *py) | 
|  | { | 
|  | cpp_hashnode *x = *(cpp_hashnode **) px; | 
|  | cpp_hashnode *y = *(cpp_hashnode **) py; | 
|  | return ustrcmp (NODE_NAME (x), NODE_NAME (y)); | 
|  | } | 
|  |  | 
|  | /* Write out the remainder of the dependency information.  This should be | 
|  | called after the PCH is ready to be saved.  */ | 
|  |  | 
|  | int | 
|  | cpp_write_pch_deps (cpp_reader *r, FILE *f) | 
|  | { | 
|  | struct macrodef_struct z; | 
|  | struct cpp_savedstate *const ss = r->savedstate; | 
|  | unsigned char *definedstrs; | 
|  | size_t i; | 
|  |  | 
|  | /* Collect the list of identifiers which have been seen and | 
|  | weren't defined to anything previously.  */ | 
|  | ss->hashsize = 0; | 
|  | ss->n_defs = 0; | 
|  | cpp_forall_identifiers (r, count_defs, ss); | 
|  |  | 
|  | ss->defs = XNEWVEC (cpp_hashnode *, ss->n_defs); | 
|  | ss->n_defs = 0; | 
|  | cpp_forall_identifiers (r, write_defs, ss); | 
|  |  | 
|  | /* Sort the list, copy it into a buffer, and write it out.  */ | 
|  | qsort (ss->defs, ss->n_defs, sizeof (cpp_hashnode *), &comp_hashnodes); | 
|  | definedstrs = ss->definedstrs = XNEWVEC (unsigned char, ss->hashsize); | 
|  | for (i = 0; i < ss->n_defs; ++i) | 
|  | { | 
|  | size_t len = NODE_LEN (ss->defs[i]); | 
|  | memcpy (definedstrs, NODE_NAME (ss->defs[i]), len + 1); | 
|  | definedstrs += len + 1; | 
|  | } | 
|  |  | 
|  | memset (&z, 0, sizeof (z)); | 
|  | z.definition_length = ss->hashsize; | 
|  | if (fwrite (&z, sizeof (z), 1, f) != 1 | 
|  | || fwrite (ss->definedstrs, ss->hashsize, 1, f) != 1) | 
|  | { | 
|  | cpp_errno (r, CPP_DL_ERROR, "while writing precompiled header"); | 
|  | return -1; | 
|  | } | 
|  | free (ss->definedstrs); | 
|  | free (ss->defs); | 
|  | htab_delete (ss->definedhash); | 
|  |  | 
|  | /* Free the saved state.  */ | 
|  | free (ss); | 
|  | r->savedstate = NULL; | 
|  |  | 
|  | /* Save the next value of __COUNTER__. */ | 
|  | if (fwrite (&r->counter, sizeof (r->counter), 1, f) != 1) | 
|  | { | 
|  | cpp_errno (r, CPP_DL_ERROR, "while writing precompiled header"); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Write out the definitions of the preprocessor, in a form suitable for | 
|  | cpp_read_state.  */ | 
|  |  | 
|  | int | 
|  | cpp_write_pch_state (cpp_reader *r, FILE *f) | 
|  | { | 
|  | if (!r->deps) | 
|  | r->deps = deps_init (); | 
|  |  | 
|  | if (deps_save (r->deps, f) != 0) | 
|  | { | 
|  | cpp_errno (r, CPP_DL_ERROR, "while writing precompiled header"); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if (! _cpp_save_file_entries (r, f)) | 
|  | { | 
|  | cpp_errno (r, CPP_DL_ERROR, "while writing precompiled header"); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* Save the next __COUNTER__ value.  When we include a precompiled header, | 
|  | we need to start at the offset we would have if the header had been | 
|  | included normally. */ | 
|  | if (fwrite (&r->counter, sizeof (r->counter), 1, f) != 1) | 
|  | { | 
|  | cpp_errno (r, CPP_DL_ERROR, "while writing precompiled header"); | 
|  | 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; | 
|  | 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); | 
|  | memset (p, 0, sizeof (struct def_pragma_macro)); | 
|  | p->name = XNEWVAR (char, nlen + 1); | 
|  | p->name[nlen] = 0; | 
|  | if (fread (p->name, nlen, 1, f) != 1) | 
|  | return 0; | 
|  | if (fread (&defnlen, sizeof (defnlen), 1, f) != 1) | 
|  | return 0; | 
|  | if (defnlen == 0) | 
|  | p->is_undef = 1; | 
|  | else | 
|  | { | 
|  | defn = XNEWVEC (uchar, defnlen + 1); | 
|  | defn[defnlen] = 0; | 
|  |  | 
|  | if (fread (defn, defnlen, 1, f) != 1) | 
|  | return 0; | 
|  |  | 
|  | p->definition = defn; | 
|  | if (fread (&(p->line), sizeof (location_t), 1, f) != 1) | 
|  | return 0; | 
|  | defnlen = 0; | 
|  | if (fread (&defnlen, sizeof (defnlen), 1, f) != 1) | 
|  | return 0; | 
|  | p->syshdr = ((defnlen & 1) != 0 ? 1 : 0); | 
|  | p->used =  ((defnlen & 2) != 0 ? 1 : 0); | 
|  | } | 
|  |  | 
|  | p->next = r->pushed_macros; | 
|  | r->pushed_macros = p; | 
|  | } | 
|  | 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; | 
|  | size_t defnlen; | 
|  |  | 
|  | /* 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++) | 
|  | { | 
|  | defnlen = strlen (pp[i]->name); | 
|  | if (fwrite (&defnlen, sizeof (size_t), 1, f) != 1 | 
|  | || fwrite (pp[i]->name, defnlen, 1, f) != 1) | 
|  | return 0; | 
|  | if (pp[i]->is_undef) | 
|  | { | 
|  | defnlen = 0; | 
|  | if (fwrite (&defnlen, sizeof (size_t), 1, f) != 1) | 
|  | return 0; | 
|  | } | 
|  | else | 
|  | { | 
|  | defnlen = ustrlen (pp[i]->definition); | 
|  | if (fwrite (&defnlen, sizeof (size_t), 1, f) != 1 | 
|  | || fwrite (pp[i]->definition, defnlen, 1, f) != 1) | 
|  | return 0; | 
|  | if (fwrite (&(pp[i]->line), sizeof (location_t), 1, f) != 1) | 
|  | return 0; | 
|  | defnlen = 0; | 
|  | defnlen |= (pp[i]->syshdr != 0 ? 1 : 0); | 
|  | defnlen |= (pp[i]->used != 0 ? 2 : 0); | 
|  | if (fwrite (&defnlen, sizeof (defnlen), 1, f) != 1) | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | return 1; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Data structure to transform hash table nodes into a sorted list */ | 
|  |  | 
|  | struct ht_node_list | 
|  | { | 
|  | /* Array of nodes */ | 
|  | cpp_hashnode **defs; | 
|  | /* Number of nodes in the array */ | 
|  | size_t n_defs; | 
|  | /* Size of the allocated array */ | 
|  | size_t asize; | 
|  | }; | 
|  |  | 
|  | /* Callback for collecting identifiers from hash table */ | 
|  |  | 
|  | static int | 
|  | collect_ht_nodes (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, | 
|  | void *nl_p) | 
|  | { | 
|  | struct ht_node_list *const nl = (struct ht_node_list *)nl_p; | 
|  |  | 
|  | if (hn->type != NT_VOID || hn->flags & NODE_POISONED) | 
|  | { | 
|  | if (nl->n_defs == nl->asize) | 
|  | { | 
|  | nl->asize *= 2; | 
|  | nl->defs = XRESIZEVEC (cpp_hashnode *, nl->defs, nl->asize); | 
|  | } | 
|  |  | 
|  | nl->defs[nl->n_defs] = hn; | 
|  | ++nl->n_defs; | 
|  | } | 
|  | return 1; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Return nonzero if FD is a precompiled header which is consistent | 
|  | with the preprocessor's current definitions.  It will be consistent | 
|  | when: | 
|  |  | 
|  | - anything that was defined just before the PCH was generated | 
|  | is defined the same way now; and | 
|  | - anything that was not defined then, but is defined now, was not | 
|  | used by the PCH. | 
|  |  | 
|  | NAME is used to print warnings if `warn_invalid_pch' is set in the | 
|  | reader's flags. | 
|  | */ | 
|  |  | 
|  | int | 
|  | cpp_valid_state (cpp_reader *r, const char *name, int fd) | 
|  | { | 
|  | struct macrodef_struct m; | 
|  | size_t namebufsz = 256; | 
|  | unsigned char *namebuf = XNEWVEC (unsigned char, namebufsz); | 
|  | unsigned char *undeftab = NULL; | 
|  | struct ht_node_list nl = { 0, 0, 0 }; | 
|  | unsigned char *first, *last; | 
|  | unsigned int i; | 
|  | unsigned int counter; | 
|  |  | 
|  | /* Read in the list of identifiers that must be defined | 
|  | Check that they are defined in the same way.  */ | 
|  | for (;;) | 
|  | { | 
|  | cpp_hashnode *h; | 
|  | const unsigned char *newdefn; | 
|  |  | 
|  | if (read (fd, &m, sizeof (m)) != sizeof (m)) | 
|  | goto error; | 
|  |  | 
|  | if (m.name_length == 0) | 
|  | break; | 
|  |  | 
|  | /* If this file is already preprocessed, there won't be any | 
|  | macros defined, and that's OK.  */ | 
|  | if (CPP_OPTION (r, preprocessed)) | 
|  | { | 
|  | if (lseek (fd, m.definition_length, SEEK_CUR) == -1) | 
|  | goto error; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | if (m.definition_length > namebufsz) | 
|  | { | 
|  | free (namebuf); | 
|  | namebufsz = m.definition_length + 256; | 
|  | namebuf = XNEWVEC (unsigned char, namebufsz); | 
|  | } | 
|  |  | 
|  | if ((size_t)read (fd, namebuf, m.definition_length) | 
|  | != m.definition_length) | 
|  | goto error; | 
|  |  | 
|  | h = cpp_lookup (r, namebuf, m.name_length); | 
|  | if (m.flags & NODE_POISONED | 
|  | || h->flags & NODE_POISONED) | 
|  | { | 
|  | if (CPP_OPTION (r, warn_invalid_pch)) | 
|  | cpp_warning_syshdr (r, CPP_W_INVALID_PCH, | 
|  | "%s: not used because `%.*s' is poisoned", | 
|  | name, m.name_length, namebuf); | 
|  | goto fail; | 
|  | } | 
|  |  | 
|  | if (h->type == NT_VOID) | 
|  | { | 
|  | /* It's ok if __GCC_HAVE_DWARF2_CFI_ASM becomes undefined, | 
|  | as in, when the PCH file is created with -g and we're | 
|  | attempting to use it without -g.  Restoring the PCH file | 
|  | is supposed to bring in this definition *and* enable the | 
|  | generation of call frame information, so that precompiled | 
|  | definitions that take this macro into account, to decide | 
|  | what asm to emit, won't issue .cfi directives when the | 
|  | compiler doesn't.  */ | 
|  | if (!(h->flags & NODE_USED) | 
|  | && m.name_length == sizeof ("__GCC_HAVE_DWARF2_CFI_ASM") - 1 | 
|  | && !memcmp (namebuf, "__GCC_HAVE_DWARF2_CFI_ASM", m.name_length)) | 
|  | continue; | 
|  |  | 
|  | if (CPP_OPTION (r, warn_invalid_pch)) | 
|  | cpp_warning_syshdr (r, CPP_W_INVALID_PCH, | 
|  | "%s: not used because `%.*s' not defined", | 
|  | name, m.name_length, namebuf); | 
|  | goto fail; | 
|  | } | 
|  |  | 
|  | newdefn = cpp_macro_definition (r, h); | 
|  |  | 
|  | if (m.definition_length != ustrlen (newdefn) | 
|  | || memcmp (namebuf, newdefn, m.definition_length) != 0) | 
|  | { | 
|  | if (CPP_OPTION (r, warn_invalid_pch)) | 
|  | cpp_warning_syshdr (r, CPP_W_INVALID_PCH, | 
|  | "%s: not used because `%.*s' defined as `%s' not `%.*s'", | 
|  | name, m.name_length, namebuf, newdefn + m.name_length, | 
|  | m.definition_length - m.name_length, | 
|  | namebuf +  m.name_length); | 
|  | goto fail; | 
|  | } | 
|  | } | 
|  | free (namebuf); | 
|  | namebuf = NULL; | 
|  |  | 
|  | /* Read in the list of identifiers that must not be defined. | 
|  | Check that they really aren't.  */ | 
|  | undeftab = XNEWVEC (unsigned char, m.definition_length); | 
|  | if ((size_t) read (fd, undeftab, m.definition_length) != m.definition_length) | 
|  | goto error; | 
|  |  | 
|  | /* Collect identifiers from the current hash table.  */ | 
|  | nl.n_defs = 0; | 
|  | nl.asize = 10; | 
|  | nl.defs = XNEWVEC (cpp_hashnode *, nl.asize); | 
|  | cpp_forall_identifiers (r, &collect_ht_nodes, &nl); | 
|  | qsort (nl.defs, nl.n_defs, sizeof (cpp_hashnode *), &comp_hashnodes); | 
|  |  | 
|  | /* Loop through nl.defs and undeftab, both of which are sorted lists. | 
|  | There should be no matches.  */ | 
|  | first = undeftab; | 
|  | last = undeftab + m.definition_length; | 
|  | i = 0; | 
|  |  | 
|  | while (first < last && i < nl.n_defs) | 
|  | { | 
|  | int cmp = ustrcmp (first, NODE_NAME (nl.defs[i])); | 
|  |  | 
|  | if (cmp < 0) | 
|  | first += ustrlen (first) + 1; | 
|  | else if (cmp > 0) | 
|  | ++i; | 
|  | else | 
|  | { | 
|  | if (CPP_OPTION (r, warn_invalid_pch)) | 
|  | cpp_warning_syshdr (r, CPP_W_INVALID_PCH, | 
|  | "%s: not used because `%s' is defined", | 
|  | name, first); | 
|  | goto fail; | 
|  | } | 
|  | } | 
|  |  | 
|  | free(nl.defs); | 
|  | nl.defs = NULL; | 
|  | free (undeftab); | 
|  | undeftab = NULL; | 
|  |  | 
|  | /* Read in the next value of __COUNTER__. | 
|  | Check that (a) __COUNTER__ was not used in the pch or (b) __COUNTER__ | 
|  | has not been used in this translation unit. */ | 
|  | if (read (fd, &counter, sizeof (counter)) != sizeof (counter)) | 
|  | goto error; | 
|  | if (counter && r->counter) | 
|  | { | 
|  | if (CPP_OPTION (r, warn_invalid_pch)) | 
|  | cpp_warning_syshdr (r, CPP_W_INVALID_PCH, | 
|  | "%s: not used because `__COUNTER__' is invalid", | 
|  | name); | 
|  | goto fail; | 
|  | } | 
|  |  | 
|  | /* We win!  */ | 
|  | return 0; | 
|  |  | 
|  | error: | 
|  | cpp_errno (r, CPP_DL_ERROR, "while reading precompiled header"); | 
|  |  | 
|  | fail: | 
|  | free (namebuf); | 
|  | free (undeftab); | 
|  | free (nl.defs); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | /* Save all the existing macros.  */ | 
|  |  | 
|  | struct save_macro_data | 
|  | { | 
|  | 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.  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, cpp_hashnode *h, void *data_p) | 
|  | { | 
|  | struct save_macro_data *data = (struct save_macro_data *)data_p; | 
|  |  | 
|  | if (cpp_user_macro_p (h)) | 
|  | { | 
|  | if (data->count == data->array_size) | 
|  | { | 
|  | data->array_size *= 2; | 
|  | data->defns = XRESIZEVEC (uchar *, data->defns, (data->array_size)); | 
|  | } | 
|  |  | 
|  | const uchar * defn = cpp_macro_definition (r, h); | 
|  | size_t defnlen = ustrlen (defn); | 
|  |  | 
|  | data->defns[data->count] = (uchar *) xmemdup (defn, defnlen, defnlen + 2); | 
|  | data->defns[data->count][defnlen] = '\n'; | 
|  | data->count++; | 
|  | } | 
|  |  | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | /* Prepare to restore the state, by saving the currently-defined | 
|  | macros in 'data'.  */ | 
|  |  | 
|  | void | 
|  | cpp_prepare_state (cpp_reader *r, struct save_macro_data **data) | 
|  | { | 
|  | struct save_macro_data *d = XNEW (struct save_macro_data); | 
|  |  | 
|  | d->array_size = 512; | 
|  | d->defns = XNEWVEC (uchar *, d->array_size); | 
|  | d->count = 0; | 
|  | cpp_forall_identifiers (r, save_macros, d); | 
|  | d->saved_pragmas = _cpp_save_pragma_names (r); | 
|  | *data = d; | 
|  | } | 
|  |  | 
|  | /* Given a precompiled header that was previously determined to be valid, | 
|  | apply all its definitions (and undefinitions) to the current state. | 
|  | DEPNAME is passed to deps_restore.  */ | 
|  |  | 
|  | int | 
|  | cpp_read_state (cpp_reader *r, const char *name, FILE *f, | 
|  | struct save_macro_data *data) | 
|  | { | 
|  | size_t i; | 
|  | struct lexer_state old_state; | 
|  | unsigned int counter; | 
|  |  | 
|  | /* Restore spec_nodes, which will be full of references to the old | 
|  | hashtable entries and so will now be invalid.  */ | 
|  | { | 
|  | struct spec_nodes *s = &r->spec_nodes; | 
|  | s->n_defined	= cpp_lookup (r, DSC("defined")); | 
|  | s->n_true		= cpp_lookup (r, DSC("true")); | 
|  | s->n_false		= cpp_lookup (r, DSC("false")); | 
|  | s->n__VA_ARGS__     = cpp_lookup (r, DSC("__VA_ARGS__")); | 
|  | s->n__VA_OPT__      = cpp_lookup (r, DSC("__VA_OPT__")); | 
|  | } | 
|  |  | 
|  | old_state = r->state; | 
|  | r->state.in_directive = 1; | 
|  | r->state.prevent_expansion = 1; | 
|  | r->state.angled_headers = 0; | 
|  |  | 
|  | /* Run through the carefully-saved macros, insert them.  */ | 
|  | for (i = 0; i < data->count; i++) | 
|  | { | 
|  | cpp_hashnode *h; | 
|  | size_t namelen; | 
|  | uchar *defn; | 
|  |  | 
|  | namelen = ustrcspn (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) | 
|  | { | 
|  | if (cpp_push_buffer (r, defn, ustrchr (defn, '\n') - defn, true) | 
|  | != NULL) | 
|  | { | 
|  | _cpp_clean_line (r); | 
|  | if (!_cpp_create_definition (r, h)) | 
|  | abort (); | 
|  | _cpp_pop_buffer (r); | 
|  | } | 
|  | else | 
|  | abort (); | 
|  | } | 
|  |  | 
|  | free (data->defns[i]); | 
|  | } | 
|  | r->state = old_state; | 
|  |  | 
|  | _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) | 
|  | goto error; | 
|  |  | 
|  | if (! _cpp_read_file_entries (r, f)) | 
|  | goto error; | 
|  |  | 
|  | if (fread (&counter, sizeof (counter), 1, f) != 1) | 
|  | goto error; | 
|  |  | 
|  | if (!r->counter) | 
|  | r->counter = counter; | 
|  |  | 
|  | /* Read pushed macros. */ | 
|  | if (! _cpp_restore_pushed_macros (r, f)) | 
|  | goto error; | 
|  | return 0; | 
|  |  | 
|  | error: | 
|  | cpp_errno (r, CPP_DL_ERROR, "while reading precompiled header"); | 
|  | return -1; | 
|  | } |