OSDN Git Service

* config/alpha/osf5.h (TARGET_LD_BUGGY_LDGP): New.
[pf3gnuchains/gcc-fork.git] / gcc / cpphash.c
index c7da2b3..9e15ab4 100644 (file)
@@ -1,5 +1,6 @@
-/* Part of CPP library.  (Macro handling.)
-   Copyright (C) 1986, 87, 89, 92-96, 98, 1999 Free Software Foundation, Inc.
+/* 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.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
    Written by Per Bothner, 1994.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -26,1733 +27,96 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #include "system.h"
 #include "cpplib.h"
 #include "cpphash.h"
 #include "system.h"
 #include "cpplib.h"
 #include "cpphash.h"
-#undef abort
 
 
-static int comp_def_part        PARAMS ((int, U_CHAR *, int, U_CHAR *,
-                                         int, int));
-static int change_newlines      PARAMS ((U_CHAR *, int));
-static void push_macro_expansion PARAMS ((cpp_reader *,
-                                         U_CHAR *, int, HASHNODE *));
-static int unsafe_chars                 PARAMS ((int, int));
-static int macro_cleanup        PARAMS ((cpp_buffer *, cpp_reader *));
-static enum cpp_token macarg    PARAMS ((cpp_reader *, int));
-static struct tm *timestamp     PARAMS ((cpp_reader *));
-static void special_symbol      PARAMS ((HASHNODE *, cpp_reader *));
+static cpp_hashnode *alloc_node PARAMS ((hash_table *));
 
 
+/* Return an identifier node for hashtable.c.  Used by cpplib except
+   when integrated with the C front ends.  */
 
 
-#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
-#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->data != NULL)
-#define FORWARD(N) CPP_FORWARD (CPP_BUFFER (pfile), (N))
-
-extern char *version_string;
-
-/* 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 arglist
+static cpp_hashnode *
+alloc_node (table)
+     hash_table *table;
 {
 {
-  struct arglist *next;
-  U_CHAR *name;
-  int length;
-  int argno;
-  char rest_args;
-};
-
-static DEFINITION *collect_expansion PARAMS ((cpp_reader *, U_CHAR *, U_CHAR *,
-                                             int, struct arglist *));
-
-/* 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.
-   `use_count' is the number of times this macro arg is substituted
-   into the macro.  If the actual use count exceeds 10, 
-   the value stored is 10.  */
-
-/* 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;
-  char newlines;
-  char use_count;
-};
-
-
-/* Return hash function on name.  must be compatible with the one
-   computed a step at a time, elsewhere  */
-
-int
-hashf (name, len, hashsize)
-     register const U_CHAR *name;
-     register int len;
-     int hashsize;
-{
-  register int r = 0;
-
-  while (len--)
-    r = HASHSTEP (r, *name++);
-
-  return MAKE_POS (r) % hashsize;
+  cpp_hashnode *node;
+  
+  node = (cpp_hashnode *) obstack_alloc (&table->pfile->hash_ob,
+                                        sizeof (cpp_hashnode));
+  memset ((PTR) node, 0, sizeof (cpp_hashnode));
+  return node;
 }
 
 }
 
-/* Find the most recent hash node for name "name" (ending with first
-   non-identifier char) installed by cpp_install
-
-   If LEN is >= 0, it is the length of the name.
-   Otherwise, compute the length by scanning the entire name.
-
-   If HASH is >= 0, it is the precomputed hash code.
-   Otherwise, compute the hash code.  */
-
-HASHNODE *
-cpp_lookup (pfile, name, len, hash)
-     cpp_reader *pfile ATTRIBUTE_UNUSED;
-     const U_CHAR *name;
-     int len;
-     int hash;
-{
-  register const U_CHAR *bp;
-  register HASHNODE *bucket;
-
-  if (len < 0)
-    {
-      for (bp = name; is_idchar[*bp]; bp++);
-      len = bp - name;
-    }
-
-  if (hash < 0)
-    hash = hashf (name, len, HASHSIZE);
-
-  bucket = pfile->hashtab[hash];
-  while (bucket)
-    {
-      if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
-       return bucket;
-      bucket = bucket->next;
-    }
-  return (HASHNODE *) 0;
-}
-
-/*
- * Delete a hash node.  Some weirdness to free junk from macros.
- * More such weirdness will have to be added if you define more hash
- * types that need it.
- */
-
-/* Note that the DEFINITION of a macro is removed from the hash table
-   but its storage is not freed.  This would be a storage leak
-   except that it is not reasonable to keep undefining and redefining
-   large numbers of macros many times.
-   In any case, this is necessary, because a macro can be #undef'd
-   in the middle of reading the arguments to a call to it.
-   If #undef freed the DEFINITION, that would crash.  */
+/* Set up the identifier hash table.  Use TABLE if non-null, otherwise
+   create our own.  */
 
 void
 
 void
-delete_macro (hp)
-     HASHNODE *hp;
-{
-
-  if (hp->prev != NULL)
-    hp->prev->next = hp->next;
-  if (hp->next != NULL)
-    hp->next->prev = hp->prev;
-
-  /* make sure that the bucket chain header that
-     the deleted guy was on points to the right thing afterwards.  */
-  if (hp == *hp->bucket_hdr)
-    *hp->bucket_hdr = hp->next;
-
-  if (hp->type == T_MACRO)
-    {
-      DEFINITION *d = hp->value.defn;
-      struct reflist *ap, *nextap;
-
-      for (ap = d->pattern; ap != NULL; ap = nextap)
-       {
-         nextap = ap->next;
-         free (ap);
-       }
-      if (d->nargs >= 0)
-       free (d->args.argnames);
-      free (d);
-    }
-
-  free (hp);
-}
-
-/* Install a name in the main hash table, even if it is already there.
-   Name stops with first non alphanumeric, except leading '#'.
-   Caller must check against redefinition if that is desired.
-   delete_macro () removes things installed by cpp_install () in fifo order.
-   this is important because of the `defined' special symbol used
-   in #if, and also if pushdef/popdef directives are ever implemented.
-
-   If LEN is >= 0, it is the length of the name.
-   Otherwise, compute the length by scanning the entire name.
-
-   If HASH is >= 0, it is the precomputed hash code.
-   Otherwise, compute the hash code.  */
-
-HASHNODE *
-cpp_install (pfile, name, len, type, value, hash)
-     cpp_reader *pfile;
-     const U_CHAR *name;
-     int len;
-     enum node_type type;
-     const char *value;
-     int hash;
-{
-  register HASHNODE *hp;
-  register int i, bucket;
-  register const U_CHAR *p;
-
-  if (len < 0)
-    {
-      p = name;
-      while (is_idchar[*p])
-       p++;
-      len = p - name;
-    }
-
-  if (hash < 0)
-    hash = hashf (name, len, HASHSIZE);
-
-  i = sizeof (HASHNODE) + len + 1;
-  hp = (HASHNODE *) xmalloc (i);
-  bucket = hash;
-  hp->bucket_hdr = &pfile->hashtab[bucket];
-  hp->next = pfile->hashtab[bucket];
-  pfile->hashtab[bucket] = hp;
-  hp->prev = NULL;
-  if (hp->next != NULL)
-    hp->next->prev = hp;
-  hp->type = type;
-  hp->length = len;
-  hp->value.cpval = value;
-  hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE);
-  bcopy (name, hp->name, len);
-  hp->name[len] = 0;
-  return hp;
-}
-
-static int
-macro_cleanup (pbuf, pfile)
-     cpp_buffer *pbuf;
-     cpp_reader *pfile ATTRIBUTE_UNUSED;
-{
-  HASHNODE *macro = (HASHNODE *) pbuf->data;
-  if (macro->type == T_DISABLED)
-    macro->type = T_MACRO;
-  if (macro->type != T_MACRO || pbuf->buf != macro->value.defn->expansion)
-    free (pbuf->buf);
-  return 0;
-}
-
-
-/* Read a replacement list for a macro with parameters.
-   Build the DEFINITION structure.
-   Reads characters of text starting at BUF until END.
-   ARGLIST specifies the formal parameters to look for
-   in the text of the definition; NARGS is the number of args
-   in that list, or -1 for a macro name that wants no argument list.
-   MACRONAME is the macro name itself (so we can avoid recursive expansion)
-   and NAMELEN is its length in characters.
-   
-   Note that comments, backslash-newlines, and leading white space
-   have already been deleted from the argument.  */
-
-static DEFINITION *
-collect_expansion (pfile, buf, limit, nargs, arglist)
-     cpp_reader *pfile;
-     U_CHAR *buf, *limit;
-     int nargs;
-     struct arglist *arglist;
-{
-  DEFINITION *defn;
-  register U_CHAR *p, *lastp, *exp_p;
-  struct reflist *endpat = NULL;
-  /* Pointer to first nonspace after last ## seen.  */
-  U_CHAR *concat = 0;
-  /* Pointer to first nonspace after last single-# seen.  */
-  U_CHAR *stringify = 0;
-  int maxsize;
-  int expected_delimiter = '\0';
-
-  /* Scan thru the replacement list, ignoring comments and quoted
-     strings, picking up on the macro calls.  It does a linear search
-     thru the arg list on every potential symbol.  Profiling might say
-     that something smarter should happen.  */
-
-  if (limit < buf)
-    {
-      cpp_fatal (pfile, "internal error: limit < buf in collect_expansion");
-      limit = buf; /* treat it like a null defn */
-    }
-
-  /* Find the beginning of the trailing whitespace.  */
-  p = buf;
-  while (p < limit && is_space[limit[-1]])
-    limit--;
-
-  /* Allocate space for the text in the macro definition.
-     Leading and trailing whitespace chars need 2 bytes each.
-     Each other input char may or may not need 1 byte,
-     so this is an upper bound.  The extra 5 are for invented
-     leading and trailing newline-marker and final null.  */
-  maxsize = (sizeof (DEFINITION)
-            + (limit - p) + 5);
-  defn = (DEFINITION *) xcalloc (1, maxsize);
-
-  defn->nargs = nargs;
-  exp_p = defn->expansion = (U_CHAR *) defn + sizeof (DEFINITION);
-  lastp = exp_p;
-
-  p = buf;
-
-  /* Add one initial space escape-marker to prevent accidental
-     token-pasting (often removed by macroexpand).  */
-  *exp_p++ = '\r';
-  *exp_p++ = ' ';
-
-  if (limit - p >= 2 && p[0] == '#' && p[1] == '#')
-    {
-      cpp_error (pfile, "`##' at start of macro definition");
-      p += 2;
-    }
-
-  /* Process the main body of the definition.  */
-  while (p < limit)
-    {
-      int skipped_arg = 0;
-      register U_CHAR c = *p++;
-
-      *exp_p++ = c;
-
-      if (!CPP_TRADITIONAL (pfile))
-       {
-         switch (c)
-           {
-           case '\'':
-           case '\"':
-             if (expected_delimiter != '\0')
-               {
-                 if (c == expected_delimiter)
-                   expected_delimiter = '\0';
-               }
-             else
-               expected_delimiter = c;
-             break;
-
-           case '\\':
-             if (p < limit && expected_delimiter)
-               {
-                 /* In a string, backslash goes through
-                    and makes next char ordinary.  */
-                 *exp_p++ = *p++;
-               }
-             break;
-
-           case '#':
-             /* # is ordinary inside a string.  */
-             if (expected_delimiter)
-               break;
-             if (p < limit && *p == '#')
-               {
-                 /* ##: concatenate preceding and following tokens.  */
-                 /* Take out the first #, discard preceding whitespace.  */
-                 exp_p--;
-                 while (exp_p > lastp && is_hor_space[exp_p[-1]])
-                   --exp_p;
-                 /* Skip the second #.  */
-                 p++;
-                 /* Discard following whitespace.  */
-                 SKIP_WHITE_SPACE (p);
-                 concat = p;
-                 if (p == limit)
-                   cpp_error (pfile, "`##' at end of macro definition");
-               }
-             else if (nargs >= 0)
-               {
-                 /* Single #: stringify following argument ref.
-                    Don't leave the # in the expansion.  */
-                 exp_p--;
-                 SKIP_WHITE_SPACE (p);
-                 if (p == limit || !is_idstart[*p]
-                     || (*p == 'L' && p + 1 < limit && (p[1] == '\'' ||
-                                                        p[1] == '"')))
-                   cpp_error (pfile,
-               "`#' operator is not followed by a macro argument name");
-                 else
-                   stringify = p;
-               }
-             break;
-           }
-       }
-      else
-       {
-         /* In -traditional mode, recognize arguments inside strings and
-            character constants, and ignore special properties of #.
-            Arguments inside strings are considered "stringified", but no
-            extra quote marks are supplied.  */
-         switch (c)
-           {
-           case '\'':
-           case '\"':
-             if (expected_delimiter != '\0')
-               {
-                 if (c == expected_delimiter)
-                   expected_delimiter = '\0';
-               }
-             else
-               expected_delimiter = c;
-             break;
-
-           case '\\':
-             /* Backslash quotes delimiters and itself,
-                but not macro args.  */
-             if (expected_delimiter != 0 && p < limit
-                 && (*p == expected_delimiter || *p == '\\'))
-               {
-                 *exp_p++ = *p++;
-                 continue;
-               }
-             break;
-
-           case '/':
-             if (expected_delimiter != '\0')
-               /* No comments inside strings.  */
-               break;
-             if (*p == '*')
-               {
-                 /* If we find a comment that wasn't removed by
-                    handle_directive, this must be -traditional.
-                    So replace the comment with nothing at all.  */
-                 exp_p--;
-                 p += 1;
-                 while (p < limit && !(p[-2] == '*' && p[-1] == '/'))
-                   p++;
-#if 0
-                 /* Mark this as a concatenation-point,
-                    as if it had been ##.  */
-                 concat = p;
-#endif
-               }
-             break;
-           }
-       }
-
-      /* Handle the start of a symbol.  */
-      if (is_idchar[c] && nargs > 0)
-       {
-         U_CHAR *id_beg = p - 1;
-         int id_len;
-
-         --exp_p;
-         while (p != limit && is_idchar[*p])
-           p++;
-         id_len = p - id_beg;
-
-         if (is_idstart[c]
-             && !(id_len == 1 && c == 'L' && (*p == '\'' || *p == '"')))
-           {
-             register struct arglist *arg;
-
-             for (arg = arglist; arg != NULL; arg = arg->next)
-               {
-                 struct reflist *tpat;
-
-                 if (arg->name[0] == c
-                     && arg->length == id_len
-                     && strncmp (arg->name, id_beg, id_len) == 0)
-                   {
-                     if (expected_delimiter && CPP_OPTIONS
-                       (pfile)->warn_stringify)
-                       {
-                         if (CPP_TRADITIONAL (pfile))
-                           {
-                             cpp_warning (pfile,
-                                      "macro argument `%.*s' is stringified.",
-                                          id_len, arg->name);
-                           }
-                         else
-                           {
-                             cpp_warning (pfile,
-                   "macro arg `%.*s' would be stringified with -traditional.",
-                                          id_len, arg->name);
-                           }
-                       }
-                     /* If ANSI, don't actually substitute
-                        inside a string.  */
-                     if (!CPP_TRADITIONAL (pfile) && expected_delimiter)
-                       break;
-                     /* make a pat node for this arg and append it
-                        to the end of the pat list */
-                     tpat = (struct reflist *)
-                       xmalloc (sizeof (struct reflist));
-                     tpat->next = NULL;
-                     tpat->raw_before = concat == id_beg;
-                     tpat->raw_after = 0;
-                     tpat->rest_args = arg->rest_args;
-                     tpat->stringify = (CPP_TRADITIONAL (pfile)
-                                        ? expected_delimiter != '\0'
-                                        : stringify == id_beg);
-
-                     if (endpat == NULL)
-                       defn->pattern = tpat;
-                     else
-                       endpat->next = tpat;
-                     endpat = tpat;
-
-                     tpat->argno = arg->argno;
-                     tpat->nchars = exp_p - lastp;
-                     {
-                       register U_CHAR *p1 = p;
-                       SKIP_WHITE_SPACE (p1);
-                       if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#')
-                         tpat->raw_after = 1;
-                     }
-                     lastp = exp_p;
-                     skipped_arg = 1;
-                     break;
-                   }
-               }
-           }
-
-         /* If this was not a macro arg, copy it into the expansion.  */
-         if (!skipped_arg)
-           {
-             register U_CHAR *lim1 = p;
-             p = id_beg;
-             while (p != lim1)
-               *exp_p++ = *p++;
-             if (stringify == id_beg)
-               cpp_error (pfile,
-               "`#' operator should be followed by a macro argument name");
-           }
-       }
-    }
-
-  if (!CPP_TRADITIONAL (pfile) && expected_delimiter == 0)
-    {
-      /* If ANSI, put in a "\r " marker to prevent token pasting.
-         But not if "inside a string" (which in ANSI mode
-         happens only for -D option).  */
-      *exp_p++ = '\r';
-      *exp_p++ = ' ';
-    }
-
-  *exp_p = '\0';
-
-  defn->length = exp_p - defn->expansion;
-
-  /* Crash now if we overrun the allocated size.  */
-  if (defn->length + 1 > maxsize)
-    abort ();
-
-#if 0
-/* This isn't worth the time it takes.  */
-  /* give back excess storage */
-  defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1);
-#endif
-
-  return defn;
-}
-
-/*
- * special extension string that can be added to the last macro argument to 
- * allow it to absorb the "rest" of the arguments when expanded.  Ex:
- *             #define wow(a, b...)            process (b, a, b)
- *             { wow (1, 2, 3); }      ->      { process (2, 3, 1, 2, 3); }
- *             { wow (one, two); }     ->      { process (two, one, two); }
- * if this "rest_arg" is used with the concat token '##' and if it is not
- * supplied then the token attached to with ## will not be outputted.  Ex:
- *             #define wow (a, b...)           process (b ## , a, ## b)
- *             { wow (1, 2); }         ->      { process (2, 1, 2); }
- *             { wow (one); }          ->      { process (one); {
- */
-static char rest_extension[] = "...";
-#define REST_EXTENSION_LENGTH  (sizeof (rest_extension) - 1)
-
-/* Create a DEFINITION node from a #define directive.  Arguments are 
-   as for do_define.  */
-
-MACRODEF
-create_definition (buf, limit, pfile, predefinition)
-     U_CHAR *buf, *limit;
+_cpp_init_hashtable (pfile, table)
      cpp_reader *pfile;
      cpp_reader *pfile;
-     int predefinition;
+     hash_table *table;
 {
 {
-  U_CHAR *bp;                  /* temp ptr into input buffer */
-  U_CHAR *symname;             /* remember where symbol name starts */
-  int sym_length;              /* and how long it is */
-  int rest_args = 0;
-  long line, col;
-  const char *file =
-    CPP_BUFFER (pfile) ? CPP_BUFFER (pfile)->nominal_fname : "";
-  DEFINITION *defn;
-  int arglengths = 0;          /* Accumulate lengths of arg names
-                                  plus number of args.  */
-  MACRODEF mdef;
-  cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
-
-  bp = buf;
-
-  while (is_hor_space[*bp])
-    bp++;
-
-  symname = bp;                        /* remember where it starts */
-
-  sym_length = check_macro_name (pfile, bp, 0);
-  bp += sym_length;
-
-  /* Lossage will occur if identifiers or control keywords are broken
-     across lines using backslash.  This is not the right place to take
-     care of that.  */
-
-  if (*bp == '(')
+  if (table == NULL)
     {
     {
-      struct arglist *arg_ptrs = NULL;
-      int argno = 0;
-
-      bp++;                    /* skip '(' */
-      SKIP_WHITE_SPACE (bp);
-
-      /* Loop over macro argument names.  */
-      while (*bp != ')')
-       {
-         struct arglist *temp;
-
-         temp = (struct arglist *) alloca (sizeof (struct arglist));
-         temp->name = bp;
-         temp->next = arg_ptrs;
-         temp->argno = argno++;
-         temp->rest_args = 0;
-         arg_ptrs = temp;
-
-         if (rest_args)
-           cpp_pedwarn (pfile, "another parameter follows `%s'",
-                        rest_extension);
-
-         if (!is_idstart[*bp])
-           cpp_pedwarn (pfile, "invalid character in macro parameter name");
-
-         /* Find the end of the arg name.  */
-         while (is_idchar[*bp])
-           {
-             bp++;
-             /* do we have a "special" rest-args extension here? */
-             if ((size_t) (limit - bp) > REST_EXTENSION_LENGTH
-                 && !strncmp (rest_extension, bp, REST_EXTENSION_LENGTH))
-               {
-                 rest_args = 1;
-                 temp->rest_args = 1;
-                 break;
-               }
-           }
-         temp->length = bp - temp->name;
-         if (rest_args == 1)
-           bp += REST_EXTENSION_LENGTH;
-         arglengths += temp->length + 2;
-         SKIP_WHITE_SPACE (bp);
-         if (temp->length == 0 || (*bp != ',' && *bp != ')'))
-           {
-             cpp_error (pfile,
-                        "badly punctuated parameter list in `#define'");
-             goto nope;
-           }
-         if (*bp == ',')
-           {
-             bp++;
-             SKIP_WHITE_SPACE (bp);
-           }
-         if (bp >= limit)
-           {
-             cpp_error (pfile, "unterminated parameter list in `#define'");
-             goto nope;
-           }
-         {
-           struct arglist *otemp;
-
-           for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
-             if (temp->length == otemp->length
-                 && strncmp (temp->name, otemp->name, temp->length) == 0)
-               {
-                 U_CHAR *name;
-
-                 name = (U_CHAR *) alloca (temp->length + 1);
-                 (void) strncpy (name, temp->name, temp->length);
-                 name[temp->length] = '\0';
-                 cpp_error (pfile,
-                            "duplicate argument name `%s' in `#define'",
-                            name);
-                 goto nope;
-               }
-         }
-       }
-
-      ++bp;                    /* skip paren */
-      SKIP_WHITE_SPACE (bp);
-      /* now everything from bp before limit is the definition.  */
-      defn = collect_expansion (pfile, bp, limit, argno, arg_ptrs);
-      defn->rest_args = rest_args;
-
-      /* Now set defn->args.argnames to the result of concatenating
-         the argument names in reverse order
-         with comma-space between them.  */
-      defn->args.argnames = (U_CHAR *) xmalloc (arglengths + 1);
-      {
-       struct arglist *temp;
-       int i = 0;
-       for (temp = arg_ptrs; temp; temp = temp->next)
-         {
-           bcopy (temp->name, &defn->args.argnames[i], temp->length);
-           i += temp->length;
-           if (temp->next != 0)
-             {
-               defn->args.argnames[i++] = ',';
-               defn->args.argnames[i++] = ' ';
-             }
-         }
-       defn->args.argnames[i] = 0;
-      }
-    }
-  else
-    {
-      /* Simple expansion or empty definition.  */
-
-      if (bp < limit)
-       {
-         if (is_hor_space[*bp])
-           {
-             bp++;
-             SKIP_WHITE_SPACE (bp);
-           }
-         else
-           /* Per C9x, missing white space after the name in a #define
-              of an object-like macro is always a constraint violation. */
-           cpp_pedwarn (pfile,
-                        "missing white space after `#define %.*s'",
-                        sym_length, symname);
-       }
-      /* now everything from bp before limit is the definition.  */
-      defn = collect_expansion (pfile, bp, limit, -1, NULL_PTR);
-      defn->args.argnames = (U_CHAR *) "";
+      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);
     }
 
     }
 
-  defn->line = line;
-  defn->file = file;
-
-  /* OP is null if this is a predefinition */
-  defn->predefined = predefinition;
-  mdef.defn = defn;
-  mdef.symnam = symname;
-  mdef.symlen = sym_length;
-
-  return mdef;
-
-nope:
-  mdef.defn = 0;
-  return mdef;
+  table->pfile = pfile;
+  pfile->hash_table = table;
 }
 
 }
 
-/*
- * 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_token
-macarg (pfile, rest_args)
-     cpp_reader *pfile;
-     int rest_args;
-{
-  int paren = 0;
-  enum cpp_token token;
-  char save_put_out_comments = CPP_OPTIONS (pfile)->put_out_comments;
-  CPP_OPTIONS (pfile)->put_out_comments = 0;
-
-  /* Try to parse as much of the argument as exists at this
-     input stack level.  */
-  pfile->no_macro_expand++;
-  CPP_OPTIONS (pfile)->no_line_commands++;
-  for (;;)
-    {
-      token = cpp_get_token (pfile);
-      switch (token)
-       {
-       case CPP_EOF:
-         goto done;
-       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)))
-           goto done;
-         break;
-       case CPP_LPAREN:
-         paren++;
-         break;
-       case CPP_RPAREN:
-         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);
-         goto done;
-       default:;
-       }
-    }
-
-done:
-  CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;
-  CPP_OPTIONS (pfile)->no_line_commands--;
-  pfile->no_macro_expand--;
-
-  return token;
-}
-\f
-/* Turn newlines to spaces in the string of length LENGTH at START,
-   except inside of string constants.
-   The string is copied into itself with its beginning staying fixed.  */
-
-static int
-change_newlines (start, length)
-     U_CHAR *start;
-     int length;
-{
-  register U_CHAR *ibp;
-  register U_CHAR *obp;
-  register U_CHAR *limit;
-  register int c;
-
-  ibp = start;
-  limit = start + length;
-  obp = start;
-
-  while (ibp < limit)
-    {
-      *obp++ = c = *ibp++;
-      switch (c)
-       {
-
-       case '\'':
-       case '\"':
-         /* Notice and skip strings, so that we don't
-            delete newlines in them.  */
-         {
-           int quotec = c;
-           while (ibp < limit)
-             {
-               *obp++ = c = *ibp++;
-               if (c == quotec)
-                 break;
-               if (c == '\n' && quotec == '\'')
-                 break;
-             }
-         }
-         break;
-       }
-    }
-
-  return obp - start;
-}
-\f
-
-static struct tm *
-timestamp (pfile)
-     cpp_reader *pfile;
-{
-  if (!pfile->timebuf)
-    {
-      time_t t = time ((time_t *) 0);
-      pfile->timebuf = localtime (&t);
-    }
-  return pfile->timebuf;
-}
-
-static const char * const monthnames[] =
-{
-  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
-};
-
-/*
- * expand things like __FILE__.  Place the expansion into the output
- * buffer *without* rescanning.
- */
-
-static void
-special_symbol (hp, pfile)
-     HASHNODE *hp;
-     cpp_reader *pfile;
-{
-  const char *buf;
-  int len;
-  cpp_buffer *ip;
-
-  switch (hp->type)
-    {
-    case T_FILE:
-    case T_BASE_FILE:
-      {
-       ip = CPP_BUFFER (pfile);
-       if (hp->type == T_BASE_FILE)
-         {
-           while (CPP_PREV_BUFFER (ip) != CPP_NULL_BUFFER (pfile))
-             ip = CPP_PREV_BUFFER (ip);
-         }
-       else
-         {
-           ip = CPP_BUFFER (pfile);
-           while (!ip->nominal_fname && ip != CPP_NULL_BUFFER (pfile))
-             ip = CPP_PREV_BUFFER (ip);
-         }
-
-       buf = ip->nominal_fname;
-
-       if (!buf)
-         buf = "";
-       CPP_RESERVE (pfile, 3 + 4 * strlen (buf));
-       quote_string (pfile, buf);
-       return;
-      }
-
-    case T_INCLUDE_LEVEL:
-      {
-       int true_indepth = 0;
-       ip = CPP_BUFFER (pfile);
-       for (; ip != CPP_NULL_BUFFER (pfile); ip = CPP_PREV_BUFFER (ip))
-         if (ip->fname != NULL)
-           true_indepth++;
-
-       CPP_RESERVE (pfile, 10);
-       sprintf (CPP_PWRITTEN (pfile), "%d", true_indepth);
-       CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
-       return;
-      }
-
-    case T_VERSION:
-      len = strlen (version_string);
-      CPP_RESERVE (pfile, 3 + len);
-      CPP_PUTC_Q (pfile, '"');
-      CPP_PUTS_Q (pfile, version_string, len);
-      CPP_PUTC_Q (pfile, '"');
-      CPP_NUL_TERMINATE_Q (pfile);
-      return;
-
-    case T_CONST:
-      buf = hp->value.cpval;
-      if (!buf)
-       return;
-      if (*buf == '\0')
-       buf = "\r ";
-
-      len = strlen (buf);
-      CPP_RESERVE (pfile, len + 1);
-      CPP_PUTS_Q (pfile, buf, len);
-      CPP_NUL_TERMINATE_Q (pfile);
-      return;
-
-    case T_STDC:
-      CPP_RESERVE (pfile, 2);
-#ifdef STDC_0_IN_SYSTEM_HEADERS
-      ip = CPP_BUFFER (pfile);
-      while (!ip->nominal_fname && ip != CPP_NULL_BUFFER (pfile))
-       ip = CPP_PREV_BUFFER (ip);
-      if (ip->system_header_p
-         && !cpp_lookup (pfile, (U_CHAR *) "__STRICT_ANSI__", 15, -1))
-       CPP_PUTC_Q (pfile, '0');
-      else
-#endif
-       CPP_PUTC_Q (pfile, '1');
-      CPP_NUL_TERMINATE_Q (pfile);
-      return;
-
-    case T_SPECLINE:
-      {
-       long line;
-       cpp_buf_line_and_col (cpp_file_buffer (pfile), &line, NULL);
-
-       CPP_RESERVE (pfile, 10);
-       sprintf (CPP_PWRITTEN (pfile), "%ld", line);
-       CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
-       return;
-      }
-
-    case T_DATE:
-    case T_TIME:
-      {
-       struct tm *timebuf;
-
-       CPP_RESERVE (pfile, 20);
-       timebuf = timestamp (pfile);
-       if (hp->type == T_DATE)
-         sprintf (CPP_PWRITTEN (pfile), "\"%s %2d %4d\"",
-                  monthnames[timebuf->tm_mon],
-                  timebuf->tm_mday, timebuf->tm_year + 1900);
-       else
-         sprintf (CPP_PWRITTEN (pfile), "\"%02d:%02d:%02d\"",
-                  timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec);
-
-       CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
-       return;
-      }
-
-    case T_POISON:
-      cpp_error (pfile, "attempt to use poisoned `%s'.", hp->name);
-      CPP_RESERVE (pfile, 1);
-      CPP_PUTC_Q (pfile, '0');
-      CPP_NUL_TERMINATE_Q (pfile);
-      break;
-
-    default:
-      cpp_fatal (pfile, "cpplib internal error: invalid special hash type");
-      return;
-    }
-}
-
-/* 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.  */
+/* Tear down the identifier hash table.  */
 
 void
 
 void
-macroexpand (pfile, hp)
+_cpp_destroy_hashtable (pfile)
      cpp_reader *pfile;
      cpp_reader *pfile;
-     HASHNODE *hp;
 {
 {
-  int nargs;
-  DEFINITION *defn;
-  register U_CHAR *xbuf;
-  long start_line, start_column;
-  int xbuf_len;
-  struct argdata *args;
-  long old_written = CPP_WRITTEN (pfile);
-#if 0
-  int start_line = instack[indepth].lineno;
-#endif
-  int rest_args, rest_zero;
-  register int i;
-
-#if 0
-  /* This macro is being used inside a #if, which means it must be */
-  /* recorded as a precondition.  */
-  if (pcp_inside_if && pcp_outfile && defn->predefined)
-    dump_single_macro (hp, pcp_outfile);
-#endif
-
-  cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
-
-  /* Check for and handle special symbols. */
-  if (hp->type != T_MACRO)
+  if (pfile->our_hashtable)
     {
     {
-      special_symbol (hp, pfile);
-      xbuf_len = CPP_WRITTEN (pfile) - old_written;
-      xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
-      CPP_SET_WRITTEN (pfile, old_written);
-      bcopy (CPP_PWRITTEN (pfile), xbuf, xbuf_len + 1);
-      push_macro_expansion (pfile, xbuf, xbuf_len, hp);
-      CPP_BUFFER (pfile)->has_escapes = 1;
-      return;
+      free (pfile->hash_table);
+      obstack_free (&pfile->hash_ob, 0);
     }
     }
-
-  defn = hp->value.defn;
-  nargs = defn->nargs;
-  pfile->output_escapes++;
-
-  if (nargs >= 0)
-    {
-      enum cpp_token token = CPP_EOF;
-
-      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;
-         args[i].use_count = 0;
-       }
-
-      /* 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;
-      rest_args = 0;
-      FORWARD (1);     /* Discard open-parenthesis before first arg.  */
-      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;
-             args[i].newlines = 0;     /* FIXME */
-           }
-         else
-           token = macarg (pfile, 0);
-         if (token == CPP_EOF || token == CPP_POP)
-           {
-             cpp_error_with_line (pfile, start_line, start_column,
-                                  "unterminated macro call");
-             return;
-           }
-         i++;
-       }
-      while (token == CPP_COMMA);
-
-      /* If we got one arg but it was just whitespace, call that 0 args.  */
-      if (i == 1)
-       {
-         register U_CHAR *bp = ARG_BASE + args[0].raw;
-         register U_CHAR *lim = bp + args[0].raw_length;
-         /* cpp.texi says for foo ( ) we provide one argument.
-            However, if foo wants just 0 arguments, treat this as 0.  */
-         if (nargs == 0)
-           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)
-       {
-         /* traditional C allows foo() if foo wants one argument.  */
-         if (nargs == 1 && i == 0 && CPP_TRADITIONAL (pfile))
-           ;
-         /* the rest args token is allowed to absorb 0 tokens */
-         else 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);
-                 if (!CPP_TRADITIONAL (pfile))
-                   CPP_PUTC (pfile, '\"');     /* insert beginning quote */
-                 for (; i < arglen; i++)
-                   {
-                     c = (ARG_BASE + arg->raw)[i];
-
-                     if (!in_string)
-                       {
-                         /* Internal sequences of whitespace are
-                            replaced by one space except within
-                            a string or char token. */
-                         if (is_space[c])
-                           {
-                             if (CPP_WRITTEN (pfile) > (unsigned) arg->stringified
-                                 && (CPP_PWRITTEN (pfile))[-1] == '\r')
-                               {
-                                 /* "\r " escape markers are removed */
-                                 CPP_ADJUST_WRITTEN (pfile, -1);
-                                 continue;
-                               }
-                             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);
-                       }
-                   }
-                 if (!CPP_TRADITIONAL (pfile))
-                   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 || CPP_TRADITIONAL (pfile))
-           /* Add 4 for two newline-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 newline-space markers to prevent
-                token concatenation.  */
-             xbuf_len += args[ap->argno].expand_length + 4;
-           }
-         if (args[ap->argno].use_count < 10)
-           args[ap->argno].use_count++;
-       }
-
-      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.  */
-         for (i = 0; i < ap->nchars; i++, offset++)
-           xbuf[totlen++] = exp[offset];
-
-         /* 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)
-           {
-             bcopy (ARG_BASE + arg->stringified,
-                    xbuf + totlen, arg->stringified_length);
-             totlen += arg->stringified_length;
-           }
-         else if (ap->raw_before || ap->raw_after || CPP_TRADITIONAL (pfile))
-           {
-             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;
-
-             bcopy (p1, xbuf + totlen, l1 - p1);
-             totlen += l1 - p1;
-           }
-         else
-           {
-             U_CHAR *expanded = ARG_BASE + arg->expanded;
-             if (!ap->raw_before && totlen > 0 && arg->expand_length
-                 && !CPP_TRADITIONAL (pfile)
-                 && unsafe_chars (xbuf[totlen - 1], expanded[0]))
-               {
-                 xbuf[totlen++] = '\r';
-                 xbuf[totlen++] = ' ';
-               }
-
-             bcopy (expanded, xbuf + totlen, arg->expand_length);
-             totlen += arg->expand_length;
-
-             if (!ap->raw_after && totlen > 0 && offset < defn->length
-                 && !CPP_TRADITIONAL (pfile)
-                 && unsafe_chars (xbuf[totlen - 1], exp[offset]))
-               {
-                 xbuf[totlen++] = '\r';
-                 xbuf[totlen++] = ' ';
-               }
-
-             /* If a macro argument with newlines is used multiple times,
-                then only expand the newlines once.  This avoids creating
-                output lines which don't correspond to any input line,
-                which confuses gdb and gcov.  */
-             if (arg->use_count > 1 && arg->newlines > 0)
-               {
-                 /* Don't bother doing change_newlines for subsequent
-                    uses of arg.  */
-                 arg->use_count = 1;
-                 arg->expand_length
-                   = change_newlines (expanded, arg->expand_length);
-               }
-           }
-
-         if (totlen > xbuf_len)
-           {
-             cpp_fatal (pfile, "internal_error: 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);
-
-  /* Recursive macro use sometimes works traditionally.
-     #define foo(x,y) bar (x (y,0), y)
-     foo (foo, baz)  */
-
-  if (!CPP_TRADITIONAL (pfile))
-    hp->type = T_DISABLED;
 }
 
 }
 
-/* Return 1 iff a token ending in C1 followed directly by a token C2
-   could cause mis-tokenization.  */
-
-static int
-unsafe_chars (c1, c2)
-     int c1, c2;
-{
-  switch (c1)
-    {
-    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 '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;
-}
+/* Returns the hash entry for the STR of length LEN, creating one
+   if necessary.  */
 
 
-static void
-push_macro_expansion (pfile, xbuf, xbuf_len, hp)
+cpp_hashnode *
+cpp_lookup (pfile, str, len)
      cpp_reader *pfile;
      cpp_reader *pfile;
-     register U_CHAR *xbuf;
-     int xbuf_len;
-     HASHNODE *hp;
+     const unsigned char *str;
+     unsigned int len;
 {
 {
-  register cpp_buffer *mbuf = cpp_push_buffer (pfile, xbuf, xbuf_len);
-  if (mbuf == NULL)
-    return;
-  mbuf->cleanup = macro_cleanup;
-  mbuf->data = hp;
-
-  /* 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.
-
-     The character before the macro invocation cannot have been an
-     idchar (or else it would have been pasted with the idchars of
-     the macro name).  Therefore, if the first non-space character
-     of the expansion is an idchar, we do not need the extra space
-     to prevent token pasting.
-
-     Also, we don't need the extra space if the first char is '(',
-     or some other (less common) characters.  */
-
-  if (xbuf[0] == '\r' && xbuf[1] == ' '
-      && (is_idchar[xbuf[2]] || xbuf[2] == '(' || xbuf[2] == '\''
-         || xbuf[2] == '\"'))
-    mbuf->cur += 2;
-
-  /* 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 (xbuf_len >= 3
-      && mbuf->rlimit[-2] == '\r'
-      && mbuf->rlimit[-1] == ' ')
-    {
-      int c1 = mbuf->rlimit[-3];
-      int c2 = CPP_BUF_PEEK (CPP_PREV_BUFFER (CPP_BUFFER (pfile)));
-      if (c2 == EOF || !unsafe_chars (c1, c2))
-       mbuf->rlimit -= 2;
-    }
+  /* ht_lookup cannot return NULL.  */
+  return CPP_HASHNODE (ht_lookup (pfile->hash_table, str, len, HT_ALLOC));
 }
 
 }
 
-/* Return zero if two DEFINITIONs are isomorphic.  */
+/* Determine whether the str STR, of length LEN, is a defined macro.  */
 
 int
 
 int
-compare_defs (pfile, d1, d2)
+cpp_defined (pfile, str, len)
      cpp_reader *pfile;
      cpp_reader *pfile;
-     DEFINITION *d1, *d2;
+     const unsigned char *str;
+     int len;
 {
 {
-  register struct reflist *a1, *a2;
-  register U_CHAR *p1 = d1->expansion;
-  register U_CHAR *p2 = d2->expansion;
-  int first = 1;
-
-  if (d1->nargs != d2->nargs)
-    return 1;
-  if (CPP_PEDANTIC (pfile)
-      && strcmp ((char *) d1->args.argnames, (char *) d2->args.argnames))
-    return 1;
-  for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
-       a1 = a1->next, a2 = a2->next)
-    {
-      if (!((a1->nchars == a2->nchars && !strncmp (p1, p2, a1->nchars))
-           || !comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
-         || a1->argno != a2->argno
-         || a1->stringify != a2->stringify
-         || a1->raw_before != a2->raw_before
-         || a1->raw_after != a2->raw_after)
-       return 1;
-      first = 0;
-      p1 += a1->nchars;
-      p2 += a2->nchars;
-    }
-  if (a1 != a2)
-    return 1;
-
-  return comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
-                       p2, d2->length - (p2 - d2->expansion), 1);
-}
+  cpp_hashnode *node;
 
 
-/* Return 1 if two parts of two macro definitions are effectively different.
-   One of the parts starts at BEG1 and has LEN1 chars;
-   the other has LEN2 chars at BEG2.
-   Any sequence of whitespace matches any other sequence of whitespace.
-   FIRST means these parts are the first of a macro definition;
-    so ignore leading whitespace entirely.
-   LAST means these parts are the last of a macro definition;
-    so ignore trailing whitespace entirely.  */
+  node = CPP_HASHNODE (ht_lookup (pfile->hash_table, str, len, HT_NO_INSERT));
 
 
-static int
-comp_def_part (first, beg1, len1, beg2, len2, last)
-     int first;
-     U_CHAR *beg1, *beg2;
-     int len1, len2;
-     int last;
-{
-  register U_CHAR *end1 = beg1 + len1;
-  register U_CHAR *end2 = beg2 + len2;
-  if (first)
-    {
-      while (beg1 != end1 && is_space[*beg1])
-       beg1++;
-      while (beg2 != end2 && is_space[*beg2])
-       beg2++;
-    }
-  if (last)
-    {
-      while (beg1 != end1 && is_space[end1[-1]])
-       end1--;
-      while (beg2 != end2 && is_space[end2[-1]])
-       end2--;
-    }
-  while (beg1 != end1 && beg2 != end2)
-    {
-      if (is_space[*beg1] && is_space[*beg2])
-       {
-         while (beg1 != end1 && is_space[*beg1])
-           beg1++;
-         while (beg2 != end2 && is_space[*beg2])
-           beg2++;
-       }
-      else if (*beg1 == *beg2)
-       {
-         beg1++;
-         beg2++;
-       }
-      else
-       break;
-    }
-  return (beg1 != end1) || (beg2 != end2);
+  /* If it's of type NT_MACRO, it cannot be poisoned.  */
+  return node && node->type == NT_MACRO;
 }
 
 }
 
-/* Dump the definition of macro MACRO on stdout.  The format is suitable
-   to be read back in again. */
+/* For all nodes in the hashtable, callback CB with parameters PFILE,
+   the node, and V.  */
 
 void
 
 void
-dump_definition (pfile, macro)
+cpp_forall_identifiers (pfile, cb, v)
      cpp_reader *pfile;
      cpp_reader *pfile;
-     MACRODEF macro;
+     cpp_cb cb;
+     PTR v;
 {
 {
-  DEFINITION *defn = macro.defn;
-
-  CPP_RESERVE (pfile, macro.symlen + sizeof "#define ");
-  CPP_PUTS_Q (pfile, "#define ", sizeof "#define " -1);
-  CPP_PUTS_Q (pfile, macro.symnam, macro.symlen);
-
-  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);
-      CPP_NUL_TERMINATE_Q (pfile);
-    }
-  else
-    {
-      struct reflist *r;
-      unsigned char *argnames = (unsigned char *) xstrdup (defn->args.argnames);
-      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 = argnames;
-      i = defn->nargs;
-      while (i--)
-       {
-         argv[i] = x;
-         while (*x != ',' && *x != '\0') x++;
-         argl[i] = x - argv[i];
-         if (*x == ',')
-           {
-             *x = '\0';
-             x += 2;  /* skip the space after the comma */
-           }
-       }
-      
-      /* Now print out the argument list. */
-      CPP_PUTC_Q (pfile, '(');
-      for (i = 0; i < defn->nargs; i++)
-       {
-         CPP_RESERVE (pfile, argl[i] + 2);
-         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, "...) ", 5);
-      else
-       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);
-
-       x += i;
-      }
-
-      i = defn->length - (x - defn->expansion) - 2;
-      if (*x == '\r') x += 2, i -= 2;
-      if (i > 0) CPP_PUTS (pfile, x, i);
-      CPP_NUL_TERMINATE (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);
 }
 }