/* Part of CPP library. (Precompiled header reading/writing.)
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
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
+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,
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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+along with this program; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
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
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 */
h = cpp_lookup (r, namebuf, m.name_length);
if (m.flags & NODE_POISONED
- || h->type != NT_MACRO
|| h->flags & NODE_POISONED)
{
if (CPP_OPTION (r, warn_invalid_pch))
- cpp_error (r, CPP_DL_WARNING_SYSHDR,
- "%s: not used because `%.*s' not defined",
- name, m.name_length, namebuf);
+ 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_MACRO)
+ {
+ /* 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 accout, 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;
}
|| memcmp (namebuf, newdefn, m.definition_length) != 0)
{
if (CPP_OPTION (r, warn_invalid_pch))
- cpp_error (r, CPP_DL_WARNING_SYSHDR,
+ 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,
else
{
if (CPP_OPTION (r, warn_invalid_pch))
- cpp_error (r, CPP_DL_WARNING_SYSHDR,
- "%s: not used because `%s' is defined",
- name, first);
+ cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+ "%s: not used because `%s' is defined",
+ name, first);
goto fail;
}
}
if (counter && r->counter)
{
if (CPP_OPTION (r, warn_invalid_pch))
- cpp_error (r, CPP_DL_WARNING_SYSHDR,
- "%s: not used because `__COUNTER__' is invalid",
- name);
+ cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+ "%s: not used because `__COUNTER__' is invalid",
+ name);
goto fail;
}
if (!r->counter)
r->counter = counter;
+ /* Read pushed macros. */
+ if (! _cpp_restore_pushed_macros (r, f))
+ goto error;
return 0;
error: