OSDN Git Service

* config/alpha/osf5.h (TARGET_LD_BUGGY_LDGP): New.
[pf3gnuchains/gcc-fork.git] / gcc / cpphash.c
index c39ca9f..9e15ab4 100644 (file)
@@ -1,4 +1,4 @@
-/* Part of CPP library.  (Macro handling.)
+/* Hash tables for the CPP library.
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
    1999, 2000 Free Software Foundation, Inc.
    Written by Per Bothner, 1994.
@@ -26,1564 +26,97 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #include "config.h"
 #include "system.h"
 #include "cpplib.h"
-#include "hashtab.h"
 #include "cpphash.h"
 
-#undef abort
+static cpp_hashnode *alloc_node PARAMS ((hash_table *));
 
-static unsigned int hash_HASHNODE PARAMS ((const void *));
-static int eq_HASHNODE           PARAMS ((const void *, const void *));
-static void del_HASHNODE         PARAMS ((void *));
-static int dump_hash_helper      PARAMS ((void **, void *));
+/* Return an identifier node for hashtable.c.  Used by cpplib except
+   when integrated with the C front ends.  */
 
-static void push_macro_expansion PARAMS ((cpp_reader *,
-                                         U_CHAR *, int, HASHNODE *));
-static int unsafe_chars                 PARAMS ((cpp_reader *, int, int));
-static int macro_cleanup        PARAMS ((cpp_buffer *, cpp_reader *));
-static enum cpp_ttype macarg    PARAMS ((cpp_reader *, int));
-static void special_symbol      PARAMS ((HASHNODE *, cpp_reader *));
-
-/* Initial hash table size.  (It can grow if necessary - see hashtab.c.)  */
-#define HASHSIZE 500
-
-/* The arglist structure is built by create_definition to tell
-   collect_expansion where the argument names begin.  That
-   is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist
-   would contain pointers to the strings x, y, and z.
-   collect_expansion would then build a DEFINITION node,
-   with reflist nodes pointing to the places x, y, and z had
-   appeared.  So the arglist is just convenience data passed
-   between these two routines.  It is not kept around after
-   the current #define has been processed and entered into the
-   hash table.  */
-
-struct arg
-{
-  const U_CHAR *name;
-  unsigned int len;
-  char rest_arg;
-};
-
-struct arglist
-{
-  U_CHAR *namebuf;
-  const struct arg *argv;
-  int argc;
-};
-
-
-static DEFINITION *collect_expansion PARAMS ((cpp_reader *, cpp_toklist *,
-                                             struct arglist *, unsigned int));
-static unsigned int collect_params PARAMS ((cpp_reader *, cpp_toklist *,
-                                           struct arglist *));
-
-static void warn_trad_stringify        PARAMS ((cpp_reader *, U_CHAR *, size_t,
-                                        unsigned int, const struct arg *));
-static int duplicate_arg_p PARAMS ((U_CHAR *, U_CHAR *));
-
-/* This structure represents one parsed argument in a macro call.
-   `raw' points to the argument text as written (`raw_length' is its length).
-   `expanded' points to the argument's macro-expansion
-   (its length is `expand_length').
-   `stringified_length' is the length the argument would have
-   if stringified.  */
-
-/* raw and expanded are relative to ARG_BASE */
-#define ARG_BASE ((pfile)->token_buffer)
-
-struct argdata
-{
-  /* Strings relative to pfile->token_buffer */
-  long raw, expanded, stringified;
-  int raw_length, expand_length;
-  int stringified_length;
-};
-
-/* Calculate hash of a string of length LEN.  */
-unsigned int
-_cpp_calc_hash (str, len)
-     const U_CHAR *str;
-     size_t len;
-{
-  size_t n = len;
-  unsigned int r = 0;
-
-  do
-    r = r * 67 + (*str++ - 113);
-  while (--n);
-  return r + len;
-}
-
-/* Calculate hash of a HASHNODE structure.  */
-static unsigned int
-hash_HASHNODE (x)
-     const void *x;
+static cpp_hashnode *
+alloc_node (table)
+     hash_table *table;
 {
-  const HASHNODE *h = (const HASHNODE *)x;
-  return h->hash;
-}
-
-/* Compare two HASHNODE structures.  */
-static int
-eq_HASHNODE (x, y)
-     const void *x;
-     const void *y;
-{
-  const HASHNODE *a = (const HASHNODE *)x;
-  const HASHNODE *b = (const HASHNODE *)y;
-
-  return (a->length == b->length
-         && !strncmp (a->name, b->name, a->length));
-}
-
-/* Destroy a HASHNODE.  */
-static void
-del_HASHNODE (x)
-     void *x;
-{
-  HASHNODE *h = (HASHNODE *)x;
+  cpp_hashnode *node;
   
-  if (h->type == T_MACRO)
-    _cpp_free_definition (h->value.defn);
-  else if (h->type == T_MCONST)
-    free ((void *) h->value.cpval);
-  free ((void *) h->name);
-  free (h);
-}
-
-/* Allocate and initialize a HASHNODE structure.
-   Caller must fill in the value field.  */
-
-HASHNODE *
-_cpp_make_hashnode (name, len, type, hash)
-     const U_CHAR *name;
-     size_t len;
-     enum node_type type;
-     unsigned long hash;
-{
-  HASHNODE *hp = (HASHNODE *) xmalloc (sizeof (HASHNODE));
-  U_CHAR *p = xmalloc (len + 1);
-
-  hp->type = type;
-  hp->length = len;
-  hp->name = p;
-  hp->hash = hash;
-
-  memcpy (p, name, len);
-  p[len] = 0;
-
-  return hp;
-}
-
-/* Find the hash node for name "name", which ends at the first
-   non-identifier char.
-
-   If LEN is >= 0, it is the length of the name.
-   Otherwise, compute the length now.  */
-
-HASHNODE *
-_cpp_lookup (pfile, name, len)
-     cpp_reader *pfile;
-     const U_CHAR *name;
-     int len;
-{
-  const U_CHAR *bp;
-  HASHNODE dummy;
-
-  if (len < 0)
-    {
-      for (bp = name; is_idchar (*bp); bp++);
-      len = bp - name;
-    }
-
-  dummy.name = name;
-  dummy.length = len;
-  dummy.hash = _cpp_calc_hash (name, len);
-
-  return (HASHNODE *) htab_find_with_hash (pfile->hashtab,
-                                          (void *)&dummy, dummy.hash);
-}
-
-/* Find the hashtable slot for name "name".  Used to insert or delete.  */
-
-HASHNODE **
-_cpp_lookup_slot (pfile, name, len, insert, hash)
-     cpp_reader *pfile;
-     const U_CHAR *name;
-     int len;
-     enum insert_option insert;
-     unsigned long *hash;
-{
-  const U_CHAR *bp;
-  HASHNODE dummy;
-  HASHNODE **slot;
-
-  if (len < 0)
-    {
-      for (bp = name; is_idchar (*bp); bp++)
-       ;
-
-      len = bp - name;
-    }
-
-  dummy.name = name;
-  dummy.length = len;
-  dummy.hash = _cpp_calc_hash (name, len);
-
-  slot = (HASHNODE **) htab_find_slot_with_hash (pfile->hashtab,
-                                                (void *) &dummy,
-                                                dummy.hash, insert);
-  if (insert)
-    *hash = dummy.hash;
-  return slot;
+  node = (cpp_hashnode *) obstack_alloc (&table->pfile->hash_ob,
+                                        sizeof (cpp_hashnode));
+  memset ((PTR) node, 0, sizeof (cpp_hashnode));
+  return node;
 }
 
-/* Init the hash table.  In here so it can see the hash and eq functions.  */
-void
-_cpp_init_macro_hash (pfile)
-     cpp_reader *pfile;
-{
-  pfile->hashtab = htab_create (HASHSIZE, hash_HASHNODE,
-                               eq_HASHNODE, del_HASHNODE);
-}
-
-/* Free a DEFINITION structure.  Used by delete_macro, and by
-   do_define when redefining macros.  */
+/* Set up the identifier hash table.  Use TABLE if non-null, otherwise
+   create our own.  */
 
 void
-_cpp_free_definition (d)
-     DEFINITION *d;
-{
-  struct reflist *ap, *nextap;
-
-  for (ap = d->pattern; ap != NULL; ap = nextap)
-    {
-      nextap = ap->next;
-      free (ap);
-    }
-  if (d->argnames)
-    free (d->argnames);
-  free (d);
-}
-
-static int
-macro_cleanup (pbuf, pfile)
-     cpp_buffer *pbuf;
-     cpp_reader *pfile ATTRIBUTE_UNUSED;
-{
-  HASHNODE *macro = pbuf->macro;
-  if (macro->type == T_DISABLED)
-    macro->type = T_MACRO;
-  if (macro->type != T_MACRO || pbuf->buf != macro->value.defn->expansion)
-    free ((PTR) pbuf->buf);
-  return 0;
-}
-
-/* Issue warnings for macro argument names seen inside strings.  */
-static void
-warn_trad_stringify (pfile, p, len, argc, argv)
-     cpp_reader *pfile;
-     U_CHAR *p;
-     size_t len;
-     unsigned int argc;
-     const struct arg *argv;
-     
-{
-  U_CHAR *limit;
-  unsigned int i;
-
-  limit = p + len;
-  for (;;)
-    {
-      while (p < limit && !is_idstart (*p)) p++;
-      if (p >= limit)
-       break;
-
-      for (i = 0; i < argc; i++)
-       if (!strncmp (p, argv[i].name, argv[i].len)
-           && ! is_idchar (p[argv[i].len]))
-         {
-           cpp_warning (pfile,
-               "macro argument \"%s\" would be stringified in traditional C",
-                        argv[i].name);
-           break;
-         }
-      p++;
-      while (p < limit && is_idchar (*p)) p++;
-      if (p >= limit)
-       break;
-    }
-}
-
-/* Read a replacement list for a macro, and build the DEFINITION
-   structure.  LIST contains the replacement list, beginning at
-   REPLACEMENT.  ARGLIST specifies the formal parameters to look for
-   in the text of the definition.  If ARGLIST is null, this is an
-   object-like macro; if it points to an empty arglist, this is a
-   function-like macro with no arguments.  */
-
-static DEFINITION *
-collect_expansion (pfile, list, arglist, replacement)
-     cpp_reader *pfile;
-     cpp_toklist *list;
-     struct arglist *arglist;
-     unsigned int replacement;
-{
-  DEFINITION *defn;
-  struct reflist *pat = 0, *endpat = 0;
-  enum cpp_ttype token;
-  long start, last;
-  unsigned int i;
-  int j, argc;
-  size_t len;
-  const struct arg *argv;
-  U_CHAR *tok, *exp;
-  enum { START = 0, NORM, ARG, STRIZE, PASTE } last_token = START;
-
-  if (arglist)
-    {
-      argv = arglist->argv;
-      argc = arglist->argc;
-    }
-  else
-    {
-      argv = 0;
-      argc = 0;
-    }
-
-  /* We copy the expansion text into the token_buffer, then out to
-     its proper home.  */
-  last = start = CPP_WRITTEN (pfile);
-  CPP_PUTS (pfile, "\r ", 2);
-
-  for (i = replacement; i < list->tokens_used; i++)
-    {
-      token = list->tokens[i].type;
-      tok = list->tokens[i].val.name.offset + list->namebuf;
-      len = list->tokens[i].val.name.len;
-      switch (token)
-       {
-       case CPP_POP:
-       case CPP_EOF:
-         cpp_ice (pfile, "EOF in collect_expansion");
-         /* fall through */
-       case CPP_VSPACE:
-         goto done;
-
-       case CPP_HASH:
-         /* # is not special in object-like macros.  It is special in
-            function-like macros with no args.  (6.10.3.2 para 1.)
-            However, it is not special after PASTE. (Implied by
-            6.10.3.3 para 4.)  */
-         if (arglist == NULL || last_token == PASTE)
-           goto norm;
-         last_token = STRIZE;
-         break;
-
-       case CPP_PASTE:
-         if (last_token == PASTE)
-           /* ## ## - the second ## is ordinary.  */
-           goto norm;
-         else if (last_token == START)
-           cpp_error (pfile, "`##' at start of macro definition");
-           
-         else if (last_token == ARG)
-           /* If the last token was an argument, mark it raw_after.  */
-           endpat->raw_after = 1;
-         else if (last_token == STRIZE)
-           /* Oops - that wasn't a stringify operator.  */
-           CPP_PUTC (pfile, '#');
-
-         last_token = PASTE;
-         break;
-
-       case CPP_STRING:
-       case CPP_CHAR:
-         if (argc && CPP_WTRADITIONAL (pfile))
-           warn_trad_stringify (pfile, tok, len, argc, argv);
-         goto norm;
-         
-       case CPP_NAME:
-         for (j = 0; j < argc; j++)
-           if (argv[j].len == len
-               && !strncmp (tok, argv[j].name, argv[j].len))
-             goto addref;
-
-         /* fall through */
-       default:
-       norm:
-         if (last_token == STRIZE)
-           cpp_error (pfile, "# is not followed by a macro argument name");
-         if (last_token != PASTE && last_token != START
-             && (list->tokens[i].flags & HSPACE_BEFORE))
-           CPP_PUTC (pfile, ' ');
-         CPP_PUTS (pfile, tok, len);
-         last_token = NORM;
-         break;
-       }
-      continue;
-
-    addref:
-      {
-       struct reflist *tpat;
-       if (last_token != PASTE && (list->tokens[i].flags & HSPACE_BEFORE))
-         CPP_PUTC (pfile, ' ');
-
-       /* Make a pat node for this arg and add it to the pat list */
-       tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
-       tpat->next = NULL;
-       tpat->raw_before = (last_token == PASTE);
-       tpat->raw_after = 0;
-       tpat->stringify = (last_token == STRIZE);
-       tpat->rest_args = argv[j].rest_arg;
-       tpat->argno = j;
-       tpat->nchars = CPP_WRITTEN (pfile) - last;
-
-       if (endpat == NULL)
-         pat = tpat;
-       else
-         endpat->next = tpat;
-       endpat = tpat;
-       last = CPP_WRITTEN (pfile);
-      }
-      last_token = ARG;
-    }
- done:
-
-  if (last_token == STRIZE)
-    cpp_error (pfile, "`#' is not followed by a macro argument name");
-  else if (last_token == PASTE)
-    cpp_error (pfile, "`##' at end of macro definition");
-
-    CPP_PUTS (pfile, "\r ", 2);
-  len = CPP_WRITTEN (pfile) - start;
-  CPP_SET_WRITTEN (pfile, start);
-
-  exp = (U_CHAR *) xmalloc (len + 1);
-  memcpy (exp, pfile->token_buffer + start, len);
-  exp[len] = '\0';
-
-  defn = (DEFINITION *) xmalloc (sizeof (DEFINITION));
-  defn->length = len;
-  defn->expansion = exp;
-  defn->pattern = pat;
-  defn->rest_args = argv && argv[argc - 1].rest_arg;
-  if (arglist)
-    {
-      defn->nargs = argc;
-      defn->argnames = arglist->namebuf;
-      if (argv)
-       free ((PTR) argv);
-    }
-  else
-    {
-      defn->nargs = -1;
-      defn->argnames = 0;
-    }
-  return defn;
-}
-
-/* Is argument NEW, which has just been added to the argument list,
-   a duplicate of a previous argument name?  */
-static int
-duplicate_arg_p (args, new)
-     U_CHAR *args, *new;
-{
-  size_t newlen = strlen (new) + 1;
-  size_t oldlen;
-
-  while (args < new)
-    {
-      oldlen = strlen (args) + 1;
-      if (!memcmp (args, new, MIN (oldlen, newlen)))
-       return 1;
-      args += oldlen;
-    }
-  return 0;
-}
-
-static unsigned int
-collect_params (pfile, list, arglist)
+_cpp_init_hashtable (pfile, table)
      cpp_reader *pfile;
-     cpp_toklist *list;
-     struct arglist *arglist;
+     hash_table *table;
 {
-  struct arg *argv = 0;
-  U_CHAR *namebuf, *p, *tok;
-  unsigned int len, argslen;
-  unsigned int argc, a, i, j;
-
-  /* The formal parameters list starts at token 1.  */
-  if (list->tokens[1].type != CPP_OPEN_PAREN)
-    {
-      cpp_ice (pfile, "first token = %d not %d in collect_formal_parameters",
-              list->tokens[1].type, CPP_OPEN_PAREN);
-      return 0;
-    }
-
-  /* Scan once and count the number of parameters; also check for
-     syntax errors here.  */
-  argc = 0;
-  argslen = 0;
-  for (i = 2; i < list->tokens_used; i++)
-    switch (list->tokens[i].type)
-      {
-      case CPP_NAME:
-       argslen += list->tokens[i].val.name.len + 1;
-       argc++;
-       break;
-      case CPP_COMMA:
-       break;
-      case CPP_CLOSE_PAREN:
-       goto scanned;
-      case CPP_VSPACE:
-       cpp_error_with_line (pfile, list->line, list->tokens[i].col,
-                            "missing right paren in macro argument list");
-       return 0;
-
-      default:
-       cpp_error_with_line (pfile, list->line, list->tokens[i].col,
-                            "syntax error in #define");
-       return 0;
-
-      case CPP_ELLIPSIS:
-       if (list->tokens[i-1].type != CPP_NAME)
-         {
-           argslen += sizeof "__VA_ARGS__";
-           argc++;
-         }
-       i++;
-       if (list->tokens[i].type != CPP_CLOSE_PAREN)
-         {
-           cpp_error_with_line (pfile, list->line, list->tokens[i].col,
-                                "another parameter follows \"...\"");
-           return 0;
-         }
-       goto scanned;
-      }
-
-  cpp_ice (pfile, "collect_params: unreachable - i=%d, ntokens=%d, type=%d",
-          i, list->tokens_used, list->tokens[i-1].type);
-  return 0;
-
- scanned:
-  if (argc == 0)       /* function-like macro, no arguments */
-    {
-      arglist->argc = 0;
-      arglist->argv = 0;
-      arglist->namebuf = 0;
-      return i + 1;
-    }
-  if (argslen == 0)
+  if (table == NULL)
     {
-      cpp_ice (pfile, "collect_params: argc=%d argslen=0", argc);
-      return 0;
+      pfile->our_hashtable = 1;
+      table = ht_create (13);  /* 8K (=2^13) entries.  */
+      table->alloc_node = (hashnode (*) PARAMS ((hash_table *))) alloc_node;
+      gcc_obstack_init (&pfile->hash_ob);
     }
 
-  /* Now allocate space and copy the suckers.  */
-  argv = (struct arg *) xmalloc (argc * sizeof (struct arg));
-  namebuf = (U_CHAR *) xmalloc (argslen);
-  p = namebuf;
-  a = 0;
-  for (j = 2; j < i; j++)
-    switch (list->tokens[j].type)
-      {
-      case CPP_NAME:
-       tok = list->tokens[j].val.name.offset + list->namebuf;
-       len = list->tokens[j].val.name.len;
-       memcpy (p, tok, len);
-       p[len] = '\0';
-       if (duplicate_arg_p (namebuf, p))
-         {
-           cpp_error (pfile, "duplicate macro argument name \"%s\"", tok);
-           a++;
-           break;
-         }
-       if (CPP_PEDANTIC (pfile) && CPP_OPTION (pfile, c99)
-           && len == sizeof "__VA_ARGS__" - 1
-           && !strcmp (p, "__VA_ARGS__"))
-         cpp_pedwarn (pfile,
-       "C99 does not permit use of __VA_ARGS__ as a macro argument name");
-       argv[a].len = len;
-       argv[a].name = p;
-       argv[a].rest_arg = 0;
-       p += len;
-       a++;
-       break;
-
-      case CPP_COMMA:
-       break;
-
-      case CPP_ELLIPSIS:
-       if (list->tokens[j-1].type != CPP_NAME)
-         {
-           if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, c99))
-             cpp_pedwarn (pfile, "C89 does not permit varargs macros");
-
-           argv[a].len = sizeof "__VA_ARGS__" - 1;
-           argv[a].name = p;
-           argv[a].rest_arg = 1;
-           strcpy (p, "__VA_ARGS__");
-         }
-       else
-         {
-           if (CPP_PEDANTIC (pfile))
-             cpp_pedwarn (pfile,
-                          "ISO C does not permit named varargs macros");
-           argv[a-1].rest_arg = 1;
-         }
-       break;
-
-      default:
-       cpp_ice (pfile, "collect_params: impossible token type %d",
-                list->tokens[j].type);
-      }
-
-  arglist->argc = argc;
-  arglist->argv = argv;
-  arglist->namebuf = namebuf;
-  return i + 1;
+  table->pfile = pfile;
+  pfile->hash_table = table;
 }
 
-/* Create a DEFINITION node for a macro.  The replacement text
-   (including formal parameters if present) is in LIST.  If FUNLIKE is
-   true, this is a function-like macro.  */
-
-DEFINITION *
-_cpp_create_definition (pfile, list, funlike)
-     cpp_reader *pfile;
-     cpp_toklist *list;
-     int funlike;
-{
-  struct arglist args;
-  DEFINITION *defn;
-  int replacement = 1;  /* replacement begins at this token */
-
-  if (funlike)
-    {
-      replacement = collect_params (pfile, list, &args);
-      if (replacement == 0)
-       return 0;
-    }
-
-  defn = collect_expansion (pfile, list, funlike ? &args : 0, replacement);
-  if (defn == 0)
-    return 0;
-
-  defn->file = CPP_BUFFER (pfile)->nominal_fname;
-  defn->line = list->line;
-  defn->col  = list->tokens[0].col;
-  return defn;
-}
-
-/*
- * Parse a macro argument and append the info on PFILE's token_buffer.
- * REST_ARGS means to absorb the rest of the args.
- * Return nonzero to indicate a syntax error.
- */
-
-static enum cpp_ttype
-macarg (pfile, rest_args)
-     cpp_reader *pfile;
-     int rest_args;
-{
-  int paren = 0;
-  enum cpp_ttype token;
-
-  /* Try to parse as much of the argument as exists at this
-     input stack level.  */
-  for (;;)
-    {
-      token = cpp_get_token (pfile);
-      switch (token)
-       {
-       case CPP_EOF:
-         return token;
-       case CPP_POP:
-         /* If we've hit end of file, it's an error (reported by caller).
-            Ditto if it's the end of cpp_expand_to_buffer text.
-            If we've hit end of macro, just continue.  */
-         if (!CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
-           return token;
-         break;
-       case CPP_OPEN_PAREN:
-         paren++;
-         break;
-       case CPP_CLOSE_PAREN:
-         if (--paren < 0)
-           goto found;
-         break;
-       case CPP_COMMA:
-         /* if we've returned to lowest level and
-            we aren't absorbing all args */
-         if (paren == 0 && rest_args == 0)
-           goto found;
-         break;
-       found:
-         /* Remove ',' or ')' from argument buffer.  */
-         CPP_ADJUST_WRITTEN (pfile, -1);
-         return token;
-       default:;
-       }
-    }
-}
-\f
-
-static const char * const monthnames[] =
-{
-  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
-};
-
-/* Place into PFILE a quoted string representing the string SRC.
-   Caller must reserve enough space in pfile->token_buffer.  */
+/* Tear down the identifier hash table.  */
 
 void
-_cpp_quote_string (pfile, src)
-     cpp_reader *pfile;
-     const char *src;
-{
-  U_CHAR c;
-
-  CPP_PUTC_Q (pfile, '\"');
-  for (;;)
-    switch ((c = *src++))
-      {
-      default:
-        if (ISPRINT (c))
-         CPP_PUTC_Q (pfile, c);
-       else
-         {
-           sprintf ((char *)CPP_PWRITTEN (pfile), "\\%03o", c);
-           CPP_ADJUST_WRITTEN (pfile, 4);
-         }
-       break;
-
-      case '\"':
-      case '\\':
-       CPP_PUTC_Q (pfile, '\\');
-       CPP_PUTC_Q (pfile, c);
-       break;
-      
-      case '\0':
-       CPP_PUTC_Q (pfile, '\"');
-       return;
-      }
-}
-
-/*
- * expand things like __FILE__.  Place the expansion into the output
- * buffer *without* rescanning.
- */
-
-#define DSC(str) (const U_CHAR *)str, sizeof str - 1
-static void
-special_symbol (hp, pfile)
-     HASHNODE *hp;
+_cpp_destroy_hashtable (pfile)
      cpp_reader *pfile;
 {
-  const char *buf;
-  cpp_buffer *ip;
-
-  switch (hp->type)
+  if (pfile->our_hashtable)
     {
-    case T_FILE:
-    case T_BASE_FILE:
-      ip = cpp_file_buffer (pfile);
-      if (ip == NULL)
-       {
-         CPP_PUTS (pfile, "\"\"", 2);
-         return;
-       }
-      if (hp->type == T_BASE_FILE)
-       while (CPP_PREV_BUFFER (ip) != NULL)
-         ip = CPP_PREV_BUFFER (ip);
-
-      buf = ip->nominal_fname;
-      CPP_RESERVE (pfile, 3 + 4 * strlen (buf));
-      _cpp_quote_string (pfile, buf);
-      return;
-
-    case T_INCLUDE_LEVEL:
-      {
-       int true_indepth = 0;
-       ip = cpp_file_buffer (pfile);
-       while (ip)
-         {
-           true_indepth++;
-           ip = CPP_PREV_BUFFER (ip);
-         }
-
-       CPP_RESERVE (pfile, 10);
-       sprintf (CPP_PWRITTEN (pfile), "%d", true_indepth);
-       CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
-       return;
-      }
-
-    case T_STDC:
-#ifdef STDC_0_IN_SYSTEM_HEADERS
-      ip = cpp_file_buffer (pfile);
-      if (ip && ip->system_header_p
-         && !cpp_defined (pfile, DSC("__STRICT_ANSI__")))
-       {
-         CPP_PUTC (pfile, '0');
-         return;
-       }
-#endif
-      /* else fall through */
-    case T_CONST:
-    case T_MCONST:
-    constant:
-      buf = hp->value.cpval;
-      if (!buf)
-       return;
-      if (*buf == '\0')
-       buf = "\r \r ";
-
-      CPP_PUTS (pfile, buf, strlen (buf));
-      return;
-
-    case T_SPECLINE:
-      ip = cpp_file_buffer (pfile);
-      if (ip == NULL)
-       {
-         CPP_PUTC (pfile, '0');
-         return;
-       }
-      CPP_RESERVE (pfile, 10);
-      sprintf (CPP_PWRITTEN (pfile), "%u", CPP_BUF_LINE (ip));
-      CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
-      return;
-
-    case T_DATE:
-    case T_TIME:
-      /* Generate both __DATE__ and __TIME__, stuff them into their
-        respective hash nodes, and mark the nodes T_MCONST so we
-        don't have to do this again.  We don't generate these strings
-        at init time because time() and localtime() are very slow on
-        some systems.  */
-      {
-       time_t tt = time (NULL);
-       struct tm *tb = localtime (&tt);
-       HASHNODE *d, *t;
-
-       if (hp->type == T_DATE)
-         d = hp, t = _cpp_lookup (pfile, DSC("__TIME__"));
-       else
-         t = hp, d = _cpp_lookup (pfile, DSC("__DATE__"));
-
-       d->value.cpval = xmalloc (sizeof "'Oct 11 1347'");
-       sprintf ((char *)d->value.cpval, "\"%s %2d %4d\"",
-                monthnames[tb->tm_mon], tb->tm_mday, tb->tm_year + 1900);
-       d->type = T_MCONST;
-
-       t->value.cpval = xmalloc (sizeof "'12:34:56'");
-       sprintf ((char *)t->value.cpval, "\"%02d:%02d:%02d\"",
-                tb->tm_hour, tb->tm_min, tb->tm_sec);
-       t->type = T_MCONST;
-       goto constant;
-      }
-
-    case T_POISON:
-      cpp_error (pfile, "attempt to use poisoned `%s'.", hp->name);
-      CPP_PUTC (pfile, '0');
-      break;
-
-    default:
-      cpp_ice (pfile, "invalid special hash type");
-      return;
+      free (pfile->hash_table);
+      obstack_free (&pfile->hash_ob, 0);
     }
 }
-#undef DSC
-
-/* Expand a macro call.
-   HP points to the symbol that is the macro being called.
-   Put the result of expansion onto the input stack
-   so that subsequent input by our caller will use it.
 
-   If macro wants arguments, caller has already verified that
-   an argument list follows; arguments come from the input stack.  */
+/* Returns the hash entry for the STR of length LEN, creating one
+   if necessary.  */
 
-void
-_cpp_macroexpand (pfile, hp)
+cpp_hashnode *
+cpp_lookup (pfile, str, len)
      cpp_reader *pfile;
-     HASHNODE *hp;
+     const unsigned char *str;
+     unsigned int len;
 {
-  int nargs;
-  DEFINITION *defn;
-  register U_CHAR *xbuf;
-  unsigned int start_line, start_column;
-  cpp_buffer *ip;
-  int xbuf_len;
-  struct argdata *args = 0;
-  long old_written = CPP_WRITTEN (pfile);
-  int rest_args, rest_zero = 0;
-  register int i;
-
-  ip = cpp_file_buffer (pfile);
-  if (ip)
-    {
-      start_line = CPP_BUF_LINE (ip);
-      start_column = CPP_BUF_COL (ip);
-    }
-  else
-    start_line = start_column = 0;
-
-  /* Check for and handle special symbols. */
-  if (hp->type != T_MACRO)
-    {
-      special_symbol (hp, pfile);
-      xbuf_len = CPP_WRITTEN (pfile) - old_written;
-      xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
-      CPP_SET_WRITTEN (pfile, old_written);
-      memcpy (xbuf, CPP_PWRITTEN (pfile), xbuf_len + 1);
-      push_macro_expansion (pfile, xbuf, xbuf_len, hp);
-      CPP_BUFFER (pfile)->has_escapes = 1;
-      return;
-    }
-
-  defn = hp->value.defn;
-  nargs = defn->nargs;
-  pfile->output_escapes++;
-
-  if (nargs >= 0)
-    {
-      enum cpp_ttype token;
-
-      args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
-
-      for (i = 0; i < nargs; i++)
-       {
-         args[i].raw = args[i].expanded = 0;
-         args[i].raw_length = 0;
-         args[i].expand_length = args[i].stringified_length = -1;
-       }
-
-      /* Parse all the macro args that are supplied.  I counts them.
-         The first NARGS args are stored in ARGS.
-         The rest are discarded.  If rest_args is set then we assume
-         macarg absorbed the rest of the args.  */
-      i = 0;
-      rest_args = 0;
-
-      /* Skip over the opening parenthesis.  */
-      CPP_OPTION (pfile, discard_comments)++;
-      pfile->no_macro_expand++;
-      pfile->no_directives++;
-
-      token = cpp_get_non_space_token (pfile);
-      if (token != CPP_OPEN_PAREN)
-       cpp_ice (pfile, "macroexpand: unexpected token %d (wanted LPAREN)",
-                token);
-      CPP_ADJUST_WRITTEN (pfile, -1);
-
-      token = CPP_EOF;
-      do
-       {
-         if (rest_args)
-           continue;
-         if (i < nargs || (nargs == 0 && i == 0))
-           {
-             /* if we are working on last arg which absorbs rest of args... */
-             if (i == nargs - 1 && defn->rest_args)
-               rest_args = 1;
-             args[i].raw = CPP_WRITTEN (pfile);
-             token = macarg (pfile, rest_args);
-             args[i].raw_length = CPP_WRITTEN (pfile) - args[i].raw;
-           }
-         else
-           token = macarg (pfile, 0);
-         if (token == CPP_EOF || token == CPP_POP)
-           cpp_error_with_line (pfile, start_line, start_column,
-                                "unterminated macro call");
-         i++;
-       }
-      while (token == CPP_COMMA);
-      CPP_OPTION (pfile, discard_comments)--;
-      pfile->no_macro_expand--;
-      pfile->no_directives--;
-      if (token != CPP_CLOSE_PAREN)
-       return;
-
-      /* foo ( ) is equivalent to foo () unless foo takes exactly one
-        argument, in which case the former is allowed and the latter
-        is not.  XXX C99 is silent on this rule, but it seems
-        inconsistent to me.  */
-      if (i == 1 && nargs != 1)
-       {
-         register U_CHAR *bp = ARG_BASE + args[0].raw;
-         register U_CHAR *lim = bp + args[0].raw_length;
-           while (bp != lim && is_space(*bp))
-             bp++;
-         if (bp == lim)
-           i = 0;
-       }
-
-      /* Don't output an error message if we have already output one for
-         a parse error above.  */
-      rest_zero = 0;
-      if (nargs == 0 && i > 0)
-       {
-         cpp_error (pfile, "arguments given to macro `%s'", hp->name);
-       }
-      else if (i < nargs)
-       {
-         /* the rest args token is allowed to absorb 0 tokens */
-         if (i == nargs - 1 && defn->rest_args)
-           rest_zero = 1;
-         else if (i == 0)
-           cpp_error (pfile, "macro `%s' used without args", hp->name);
-         else if (i == 1)
-           cpp_error (pfile, "macro `%s' used with just one arg", hp->name);
-         else
-           cpp_error (pfile, "macro `%s' used with only %d args",
-                      hp->name, i);
-       }
-      else if (i > nargs)
-       {
-         cpp_error (pfile,
-                    "macro `%s' used with too many (%d) args", hp->name, i);
-       }
-    }
-
-  /* If macro wants zero args, we parsed the arglist for checking only.
-     Read directly from the macro definition.  */
-  if (nargs <= 0)
-    {
-      xbuf = defn->expansion;
-      xbuf_len = defn->length;
-    }
-  else
-    {
-      register U_CHAR *exp = defn->expansion;
-      register int offset;     /* offset in expansion,
-                                  copied a piece at a time */
-      register int totlen;     /* total amount of exp buffer filled so far */
-
-      register struct reflist *ap, *last_ap;
-
-      /* Macro really takes args.  Compute the expansion of this call.  */
-
-      /* Compute length in characters of the macro's expansion.
-         Also count number of times each arg is used.  */
-      xbuf_len = defn->length;
-      for (ap = defn->pattern; ap != NULL; ap = ap->next)
-       {
-         if (ap->stringify)
-           {
-             register struct argdata *arg = &args[ap->argno];
-             /* Stringify if it hasn't already been */
-             if (arg->stringified_length < 0)
-               {
-                 int arglen = arg->raw_length;
-                 int escaped = 0;
-                 int in_string = 0;
-                 int c;
-                 /* Initially need_space is -1.  Otherwise, 1 means the
-                    previous character was a space, but we suppressed it;
-                    0 means the previous character was a non-space.  */
-                 int need_space = -1;
-                 i = 0;
-                 arg->stringified = CPP_WRITTEN (pfile);
-                 CPP_PUTC (pfile, '\"');       /* insert beginning quote */
-                 for (; i < arglen; i++)
-                   {
-                     c = (ARG_BASE + arg->raw)[i];
-
-                     if (!in_string)
-                       {
-                         /* Delete "\r " and "\r-" escapes.  */
-                         if (c == '\r')
-                           {
-                             i++;
-                             continue;
-                           }
-                         /* Internal sequences of whitespace are
-                            replaced by one space except within
-                            a string or char token. */
-                         else if (is_space(c))
-                           {
-                             if (need_space == 0)
-                               need_space = 1;
-                             continue;
-                           }
-                         else if (need_space > 0)
-                           CPP_PUTC (pfile, ' ');
-                         need_space = 0;
-                       }
-
-                     if (escaped)
-                       escaped = 0;
-                     else
-                       {
-                         if (c == '\\')
-                           escaped = 1;
-                         if (in_string)
-                           {
-                             if (c == in_string)
-                               in_string = 0;
-                           }
-                         else if (c == '\"' || c == '\'')
-                           in_string = c;
-                       }
-
-                     /* Escape these chars */
-                     if (c == '\"' || (in_string && c == '\\'))
-                       CPP_PUTC (pfile, '\\');
-                     if (ISPRINT (c))
-                       CPP_PUTC (pfile, c);
-                     else
-                       {
-                         CPP_RESERVE (pfile, 4);
-                         sprintf ((char *) CPP_PWRITTEN (pfile), "\\%03o",
-                                  (unsigned int) c);
-                         CPP_ADJUST_WRITTEN (pfile, 4);
-                       }
-                   }
-                 CPP_PUTC (pfile, '\"');       /* insert ending quote */
-                 arg->stringified_length
-                   = CPP_WRITTEN (pfile) - arg->stringified;
-               }
-             xbuf_len += args[ap->argno].stringified_length;
-           }
-         else if (ap->raw_before || ap->raw_after)
-           /* Add 4 for two \r-space markers to prevent
-              token concatenation.  */
-           xbuf_len += args[ap->argno].raw_length + 4;
-         else
-           {
-             /* We have an ordinary (expanded) occurrence of the arg.
-                So compute its expansion, if we have not already.  */
-             if (args[ap->argno].expand_length < 0)
-               {
-                 args[ap->argno].expanded = CPP_WRITTEN (pfile);
-                 _cpp_expand_to_buffer (pfile,
-                                        ARG_BASE + args[ap->argno].raw,
-                                        args[ap->argno].raw_length);
-
-                 args[ap->argno].expand_length
-                   = CPP_WRITTEN (pfile) - args[ap->argno].expanded;
-               }
-
-             /* Add 4 for two \r-space markers to prevent
-                token concatenation.  */
-             xbuf_len += args[ap->argno].expand_length + 4;
-           }
-       }
-
-      xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
-
-      /* Generate in XBUF the complete expansion
-         with arguments substituted in.
-         TOTLEN is the total size generated so far.
-         OFFSET is the index in the definition
-         of where we are copying from.  */
-      offset = totlen = 0;
-      for (last_ap = NULL, ap = defn->pattern; ap != NULL;
-          last_ap = ap, ap = ap->next)
-       {
-         register struct argdata *arg = &args[ap->argno];
-         int count_before = totlen;
-
-         /* Add chars to XBUF.  */
-         i = ap->nchars;
-         memcpy (&xbuf[totlen], &exp[offset], i);
-         totlen += i;
-         offset += i;
-
-         /* If followed by an empty rest arg with concatenation,
-            delete the last run of nonwhite chars.  */
-         if (rest_zero && totlen > count_before
-             && ((ap->rest_args && ap->raw_before)
-                 || (last_ap != NULL && last_ap->rest_args
-                     && last_ap->raw_after)))
-           {
-             /* Delete final whitespace.  */
-             while (totlen > count_before && is_space(xbuf[totlen - 1]))
-               totlen--;
-
-             /* Delete the nonwhites before them.  */
-             while (totlen > count_before && !is_space(xbuf[totlen - 1]))
-               totlen--;
-           }
-
-         if (ap->stringify != 0)
-           {
-             memcpy (xbuf + totlen, ARG_BASE + arg->stringified,
-                     arg->stringified_length);
-             totlen += arg->stringified_length;
-           }
-         else if (ap->raw_before || ap->raw_after)
-           {
-             U_CHAR *p1 = ARG_BASE + arg->raw;
-             U_CHAR *l1 = p1 + arg->raw_length;
-             if (ap->raw_before)
-               {
-                 /* Arg is concatenated before: delete leading whitespace,
-                    whitespace markers, and no-reexpansion markers.  */
-                 while (p1 != l1)
-                   {
-                     if (is_space(p1[0]))
-                       p1++;
-                     else if (p1[0] == '\r')
-                       p1 += 2;
-                     else
-                       break;
-                   }
-               }
-             if (ap->raw_after)
-               {
-                 /* Arg is concatenated after: delete trailing whitespace,
-                    whitespace markers, and no-reexpansion markers.  */
-                 while (p1 != l1)
-                   {
-                     if (is_space(l1[-1]))
-                       l1--;
-                     else if (l1[-1] == '\r')
-                       l1--;
-                     else if (l1[-1] == '-')
-                       {
-                         if (l1 != p1 + 1 && l1[-2] == '\r')
-                           l1 -= 2;
-                         else
-                           break;
-                       }
-                     else
-                       break;
-                   }
-               }
-
-             /* Delete any no-reexpansion marker that precedes
-                an identifier at the beginning of the argument. */
-             if (p1[0] == '\r' && p1[1] == '-')
-               p1 += 2;
-
-             memcpy (xbuf + totlen, p1, l1 - p1);
-             totlen += l1 - p1;
-           }
-         else
-           {
-             U_CHAR *expanded = ARG_BASE + arg->expanded;
-             if (!ap->raw_before && totlen > 0 && arg->expand_length
-                 && unsafe_chars (pfile, xbuf[totlen - 1], expanded[0]))
-               {
-                 xbuf[totlen++] = '\r';
-                 xbuf[totlen++] = ' ';
-               }
-
-             memcpy (xbuf + totlen, expanded, arg->expand_length);
-             totlen += arg->expand_length;
-
-             if (!ap->raw_after && totlen > 0 && offset < defn->length
-                 && unsafe_chars (pfile, xbuf[totlen - 1], exp[offset]))
-               {
-                 xbuf[totlen++] = '\r';
-                 xbuf[totlen++] = ' ';
-               }
-           }
-
-         if (totlen > xbuf_len)
-           {
-             cpp_ice (pfile, "buffer overrun in macroexpand");
-             return;
-           }
-       }
-
-      /* if there is anything left of the definition
-         after handling the arg list, copy that in too.  */
-
-      for (i = offset; i < defn->length; i++)
-       {
-         /* if we've reached the end of the macro */
-         if (exp[i] == ')')
-           rest_zero = 0;
-         if (!(rest_zero && last_ap != NULL && last_ap->rest_args
-               && last_ap->raw_after))
-           xbuf[totlen++] = exp[i];
-       }
-
-      xbuf[totlen] = 0;
-      xbuf_len = totlen;
-
-    }
-
-  pfile->output_escapes--;
-
-  /* Now put the expansion on the input stack
-     so our caller will commence reading from it.  */
-  push_macro_expansion (pfile, xbuf, xbuf_len, hp);
-  CPP_BUFFER (pfile)->has_escapes = 1;
-
-  /* Pop the space we've used in the token_buffer for argument expansion.  */
-  CPP_SET_WRITTEN (pfile, old_written);
-
-  /* Per C89, a macro cannot be expanded recursively.  */
-  hp->type = T_DISABLED;
+  /* ht_lookup cannot return NULL.  */
+  return CPP_HASHNODE (ht_lookup (pfile->hash_table, str, len, HT_ALLOC));
 }
 
-/* Return 1 iff a token ending in C1 followed directly by a token C2
-   could cause mis-tokenization.  */
-
-static int
-unsafe_chars (pfile, c1, c2)
-     cpp_reader *pfile;
-     int c1, c2;
-{
-  /* If c2 is EOF, that's always safe.  */
-  if (c2 == EOF)
-    return 0;
-
-  switch (c1)
-    {
-    case EOF:
-      /* We don't know what the previous character was.  We do know
-        that it can't have been an idchar (or else it would have been
-        pasted with the idchars of the macro name), and there are a
-        number of second characters for which it doesn't matter what
-        the first was.  */
-      if (is_idchar (c2) || c2 == '\'' || c2 == '\"'
-         || c2 == '(' || c2 == '[' || c2 == '{'
-         || c2 == ')' || c2 == ']' || c2 == '}')
-       return 0;
-      return 1;
-
-    case '+':  case '-':
-      if (c2 == c1 || c2 == '=')
-       return 1;
-      goto letter;
-
-    case 'e':  case 'E':  case 'p':  case 'P':
-      if (c2 == '-' || c2 == '+')
-       return 1;               /* could extend a pre-processing number */
-      goto letter;
-
-    case '$':
-      if (CPP_OPTION (pfile, dollars_in_ident))
-       goto letter;
-      return 0;
-
-    case 'L':
-      if (c2 == '\'' || c2 == '\"')
-       return 1;               /* Could turn into L"xxx" or L'xxx'.  */
-      goto letter;
-
-    case '.':  case '0':  case '1':  case '2':  case '3':
-    case '4':  case '5':  case '6':  case '7':  case '8':  case '9':
-    case '_':  case 'a':  case 'b':  case 'c':  case 'd':  case 'f':
-    case 'g':  case 'h':  case 'i':  case 'j':  case 'k':  case 'l':
-    case 'm':  case 'n':  case 'o':  case 'q':  case 'r':  case 's':
-    case 't':  case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
-    case 'z':  case 'A':  case 'B':  case 'C':  case 'D':  case 'F':
-    case 'G':  case 'H':  case 'I':  case 'J':  case 'K':  case 'M':
-    case 'N':  case 'O':  case 'Q':  case 'R':  case 'S':  case 'T':
-    case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':  case 'Z':
-    letter:
-    /* We're in the middle of either a name or a pre-processing number.  */
-      return (is_idchar(c2) || c2 == '.');
-
-    case '<':  case '>':  case '!':  case '%':  case '#':  case ':':
-    case '^':  case '&':  case '|':  case '*':  case '/':  case '=':
-      return (c2 == c1 || c2 == '=');
-    }
-  return 0;
-}
-
-static void
-push_macro_expansion (pfile, xbuf, len, hp)
-     cpp_reader *pfile;
-     register U_CHAR *xbuf;
-     int len;
-     HASHNODE *hp;
-{
-  cpp_buffer *mbuf;
-  int advance_cur = 0;
-
-  /* The first chars of the expansion should be a "\r " added by
-     collect_expansion.  This is to prevent accidental token-pasting
-     between the text preceding the macro invocation, and the macro
-     expansion text.
-
-     We would like to avoid adding unneeded spaces (for the sake of
-     tools that use cpp, such as imake).  In some common cases we can
-     tell that it is safe to omit the space.  */
-
-  if (xbuf[0] == '\r' && xbuf[1] == ' '
-      && !unsafe_chars (pfile, EOF, xbuf[2]))
-    advance_cur = 1;
-
-  /* Likewise, avoid the extra space at the end of the macro expansion
-     if this is safe.  We can do a better job here since we can know
-     what the next char will be.  */
-  if (len >= 3 && xbuf[len-2] == '\r' && xbuf[len-1] == ' '
-      && !unsafe_chars (pfile, xbuf[len-3], CPP_BUF_PEEK (CPP_BUFFER (pfile))))
-    len -= 2;
-
-  /* If the total expansion is "\r \r", we must not trim both escapes.  */
-  if (len == 2 && advance_cur)
-    advance_cur = 0;
-
-  mbuf = cpp_push_buffer (pfile, xbuf, len);
-  if (mbuf == NULL)
-    return;
-  if (advance_cur)
-    mbuf->cur += 2;
-  mbuf->cleanup = macro_cleanup;
-  mbuf->macro = hp;
-}
-
-/* Return zero if two DEFINITIONs are isomorphic.  */
+/* Determine whether the str STR, of length LEN, is a defined macro.  */
 
 int
-_cpp_compare_defs (pfile, d1, d2)
+cpp_defined (pfile, str, len)
      cpp_reader *pfile;
-     DEFINITION *d1, *d2;
-{
-  struct reflist *a1, *a2;
-
-  if (d1->nargs != d2->nargs)
-    return 1;
-  if (strcmp (d1->expansion, d2->expansion))
-    return 1;
-  if (CPP_PEDANTIC (pfile)
-      && d1->argnames && d2->argnames)
-    {
-      U_CHAR *arg1 = d1->argnames;
-      U_CHAR *arg2 = d2->argnames;
-      size_t len;
-      int i = d1->nargs;
-      while (i--)
-       {
-         len = strlen (arg1) + 1;
-         if (strcmp (arg1, arg2))
-           return 1;
-         arg1 += len;
-         arg2 += len;
-       }
-    }
-  for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
-       a1 = a1->next, a2 = a2->next)
-    {
-      if (a1->nchars != a2->nchars
-         || a1->argno != a2->argno
-         || a1->stringify != a2->stringify
-         || a1->raw_before != a2->raw_before
-         || a1->raw_after != a2->raw_after)
-       return 1;
-    }
-  if (a1 != a2)
-    return 1;
-
-  return 0;
-}
-
-/* Dump the definition of macro MACRO on stdout.  The format is suitable
-   to be read back in again. */
-
-void
-_cpp_dump_definition (pfile, sym, len, defn)
-     cpp_reader *pfile;
-     const U_CHAR *sym;
-     long len;
-     DEFINITION *defn;
+     const unsigned char *str;
+     int len;
 {
-  CPP_RESERVE (pfile, len + sizeof "#define ");
-  CPP_PUTS_Q (pfile, "#define ", sizeof "#define " -1);
-  CPP_PUTS_Q (pfile, sym, len);
-
-  if (defn->nargs == -1)
-    {
-      CPP_PUTC_Q (pfile, ' ');
-
-      /* The first and last two characters of a macro expansion are
-        always "\r "; this needs to be trimmed out.
-        So we need length-4 chars of space, plus one for the NUL.  */
-      CPP_RESERVE (pfile, defn->length - 4 + 1);
-      CPP_PUTS_Q (pfile, defn->expansion + 2, defn->length - 4);
-    }
-  else
-    {
-      struct reflist *r;
-      unsigned char **argv = (unsigned char **) alloca (defn->nargs *
-                                                       sizeof(char *));
-      int *argl = (int *) alloca (defn->nargs * sizeof(int));
-      unsigned char *x;
-      int i;
-
-      /* First extract the argument list. */
-      x = defn->argnames;
-      for (i = 0; i < defn->nargs; i++)
-       {
-         argv[i] = x;
-         argl[i] = strlen (x);
-         x += argl[i] + 1;
-       }
-      
-      /* Now print out the argument list. */
-      CPP_PUTC_Q (pfile, '(');
-      for (i = 0; i < defn->nargs; i++)
-       {
-         CPP_RESERVE (pfile, argl[i] + 2);
-         if (!(i == defn->nargs-1 && defn->rest_args
-               && !strcmp (argv[i], "__VA_ARGS__")))
-           CPP_PUTS_Q (pfile, argv[i], argl[i]);
-         if (i < defn->nargs-1)
-           CPP_PUTS_Q (pfile, ", ", 2);
-       }
-      if (defn->rest_args)
-       CPP_PUTS (pfile, "...", 3);
-      CPP_PUTS (pfile, ") ", 2);
-
-      /* Now the definition. */
-      x = defn->expansion;
-      for (r = defn->pattern; r; r = r->next)
-      {
-       i = r->nchars;
-       if (*x == '\r') x += 2, i -= 2;
-       /* i chars for macro text, plus the length of the macro
-          argument name, plus one for a stringify marker, plus two for
-          each concatenation marker. */
-       CPP_RESERVE (pfile,
-                    i + argl[r->argno] + r->stringify
-                    + (r->raw_before + r->raw_after) * 2);
-
-       if (i > 0) CPP_PUTS_Q (pfile, x, i);
-       if (r->raw_before)
-         CPP_PUTS_Q (pfile, "##", 2);
-       if (r->stringify)
-         CPP_PUTC_Q (pfile, '#');
-       CPP_PUTS_Q (pfile, argv[r->argno], argl[r->argno]);
-       if (r->raw_after && !(r->next && r->next->nchars == 0
-                             && r->next->raw_before))
-         CPP_PUTS_Q (pfile, "##", 2);
+  cpp_hashnode *node;
 
-       x += i;
-      }
+  node = CPP_HASHNODE (ht_lookup (pfile->hash_table, str, len, HT_NO_INSERT));
 
-      i = defn->length - (x - defn->expansion) - 2;
-      if (*x == '\r') x += 2, i -= 2;
-      if (i > 0) CPP_PUTS (pfile, x, i);
-    }
-  if (CPP_BUFFER (pfile) == 0 || ! pfile->done_initializing)
-    CPP_PUTC (pfile, '\n');
+  /* If it's of type NT_MACRO, it cannot be poisoned.  */
+  return node && node->type == NT_MACRO;
 }
 
-/* Dump out the hash table.  */
-static int
-dump_hash_helper (h, p)
-     void **h;
-     void *p;
-{
-  HASHNODE *hp = (HASHNODE *)*h;
-  cpp_reader *pfile = (cpp_reader *)p;
-
-  if (hp->type == T_MACRO)
-    _cpp_dump_definition (pfile, hp->name, hp->length, hp->value.defn);
-  return 1;
-}
+/* For all nodes in the hashtable, callback CB with parameters PFILE,
+   the node, and V.  */
 
 void
-_cpp_dump_macro_hash (pfile)
+cpp_forall_identifiers (pfile, cb, v)
      cpp_reader *pfile;
+     cpp_cb cb;
+     PTR v;
 {
-  htab_traverse (pfile->hashtab, dump_hash_helper, pfile);
+  /* We don't need a proxy since the hash table's identifier comes
+     first in cpp_hashnode.  */
+  ht_forall (pfile->hash_table, (ht_cb) cb, v);
 }