Wolfgang Thallergcc16 merge934c3885 months agoHistory
970 lines · 26.1 KB · C++
RawDownload
/* Part of CPP library.  (Precompiled header reading/writing.)   Copyright (C) 2000-2026 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify itunder the terms of the GNU General Public License as published by theFree Software Foundation; either version 3, or (at your option) anylater version. This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details. You should have received a copy of the GNU General Public Licensealong 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 intwrite_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 intsave_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_thashmem (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_tcpp_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 intcpp_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 voidcpp_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.  */ intcpp_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 intcount_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 intwrite_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 intcomp_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.  */ intcpp_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.  */ intcpp_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);

Lines 1–500 of 970.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t