cpplib.c: Kill define of STDC_VALUE.
authorZack Weinberg <zack@rabi.columbia.edu>
Thu, 18 Feb 1999 15:35:49 +0000 (15:35 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Thu, 18 Feb 1999 15:35:49 +0000 (15:35 +0000)
1999-02-18 18:32 -0500  Zack Weinberg  <zack@rabi.columbia.edu>
* cpplib.c: Kill define of STDC_VALUE.  Don't include output.h
          or prefix.h. Change CPP_IS_MACRO_BUFFER to not refer to
          macro_cleanup.
  (GET_ENV_PATH_LIST, PATH_SEPARATOR, STANDARD_INCLUDE_DIR,
          predefs, SIZE_TYPE, PTRDIFF_TYPE, WCHAR_TYPE,
          CPP_WCHAR_TYPE, USER_LABEL_PREFIX, REGISTER_PREFIX, struct
          cpp_pending, version_string, struct default_include,
          include_defaults_array, path_include, cpp_options_init,
          dump_special_to_buffer, initialize_builtins, cpp_start_read,
          cpp_reader_init, nreverse_pending, push_pending, print_help,
          cpp_handle_option, cpp_handle_options, cpp_finish,
          cpp_cleanup): Move to cppinit.c.
  (macro_cleanup, struct arglist, collect_expansion,
  create_definition, compare_defs, comp_def_part, ARG_BASE,
  struct argdata, macarg, change_newlines, timestamp,
  monthnames, special_symbol, unsafe_chars, macroexpand,
  push_macro_expansion): Move to cpphash.c.
  (quote_string, check_macro_name, cpp_expand_to_buffer,
  output_line_command, cpp_undef): Export.
  (null_underflow, null_cleanup, handle_directive): Make static.
* cpplib.h: Prototype now-exported functions.  Adjust decls of
          syntax tables so we can include cpplib.h in cppinit.c.
* cpphash.h: Prototype all functions exported by cpphash.c.
* cppinit.c: Make syntax tables initialized data if possible
          (uses GCC designated-initializer extension).
* cppexp.c:  Make cpp_lex static.
* Makefile.in: Move -D switches for the various include dirs
          from cpplib.o rule to cppinit.o rule.  Adjust dependencies.

From-SVN: r25287

gcc/ChangeLog
gcc/Makefile.in
gcc/cppexp.c
gcc/cpphash.c
gcc/cpphash.h
gcc/cppinit.c
gcc/cpplib.c
gcc/cpplib.h

index 83748fd..d8a8c01 100644 (file)
@@ -1,3 +1,35 @@
+1999-02-18 18:32 -0500  Zack Weinberg  <zack@rabi.columbia.edu>
+
+       * cpplib.c: Kill define of STDC_VALUE.  Don't include output.h
+          or prefix.h. Change CPP_IS_MACRO_BUFFER to not refer to
+          macro_cleanup.
+         (GET_ENV_PATH_LIST, PATH_SEPARATOR, STANDARD_INCLUDE_DIR,
+          predefs, SIZE_TYPE, PTRDIFF_TYPE, WCHAR_TYPE,
+          CPP_WCHAR_TYPE, USER_LABEL_PREFIX, REGISTER_PREFIX, struct
+          cpp_pending, version_string, struct default_include,
+          include_defaults_array, path_include, cpp_options_init,
+          dump_special_to_buffer, initialize_builtins, cpp_start_read,
+          cpp_reader_init, nreverse_pending, push_pending, print_help,
+          cpp_handle_option, cpp_handle_options, cpp_finish,
+          cpp_cleanup): Move to cppinit.c.
+         (macro_cleanup, struct arglist, collect_expansion,
+         create_definition, compare_defs, comp_def_part, ARG_BASE,
+         struct argdata, macarg, change_newlines, timestamp,
+         monthnames, special_symbol, unsafe_chars, macroexpand,
+         push_macro_expansion): Move to cpphash.c.
+         (quote_string, check_macro_name, cpp_expand_to_buffer,
+         output_line_command, cpp_undef): Export.
+         (null_underflow, null_cleanup, handle_directive): Make static.
+
+       * cpplib.h: Prototype now-exported functions.  Adjust decls of
+          syntax tables so we can include cpplib.h in cppinit.c.
+       * cpphash.h: Prototype all functions exported by cpphash.c.
+       * cppinit.c: Make syntax tables initialized data if possible
+          (uses GCC designated-initializer extension).
+       * cppexp.c:  Make cpp_lex static.
+       * Makefile.in: Move -D switches for the various include dirs
+          from cpplib.o rule to cppinit.o rule.  Adjust dependencies.
+
 Thu Feb 18 13:15:56 1999  Marc Espie <espie@cvs.openbsd.org>
 
        * alpha/openbsd.h: New file.
index 8a159b1..f42fcad 100644 (file)
@@ -1970,23 +1970,23 @@ cppmain$(exeext): cppmain.o libcpp.a $(LIBDEPS)
 
 cppmain.o: cppmain.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
 
-cpplib.o: cpplib.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h cpphash.h \
-               prefix.h output.h Makefile
+cppulp.o:  cppulp.c  $(CONFIG_H) system.h output.h
+cpplib.o:  cpplib.c  $(CONFIG_H) cpplib.h intl.h machmode.h system.h cpphash.h
+cpphash.o: cpphash.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h cpphash.h
+cppalloc.o: cppalloc.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
+cpperror.o: cpperror.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
+cppexp.o:   cppexp.c   $(CONFIG_H) cpplib.h intl.h machmode.h system.h
+cppfiles.o: cppfiles.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
+
+cppinit.o:  cppalloc.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h \
+               cpphash.h prefix.h output.h Makefile
        $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
          -DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \
          -DGPLUSPLUS_INCLUDE_DIR=\"$(gxx_include_dir)\" \
          -DLOCAL_INCLUDE_DIR=\"$(includedir)\" \
          -DCROSS_INCLUDE_DIR=\"$(gcc_tooldir)/sys-include\" \
          -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
-         -c `echo $(srcdir)/cpplib.c | sed 's,^\./,,'`
-
-cppulp.o: cppulp.c $(CONFIG_H) system.h output.h
-cpphash.o: cpphash.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h cpphash.h
-cppalloc.o: cppalloc.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
-cpperror.o: cpperror.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
-cppexp.o:   cppexp.c   $(CONFIG_H) cpplib.h intl.h machmode.h system.h
-cppfiles.o: cppfiles.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
-cppinit.o:  cppalloc.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
+         -c `echo $(srcdir)/cppinit.c | sed 's,^\./,,'`
 
 # Note for the stamp targets, we run the program `true' instead of
 # having an empty command (nothing following the semicolon).
index 093412e..3b146d2 100644 (file)
@@ -376,7 +376,7 @@ static struct token tokentab2[] = {
 
 /* Read one token.  */
 
-struct operation
+static struct operation
 cpp_lex (pfile, skip_evaluation)
      cpp_reader *pfile;
      int skip_evaluation;
index bb0b46d..a9061a9 100644 (file)
@@ -1,4 +1,4 @@
-/* Part of CPP library.  (Macro hash table support.)
+/* Part of CPP library.  (Macro handling.)
    Copyright (C) 1986, 87, 89, 92-95, 1996, 1998 Free Software Foundation, Inc.
    Written by Per Bothner, 1994.
    Based on CCCP program by Paul Rubin, June 1986
@@ -29,6 +29,63 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 static HASHNODE *hashtab[HASHSIZE];
 
+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));
+
+#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
+{
+  struct arglist *next;
+  U_CHAR *name;
+  int length;
+  int argno;
+  char rest_args;
+};
+
+/* 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  */
 
@@ -67,7 +124,7 @@ cpp_lookup (pfile, name, len, hash)
 
   if (len < 0)
     {
-      for (bp = name; is_idchar[*bp]; bp++) ;
+      for (bp = name; is_idchar[*bp]; bp++);
       len = bp - name;
     }
 
@@ -75,11 +132,12 @@ cpp_lookup (pfile, name, len, hash)
     hash = hashf (name, len, HASHSIZE);
 
   bucket = hashtab[hash];
-  while (bucket) {
-    if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
-      return bucket;
-    bucket = bucket->next;
-  }
+  while (bucket)
+    {
+      if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
+       return bucket;
+      bucket = bucket->next;
+    }
   return (HASHNODE *) 0;
 }
 
@@ -155,12 +213,13 @@ install (name, len, type, value, hash)
   register int i, bucket;
   register U_CHAR *p;
 
-  if (len < 0) {
-    p = name;
-    while (is_idchar[*p])
-      p++;
-    len = p - name;
-  }
+  if (len < 0)
+    {
+      p = name;
+      while (is_idchar[*p])
+       p++;
+      len = p - name;
+    }
 
   if (hash < 0)
     hash = hashf (name, len, HASHSIZE);
@@ -188,9 +247,1426 @@ cpp_hash_cleanup (pfile)
      cpp_reader *pfile ATTRIBUTE_UNUSED;
 {
   register int i;
-  for (i = HASHSIZE; --i >= 0; )
+  for (i = HASHSIZE; --i >= 0;)
     {
       while (hashtab[i])
        delete_macro (hashtab[i]);
     }
 }
+
+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)
+    abort ();
+
+  /* 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);
+  /* Occurrences of '@' get doubled, so allocate extra space for them.  */
+  while (p < limit)
+    if (*p++ == '@')
+      maxsize++;
+  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++ = '@';
+  *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 '@':
+             /* An '@' in a string or character constant stands for itself,
+                and does not need to be escaped.  */
+             if (!expected_delimiter)
+               *exp_p++ = c;
+             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 "@ " marker to prevent token pasting.
+         But not if "inside a string" (which in ANSI mode
+         happens only for -D option).  */
+      *exp_p++ = '@';
+      *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_reader *pfile;
+     int predefinition;
+{
+  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;
+  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 == '(')
+    {
+      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 *) "";
+    }
+
+  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;
+}
+
+/*
+ * 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++;
+  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;
+  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 char *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 = "@ ";
+
+      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_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;
+      }
+
+    default:
+      cpp_fatal (pfile, "cpplib internal error: invalid special hash type");
+      return;
+    }
+
+  /* This point should be unreachable. */
+  abort ();
+}
+
+/* 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.  */
+
+void
+macroexpand (pfile, hp)
+     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)
+    {
+      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;
+    }
+
+  defn = hp->value.defn;
+  nargs = defn->nargs;
+  pfile->output_escapes++;
+
+  if (nargs >= 0)
+    {
+      enum cpp_token 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;
+         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] == '@')
+                               {
+                                 /* "@ " 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)
+               {
+                 while (p1 != l1 && is_space[*p1])
+                   p1++;
+                 while (p1 != l1 && is_idchar[*p1])
+                   xbuf[totlen++] = *p1++;
+               }
+             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] == '@')
+                       {
+                         U_CHAR *p2 = l1 - 1;
+                         /* If whitespace is preceded by an odd number
+                            of `@' signs, the last `@' was a whitespace
+                            marker; drop it too. */
+                         while (p2 != p1 && p2[0] == '@')
+                           p2--;
+                         if ((l1 - p2) & 1)
+                           l1--;
+                         break;
+                       }
+                     else if (l1[-1] == '-')
+                       {
+                         U_CHAR *p2 = l1 - 1;
+                         /* If a `-' is preceded by an odd number of
+                            `@' signs then it and the last `@' are
+                            a no-reexpansion marker.  */
+                         while (p2 != p1 && p2[0] == '@')
+                           p2--;
+                         if ((l1 - p2) & 1)
+                           l1 -= 2;
+                         else
+                           break;
+                       }
+                     else
+                       break;
+                   }
+               }
+
+             /* Delete any no-reexpansion marker that precedes
+                an identifier at the beginning of the argument. */
+             if (p1[0] == '@' && 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++] = '@';
+                 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++] = '@';
+                 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)
+           abort ();
+       }
+
+      /* 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 '.':    case '0':    case '1':    case '2':    case '3':
+    case '4':    case '5':    case '6':    case '7':    case '8':
+    case '9':    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 '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, xbuf_len, hp)
+     cpp_reader *pfile;
+     register U_CHAR *xbuf;
+     int xbuf_len;
+     HASHNODE *hp;
+{
+  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 "@ " 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] == '@' && 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] == '@'
+      && 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;
+    }
+}
+
+/* Return zero if two DEFINITIONs are isomorphic.  */
+
+int
+compare_defs (pfile, d1, d2)
+     cpp_reader *pfile;
+     DEFINITION *d1, *d2;
+{
+  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);
+}
+
+/* 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.  */
+
+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);
+}
index 28271f7..7f7f7d6 100644 (file)
@@ -53,3 +53,10 @@ extern HASHNODE *install PARAMS ((U_CHAR *, int, enum node_type,
                                  const char *, int));
 extern int hashf PARAMS ((const U_CHAR *, int, int));
 extern void delete_macro PARAMS ((HASHNODE *));
+
+extern MACRODEF create_definition PARAMS ((U_CHAR *, U_CHAR *,
+                                          cpp_reader *, int));
+extern int compare_defs                  PARAMS ((cpp_reader *, DEFINITION *,
+                                          DEFINITION *));
+extern void macroexpand                  PARAMS ((cpp_reader *, HASHNODE *));
+extern void cpp_hash_cleanup     PARAMS ((cpp_reader *));
index 32ebad9..8171903 100644 (file)
@@ -18,24 +18,206 @@ You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-/* This file will have more stuff in it eventually, but right now
-   we just have one hack: we move all the is_* table initialization
-   in here, and we can declare them const in cpplib.h, which improves
-   code a bit. */
-
 #include "config.h"
 #include "system.h"
 
-typedef unsigned char U_CHAR;
+#define FAKE_CONST
+#include "cpplib.h"
+#include "cpphash.h"
+#include "output.h"
+#include "prefix.h"
+#include "intl.h"
 
-/* table to tell if char can be part of a C identifier.  */
-U_CHAR is_idchar[256] = { 0 };
-/* table to tell if char can be first char of a c identifier.  */
-U_CHAR is_idstart[256] = { 0 };
-/* table to tell if c is horizontal space.  */
-U_CHAR is_hor_space[256] = { 0 };
-/* table to tell if c is horizontal or vertical space.  */
-U_CHAR is_space[256] = { 0 };
+/* XXX Should be in a header file. */
+extern char *version_string;
+
+/* Predefined symbols, built-in macros, and the default include path. */
+
+#ifndef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME)    do { (VAR) = getenv (NAME); } while (0)
+#endif
+
+/* By default, colon separates directories in a path.  */
+#ifndef PATH_SEPARATOR
+#define PATH_SEPARATOR ':'
+#endif
+
+#ifndef STANDARD_INCLUDE_DIR
+#define STANDARD_INCLUDE_DIR "/usr/include"
+#endif
+
+/* Symbols to predefine.  */
+
+#ifdef CPP_PREDEFINES
+static char *predefs = CPP_PREDEFINES;
+#else
+static char *predefs = "";
+#endif
+
+/* We let tm.h override the types used here, to handle trivial differences
+   such as the choice of unsigned int or long unsigned int for size_t.
+   When machines start needing nontrivial differences in the size type,
+   it would be best to do something here to figure out automatically
+   from other information what type to use.  */
+
+/* The string value for __SIZE_TYPE__.  */
+
+#ifndef SIZE_TYPE
+#define SIZE_TYPE "long unsigned int"
+#endif
+
+/* The string value for __PTRDIFF_TYPE__.  */
+
+#ifndef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+#endif
+
+/* The string value for __WCHAR_TYPE__.  */
+
+#ifndef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+#endif
+#define CPP_WCHAR_TYPE(PFILE) \
+       (CPP_OPTIONS (PFILE)->cplusplus ? "__wchar_t" : WCHAR_TYPE)
+
+/* The string value for __USER_LABEL_PREFIX__ */
+
+#ifndef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+#endif
+
+/* The string value for __REGISTER_PREFIX__ */
+
+#ifndef REGISTER_PREFIX
+#define REGISTER_PREFIX ""
+#endif
+
+/* #include "file" looks in source file dir, then stack.  */
+/* #include <file> just looks in the stack.  */
+/* -I directories are added to the end, then the defaults are added.  */
+/* The */
+static struct default_include {
+  char *fname;                 /* The name of the directory.  */
+  char *component;             /* The component containing the directory */
+  int cplusplus;               /* Only look here if we're compiling C++.  */
+  int cxx_aware;               /* Includes in this directory don't need to
+                                  be wrapped in extern "C" when compiling
+                                  C++.  */
+} include_defaults_array[]
+#ifdef INCLUDE_DEFAULTS
+  = INCLUDE_DEFAULTS;
+#else
+  = {
+    /* Pick up GNU C++ specific include files.  */
+    { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
+#ifdef CROSS_COMPILE
+    /* This is the dir for fixincludes.  Put it just before
+       the files that we fix.  */
+    { GCC_INCLUDE_DIR, "GCC", 0, 0 },
+    /* For cross-compilation, this dir name is generated
+       automatically in Makefile.in.  */
+    { CROSS_INCLUDE_DIR, "GCC",0, 0 },
+#ifdef TOOL_INCLUDE_DIR
+    /* This is another place that the target system's headers might be.  */
+    { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
+#endif
+#else /* not CROSS_COMPILE */
+#ifdef LOCAL_INCLUDE_DIR
+    /* This should be /usr/local/include and should come before
+       the fixincludes-fixed header files.  */
+    { LOCAL_INCLUDE_DIR, 0, 0, 1 },
+#endif
+#ifdef TOOL_INCLUDE_DIR
+    /* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here.
+       Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h.  */
+    { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
+#endif
+    /* This is the dir for fixincludes.  Put it just before
+       the files that we fix.  */
+    { GCC_INCLUDE_DIR, "GCC", 0, 0 },
+    /* Some systems have an extra dir of include files.  */
+#ifdef SYSTEM_INCLUDE_DIR
+    { SYSTEM_INCLUDE_DIR, 0, 0, 0 },
+#endif
+#ifndef STANDARD_INCLUDE_COMPONENT
+#define STANDARD_INCLUDE_COMPONENT 0
+#endif
+    { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 },
+#endif /* not CROSS_COMPILE */
+    { 0, 0, 0, 0 }
+    };
+#endif /* no INCLUDE_DEFAULTS */
+
+/* Internal structures and prototypes. */
+
+struct cpp_pending
+{
+  struct cpp_pending *next;
+  char *cmd;
+  char *arg;
+};
+static struct cpp_pending *nreverse_pending PARAMS ((struct cpp_pending *));
+
+static void initialize_char_syntax     PARAMS ((int));
+static void print_help                  PARAMS ((void));
+static void path_include               PARAMS ((cpp_reader *, char *));
+static void initialize_builtins                PARAMS ((cpp_reader *));
+
+
+/* If gcc is in use (stage2/stage3) we can make these tables initialized
+   data. */
+#if defined __GNUC__ && __GNUC__ >= 2
+/* Table to tell if a character is legal as the second or later character
+   of a C identifier. */
+U_CHAR is_idchar[256] =
+{
+  ['a'] = 1, ['b'] = 1, ['c'] = 1,  ['d'] = 1, ['e'] = 1, ['f'] = 1,
+  ['g'] = 1, ['h'] = 1, ['i'] = 1,  ['j'] = 1, ['k'] = 1, ['l'] = 1,
+  ['m'] = 1, ['n'] = 1, ['o'] = 1,  ['p'] = 1, ['q'] = 1, ['r'] = 1,
+  ['s'] = 1, ['t'] = 1, ['u'] = 1,  ['v'] = 1, ['w'] = 1, ['x'] = 1,
+  ['y'] = 1, ['z'] = 1,
+
+  ['A'] = 1, ['B'] = 1, ['C'] = 1,  ['D'] = 1, ['E'] = 1, ['F'] = 1,
+  ['G'] = 1, ['H'] = 1, ['I'] = 1,  ['J'] = 1, ['K'] = 1, ['L'] = 1,
+  ['M'] = 1, ['N'] = 1, ['O'] = 1,  ['P'] = 1, ['Q'] = 1, ['R'] = 1,
+  ['S'] = 1, ['T'] = 1, ['U'] = 1,  ['V'] = 1, ['W'] = 1, ['X'] = 1,
+  ['Y'] = 1, ['Z'] = 1,
+
+  ['1'] = 1, ['2'] = 1, ['3'] = 1,  ['4'] = 1, ['5'] = 1, ['6'] = 1,
+  ['7'] = 1, ['8'] = 1, ['9'] = 1,  ['0'] = 1,
+
+  ['_']  = 1,
+};
+
+/* Table to tell if a character is legal as the first character of
+   a C identifier. */
+U_CHAR is_idstart[256] =
+{
+  ['a'] = 1, ['b'] = 1, ['c'] = 1,  ['d'] = 1, ['e'] = 1, ['f'] = 1,
+  ['g'] = 1, ['h'] = 1, ['i'] = 1,  ['j'] = 1, ['k'] = 1, ['l'] = 1,
+  ['m'] = 1, ['n'] = 1, ['o'] = 1,  ['p'] = 1, ['q'] = 1, ['r'] = 1,
+  ['s'] = 1, ['t'] = 1, ['u'] = 1,  ['v'] = 1, ['w'] = 1, ['x'] = 1,
+  ['y'] = 1, ['z'] = 1,
+
+  ['A'] = 1, ['B'] = 1, ['C'] = 1,  ['D'] = 1, ['E'] = 1, ['F'] = 1,
+  ['G'] = 1, ['H'] = 1, ['I'] = 1,  ['J'] = 1, ['K'] = 1, ['L'] = 1,
+  ['M'] = 1, ['N'] = 1, ['O'] = 1,  ['P'] = 1, ['Q'] = 1, ['R'] = 1,
+  ['S'] = 1, ['T'] = 1, ['U'] = 1,  ['V'] = 1, ['W'] = 1, ['X'] = 1,
+  ['Y'] = 1, ['Z'] = 1,
+
+  ['_']  = 1,
+};
+
+/* Table to tell if a character is horizontal space. */
+U_CHAR is_hor_space[256] =
+{
+  [' '] = 1, ['\t'] = 1, ['\v'] = 1, ['\f'] = 1, ['\r'] = 1
+};
+/* table to tell if a character is horizontal or vertical space.  */
+U_CHAR is_space[256] =
+{
+  [' '] = 1, ['\t'] = 1, ['\v'] = 1, ['\f'] = 1, ['\r'] = 1, ['\n'] = 1,
+};
 /* Table to handle trigraph conversion, which occurs before all other
    processing, everywhere in the file.  (This is necessary since one
    of the trigraphs encodes backslash.)  Note it's off by default.
@@ -47,10 +229,32 @@ U_CHAR is_space[256] = { 0 };
 
    There is not a space between the ?? and the third char.  I put spaces
    there to avoid warnings when compiling this file. */
+U_CHAR trigraph_table[256] =
+{
+  ['='] = '#',  [')'] = ']',  ['!'] = '|',
+  ['('] = '[',  ['\''] = '^', ['>'] = '}',
+  ['/'] = '\\', ['<'] = '{',  ['-'] = '~',
+};
+
+/* This function will be entirely removed soon. */
+static inline void
+initialize_char_syntax (dollar_in_ident)
+     int dollar_in_ident;
+{
+  is_idchar['$'] = dollar_in_ident;
+  is_idstart['$'] = dollar_in_ident;
+}
+
+#else /* Not GCC. */
+
+U_CHAR is_idchar[256] = { 0 };
+U_CHAR is_idstart[256] = { 0 };
+U_CHAR is_hor_space[256] = { 0 };
+U_CHAR is_space[256] = { 0 };
 U_CHAR trigraph_table[256] = { 0 };
 
 /* Initialize syntactic classifications of characters. */
-void
+static void
 initialize_char_syntax (dollar_in_ident)
      int dollar_in_ident;
 {
@@ -103,11 +307,10 @@ initialize_char_syntax (dollar_in_ident)
 
   is_idchar['_']  = 1;
 
-  /* These will be reset later if -$ is in effect. */
   is_idchar['$']  = dollar_in_ident;
   is_idstart['$'] = dollar_in_ident;
 
-  /* horizontal space table */
+  /* white space tables */
   is_hor_space[' '] = 1;
   is_hor_space['\t'] = 1;
   is_hor_space['\v'] = 1;
@@ -128,3 +331,1363 @@ initialize_char_syntax (dollar_in_ident)
   trigraph_table['/'] = '\\'; trigraph_table['<'] = '{';
   trigraph_table['-'] = '~';
 }
+
+#endif /* Not GCC. */
+
+/* Given a colon-separated list of file names PATH,
+   add all the names to the search path for include files.  */
+
+static void
+path_include (pfile, path)
+     cpp_reader *pfile;
+     char *path;
+{
+  char *p;
+
+  p = path;
+
+  if (*p)
+    while (1) {
+      char *q = p;
+      char *name;
+
+      /* Find the end of this name.  */
+      while (*q != 0 && *q != PATH_SEPARATOR) q++;
+      if (p == q) {
+       /* An empty name in the path stands for the current directory.  */
+       name = (char *) xmalloc (2);
+       name[0] = '.';
+       name[1] = 0;
+      } else {
+       /* Otherwise use the directory that is named.  */
+       name = (char *) xmalloc (q - p + 1);
+       bcopy (p, name, q - p);
+       name[q - p] = 0;
+      }
+
+      append_include_chain (pfile,
+                           &(CPP_OPTIONS (pfile)->bracket_include), name, 0);
+
+      /* Advance past this name.  */
+      p = q;
+      if (*p == 0)
+       break;
+      /* Skip the colon.  */
+      p++;
+    }
+}
+
+/* Write out a #define command for the special named MACRO_NAME
+   to PFILE's token_buffer.  */
+
+static void
+dump_special_to_buffer (pfile, macro_name)
+     cpp_reader *pfile;
+     char *macro_name;
+{
+  static char define_directive[] = "#define ";
+  int macro_name_length = strlen (macro_name);
+  output_line_command (pfile, 0, same_file);
+  CPP_RESERVE (pfile, sizeof(define_directive) + macro_name_length);
+  CPP_PUTS_Q (pfile, define_directive, sizeof(define_directive)-1);
+  CPP_PUTS_Q (pfile, macro_name, macro_name_length);
+  CPP_PUTC_Q (pfile, ' ');
+  cpp_expand_to_buffer (pfile, macro_name, macro_name_length);
+  CPP_PUTC (pfile, '\n');
+}
+
+/* Pending-list utility routines.  Will go away soon.  */
+static struct cpp_pending *
+nreverse_pending (list)
+     struct cpp_pending *list;
+     
+{
+  register struct cpp_pending *prev = 0, *next, *pend;
+  for (pend = list;  pend;  pend = next)
+    {
+      next = pend->next;
+      pend->next = prev;
+      prev = pend;
+    }
+  return prev;
+}
+
+static void
+push_pending (pfile, cmd, arg)
+     cpp_reader *pfile;
+     char *cmd;
+     char *arg;
+{
+  struct cpp_pending *pend
+    = (struct cpp_pending *) xmalloc (sizeof (struct cpp_pending));
+  pend->cmd = cmd;
+  pend->arg = arg;
+  pend->next = CPP_OPTIONS (pfile)->pending;
+  CPP_OPTIONS (pfile)->pending = pend;
+}
+
+
+/* Initialize a cpp_options structure. */
+void
+cpp_options_init (opts)
+     cpp_options *opts;
+{
+  bzero ((char *) opts, sizeof *opts);
+
+  opts->dollars_in_ident = 1;
+  opts->cplusplus_comments = 1;
+  opts->warn_import = 1;
+}
+
+/* Initialize a cpp_reader structure. */
+void
+cpp_reader_init (pfile)
+     cpp_reader *pfile;
+{
+  bzero ((char *) pfile, sizeof (cpp_reader));
+#if 0
+  pfile->get_token = cpp_get_token;
+#endif
+
+  pfile->token_buffer_size = 200;
+  pfile->token_buffer = (U_CHAR *) xmalloc (pfile->token_buffer_size);
+  CPP_SET_WRITTEN (pfile, 0);
+}
+
+/* Free resources used by PFILE.
+   This is the cpp_reader 'finalizer' or 'destructor' (in C++ terminology).  */
+void
+cpp_cleanup (pfile)
+     cpp_reader *pfile;
+{
+  int i;
+  while (CPP_BUFFER (pfile) != CPP_NULL_BUFFER (pfile))
+    cpp_pop_buffer (pfile);
+
+  if (pfile->token_buffer)
+    {
+      free (pfile->token_buffer);
+      pfile->token_buffer = NULL;
+    }
+
+  if (pfile->deps_buffer)
+    {
+      free (pfile->deps_buffer);
+      pfile->deps_buffer = NULL;
+      pfile->deps_allocated_size = 0;
+    }
+
+  while (pfile->if_stack)
+    {
+      IF_STACK_FRAME *temp = pfile->if_stack;
+      pfile->if_stack = temp->next;
+      free (temp);
+    }
+
+  for (i = ALL_INCLUDE_HASHSIZE; --i >= 0; )
+    {
+      struct include_hash *imp = pfile->all_include_files[i];
+      while (imp)
+       {
+         struct include_hash *next = imp->next;
+#if 0
+         /* This gets freed elsewhere - I think. */
+         free (imp->name);
+#endif
+         free (imp);
+         imp = next;
+       }
+      pfile->all_include_files[i] = 0;
+    }
+
+  cpp_hash_cleanup (pfile);
+}
+
+
+/* Initialize the built-in macros.  */
+static void
+initialize_builtins (pfile)
+     cpp_reader *pfile;
+{
+#define NAME(str) (U_CHAR *)str, sizeof str - 1
+  install (NAME("__TIME__"),             T_TIME,       0, -1);
+  install (NAME("__DATE__"),             T_DATE,       0, -1);
+  install (NAME("__FILE__"),             T_FILE,       0, -1);
+  install (NAME("__BASE_FILE__"),        T_BASE_FILE,  0, -1);
+  install (NAME("__LINE__"),             T_SPECLINE,   0, -1);
+  install (NAME("__INCLUDE_LEVEL__"),    T_INCLUDE_LEVEL, 0, -1);
+  install (NAME("__VERSION__"),                  T_VERSION,    0, -1);
+#ifndef NO_BUILTIN_SIZE_TYPE
+  install (NAME("__SIZE_TYPE__"),        T_CONST, SIZE_TYPE, -1);
+#endif
+#ifndef NO_BUILTIN_PTRDIFF_TYPE
+  install (NAME("__PTRDIFF_TYPE__ "),    T_CONST, PTRDIFF_TYPE, -1);
+#endif
+  install (NAME("__WCHAR_TYPE__"),       T_CONST, WCHAR_TYPE, -1);
+  install (NAME("__USER_LABEL_PREFIX__"), T_CONST, user_label_prefix, -1);
+  install (NAME("__REGISTER_PREFIX__"),          T_CONST, REGISTER_PREFIX, -1);
+  if (!CPP_TRADITIONAL (pfile))
+    {
+      install (NAME("__STDC__"),         T_STDC,  0, -1);
+#if 0
+      if (CPP_OPTIONS (pfile)->c9x)
+       install (NAME("__STDC_VERSION__"),T_CONST, "199909L", -1);
+      else
+#endif
+       install (NAME("__STDC_VERSION__"),T_CONST, "199409L", -1);
+    }
+#undef NAME
+
+  if (CPP_OPTIONS (pfile)->debug_output)
+    {
+      dump_special_to_buffer (pfile, "__BASE_FILE__");
+      dump_special_to_buffer (pfile, "__VERSION__");
+#ifndef NO_BUILTIN_SIZE_TYPE
+      dump_special_to_buffer (pfile, "__SIZE_TYPE__");
+#endif
+#ifndef NO_BUILTIN_PTRDIFF_TYPE
+      dump_special_to_buffer (pfile, "__PTRDIFF_TYPE__");
+#endif
+      dump_special_to_buffer (pfile, "__WCHAR_TYPE__");
+      dump_special_to_buffer (pfile, "__DATE__");
+      dump_special_to_buffer (pfile, "__TIME__");
+      if (!CPP_TRADITIONAL (pfile))
+       dump_special_to_buffer (pfile, "__STDC__");
+    }
+}
+
+/* This is called after options have been processed.
+ * Check options for consistency, and setup for processing input
+ * from the file named FNAME.  (Use standard input if FNAME==NULL.)
+ * Return 1 on success, 0 on failure.
+ */
+
+int
+cpp_start_read (pfile, fname)
+     cpp_reader *pfile;
+     char *fname;
+{
+  struct cpp_options *opts = CPP_OPTIONS (pfile);
+  struct cpp_pending *pend;
+  char *p;
+  int f;
+  cpp_buffer *fp;
+  struct include_hash *ih_fake;
+
+  /* The code looks at the defaults through this pointer, rather than
+     through the constant structure above.  This pointer gets changed
+     if an environment variable specifies other defaults.  */
+  struct default_include *include_defaults = include_defaults_array;
+
+  /* Now that we know dollars_in_ident, we can initialize the syntax
+     tables. */
+  initialize_char_syntax (opts->dollars_in_ident);
+  
+  /* Add dirs from CPATH after dirs from -I.  */
+  /* There seems to be confusion about what CPATH should do,
+     so for the moment it is not documented.  */
+  /* Some people say that CPATH should replace the standard include
+     dirs, but that seems pointless: it comes before them, so it
+     overrides them anyway.  */
+  GET_ENV_PATH_LIST (p, "CPATH");
+  if (p != 0 && ! opts->no_standard_includes)
+    path_include (pfile, p);
+
+  /* Do partial setup of input buffer for the sake of generating
+     early #line directives (when -g is in effect).  */
+  fp = cpp_push_buffer (pfile, NULL, 0);
+  if (!fp)
+    return 0;
+  if (opts->in_fname == NULL || *opts->in_fname == 0)
+    {
+      opts->in_fname = fname;
+      if (opts->in_fname == NULL)
+       opts->in_fname = "";
+    }
+  fp->nominal_fname = fp->fname = opts->in_fname;
+  fp->lineno = 0;
+
+  /* Install __LINE__, etc.  Must follow initialize_char_syntax
+     and option processing.  */
+  initialize_builtins (pfile);
+
+  /* Do standard #defines and assertions
+     that identify system and machine type.  */
+
+  if (!opts->inhibit_predefs) {
+    char *p = (char *) alloca (strlen (predefs) + 1);
+    strcpy (p, predefs);
+    while (*p) {
+      char *q;
+      while (*p == ' ' || *p == '\t')
+       p++;
+      /* Handle -D options.  */ 
+      if (p[0] == '-' && p[1] == 'D') {
+       q = &p[2];
+       while (*p && *p != ' ' && *p != '\t')
+         p++;
+       if (*p != 0)
+         *p++= 0;
+       if (opts->debug_output)
+         output_line_command (pfile, 0, same_file);
+       cpp_define (pfile, q);
+       while (*p == ' ' || *p == '\t')
+         p++;
+      } else if (p[0] == '-' && p[1] == 'A') {
+       /* Handle -A options (assertions).  */ 
+       char *assertion;
+       char *past_name;
+       char *value;
+       char *past_value;
+       char *termination;
+       int save_char;
+
+       assertion = &p[2];
+       past_name = assertion;
+       /* Locate end of name.  */
+       while (*past_name && *past_name != ' '
+              && *past_name != '\t' && *past_name != '(')
+         past_name++;
+       /* Locate `(' at start of value.  */
+       value = past_name;
+       while (*value && (*value == ' ' || *value == '\t'))
+         value++;
+       if (*value++ != '(')
+         abort ();
+       while (*value && (*value == ' ' || *value == '\t'))
+         value++;
+       past_value = value;
+       /* Locate end of value.  */
+       while (*past_value && *past_value != ' '
+              && *past_value != '\t' && *past_value != ')')
+         past_value++;
+       termination = past_value;
+       while (*termination && (*termination == ' ' || *termination == '\t'))
+         termination++;
+       if (*termination++ != ')')
+         abort ();
+       if (*termination && *termination != ' ' && *termination != '\t')
+         abort ();
+       /* Temporarily null-terminate the value.  */
+       save_char = *termination;
+       *termination = '\0';
+       /* Install the assertion.  */
+       cpp_assert (pfile, assertion);
+       *termination = (char) save_char;
+       p = termination;
+       while (*p == ' ' || *p == '\t')
+         p++;
+      } else {
+       abort ();
+      }
+    }
+  }
+
+  /* Now handle the command line options.  */
+
+  /* Do -U's, -D's and -A's in the order they were seen.  */
+  /* First reverse the list.  */
+  opts->pending = nreverse_pending (opts->pending);
+
+  for (pend = opts->pending;  pend;  pend = pend->next)
+    {
+      if (pend->cmd != NULL && pend->cmd[0] == '-')
+       {
+         switch (pend->cmd[1])
+           {
+           case 'U':
+             if (opts->debug_output)
+               output_line_command (pfile, 0, same_file);
+             cpp_undef (pfile, pend->arg);
+             break;
+           case 'D':
+             if (opts->debug_output)
+               output_line_command (pfile, 0, same_file);
+             cpp_define (pfile, pend->arg);
+             break;
+           case 'A':
+             cpp_assert (pfile, pend->arg);
+             break;
+           }
+       }
+    }
+
+  opts->done_initializing = 1;
+
+  { /* Read the appropriate environment variable and if it exists
+       replace include_defaults with the listed path.  */
+    char *epath = 0;
+    switch ((opts->objc << 1) + opts->cplusplus)
+      {
+      case 0:
+       GET_ENV_PATH_LIST (epath, "C_INCLUDE_PATH");
+       break;
+      case 1:
+       GET_ENV_PATH_LIST (epath, "CPLUS_INCLUDE_PATH");
+       break;
+      case 2:
+       GET_ENV_PATH_LIST (epath, "OBJC_INCLUDE_PATH");
+       break;
+      case 3:
+       GET_ENV_PATH_LIST (epath, "OBJCPLUS_INCLUDE_PATH");
+       break;
+      }
+    /* If the environment var for this language is set,
+       add to the default list of include directories.  */
+    if (epath) {
+      char *nstore = (char *) alloca (strlen (epath) + 2);
+      int num_dirs;
+      char *startp, *endp;
+
+      for (num_dirs = 1, startp = epath; *startp; startp++)
+       if (*startp == PATH_SEPARATOR)
+         num_dirs++;
+      include_defaults
+       = (struct default_include *) xmalloc ((num_dirs
+                                              * sizeof (struct default_include))
+                                             + sizeof (include_defaults_array));
+      startp = endp = epath;
+      num_dirs = 0;
+      while (1) {
+        /* Handle cases like c:/usr/lib:d:/gcc/lib */
+        if ((*endp == PATH_SEPARATOR)
+            || *endp == 0) {
+         strncpy (nstore, startp, endp-startp);
+         if (endp == startp)
+           strcpy (nstore, ".");
+         else
+           nstore[endp-startp] = '\0';
+
+         include_defaults[num_dirs].fname = xstrdup (nstore);
+         include_defaults[num_dirs].component = 0;
+         include_defaults[num_dirs].cplusplus = opts->cplusplus;
+         include_defaults[num_dirs].cxx_aware = 1;
+         num_dirs++;
+         if (*endp == '\0')
+           break;
+         endp = startp = endp + 1;
+       } else
+         endp++;
+      }
+      /* Put the usual defaults back in at the end.  */
+      bcopy ((char *) include_defaults_array,
+            (char *) &include_defaults[num_dirs],
+            sizeof (include_defaults_array));
+    }
+  }
+
+  /* Unless -fnostdinc,
+     tack on the standard include file dirs to the specified list */
+  if (!opts->no_standard_includes) {
+    struct default_include *p = include_defaults;
+    char *specd_prefix = opts->include_prefix;
+    char *default_prefix = xstrdup (GCC_INCLUDE_DIR);
+    int default_len = 0;
+    /* Remove the `include' from /usr/local/lib/gcc.../include.  */
+    if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) {
+      default_len = strlen (default_prefix) - 7;
+      default_prefix[default_len] = 0;
+    }
+    /* Search "translated" versions of GNU directories.
+       These have /usr/local/lib/gcc... replaced by specd_prefix.  */
+    if (specd_prefix != 0 && default_len != 0)
+      for (p = include_defaults; p->fname; p++) {
+       /* Some standard dirs are only for C++.  */
+       if (!p->cplusplus
+           || (opts->cplusplus && !opts->no_standard_cplusplus_includes)) {
+         /* Does this dir start with the prefix?  */
+         if (!strncmp (p->fname, default_prefix, default_len)) {
+           /* Yes; change prefix and add to search list.  */
+           int this_len = strlen (specd_prefix)
+                          + strlen (p->fname) - default_len;
+           char *str = (char *) xmalloc (this_len + 1);
+           strcpy (str, specd_prefix);
+           strcat (str, p->fname + default_len);
+
+           append_include_chain (pfile, &opts->system_include,
+                                 str, !p->cxx_aware);
+         }
+       }
+      }
+    /* Search ordinary names for GNU include directories.  */
+    for (p = include_defaults; p->fname; p++) {
+      /* Some standard dirs are only for C++.  */
+      if (!p->cplusplus
+         || (opts->cplusplus && !opts->no_standard_cplusplus_includes)) {
+       const char *str = update_path (p->fname, p->component);
+       append_include_chain (pfile, &opts->system_include,
+                             str, !p->cxx_aware);
+      }
+    }
+  }
+
+  merge_include_chains (opts);
+
+  /* With -v, print the list of dirs to search.  */
+  if (opts->verbose) {
+    struct file_name_list *p;
+    cpp_notice ("#include \"...\" search starts here:\n");
+    for (p = opts->quote_include; p; p = p->next) {
+      if (p == opts->bracket_include)
+       cpp_notice ("#include <...> search starts here:\n");
+      fprintf (stderr, " %s\n", p->name);
+    }
+    cpp_notice ("End of search list.\n");
+  }
+
+  /* Copy the entire contents of the main input file into
+     the stacked input buffer previously allocated for it.  */
+  if (fname == NULL || *fname == 0) {
+    fname = "";
+    f = 0;
+  } else if ((f = open (fname, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666)) < 0)
+    cpp_pfatal_with_name (pfile, fname);
+
+  /* -MG doesn't select the form of output and must be specified with one of
+     -M or -MM.  -MG doesn't make sense with -MD or -MMD since they don't
+     inhibit compilation.  */
+  if (opts->print_deps_missing_files
+      && (opts->print_deps == 0 || !opts->no_output))
+    {
+      cpp_fatal (pfile, "-MG must be specified with one of -M or -MM");
+      return 0;
+    }
+
+  /* Either of two environment variables can specify output of deps.
+     Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
+     where OUTPUT_FILE is the file to write deps info to
+     and DEPS_TARGET is the target to mention in the deps.  */
+
+  if (opts->print_deps == 0
+      && (getenv ("SUNPRO_DEPENDENCIES") != 0
+         || getenv ("DEPENDENCIES_OUTPUT") != 0)) {
+    char *spec = getenv ("DEPENDENCIES_OUTPUT");
+    char *s;
+    char *output_file;
+
+    if (spec == 0)
+      {
+       spec = getenv ("SUNPRO_DEPENDENCIES");
+       opts->print_deps = 2;
+      }
+    else
+      opts->print_deps = 1;
+
+    s = spec;
+    /* Find the space before the DEPS_TARGET, if there is one.  */
+    /* This should use index.  (mrs) */
+    while (*s != 0 && *s != ' ') s++;
+    if (*s != 0)
+      {
+       opts->deps_target = s + 1;
+       output_file = (char *) xmalloc (s - spec + 1);
+       bcopy (spec, output_file, s - spec);
+       output_file[s - spec] = 0;
+      }
+    else
+      {
+       opts->deps_target = 0;
+       output_file = spec;
+      }
+
+    opts->deps_file = output_file;
+    opts->print_deps_append = 1;
+  }
+
+  /* For -M, print the expected object file name
+     as the target of this Make-rule.  */
+  if (opts->print_deps)
+    {
+      pfile->deps_allocated_size = 200;
+      pfile->deps_buffer = (char *) xmalloc (pfile->deps_allocated_size);
+      pfile->deps_buffer[0] = 0;
+      pfile->deps_size = 0;
+      pfile->deps_column = 0;
+
+      if (opts->deps_target)
+       deps_output (pfile, opts->deps_target, ':');
+      else if (*opts->in_fname == 0)
+       deps_output (pfile, "-", ':');
+      else
+       {
+         char *p, *q, *r;
+         int len, x;
+         static char *known_suffixes[] = { ".c", ".C", ".s", ".S", ".m",
+                                    ".cc", ".cxx", ".cpp", ".cp",
+                                    ".c++", 0
+                                  };
+
+         /* Discard all directory prefixes from filename.  */
+         if ((q = rindex (opts->in_fname, '/')) != NULL
+#ifdef DIR_SEPARATOR
+             && (q = rindex (opts->in_fname, DIR_SEPARATOR)) != NULL
+#endif
+             )
+           ++q;
+         else
+           q = opts->in_fname;
+
+         /* Copy remainder to mungable area.  */
+         p = (char *) alloca (strlen(q) + 8);
+         strcpy (p, q);
+
+         /* Output P, but remove known suffixes.  */
+         len = strlen (p);
+         q = p + len;
+         /* Point to the filename suffix.  */
+         r = rindex (p, '.');
+         /* Compare against the known suffixes.  */
+         x = 0;
+         while (known_suffixes[x] != 0)
+           {
+             if (strncmp (known_suffixes[x], r, q - r) == 0)
+               {
+                 /* Make q point to the bit we're going to overwrite
+                    with an object suffix.  */
+                 q = r;
+                 break;
+               }
+             x++;
+           }
+
+         /* Supply our own suffix.  */
+#ifndef VMS
+         strcpy (q, ".o");
+#else
+         strcpy (q, ".obj");
+#endif
+
+         deps_output (pfile, p, ':');
+         deps_output (pfile, opts->in_fname, ' ');
+       }
+    }
+
+  /* Must call finclude() on the main input before processing
+     -include switches; otherwise the -included text winds up
+     after the main input. */
+  ih_fake = (struct include_hash *) xmalloc (sizeof (struct include_hash));
+  ih_fake->next = 0;
+  ih_fake->next_this_file = 0;
+  ih_fake->foundhere = ABSOLUTE_PATH;  /* well sort of ... */
+  ih_fake->name = fname;
+  ih_fake->control_macro = 0;
+  ih_fake->buf = (char *)-1;
+  ih_fake->limit = 0;
+  if (!finclude (pfile, f, ih_fake))
+    return 0;
+  output_line_command (pfile, 0, same_file);
+  pfile->only_seen_white = 2;
+
+  /* The -imacros files can be scanned now, but the -include files
+     have to be pushed onto the include stack and processed later,
+     in the main loop calling cpp_get_token.  That means the -include
+     files have to be processed in reverse order of the pending list,
+     which means the pending list has to be reversed again, which
+     means the -imacros files have to be done separately and first. */
+  
+  pfile->no_record_file++;
+  opts->no_output++;
+  for (pend = opts->pending; pend; pend = pend->next)
+    {
+      if (pend->cmd != NULL)
+        {
+         if (strcmp (pend->cmd, "-imacros") == 0)
+           {
+             int fd = open (pend->arg, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666);
+             if (fd < 0)
+               {
+                 cpp_perror_with_name (pfile, pend->arg);
+                 return 0;
+               }
+             if (!cpp_push_buffer (pfile, NULL, 0))
+               return 0;
+
+             ih_fake = (struct include_hash *)
+                 xmalloc (sizeof (struct include_hash));
+             ih_fake->next = 0;
+             ih_fake->next_this_file = 0;
+             ih_fake->foundhere = ABSOLUTE_PATH;  /* well sort of ... */
+             ih_fake->name = pend->arg;
+             ih_fake->control_macro = 0;
+             ih_fake->buf = (char *)-1;
+             ih_fake->limit = 0;
+             if (!finclude (pfile, fd, ih_fake))
+               cpp_scan_buffer (pfile);
+             free (ih_fake);
+           }
+       }
+    }
+  opts->no_output--;
+  opts->pending = nreverse_pending (opts->pending);
+  for (pend = opts->pending; pend; pend = pend->next)
+    {
+      if (pend->cmd != NULL)
+        {
+         if (strcmp (pend->cmd, "-include") == 0)
+           {
+             int fd = open (pend->arg, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666);
+             if (fd < 0)
+               {
+                 cpp_perror_with_name (pfile, pend->arg);
+                 return 0;
+               }
+             if (!cpp_push_buffer (pfile, NULL, 0))
+               return 0;
+
+             ih_fake = (struct include_hash *)
+                 xmalloc (sizeof (struct include_hash));
+             ih_fake->next = 0;
+             ih_fake->next_this_file = 0;
+             ih_fake->foundhere = ABSOLUTE_PATH;  /* well sort of ... */
+             ih_fake->name = pend->arg;
+             ih_fake->control_macro = 0;
+             ih_fake->buf = (char *)-1;
+             ih_fake->limit = 0;
+             if (finclude (pfile, fd, ih_fake))
+               output_line_command (pfile, 0, enter_file);
+           }
+       }
+    }
+  pfile->no_record_file--;
+
+  /* Free the pending list.  */
+  for (pend = opts->pending;  pend; )
+    {
+      struct cpp_pending *next = pend->next;
+      free (pend);
+      pend = next;
+    }
+  opts->pending = NULL;
+
+  return 1;
+}
+
+/* This is called at the end of preprocessing.  It pops the
+   last buffer and writes dependency output.  It should also
+   clear macro definitions, such that you could call cpp_start_read
+   with a new filename to restart processing. */
+void
+cpp_finish (pfile)
+     cpp_reader *pfile;
+{
+  struct cpp_options *opts = CPP_OPTIONS (pfile);
+
+  if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != CPP_NULL_BUFFER (pfile))
+    cpp_fatal (pfile,
+              "cpplib internal error: buffers still stacked in cpp_finish");
+  cpp_pop_buffer (pfile);
+  
+  if (opts->print_deps)
+    {
+      /* Stream on which to print the dependency information.  */
+      FILE *deps_stream;
+
+      /* Don't actually write the deps file if compilation has failed.  */
+      if (pfile->errors == 0)
+       {
+         char *deps_mode = opts->print_deps_append ? "a" : "w";
+         if (opts->deps_file == 0)
+           deps_stream = stdout;
+         else if ((deps_stream = fopen (opts->deps_file, deps_mode)) == 0)
+           cpp_pfatal_with_name (pfile, opts->deps_file);
+         fputs (pfile->deps_buffer, deps_stream);
+         putc ('\n', deps_stream);
+         if (opts->deps_file)
+           {
+             if (ferror (deps_stream) || fclose (deps_stream) != 0)
+               cpp_fatal (pfile, "I/O error on output");
+           }
+       }
+    }
+}
+
+/* Handle one command-line option in (argc, argv).
+   Can be called multiple times, to handle multiple sets of options.
+   Returns number of strings consumed.  */
+int
+cpp_handle_option (pfile, argc, argv)
+     cpp_reader *pfile;
+     int argc;
+     char **argv;
+{
+  struct cpp_options *opts = CPP_OPTIONS (pfile);
+  int i = 0;
+
+  if (user_label_prefix == NULL)
+    user_label_prefix = USER_LABEL_PREFIX;
+
+  if (argv[i][0] != '-') {
+    if (opts->out_fname != NULL)
+      {
+       print_help ();
+       cpp_fatal (pfile, "Too many arguments");
+      }
+    else if (opts->in_fname != NULL)
+      opts->out_fname = argv[i];
+    else
+      opts->in_fname = argv[i];
+  } else {
+    switch (argv[i][1]) {
+      
+    missing_filename:
+      cpp_fatal (pfile, "Filename missing after `%s' option", argv[i]);
+      return argc;
+    missing_dirname:
+      cpp_fatal (pfile, "Directory name missing after `%s' option", argv[i]);
+      return argc;
+      
+    case 'f':
+      if (!strcmp (argv[i], "-fleading-underscore"))
+       user_label_prefix = "_";
+      else if (!strcmp (argv[i], "-fno-leading-underscore"))
+       user_label_prefix = "";
+      break;
+
+    case 'I':                  /* Add directory to path for includes.  */
+      if (!strcmp (argv[i] + 2, "-"))
+        {
+         if (! opts->ignore_srcdir)
+           {
+             opts->ignore_srcdir = 1;
+             /* Don't use any preceding -I directories for #include <...>. */
+             opts->quote_include = opts->bracket_include;
+             opts->bracket_include = 0;
+           }
+       }
+      else
+       {
+         char *fname;
+         if (argv[i][2] != 0)
+           fname = argv[i] + 2;
+         else if (i + 1 == argc)
+           goto missing_dirname;
+         else
+           fname = argv[++i];
+         append_include_chain (pfile, &opts->bracket_include, fname, 0);
+       }
+      break;
+
+    case 'i':
+      /* Add directory to beginning of system include path, as a system
+        include directory. */
+      if (!strcmp (argv[i], "-isystem"))
+        {
+         if (i + 1 == argc)
+           goto missing_filename;
+         append_include_chain (pfile, &opts->system_include, argv[++i], 1);
+       }
+      /* Add directory to end of path for includes,
+        with the default prefix at the front of its name.  */
+      else if (!strcmp (argv[i], "-iwithprefix"))
+        {
+         char *fname;
+         if (i + 1 == argc)
+           goto missing_dirname;
+         ++i;
+
+         if (opts->include_prefix != 0)
+           {
+             fname = xmalloc (strlen (opts->include_prefix)
+                              + strlen (argv[i]) + 1);
+             strcpy (fname, opts->include_prefix);
+             strcat (fname, argv[i]);
+           }
+         else
+           {
+             fname = xmalloc (strlen (GCC_INCLUDE_DIR)
+                              + strlen (argv[i]) + 1);
+             strcpy (fname, GCC_INCLUDE_DIR);
+             /* Remove the `include' from /usr/local/lib/gcc.../include.  */
+             if (!strcmp (fname + strlen (fname) - 8, "/include"))
+               fname[strlen (fname) - 7] = 0;
+             strcat (fname, argv[i]);
+           }
+         
+         append_include_chain (pfile, &opts->system_include, fname, 0);
+      }
+      /* Add directory to main path for includes,
+        with the default prefix at the front of its name.  */
+      else if (!strcmp (argv[i], "-iwithprefix"))
+        {
+         char *fname;
+         if (i + 1 == argc)
+           goto missing_dirname;
+         ++i;
+
+         if (opts->include_prefix != 0)
+           {
+             fname = xmalloc (strlen (opts->include_prefix)
+                              + strlen (argv[i]) + 1);
+             strcpy (fname, opts->include_prefix);
+             strcat (fname, argv[i]);
+           }
+         else
+           {
+             fname = xmalloc (strlen (GCC_INCLUDE_DIR)
+                              + strlen (argv[i]) + 1);
+             strcpy (fname, GCC_INCLUDE_DIR);
+             /* Remove the `include' from /usr/local/lib/gcc.../include.  */
+             if (!strcmp (fname + strlen (fname) - 8, "/include"))
+               fname[strlen (fname) - 7] = 0;
+             strcat (fname, argv[i]);
+           }
+         
+         append_include_chain (pfile, &opts->bracket_include, fname, 0);
+        }
+      /* Add directory to end of path for includes.  */
+      else if (!strcmp (argv[i], "-idirafter"))
+        {
+         if (i + 1 == argc)
+           goto missing_dirname;
+         append_include_chain (pfile, &opts->after_include, argv[++i], 0);
+       }
+      else if (!strcmp (argv[i], "-include") || !strcmp (argv[i], "-imacros"))
+        {
+         if (i + 1 == argc)
+           goto missing_filename;
+         else
+           push_pending (pfile, argv[i], argv[i+1]), i++;
+        }
+      else if (!strcmp (argv[i], "-iprefix"))
+        {
+         if (i + 1 == argc)
+           goto missing_filename;
+         else
+             opts->include_prefix = argv[++i];
+       }
+      else if (!strcmp (argv[i], "-ifoutput"))
+       opts->output_conditionals = 1;
+
+      break;
+      
+    case 'o':
+      if (opts->out_fname != NULL)
+       {
+         cpp_fatal (pfile, "Output filename specified twice");
+         return argc;
+       }
+      if (i + 1 == argc)
+       goto missing_filename;
+      opts->out_fname = argv[++i];
+      if (!strcmp (opts->out_fname, "-"))
+       opts->out_fname = "";
+      break;
+      
+    case 'p':
+      if (!strcmp (argv[i], "-pedantic"))
+       CPP_PEDANTIC (pfile) = 1;
+      else if (!strcmp (argv[i], "-pedantic-errors")) {
+       CPP_PEDANTIC (pfile) = 1;
+       opts->pedantic_errors = 1;
+      }
+#if 0
+      else if (!strcmp (argv[i], "-pcp")) {
+       char *pcp_fname = argv[++i];
+       pcp_outfile = ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
+                      ? fopen (pcp_fname, "w")
+                      : fdopen (dup (fileno (stdout)), "w"));
+       if (pcp_outfile == 0)
+         cpp_pfatal_with_name (pfile, pcp_fname);
+       no_precomp = 1;
+      }
+#endif
+      break;
+      
+    case 't':
+      if (!strcmp (argv[i], "-traditional")) {
+       opts->traditional = 1;
+       opts->cplusplus_comments = 0;
+      } else if (!strcmp (argv[i], "-trigraphs")) {
+       if (!opts->chill)
+         opts->trigraphs = 1;
+      }
+      break;
+      
+    case 'l':
+      if (! strcmp (argv[i], "-lang-c"))
+       opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
+         opts->c9x = 1, opts->objc = 0;
+      if (! strcmp (argv[i], "-lang-c89"))
+       opts->cplusplus = 0, opts->cplusplus_comments = 0, opts->c89 = 1,
+         opts->c9x = 0, opts->objc = 0;
+      if (! strcmp (argv[i], "-lang-c++"))
+       opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
+         opts->c9x = 0, opts->objc = 0;
+      if (! strcmp (argv[i], "-lang-objc"))
+       opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
+         opts->c9x = 0, opts->objc = 1;
+      if (! strcmp (argv[i], "-lang-objc++"))
+       opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
+         opts->c9x = 0, opts->objc = 1;
+      if (! strcmp (argv[i], "-lang-asm"))
+       opts->lang_asm = 1;
+      if (! strcmp (argv[i], "-lint"))
+       opts->for_lint = 1;
+      if (! strcmp (argv[i], "-lang-chill"))
+       opts->objc = 0, opts->cplusplus = 0, opts->chill = 1,
+         opts->traditional = 1, opts->trigraphs = 0;
+      break;
+      
+    case '+':
+      opts->cplusplus = 1, opts->cplusplus_comments = 1;
+      break;
+
+    case 's':
+      if (!strcmp (argv[i], "-std=iso9899:1990")
+         || !strcmp (argv[i], "-std=iso9899:199409")
+         || !strcmp (argv[i], "-std=c89")
+         || !strcmp (argv[i], "-std=gnu89"))
+         opts->cplusplus = 0, opts->cplusplus_comments = 0,
+           opts->c89 = 1, opts->c9x = 0, opts->objc = 0;
+      else if (!strcmp (argv[i], "-std=iso9899:199x")
+              || !strcmp (argv[i], "-std=c9x")
+              || !strcmp (argv[i], "-std=gnu9x"))
+       opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
+         opts->c9x = 1, opts->objc = 0;
+      break;
+
+    case 'w':
+      opts->inhibit_warnings = 1;
+      break;
+      
+    case 'W':
+      if (!strcmp (argv[i], "-Wtrigraphs"))
+       opts->warn_trigraphs = 1;
+      else if (!strcmp (argv[i], "-Wno-trigraphs"))
+       opts->warn_trigraphs = 0;
+      else if (!strcmp (argv[i], "-Wcomment"))
+       opts->warn_comments = 1;
+      else if (!strcmp (argv[i], "-Wno-comment"))
+       opts->warn_comments = 0;
+      else if (!strcmp (argv[i], "-Wcomments"))
+       opts->warn_comments = 1;
+      else if (!strcmp (argv[i], "-Wno-comments"))
+       opts->warn_comments = 0;
+      else if (!strcmp (argv[i], "-Wtraditional"))
+       opts->warn_stringify = 1;
+      else if (!strcmp (argv[i], "-Wno-traditional"))
+       opts->warn_stringify = 0;
+      else if (!strcmp (argv[i], "-Wundef"))
+       opts->warn_undef = 1;
+      else if (!strcmp (argv[i], "-Wno-undef"))
+       opts->warn_undef = 0;
+      else if (!strcmp (argv[i], "-Wimport"))
+       opts->warn_import = 1;
+      else if (!strcmp (argv[i], "-Wno-import"))
+       opts->warn_import = 0;
+      else if (!strcmp (argv[i], "-Werror"))
+       opts->warnings_are_errors = 1;
+      else if (!strcmp (argv[i], "-Wno-error"))
+       opts->warnings_are_errors = 0;
+      else if (!strcmp (argv[i], "-Wall"))
+       {
+         opts->warn_trigraphs = 1;
+         opts->warn_comments = 1;
+       }
+      break;
+      
+    case 'M':
+      /* The style of the choices here is a bit mixed.
+        The chosen scheme is a hybrid of keeping all options in one string
+        and specifying each option in a separate argument:
+        -M|-MM|-MD file|-MMD file [-MG].  An alternative is:
+        -M|-MM|-MD file|-MMD file|-MG|-MMG; or more concisely:
+        -M[M][G][D file].  This is awkward to handle in specs, and is not
+        as extensible.  */
+      /* ??? -MG must be specified in addition to one of -M or -MM.
+        This can be relaxed in the future without breaking anything.
+        The converse isn't true.  */
+      
+      /* -MG isn't valid with -MD or -MMD.  This is checked for later.  */
+      if (!strcmp (argv[i], "-MG"))
+       {
+         opts->print_deps_missing_files = 1;
+         break;
+       }
+      if (!strcmp (argv[i], "-M"))
+       opts->print_deps = 2;
+      else if (!strcmp (argv[i], "-MM"))
+       opts->print_deps = 1;
+      else if (!strcmp (argv[i], "-MD"))
+       opts->print_deps = 2;
+      else if (!strcmp (argv[i], "-MMD"))
+       opts->print_deps = 1;
+      /* For -MD and -MMD options, write deps on file named by next arg.  */
+      if (!strcmp (argv[i], "-MD") || !strcmp (argv[i], "-MMD"))
+       {
+         if (i+1 == argc)
+           goto missing_filename;
+         opts->deps_file = argv[++i];
+       }
+      else
+       {
+         /* For -M and -MM, write deps on standard output
+            and suppress the usual output.  */
+         opts->no_output = 1;
+       }         
+      break;
+      
+    case 'd':
+      {
+       char *p = argv[i] + 2;
+       char c;
+       while ((c = *p++) != 0) {
+         /* Arg to -d specifies what parts of macros to dump */
+         switch (c) {
+         case 'M':
+           opts->dump_macros = dump_only;
+           opts->no_output = 1;
+           break;
+         case 'N':
+           opts->dump_macros = dump_names;
+           break;
+         case 'D':
+           opts->dump_macros = dump_definitions;
+           break;
+         case 'I':
+           opts->dump_includes = 1;
+           break;
+         }
+       }
+      }
+    break;
+    
+    case 'g':
+      if (argv[i][2] == '3')
+       opts->debug_output = 1;
+      break;
+      
+    case '-':
+      if (strcmp (argv[i], "--help") != 0)
+       return i;
+      print_help ();
+      break;
+       
+    case 'v':
+      cpp_notice ("GNU CPP version %s", version_string);
+#ifdef TARGET_VERSION
+      TARGET_VERSION;
+#endif
+      fprintf (stderr, "\n");
+      opts->verbose = 1;
+      break;
+      
+    case 'H':
+      opts->print_include_names = 1;
+      break;
+      
+    case 'D':
+      if (argv[i][2] != 0)
+       push_pending (pfile, "-D", argv[i] + 2);
+      else if (i + 1 == argc)
+       {
+         cpp_fatal (pfile, "Macro name missing after -D option");
+         return argc;
+       }
+      else
+       i++, push_pending (pfile, "-D", argv[i]);
+      break;
+      
+    case 'A':
+      {
+       char *p;
+       
+       if (argv[i][2] != 0)
+         p = argv[i] + 2;
+       else if (i + 1 == argc)
+         {
+           cpp_fatal (pfile, "Assertion missing after -A option");
+           return argc;
+         }
+       else
+         p = argv[++i];
+       
+       if (!strcmp (p, "-")) {
+         struct cpp_pending **ptr;
+         /* -A- eliminates all predefined macros and assertions.
+            Let's include also any that were specified earlier
+            on the command line.  That way we can get rid of any
+            that were passed automatically in from GCC.  */
+         opts->inhibit_predefs = 1;
+         for (ptr = &opts->pending; *ptr != NULL; )
+           {
+             struct cpp_pending *pend = *ptr;
+             if (pend->cmd && pend->cmd[0] == '-'
+                 && (pend->cmd[1] == 'D' || pend->cmd[1] == 'A'))
+               {
+                 *ptr = pend->next;
+                 free (pend);
+               }
+             else
+               ptr = &pend->next;
+           }
+       } else {
+         push_pending (pfile, "-A", p);
+       }
+      }
+    break;
+    
+    case 'U':          /* JF #undef something */
+      if (argv[i][2] != 0)
+       push_pending (pfile, "-U", argv[i] + 2);
+      else if (i + 1 == argc)
+       {
+         cpp_fatal (pfile, "Macro name missing after -U option");
+         return argc;
+       }
+      else
+       push_pending (pfile, "-U", argv[i+1]), i++;
+      break;
+      
+    case 'C':
+      opts->put_out_comments = 1;
+      break;
+      
+    case 'E':                  /* -E comes from cc -E; ignore it.  */
+      break;
+      
+    case 'P':
+      opts->no_line_commands = 1;
+      break;
+      
+    case '$':                  /* Don't include $ in identifiers.  */
+      opts->dollars_in_ident = 0;
+      break;
+      
+    case 'n':
+      if (!strcmp (argv[i], "-nostdinc"))
+       /* -nostdinc causes no default include directories.
+          You must specify all include-file directories with -I.  */
+       opts->no_standard_includes = 1;
+      else if (!strcmp (argv[i], "-nostdinc++"))
+       /* -nostdinc++ causes no default C++-specific include directories. */
+       opts->no_standard_cplusplus_includes = 1;
+#if 0
+      else if (!strcmp (argv[i], "-noprecomp"))
+       no_precomp = 1;
+#endif
+      break;
+      
+    case 'r':
+      if (!strcmp (argv[i], "-remap"))
+       opts->remap = 1;
+      break;
+      
+    case 'u':
+      /* Sun compiler passes undocumented switch "-undef".
+        Let's assume it means to inhibit the predefined symbols.  */
+      opts->inhibit_predefs = 1;
+      break;
+      
+    case '\0': /* JF handle '-' as file name meaning stdin or stdout */
+      if (opts->in_fname == NULL) {
+       opts->in_fname = "";
+       break;
+      } else if (opts->out_fname == NULL) {
+       opts->out_fname = "";
+       break;
+      }        /* else fall through into error */
+
+    default:
+      return i;
+    }
+  }
+
+  return i + 1;
+}
+
+/* Handle command-line options in (argc, argv).
+   Can be called multiple times, to handle multiple sets of options.
+   Returns if an unrecognized option is seen.
+   Returns number of strings consumed.  */
+
+int
+cpp_handle_options (pfile, argc, argv)
+     cpp_reader *pfile;
+     int argc;
+     char **argv;
+{
+  int i;
+  int strings_processed;
+  for (i = 0; i < argc; i += strings_processed)
+    {
+      strings_processed = cpp_handle_option (pfile, argc - i, argv + i);
+      if (strings_processed == 0)
+       break;
+    }
+  return i;
+}
+
+static void
+print_help ()
+{
+  cpp_notice ("Usage: %s [switches] input output\n", progname);
+  fputs (_("\
+Switches:\n\
+  -include <file>           Include the contents of <file> before other files\n\
+  -imacros <file>           Accept definition of macros in <file>\n\
+  -iprefix <path>           Specify <path> as a prefix for next two options\n\
+  -iwithprefix <dir>        Add <dir> to the end of the system include path\n\
+  -iwithprefixbefore <dir>  Add <dir> to the end of the main include path\n\
+  -isystem <dir>            Add <dir> to the start of the system include path\n\
+  -idirafter <dir>          Add <dir> to the end of the system include path\n\
+  -I <dir>                  Add <dir> to the end of the main include path\n\
+  -nostdinc                 Do not search system include directories\n\
+                             (dirs specified with -isystem will still be used)\n\
+  -nostdinc++               Do not search system include directories for C++\n\
+  -o <file>                 Put output into <file>\n\
+  -pedantic                 Issue all warnings demanded by strict ANSI C\n\
+  -traditional              Follow K&R pre-processor behaviour\n\
+  -trigraphs                Support ANSI C trigraphs\n\
+  -lang-c                   Assume that the input sources are in C\n\
+  -lang-c89                 Assume that the input sources are in C89\n\
+  -lang-c++                 Assume that the input sources are in C++\n\
+  -lang-objc                Assume that the input sources are in ObjectiveC\n\
+  -lang-objc++              Assume that the input sources are in ObjectiveC++\n\
+  -lang-asm                 Assume that the input sources are in assembler\n\
+  -lang-chill               Assume that the input sources are in Chill\n\
+  -std=<std name>           Specify the conformance standard; one of:\n\
+                            gnu89, gnu9x, c89, c9x, iso9899:1990,\n\
+                            iso9899:199409, iso9899:199x\n\
+
+  -+                        Allow parsing of C++ style features\n\
+  -w                        Inhibit warning messages\n\
+  -Wtrigraphs               Warn if trigraphs are encountered\n\
+  -Wno-trigraphs            Do not warn about trigraphs\n\
+  -Wcomment{s}              Warn if one comment starts inside another\n\
+  -Wno-comment{s}           Do not warn about comments\n\
+  -Wtraditional             Warn if a macro argument is/would be turned into\n\
+                             a string if -traditional is specified\n\
+  -Wno-traditional          Do not warn about stringification\n\
+  -Wundef                   Warn if an undefined macro is used by #if\n\
+  -Wno-undef                Do not warn about testing undefined macros\n\
+  -Wimport                  Warn about the use of the #import directive\n\
+  -Wno-import               Do not warn about the use of #import\n\
+  -Werror                   Treat all warnings as errors\n\
+  -Wno-error                Do not treat warnings as errors\n\
+  -Wall                     Enable all preprocessor warnings\n\
+  -M                        Generate make dependencies\n\
+  -MM                       As -M, but ignore system header files\n\
+  -MD                       As -M, but put output in a .d file\n\
+  -MMD                      As -MD, but ignore system header files\n\
+  -MG                       Treat missing header file as generated files\n\
+  -g                        Include #define and #undef directives in the output\n\
+  -D<macro>                 Define a <macro> with string '1' as its value\n\
+  -D<macro>=<val>           Define a <macro> with <val> as its value\n\
+  -A<question> (<answer>)   Assert the <answer> to <question>\n\
+  -U<macro>                 Undefine <macro> \n\
+  -u or -undef              Do not predefine any macros\n\
+  -v                        Display the version number\n\
+  -H                        Print the name of header files as they are used\n\
+  -C                        Do not discard comments\n\
+  -dM                       Display a list of macro definitions active at end\n\
+  -dD                       Preserve macro definitions in output\n\
+  -dN                       As -dD except that only the names are preserved\n\
+  -dI                       Include #include directives in the output\n\
+  -ifoutput                 Describe skipped code blocks in output \n\
+  -P                        Do not generate #line directives\n\
+  -$                        Do not allow '$' in identifiers\n\
+  -remap                    Remap file names when including files.\n\
+  -h or --help              Display this information\n\
+"), stdout);
+}
index 838935f..d7499dd 100644 (file)
@@ -21,75 +21,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "config.h"
 #include "system.h"
 
-#ifndef STDC_VALUE
-#define STDC_VALUE 1
-#endif
-
 #include "cpplib.h"
 #include "cpphash.h"
-#include "output.h"
 #include "intl.h"
-#include "prefix.h"
-
-#ifndef GET_ENV_PATH_LIST
-#define GET_ENV_PATH_LIST(VAR,NAME)    do { (VAR) = getenv (NAME); } while (0)
-#endif
-
-/* By default, colon separates directories in a path.  */
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR ':'
-#endif
-
-#ifndef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/usr/include"
-#endif
-
-/* Symbols to predefine.  */
-
-#ifdef CPP_PREDEFINES
-static char *predefs = CPP_PREDEFINES;
-#else
-static char *predefs = "";
-#endif
-\f
-/* We let tm.h override the types used here, to handle trivial differences
-   such as the choice of unsigned int or long unsigned int for size_t.
-   When machines start needing nontrivial differences in the size type,
-   it would be best to do something here to figure out automatically
-   from other information what type to use.  */
-
-/* The string value for __SIZE_TYPE__.  */
-
-#ifndef SIZE_TYPE
-#define SIZE_TYPE "long unsigned int"
-#endif
 
-/* The string value for __PTRDIFF_TYPE__.  */
-
-#ifndef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-#endif
-
-/* The string value for __WCHAR_TYPE__.  */
-
-#ifndef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-#endif
-#define CPP_WCHAR_TYPE(PFILE) \
-       (CPP_OPTIONS (PFILE)->cplusplus ? "__wchar_t" : WCHAR_TYPE)
-
-/* The string value for __USER_LABEL_PREFIX__ */
-
-#ifndef USER_LABEL_PREFIX
-#define USER_LABEL_PREFIX ""
-#endif
-
-/* The string value for __REGISTER_PREFIX__ */
-
-#ifndef REGISTER_PREFIX
-#define REGISTER_PREFIX ""
-#endif
-\f
 #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
 #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
 
@@ -98,8 +33,8 @@ static char *predefs = "";
 #define GETC() CPP_BUF_GET (CPP_BUFFER (pfile))
 #define PEEKC() CPP_BUF_PEEK (CPP_BUFFER (pfile))
 /* CPP_IS_MACRO_BUFFER is true if the buffer contains macro expansion.
-   (Note that it is false while we're expanding marco *arguments*.) */
-#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->cleanup == macro_cleanup)
+   (Note that it is false while we're expanding macro *arguments*.) */
+#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->data != NULL)
 
 /* Move all backslash-newline pairs out of embarrassing places.
    Exchange all such pairs following BP
@@ -116,103 +51,20 @@ static char *predefs = "";
     while ((C) == '\\' && PEEKC() == '\n') { FORWARD(1); (C) = GETC(); }\
   } while(0)
 
-struct cpp_pending {
-  struct cpp_pending *next;
-  char *cmd;
-  char *arg;
-};
-
 /* Forward declarations.  */
 
-extern void cpp_hash_cleanup PARAMS ((cpp_reader *));
-
 static char *my_strerror               PROTO ((int));
-static void path_include               PROTO ((cpp_reader *, char *));
-static void initialize_builtins                PROTO ((cpp_reader *));
 static void validate_else              PROTO ((cpp_reader *, char *));
-static int comp_def_part               PROTO ((int, U_CHAR *, int, U_CHAR *,
-                                               int, int));
-#ifdef abort
-extern void fancy_abort ();
-#endif
-static int check_macro_name            PROTO ((cpp_reader *, U_CHAR *, int));
-static int compare_defs                        PROTO ((cpp_reader *,
-                                               DEFINITION *, DEFINITION *));
 static HOST_WIDE_INT eval_if_expression        PROTO ((cpp_reader *));
-static int change_newlines             PROTO ((U_CHAR *, int));
-static void push_macro_expansion PARAMS ((cpp_reader *,
-                                         U_CHAR *, int, HASHNODE *));
-static struct cpp_pending *nreverse_pending PARAMS ((struct cpp_pending *));
 
 static void conditional_skip           PROTO ((cpp_reader *, int,
                                                enum node_type, U_CHAR *));
 static void skip_if_group              PROTO ((cpp_reader *));
 static int parse_name                   PARAMS ((cpp_reader *, int));
-static void print_help                  PROTO ((void));
-
-/* Last arg to output_line_command.  */
-enum file_change_code {same_file, enter_file, leave_file};
 
 /* External declarations.  */
 
 extern HOST_WIDE_INT cpp_parse_expr PARAMS ((cpp_reader *));
-extern char *version_string;
-
-/* #include "file" looks in source file dir, then stack.  */
-/* #include <file> just looks in the stack.  */
-/* -I directories are added to the end, then the defaults are added.  */
-/* The */
-static struct default_include {
-  char *fname;                 /* The name of the directory.  */
-  char *component;             /* The component containing the directory */
-  int cplusplus;               /* Only look here if we're compiling C++.  */
-  int cxx_aware;               /* Includes in this directory don't need to
-                                  be wrapped in extern "C" when compiling
-                                  C++.  */
-} include_defaults_array[]
-#ifdef INCLUDE_DEFAULTS
-  = INCLUDE_DEFAULTS;
-#else
-  = {
-    /* Pick up GNU C++ specific include files.  */
-    { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
-#ifdef CROSS_COMPILE
-    /* This is the dir for fixincludes.  Put it just before
-       the files that we fix.  */
-    { GCC_INCLUDE_DIR, "GCC", 0, 0 },
-    /* For cross-compilation, this dir name is generated
-       automatically in Makefile.in.  */
-    { CROSS_INCLUDE_DIR, "GCC",0, 0 },
-#ifdef TOOL_INCLUDE_DIR
-    /* This is another place that the target system's headers might be.  */
-    { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
-#endif
-#else /* not CROSS_COMPILE */
-#ifdef LOCAL_INCLUDE_DIR
-    /* This should be /usr/local/include and should come before
-       the fixincludes-fixed header files.  */
-    { LOCAL_INCLUDE_DIR, 0, 0, 1 },
-#endif
-#ifdef TOOL_INCLUDE_DIR
-    /* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here.
-       Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h.  */
-    { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
-#endif
-    /* This is the dir for fixincludes.  Put it just before
-       the files that we fix.  */
-    { GCC_INCLUDE_DIR, "GCC", 0, 0 },
-    /* Some systems have an extra dir of include files.  */
-#ifdef SYSTEM_INCLUDE_DIR
-    { SYSTEM_INCLUDE_DIR, 0, 0, 0 },
-#endif
-#ifndef STANDARD_INCLUDE_COMPONENT
-#define STANDARD_INCLUDE_COMPONENT 0
-#endif
-    { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 },
-#endif /* not CROSS_COMPILE */
-    { 0, 0, 0, 0 }
-    };
-#endif /* no INCLUDE_DEFAULTS */
 
 /* `struct directive' defines one #-directive, including how to handle it.  */
 
@@ -281,10 +133,10 @@ static struct directive directive_table[] = {
 /* Place into PFILE a quoted string representing the string SRC.
    Caller must reserve enough space in pfile->token_buffer.  */
 
-static void
+void
 quote_string (pfile, src)
      cpp_reader *pfile;
-     char *src;
+     const char *src;
 {
   U_CHAR c;
 
@@ -377,68 +229,15 @@ cpp_assert (pfile, str)
     }
 }
 
-/* Given a colon-separated list of file names PATH,
-   add all the names to the search path for include files.  */
-
-static void
-path_include (pfile, path)
-     cpp_reader *pfile;
-     char *path;
-{
-  char *p;
-
-  p = path;
-
-  if (*p)
-    while (1) {
-      char *q = p;
-      char *name;
-
-      /* Find the end of this name.  */
-      while (*q != 0 && *q != PATH_SEPARATOR) q++;
-      if (p == q) {
-       /* An empty name in the path stands for the current directory.  */
-       name = (char *) xmalloc (2);
-       name[0] = '.';
-       name[1] = 0;
-      } else {
-       /* Otherwise use the directory that is named.  */
-       name = (char *) xmalloc (q - p + 1);
-       bcopy (p, name, q - p);
-       name[q - p] = 0;
-      }
-
-      append_include_chain (pfile,
-                           &(CPP_OPTIONS (pfile)->bracket_include), name, 0);
-
-      /* Advance past this name.  */
-      p = q;
-      if (*p == 0)
-       break;
-      /* Skip the colon.  */
-      p++;
-    }
-}
-\f
-void
-cpp_options_init (opts)
-     cpp_options *opts;
-{
-  bzero ((char *) opts, sizeof *opts);
-
-  opts->dollars_in_ident = 1;
-  opts->cplusplus_comments = 1;
-  opts->warn_import = 1;
-}
 
-enum cpp_token
+static enum cpp_token
 null_underflow (pfile)
      cpp_reader *pfile ATTRIBUTE_UNUSED;
 {
   return CPP_EOF;
 }
 
-int
+static int
 null_cleanup (pbuf, pfile)
      cpp_buffer *pbuf ATTRIBUTE_UNUSED;
      cpp_reader *pfile ATTRIBUTE_UNUSED;
@@ -446,19 +245,6 @@ null_cleanup (pbuf, pfile)
   return 0;
 }
 
-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;
-}
-
 /* Assuming we have read '/'.
    If this is the start of a comment (followed by '*' or '/'),
    skip to the end of the comment, and return ' '.
@@ -626,7 +412,7 @@ skip_rest_of_line (pfile)
 /* Handle a possible # directive.
    '#' has already been read.  */
 
-int
+static int
 handle_directive (pfile)
      cpp_reader *pfile;
 { int c;
@@ -756,501 +542,11 @@ pass_thru_directive (buf, limit, pfile, keyword)
   pfile->lineno++;
 #endif
 }
-\f
-/* The arglist structure is built by do_define to tell
-   collect_definition 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_definition 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 {
-  struct arglist *next;
-  U_CHAR *name;
-  int length;
-  int argno;
-  char rest_args;
-};
-
-/* 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)
-    abort ();
-
-  /* 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);
-  /* Occurrences of '@' get doubled, so allocate extra space for them.  */
-  while (p < limit)
-    if (*p++ == '@')
-      maxsize++;
-  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++ = '@';
-  *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 '@':
-       /* An '@' in a string or character constant stands for itself,
-          and does not need to be escaped.  */
-       if (!expected_delimiter)
-         *exp_p++ = c;
-       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;      /* place to start copying from next time */
-           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 "@ " marker to prevent token pasting.
-         But not if "inside a string" (which in ANSI mode
-         happens only for -D option).  */
-      *exp_p++ = '@';
-      *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.  */
-
-static MACRODEF
-create_definition (buf, limit, pfile, predefinition)
-     U_CHAR *buf, *limit;
-     cpp_reader *pfile;
-     int predefinition;
-{
-  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;
-  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 == '(') {
-    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) == 0) {
-         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 {
-         switch (*bp) {
-           case '!':  case '"':  case '#':  case '%':  case '&':  case '\'':
-           case ')':  case '*':  case '+':  case ',':  case '-':  case '.':
-           case '/':  case ':':  case ';':  case '<':  case '=':  case '>':
-           case '?':  case '[':  case '\\': case ']':  case '^':  case '{':
-           case '|':  case '}':  case '~':
-             cpp_warning (pfile, "missing white space after `#define %.*s'",
-                          sym_length, symname);
-             break;
-
-           default:
-             cpp_pedwarn (pfile, "missing white space after `#define %.*s'",
-                          sym_length, symname);
-             break;
-         }
-       }
-      }
-    /* now everything from bp before limit is the definition.  */
-    defn = collect_expansion (pfile, bp, limit, -1, NULL_PTR);
-    defn->args.argnames = (U_CHAR *) "";
-  }
-
-  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;
-}
 
 /* Check a purported macro name SYMNAME, and yield its length.
    ASSERTION is nonzero if this is really for an assertion name.  */
 
-static int
+int
 check_macro_name (pfile, symname, assertion)
      cpp_reader *pfile;
      U_CHAR *symname;
@@ -1281,80 +577,6 @@ check_macro_name (pfile, symname, assertion)
   return sym_length;
 }
 
-/* Return zero if two DEFINITIONs are isomorphic.  */
-
-static int
-compare_defs (pfile, d1, d2)
-     cpp_reader *pfile;
-     DEFINITION *d1, *d2;
-{
-  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;
-  if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
-                    p2, d2->length - (p2 - d2->expansion), 1))
-    return 1;
-  return 0;
-}
-
-/* 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.  */
-
-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);
-}
 
 /* Process a #define command.
 KEYWORD is the keyword-table entry for #define,
@@ -1446,27 +668,6 @@ nope:
   return 1;
 }
 
-/* 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;
-};
 
 /* Allocate a new cpp_buffer for PFILE, and push it on the input buffer stack.
    If BUFFER != NULL, then use the LENGTH characters in BUFFER
@@ -1542,7 +743,7 @@ cpp_scan_buffer (pfile)
  * (because it follows CPP_WRITTEN).  This is used by do_include.
  */
 
-static void
+void
 cpp_expand_to_buffer (pfile, buf, length)
      cpp_reader *pfile;
      U_CHAR *buf;
@@ -1580,7 +781,6 @@ cpp_expand_to_buffer (pfile, buf, length)
   CPP_NUL_TERMINATE (pfile);
 }
 
-\f
 static void
 adjust_position (buf, limit, linep, colp)
      U_CHAR *buf;
@@ -1674,7 +874,7 @@ count_newlines (buf, limit)
  * FILE_CHANGE says whether we are entering a file, leaving, or neither.
  */
 
-static void
+void
 output_line_command (pfile, conditional, file_change)
      cpp_reader *pfile;
      int conditional;
@@ -1757,1185 +957,326 @@ output_line_command (pfile, conditional, file_change)
   CPP_PUTC_Q (pfile, '\n');
   pfile->lineno = line;
 }
-\f
-/*
- * 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.
- */
+
+
+/* Like cpp_get_token, except that it does not read past end-of-line.
+   Also, horizontal space is skipped, and macros are popped.  */
 
 static enum cpp_token
-macarg (pfile, rest_args)
+get_directive_token (pfile)
      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++;
   for (;;)
     {
+      long old_written = CPP_WRITTEN (pfile);
+      enum cpp_token token;
+      cpp_skip_hspace (pfile);
+      if (PEEKC () == '\n')
+         return CPP_VSPACE;
       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.  */
+      {
+      case CPP_POP:
          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;
+             return token;
+         /* ... else fall though ...  */
+      case CPP_HSPACE:  case CPP_COMMENT:
+         CPP_SET_WRITTEN (pfile, old_written);
          break;
-       found:
-         /* Remove ',' or ')' from argument buffer.  */
-         CPP_ADJUST_WRITTEN (pfile, -1);
-         goto done;
-      default: ;
-       }
+      default:
+         return token;
+      }
     }
-
- done:
-  CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;
-  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.  */
+/* Handle #include and #import.
+   This function expects to see "fname" or <fname> on the input.
 
-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;
-}
+   The input is normally in part of the output_buffer following
+   CPP_WRITTEN, and will get overwritten by output_line_command.
+   I.e. in input file specification has been popped by handle_directive.
+   This is safe.  */
 
-\f
-static struct tm *
-timestamp (pfile)
+static int
+do_include (pfile, keyword)
      cpp_reader *pfile;
+     struct directive *keyword;
 {
-  if (!pfile->timebuf) {
-    time_t t = time ((time_t *) 0);
-    pfile->timebuf = localtime (&t);
-  }
-  return pfile->timebuf;
-}
+  int importing = (keyword->type == T_IMPORT);
+  int skip_dirs = (keyword->type == T_INCLUDE_NEXT);
+  int angle_brackets = 0;      /* 0 for "...", 1 for <...> */
+  int before;  /* included before? */
+  long flen;
+  char *fbeg, *fend;
+  cpp_buffer *fp;
 
-static char *monthnames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
-                           };
+  enum cpp_token token;
 
-/*
- * expand things like __FILE__.  Place the expansion into the output
- * buffer *without* rescanning.
- */
+  /* Chain of dirs to search */
+  struct include_hash *ihash;
+  struct file_name_list *search_start;
+  
+  long old_written = CPP_WRITTEN (pfile);
 
-static void
-special_symbol (hp, pfile)
-     HASHNODE *hp;
-     cpp_reader *pfile;
-{
-  const char *buf;
-  int len;
-  cpp_buffer *ip;
+  int fd;
 
-  switch (hp->type)
+  if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
     {
-    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;
-      }
+      if (importing)
+       cpp_pedwarn (pfile, "ANSI C does not allow `#import'");
+      if (skip_dirs)
+       cpp_pedwarn (pfile, "ANSI C does not allow `#include_next'");
+    }
 
-    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;
+  if (importing && CPP_OPTIONS (pfile)->warn_import
+      && !CPP_OPTIONS (pfile)->inhibit_warnings
+      && !CPP_BUFFER (pfile)->system_header_p && !pfile->import_warning)
+    {
+      pfile->import_warning = 1;
+      cpp_warning (pfile, "`#import' is obsolete, use an #ifndef wrapper in the header file");
+    }
 
-    case T_CONST:
-      buf = hp->value.cpval;
-      if (!buf)
-       return;
-      if (*buf == '\0')
-       buf = "@ ";
+  pfile->parsing_include_directive++;
+  token = get_directive_token (pfile);
+  pfile->parsing_include_directive--;
 
-      len = strlen (buf);
-      CPP_RESERVE (pfile, len + 1);
-      CPP_PUTS_Q (pfile, buf, len);
-      CPP_NUL_TERMINATE_Q (pfile);
-      return;
+  if (token == CPP_STRING)
+    {
+      fbeg = pfile->token_buffer + old_written + 1;
+      fend = CPP_PWRITTEN (pfile) - 1;
+      *fend = '\0';
+      if (fbeg[-1] == '<')
+         angle_brackets = 1;
+    }
+#ifdef VMS
+  else if (token == CPP_NAME)
+    {
+      /* Support '#include xyz' like VAX-C to allow for easy use of
+       * all the decwindow include files. It defaults to '#include
+       * <xyz.h>' and generates a warning.  */
+      cpp_warning (pfile,
+                  "VAX-C-style include specification found, use '#include <filename.h>' !");
+      angle_brackets = 1;
 
-    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');
+      /* Append the missing `.h' to the name. */
+      CPP_PUTS (pfile, ".h", 3)
       CPP_NUL_TERMINATE_Q (pfile);
-      return;
-
-    case T_SPECLINE:
-      {
-       long line;
-       cpp_buf_line_and_col (CPP_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;
-      }
 
-    default:
-      cpp_fatal (pfile, "cpplib internal error: invalid special hash type");
-      return;
+      fbeg = pfile->token_buffer + old_written;
+      fend = CPP_PWRITTEN (pfile);
     }
-
-  /* This point should be unreachable. */
-  abort();
-}
-
-/* Write out a #define command for the special named MACRO_NAME
-   to PFILE's token_buffer.  */
-
-static void
-dump_special_to_buffer (pfile, macro_name)
-     cpp_reader *pfile;
-     char *macro_name;
-{
-  static char define_directive[] = "#define ";
-  int macro_name_length = strlen (macro_name);
-  output_line_command (pfile, 0, same_file);
-  CPP_RESERVE (pfile, sizeof(define_directive) + macro_name_length);
-  CPP_PUTS_Q (pfile, define_directive, sizeof(define_directive)-1);
-  CPP_PUTS_Q (pfile, macro_name, macro_name_length);
-  CPP_PUTC_Q (pfile, ' ');
-  cpp_expand_to_buffer (pfile, macro_name, macro_name_length);
-  CPP_PUTC (pfile, '\n');
-}
-
-/* Initialize the built-in macros.  */
-
-static void
-initialize_builtins (pfile)
-     cpp_reader *pfile;
-{
-#define NAME(str) (U_CHAR *)str, sizeof str - 1
-  install (NAME("__TIME__"),             T_TIME,       0, -1);
-  install (NAME("__DATE__"),             T_DATE,       0, -1);
-  install (NAME("__FILE__"),             T_FILE,       0, -1);
-  install (NAME("__BASE_FILE__"),        T_BASE_FILE,  0, -1);
-  install (NAME("__LINE__"),             T_SPECLINE,   0, -1);
-  install (NAME("__INCLUDE_LEVEL__"),    T_INCLUDE_LEVEL, 0, -1);
-  install (NAME("__VERSION__"),                  T_VERSION,    0, -1);
-#ifndef NO_BUILTIN_SIZE_TYPE
-  install (NAME("__SIZE_TYPE__"),        T_CONST, SIZE_TYPE, -1);
-#endif
-#ifndef NO_BUILTIN_PTRDIFF_TYPE
-  install (NAME("__PTRDIFF_TYPE__ "),    T_CONST, PTRDIFF_TYPE, -1);
-#endif
-  install (NAME("__WCHAR_TYPE__"),       T_CONST, WCHAR_TYPE, -1);
-  install (NAME("__USER_LABEL_PREFIX__"), T_CONST, user_label_prefix, -1);
-  install (NAME("__REGISTER_PREFIX__"),          T_CONST, REGISTER_PREFIX, -1);
-  if (!CPP_TRADITIONAL (pfile))
-    {
-      install (NAME("__STDC__"),         T_STDC,  0, -1);
-#if 0
-      if (CPP_OPTIONS (pfile)->c9x)
-       install (NAME("__STDC_VERSION__"),T_CONST, "199909L", -1);
-      else
 #endif
-       install (NAME("__STDC_VERSION__"),T_CONST, "199409L", -1);
-    }
-#undef NAME
-
-  if (CPP_OPTIONS (pfile)->debug_output)
+  else
     {
-      dump_special_to_buffer (pfile, "__BASE_FILE__");
-      dump_special_to_buffer (pfile, "__VERSION__");
-#ifndef NO_BUILTIN_SIZE_TYPE
-      dump_special_to_buffer (pfile, "__SIZE_TYPE__");
-#endif
-#ifndef NO_BUILTIN_PTRDIFF_TYPE
-      dump_special_to_buffer (pfile, "__PTRDIFF_TYPE__");
-#endif
-      dump_special_to_buffer (pfile, "__WCHAR_TYPE__");
-      dump_special_to_buffer (pfile, "__DATE__");
-      dump_special_to_buffer (pfile, "__TIME__");
-      if (!CPP_TRADITIONAL (pfile))
-       dump_special_to_buffer (pfile, "__STDC__");
+      cpp_error (pfile,
+                "`#%s' expects \"FILENAME\" or <FILENAME>", keyword->name);
+      CPP_SET_WRITTEN (pfile, old_written);
+      skip_rest_of_line (pfile);
+      return 0;
     }
-}
-\f
-/* 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)
+  token = get_directive_token (pfile);
+  if (token != CPP_VSPACE)
     {
-    case '+': case '-':
-      if (c2 == c1 || c2 == '=')
-       return 1;
-      goto letter;
-    case '.':
-    case '0': case '1': case '2': case '3': case '4':
-    case '5': case '6': case '7': case '8': case '9':
-    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;
-    letter:
-    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':
-      /* 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 == '=');
+      cpp_error (pfile, "junk at end of `#include'");
+      skip_rest_of_line (pfile);
     }
-  return 0;
-}
-
-/* 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.  */
+  CPP_SET_WRITTEN (pfile, old_written);
 
-static void
-macroexpand (pfile, hp)
-     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;
+  flen = fend - fbeg;
 
-#if 0
-  CHECK_DEPTH (return;);
-#endif
+  if (flen == 0)
+    {
+      cpp_error (pfile, "empty file name in `#%s'", keyword->name);
+      return 0;
+    }
 
-#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
+  search_start = 0;
 
-  cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
+  for (fp = CPP_BUFFER (pfile);
+       fp != CPP_NULL_BUFFER (pfile);
+       fp = CPP_PREV_BUFFER (fp))
+    if (fp->fname != NULL)
+      break;
 
-  /* Check for and handle special symbols. */
-  if (hp->type != T_MACRO)
+  if (fp == CPP_NULL_BUFFER (pfile))
     {
-      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;
+      cpp_fatal (pfile, "cpp internal error: fp == NULL_BUFFER in do_include");
+      return 1;
     }
-
-  defn = hp->value.defn;
-  nargs = defn->nargs;
-  pfile->output_escapes++;
-
-  if (nargs >= 0)
+  
+  /* For #include_next, skip in the search path past the dir in which the
+     containing file was found.  Treat files specified using an absolute path
+     as if there are no more directories to search.  Treat the primary source
+     file like any other included source, but generate a warning.  */
+  if (skip_dirs && CPP_PREV_BUFFER(fp) != CPP_NULL_BUFFER (pfile))
     {
-      enum cpp_token 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;
-         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 the open-parenthesis before the 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)
+      if (fp->ihash->foundhere != ABSOLUTE_PATH)
+       search_start = fp->ihash->foundhere->next;
+    }
+  else
+    {
+      if (skip_dirs)
+       cpp_warning (pfile, "#include_next in primary source file");
+      
+      if (angle_brackets)
+       search_start = CPP_OPTIONS (pfile)->bracket_include;
+      else
+        {
+         if (!CPP_OPTIONS (pfile)->ignore_srcdir)
            {
-             cpp_error_with_line (pfile, start_line, start_column,
-                                  "unterminated macro call");
-             return;
+             if (fp)
+               search_start = fp->actual_dir;
            }
-         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);
+           search_start = CPP_OPTIONS (pfile)->quote_include;
        }
     }
 
-  /* If macro wants zero args, we parsed the arglist for checking only.
-     Read directly from the macro definition.  */
-  if (nargs <= 0)
+  if (!search_start)
     {
-      xbuf = defn->expansion;
-      xbuf_len = defn->length;
+      cpp_error (pfile, "No include path in which to find %s", fbeg);
+      return 0;
     }
-  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.  */
+  fd = find_include_file (pfile, fbeg, search_start, &ihash, &before);
 
-      /* 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)
+  if (fd == -2)
+    return 0;
+  
+  if (fd == -1)
+    {
+      if (CPP_OPTIONS (pfile)->print_deps_missing_files
+         && CPP_PRINT_DEPS (pfile) > (angle_brackets ||
+                                      (pfile->system_include_depth > 0)))
+        {
+         if (!angle_brackets)
+           deps_output (pfile, fbeg, ' ');
+         else
            {
-             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 an string or char token.*/
-                         if (is_space[c])
-                           {
-                             if (CPP_WRITTEN (pfile) > (unsigned)arg->stringified
-                                 && (CPP_PWRITTEN (pfile))[-1] == '@')
-                               {
-                                 /* "@ " 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;
-               }
+             char *p;
+             struct file_name_list *ptr;
+             /* If requested as a system header, assume it belongs in
+                the first system header directory. */
+             if (CPP_OPTIONS (pfile)->bracket_include)
+               ptr = CPP_OPTIONS (pfile)->bracket_include;
+             else
+               ptr = CPP_OPTIONS (pfile)->quote_include;
 
-             /* Add 4 for two newline-space markers to prevent
-                token concatenation.  */
-             xbuf_len += args[ap->argno].expand_length + 4;
+             p = (char *) alloca (strlen (ptr->name)
+                                  + strlen (fbeg) + 2);
+             if (*ptr->name != '\0')
+               {
+                 strcpy (p, ptr->name);
+                 strcat (p, "/");
+               }
+             strcat (p, fbeg);
+             deps_output (pfile, p, ' ');
            }
-         if (args[ap->argno].use_count < 10)
-           args[ap->argno].use_count++;
        }
+      /* If -M was specified, and this header file won't be added to
+        the dependency list, then don't count this as an error,
+        because we can still produce correct output.  Otherwise, we
+        can't produce correct output, because there may be
+        dependencies we need inside the missing file, and we don't
+        know what directory this missing file exists in. */
+      else if (CPP_PRINT_DEPS (pfile)
+              && (CPP_PRINT_DEPS (pfile)
+                  <= (angle_brackets || (pfile->system_include_depth > 0))))
+       cpp_warning (pfile, "No include path in which to find %s", fbeg);
+      else
+       cpp_error_from_errno (pfile, fbeg);
 
-      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)
-               {
-                 while (p1 != l1 && is_space[*p1]) p1++;
-                 while (p1 != l1 && is_idchar[*p1])
-                   xbuf[totlen++] = *p1++;
-               }
-             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] == '@')
-                       {
-                         U_CHAR *p2 = l1 - 1;
-                         /* If whitespace is preceded by an odd number
-                            of `@' signs, the last `@' was a whitespace
-                            marker; drop it too. */
-                         while (p2 != p1 && p2[0] == '@') p2--;
-                         if ((l1 - p2) & 1)
-                           l1--;
-                         break;
-                       }
-                     else if (l1[-1] == '-')
-                       {
-                         U_CHAR *p2 = l1 - 1;
-                         /* If a `-' is preceded by an odd number of
-                            `@' signs then it and the last `@' are
-                            a no-reexpansion marker.  */
-                         while (p2 != p1 && p2[0] == '@') p2--;
-                         if ((l1 - p2) & 1)
-                           l1 -= 2;
-                         else
-                           break;
-                       }
-                     else break;
-                   }
-               }
-
-             /* Delete any no-reexpansion marker that precedes
-                an identifier at the beginning of the argument. */
-             if (p1[0] == '@' && 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++] = '@';
-                 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++] = '@';
-                 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)
-           abort ();
-      }
-
-      /* 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];
-       }
+      return 0;
+    }
 
-      xbuf[totlen] = 0;
-      xbuf_len = totlen;
+  /* For -M, add the file to the dependencies on its first inclusion. */
+  if (!before && (CPP_PRINT_DEPS (pfile)
+                 > (angle_brackets || (pfile->system_include_depth > 0))))
+    deps_output (pfile, ihash->name, ' ');
 
+  /* Handle -H option.  */
+  if (CPP_OPTIONS(pfile)->print_include_names)
+    {
+      fp = CPP_BUFFER (pfile);
+      while ((fp = CPP_PREV_BUFFER (fp)) != CPP_NULL_BUFFER (pfile))
+       putc ('.', stderr);
+      fprintf (stderr, " %s\n", ihash->name);
     }
 
-  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;
+  /* Actually process the file */
 
-  /* 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 (importing)
+    ihash->control_macro = "";
   
-  if (!CPP_TRADITIONAL (pfile))
-    hp->type = T_DISABLED;
-}
-
-static void
-push_macro_expansion (pfile, xbuf, xbuf_len, hp)
-     cpp_reader *pfile;
-     register U_CHAR *xbuf;
-     int xbuf_len;
-     HASHNODE *hp;
-{
-  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 "@ " 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] == '@' && 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] == '@'
-      && mbuf->rlimit[-1] == ' ')
+  if (cpp_push_buffer (pfile, NULL, 0) == NULL)
     {
-      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;
+      close (fd);
+      return 0;
     }
-}
-\f
-/* Like cpp_get_token, except that it does not read past end-of-line.
-   Also, horizontal space is skipped, and macros are popped.  */
+  
+  if (angle_brackets)
+    pfile->system_include_depth++;   /* Decremented in file_cleanup. */
 
-static enum cpp_token
-get_directive_token (pfile)
-     cpp_reader *pfile;
-{
-  for (;;)
+  if (finclude (pfile, fd, ihash))
     {
-      long old_written = CPP_WRITTEN (pfile);
-      enum cpp_token token;
-      cpp_skip_hspace (pfile);
-      if (PEEKC () == '\n')
-         return CPP_VSPACE;
-      token = cpp_get_token (pfile);
-      switch (token)
-      {
-      case CPP_POP:
-         if (! CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
-             return token;
-         /* ... else fall though ...  */
-      case CPP_HSPACE:  case CPP_COMMENT:
-         CPP_SET_WRITTEN (pfile, old_written);
-         break;
-      default:
-         return token;
-      }
+      output_line_command (pfile, 0, enter_file);
+      pfile->only_seen_white = 2;
     }
+
+  return 0;
 }
-\f
-/* Handle #include and #import.
-   This function expects to see "fname" or <fname> on the input.
 
-   The input is normally in part of the output_buffer following
-   CPP_WRITTEN, and will get overwritten by output_line_command.
-   I.e. in input file specification has been popped by handle_directive.
-   This is safe.  */
+/* Interpret #line command.
+   Note that the filename string (if any) is treated as if it were an
+   include filename.  That means no escape handling.  */
 
 static int
-do_include (pfile, keyword)
+do_line (pfile, keyword)
      cpp_reader *pfile;
-     struct directive *keyword;
+     struct directive *keyword ATTRIBUTE_UNUSED;
 {
-  int importing = (keyword->type == T_IMPORT);
-  int skip_dirs = (keyword->type == T_INCLUDE_NEXT);
-  int angle_brackets = 0;      /* 0 for "...", 1 for <...> */
-  int before;  /* included before? */
-  long flen;
-  char *fbeg, *fend;
-  cpp_buffer *fp;
-
-  enum cpp_token token;
-
-  /* Chain of dirs to search */
-  struct include_hash *ihash;
-  struct file_name_list *search_start;
-  
+  cpp_buffer *ip = CPP_BUFFER (pfile);
+  int new_lineno;
   long old_written = CPP_WRITTEN (pfile);
+  enum file_change_code file_change = same_file;
+  enum cpp_token token;
+  char *x;
 
-  int fd;
+  token = get_directive_token (pfile);
 
-  if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
+  if (token != CPP_NUMBER)
     {
-      if (importing)
-       cpp_pedwarn (pfile, "ANSI C does not allow `#import'");
-      if (skip_dirs)
-       cpp_pedwarn (pfile, "ANSI C does not allow `#include_next'");
+      cpp_error (pfile, "token after `#line' is not an integer");
+      goto bad_line_directive;
     }
 
-  if (importing && CPP_OPTIONS (pfile)->warn_import
-      && !CPP_OPTIONS (pfile)->inhibit_warnings
-      && !CPP_BUFFER (pfile)->system_header_p && !pfile->import_warning)
+  new_lineno = strtol (pfile->token_buffer + old_written, &x, 10);
+  if (x[0] != '\0')
     {
-      pfile->import_warning = 1;
-      cpp_warning (pfile, "`#import' is obsolete, use an #ifndef wrapper in the header file");
-    }
+      cpp_error (pfile, "token after `#line' is not an integer");
+      goto bad_line_directive;
+    }      
+  CPP_SET_WRITTEN (pfile, old_written);
+
+  if (CPP_PEDANTIC (pfile) && new_lineno <= 0)
+    cpp_pedwarn (pfile, "line number out of range in `#line' command");
 
-  pfile->parsing_include_directive++;
   token = get_directive_token (pfile);
-  pfile->parsing_include_directive--;
 
   if (token == CPP_STRING)
     {
-      fbeg = pfile->token_buffer + old_written + 1;
-      fend = CPP_PWRITTEN (pfile) - 1;
-      *fend = '\0';
-      if (fbeg[-1] == '<')
-         angle_brackets = 1;
-    }
-#ifdef VMS
-  else if (token == CPP_NAME)
-    {
-      /* Support '#include xyz' like VAX-C to allow for easy use of
-       * all the decwindow include files. It defaults to '#include
-       * <xyz.h>' and generates a warning.  */
-      cpp_warning (pfile,
-                  "VAX-C-style include specification found, use '#include <filename.h>' !");
-      angle_brackets = 1;
-
-      /* Append the missing `.h' to the name. */
-      CPP_PUTS (pfile, ".h", 3)
-      CPP_NUL_TERMINATE_Q (pfile);
-
-      fbeg = pfile->token_buffer + old_written;
-      fend = CPP_PWRITTEN (pfile);
-    }
-#endif
-  else
-    {
-      cpp_error (pfile,
-                "`#%s' expects \"FILENAME\" or <FILENAME>", keyword->name);
-      CPP_SET_WRITTEN (pfile, old_written);
-      skip_rest_of_line (pfile);
-      return 0;
-    }
-
-  token = get_directive_token (pfile);
-  if (token != CPP_VSPACE)
-    {
-      cpp_error (pfile, "junk at end of `#include'");
-      skip_rest_of_line (pfile);
-    }
+      U_CHAR *fname = pfile->token_buffer + old_written + 1;
+      U_CHAR *end_name = CPP_PWRITTEN (pfile) - 1;
+      long num_start = CPP_WRITTEN (pfile);
 
-  CPP_SET_WRITTEN (pfile, old_written);
-
-  flen = fend - fbeg;
-
-  if (flen == 0)
-    {
-      cpp_error (pfile, "empty file name in `#%s'", keyword->name);
-      return 0;
-    }
-
-  search_start = 0;
-
-  for (fp = CPP_BUFFER (pfile);
-       fp != CPP_NULL_BUFFER (pfile);
-       fp = CPP_PREV_BUFFER (fp))
-    if (fp->fname != NULL)
-      break;
-
-  if (fp == CPP_NULL_BUFFER (pfile))
-    {
-      cpp_fatal (pfile, "cpp internal error: fp == NULL_BUFFER in do_include");
-      return 1;
-    }
-  
-  /* For #include_next, skip in the search path past the dir in which the
-     containing file was found.  Treat files specified using an absolute path
-     as if there are no more directories to search.  Treat the primary source
-     file like any other included source, but generate a warning.  */
-  if (skip_dirs && CPP_PREV_BUFFER(fp) != CPP_NULL_BUFFER (pfile))
-    {
-      if (fp->ihash->foundhere != ABSOLUTE_PATH)
-       search_start = fp->ihash->foundhere->next;
-    }
-  else
-    {
-      if (skip_dirs)
-       cpp_warning (pfile, "#include_next in primary source file");
-      
-      if (angle_brackets)
-       search_start = CPP_OPTIONS (pfile)->bracket_include;
-      else
-        {
-         if (!CPP_OPTIONS (pfile)->ignore_srcdir)
-           {
-             if (fp)
-               search_start = fp->actual_dir;
-           }
-         else
-           search_start = CPP_OPTIONS (pfile)->quote_include;
-       }
-    }
-
-  if (!search_start)
-    {
-      cpp_error (pfile, "No include path in which to find %s", fbeg);
-      return 0;
-    }
-
-  fd = find_include_file (pfile, fbeg, search_start, &ihash, &before);
-
-  if (fd == -2)
-    return 0;
-  
-  if (fd == -1)
-    {
-      if (CPP_OPTIONS (pfile)->print_deps_missing_files
-         && CPP_PRINT_DEPS (pfile) > (angle_brackets ||
-                                      (pfile->system_include_depth > 0)))
-        {
-         if (!angle_brackets)
-           deps_output (pfile, fbeg, ' ');
-         else
-           {
-             char *p;
-             struct file_name_list *ptr;
-             /* If requested as a system header, assume it belongs in
-                the first system header directory. */
-             if (CPP_OPTIONS (pfile)->bracket_include)
-               ptr = CPP_OPTIONS (pfile)->bracket_include;
-             else
-               ptr = CPP_OPTIONS (pfile)->quote_include;
-
-             p = (char *) alloca (strlen (ptr->name)
-                                  + strlen (fbeg) + 2);
-             if (*ptr->name != '\0')
-               {
-                 strcpy (p, ptr->name);
-                 strcat (p, "/");
-               }
-             strcat (p, fbeg);
-             deps_output (pfile, p, ' ');
-           }
-       }
-      /* If -M was specified, and this header file won't be added to
-        the dependency list, then don't count this as an error,
-        because we can still produce correct output.  Otherwise, we
-        can't produce correct output, because there may be
-        dependencies we need inside the missing file, and we don't
-        know what directory this missing file exists in. */
-      else if (CPP_PRINT_DEPS (pfile)
-              && (CPP_PRINT_DEPS (pfile)
-                  <= (angle_brackets || (pfile->system_include_depth > 0))))
-       cpp_warning (pfile, "No include path in which to find %s", fbeg);
-      else
-       cpp_error_from_errno (pfile, fbeg);
-
-      return 0;
-    }
-
-  /* For -M, add the file to the dependencies on its first inclusion. */
-  if (!before && (CPP_PRINT_DEPS (pfile)
-                 > (angle_brackets || (pfile->system_include_depth > 0))))
-    deps_output (pfile, ihash->name, ' ');
-
-  /* Handle -H option.  */
-  if (CPP_OPTIONS(pfile)->print_include_names)
-    {
-      fp = CPP_BUFFER (pfile);
-      while ((fp = CPP_PREV_BUFFER (fp)) != CPP_NULL_BUFFER (pfile))
-       putc ('.', stderr);
-      fprintf (stderr, " %s\n", ihash->name);
-    }
-
-  /* Actually process the file */
-
-  if (importing)
-    ihash->control_macro = "";
-  
-  if (cpp_push_buffer (pfile, NULL, 0) == NULL)
-    {
-      close (fd);
-      return 0;
-    }
-  
-  if (angle_brackets)
-    pfile->system_include_depth++;   /* Decremented in file_cleanup. */
-
-  if (finclude (pfile, fd, ihash))
-    {
-      output_line_command (pfile, 0, enter_file);
-      pfile->only_seen_white = 2;
-    }
-
-  return 0;
-}
-
-/* Interpret #line command.
-   Note that the filename string (if any) is treated as if it were an
-   include filename.  That means no escape handling.  */
-
-static int
-do_line (pfile, keyword)
-     cpp_reader *pfile;
-     struct directive *keyword ATTRIBUTE_UNUSED;
-{
-  cpp_buffer *ip = CPP_BUFFER (pfile);
-  int new_lineno;
-  long old_written = CPP_WRITTEN (pfile);
-  enum file_change_code file_change = same_file;
-  enum cpp_token token;
-  char *x;
-
-  token = get_directive_token (pfile);
-
-  if (token != CPP_NUMBER)
-    {
-      cpp_error (pfile, "token after `#line' is not an integer");
-      goto bad_line_directive;
-    }
-
-  new_lineno = strtol (pfile->token_buffer + old_written, &x, 10);
-  if (x[0] != '\0')
-    {
-      cpp_error (pfile, "token after `#line' is not an integer");
-      goto bad_line_directive;
-    }      
-  CPP_SET_WRITTEN (pfile, old_written);
-
-  if (CPP_PEDANTIC (pfile) && new_lineno <= 0)
-    cpp_pedwarn (pfile, "line number out of range in `#line' command");
-
-  token = get_directive_token (pfile);
-
-  if (token == CPP_STRING)
-    {
-      U_CHAR *fname = pfile->token_buffer + old_written + 1;
-      U_CHAR *end_name = CPP_PWRITTEN (pfile) - 1;
-      long num_start = CPP_WRITTEN (pfile);
-
-      token = get_directive_token (pfile);
-      if (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP)
-       {
-         U_CHAR *p = pfile->token_buffer + num_start;
-         if (CPP_PEDANTIC (pfile))
-           cpp_pedwarn (pfile, "garbage at end of `#line' command");
+      token = get_directive_token (pfile);
+      if (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP)
+       {
+         U_CHAR *p = pfile->token_buffer + num_start;
+         if (CPP_PEDANTIC (pfile))
+           cpp_pedwarn (pfile, "garbage at end of `#line' command");
 
          if (token != CPP_NUMBER || *p < '0' || *p > '4' || p[1] != '\0')
            {
@@ -3079,15 +1420,15 @@ do_undef (pfile, keyword)
 }
 
 /* Wrap do_undef for -U processing. */
-static void
+void
 cpp_undef (pfile, macro)
      cpp_reader *pfile;
      U_CHAR *macro;
 {
-    if (cpp_push_buffer (pfile, macro, strlen(macro)))
+  if (cpp_push_buffer (pfile, macro, strlen (macro)))
     {
-       do_undef (pfile, NULL);
-       cpp_pop_buffer (pfile);
+      do_undef (pfile, NULL);
+      cpp_pop_buffer (pfile);
     }
 }
 
@@ -4386,1255 +2727,6 @@ parse_name (pfile, c)
   return 1;
 }
 
-/* This is called after options have been processed.
- * Check options for consistency, and setup for processing input
- * from the file named FNAME.  (Use standard input if FNAME==NULL.)
- * Return 1 on success, 0 on failure.
- */
-
-int
-cpp_start_read (pfile, fname)
-     cpp_reader *pfile;
-     char *fname;
-{
-  struct cpp_options *opts = CPP_OPTIONS (pfile);
-  struct cpp_pending *pend;
-  char *p;
-  int f;
-  cpp_buffer *fp;
-  struct include_hash *ih_fake;
-
-  /* The code looks at the defaults through this pointer, rather than
-     through the constant structure above.  This pointer gets changed
-     if an environment variable specifies other defaults.  */
-  struct default_include *include_defaults = include_defaults_array;
-
-  /* Now that we know dollars_in_ident, we can initialize the syntax
-     tables. */
-  initialize_char_syntax (opts->dollars_in_ident);
-  
-  /* Add dirs from CPATH after dirs from -I.  */
-  /* There seems to be confusion about what CPATH should do,
-     so for the moment it is not documented.  */
-  /* Some people say that CPATH should replace the standard include
-     dirs, but that seems pointless: it comes before them, so it
-     overrides them anyway.  */
-  GET_ENV_PATH_LIST (p, "CPATH");
-  if (p != 0 && ! opts->no_standard_includes)
-    path_include (pfile, p);
-
-  /* Do partial setup of input buffer for the sake of generating
-     early #line directives (when -g is in effect).  */
-  fp = cpp_push_buffer (pfile, NULL, 0);
-  if (!fp)
-    return 0;
-  if (opts->in_fname == NULL || *opts->in_fname == 0)
-    {
-      opts->in_fname = fname;
-      if (opts->in_fname == NULL)
-       opts->in_fname = "";
-    }
-  fp->nominal_fname = fp->fname = opts->in_fname;
-  fp->lineno = 0;
-
-  /* Install __LINE__, etc.  Must follow initialize_char_syntax
-     and option processing.  */
-  initialize_builtins (pfile);
-
-  /* Do standard #defines and assertions
-     that identify system and machine type.  */
-
-  if (!opts->inhibit_predefs) {
-    char *p = (char *) alloca (strlen (predefs) + 1);
-    strcpy (p, predefs);
-    while (*p) {
-      char *q;
-      while (*p == ' ' || *p == '\t')
-       p++;
-      /* Handle -D options.  */ 
-      if (p[0] == '-' && p[1] == 'D') {
-       q = &p[2];
-       while (*p && *p != ' ' && *p != '\t')
-         p++;
-       if (*p != 0)
-         *p++= 0;
-       if (opts->debug_output)
-         output_line_command (pfile, 0, same_file);
-       cpp_define (pfile, q);
-       while (*p == ' ' || *p == '\t')
-         p++;
-      } else if (p[0] == '-' && p[1] == 'A') {
-       /* Handle -A options (assertions).  */ 
-       char *assertion;
-       char *past_name;
-       char *value;
-       char *past_value;
-       char *termination;
-       int save_char;
-
-       assertion = &p[2];
-       past_name = assertion;
-       /* Locate end of name.  */
-       while (*past_name && *past_name != ' '
-              && *past_name != '\t' && *past_name != '(')
-         past_name++;
-       /* Locate `(' at start of value.  */
-       value = past_name;
-       while (*value && (*value == ' ' || *value == '\t'))
-         value++;
-       if (*value++ != '(')
-         abort ();
-       while (*value && (*value == ' ' || *value == '\t'))
-         value++;
-       past_value = value;
-       /* Locate end of value.  */
-       while (*past_value && *past_value != ' '
-              && *past_value != '\t' && *past_value != ')')
-         past_value++;
-       termination = past_value;
-       while (*termination && (*termination == ' ' || *termination == '\t'))
-         termination++;
-       if (*termination++ != ')')
-         abort ();
-       if (*termination && *termination != ' ' && *termination != '\t')
-         abort ();
-       /* Temporarily null-terminate the value.  */
-       save_char = *termination;
-       *termination = '\0';
-       /* Install the assertion.  */
-       cpp_assert (pfile, assertion);
-       *termination = (char) save_char;
-       p = termination;
-       while (*p == ' ' || *p == '\t')
-         p++;
-      } else {
-       abort ();
-      }
-    }
-  }
-
-  /* Now handle the command line options.  */
-
-  /* Do -U's, -D's and -A's in the order they were seen.  */
-  /* First reverse the list.  */
-  opts->pending = nreverse_pending (opts->pending);
-
-  for (pend = opts->pending;  pend;  pend = pend->next)
-    {
-      if (pend->cmd != NULL && pend->cmd[0] == '-')
-       {
-         switch (pend->cmd[1])
-           {
-           case 'U':
-             if (opts->debug_output)
-               output_line_command (pfile, 0, same_file);
-             cpp_undef (pfile, pend->arg);
-             break;
-           case 'D':
-             if (opts->debug_output)
-               output_line_command (pfile, 0, same_file);
-             cpp_define (pfile, pend->arg);
-             break;
-           case 'A':
-             cpp_assert (pfile, pend->arg);
-             break;
-           }
-       }
-    }
-
-  opts->done_initializing = 1;
-
-  { /* Read the appropriate environment variable and if it exists
-       replace include_defaults with the listed path.  */
-    char *epath = 0;
-    switch ((opts->objc << 1) + opts->cplusplus)
-      {
-      case 0:
-       GET_ENV_PATH_LIST (epath, "C_INCLUDE_PATH");
-       break;
-      case 1:
-       GET_ENV_PATH_LIST (epath, "CPLUS_INCLUDE_PATH");
-       break;
-      case 2:
-       GET_ENV_PATH_LIST (epath, "OBJC_INCLUDE_PATH");
-       break;
-      case 3:
-       GET_ENV_PATH_LIST (epath, "OBJCPLUS_INCLUDE_PATH");
-       break;
-      }
-    /* If the environment var for this language is set,
-       add to the default list of include directories.  */
-    if (epath) {
-      char *nstore = (char *) alloca (strlen (epath) + 2);
-      int num_dirs;
-      char *startp, *endp;
-
-      for (num_dirs = 1, startp = epath; *startp; startp++)
-       if (*startp == PATH_SEPARATOR)
-         num_dirs++;
-      include_defaults
-       = (struct default_include *) xmalloc ((num_dirs
-                                              * sizeof (struct default_include))
-                                             + sizeof (include_defaults_array));
-      startp = endp = epath;
-      num_dirs = 0;
-      while (1) {
-        /* Handle cases like c:/usr/lib:d:/gcc/lib */
-        if ((*endp == PATH_SEPARATOR)
-            || *endp == 0) {
-         strncpy (nstore, startp, endp-startp);
-         if (endp == startp)
-           strcpy (nstore, ".");
-         else
-           nstore[endp-startp] = '\0';
-
-         include_defaults[num_dirs].fname = xstrdup (nstore);
-         include_defaults[num_dirs].component = 0;
-         include_defaults[num_dirs].cplusplus = opts->cplusplus;
-         include_defaults[num_dirs].cxx_aware = 1;
-         num_dirs++;
-         if (*endp == '\0')
-           break;
-         endp = startp = endp + 1;
-       } else
-         endp++;
-      }
-      /* Put the usual defaults back in at the end.  */
-      bcopy ((char *) include_defaults_array,
-            (char *) &include_defaults[num_dirs],
-            sizeof (include_defaults_array));
-    }
-  }
-
-  /* Unless -fnostdinc,
-     tack on the standard include file dirs to the specified list */
-  if (!opts->no_standard_includes) {
-    struct default_include *p = include_defaults;
-    char *specd_prefix = opts->include_prefix;
-    char *default_prefix = xstrdup (GCC_INCLUDE_DIR);
-    int default_len = 0;
-    /* Remove the `include' from /usr/local/lib/gcc.../include.  */
-    if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) {
-      default_len = strlen (default_prefix) - 7;
-      default_prefix[default_len] = 0;
-    }
-    /* Search "translated" versions of GNU directories.
-       These have /usr/local/lib/gcc... replaced by specd_prefix.  */
-    if (specd_prefix != 0 && default_len != 0)
-      for (p = include_defaults; p->fname; p++) {
-       /* Some standard dirs are only for C++.  */
-       if (!p->cplusplus
-           || (opts->cplusplus && !opts->no_standard_cplusplus_includes)) {
-         /* Does this dir start with the prefix?  */
-         if (!strncmp (p->fname, default_prefix, default_len)) {
-           /* Yes; change prefix and add to search list.  */
-           int this_len = strlen (specd_prefix)
-                          + strlen (p->fname) - default_len;
-           char *str = (char *) xmalloc (this_len + 1);
-           strcpy (str, specd_prefix);
-           strcat (str, p->fname + default_len);
-
-           append_include_chain (pfile, &opts->system_include,
-                                 str, !p->cxx_aware);
-         }
-       }
-      }
-    /* Search ordinary names for GNU include directories.  */
-    for (p = include_defaults; p->fname; p++) {
-      /* Some standard dirs are only for C++.  */
-      if (!p->cplusplus
-         || (opts->cplusplus && !opts->no_standard_cplusplus_includes)) {
-       const char *str = update_path (p->fname, p->component);
-       append_include_chain (pfile, &opts->system_include,
-                             str, !p->cxx_aware);
-      }
-    }
-  }
-
-  merge_include_chains (opts);
-
-  /* With -v, print the list of dirs to search.  */
-  if (opts->verbose) {
-    struct file_name_list *p;
-    cpp_notice ("#include \"...\" search starts here:\n");
-    for (p = opts->quote_include; p; p = p->next) {
-      if (p == opts->bracket_include)
-       cpp_notice ("#include <...> search starts here:\n");
-      fprintf (stderr, " %s\n", p->name);
-    }
-    cpp_notice ("End of search list.\n");
-  }
-
-  /* Copy the entire contents of the main input file into
-     the stacked input buffer previously allocated for it.  */
-  if (fname == NULL || *fname == 0) {
-    fname = "";
-    f = 0;
-  } else if ((f = open (fname, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666)) < 0)
-    cpp_pfatal_with_name (pfile, fname);
-
-  /* -MG doesn't select the form of output and must be specified with one of
-     -M or -MM.  -MG doesn't make sense with -MD or -MMD since they don't
-     inhibit compilation.  */
-  if (opts->print_deps_missing_files
-      && (opts->print_deps == 0 || !opts->no_output))
-    {
-      cpp_fatal (pfile, "-MG must be specified with one of -M or -MM");
-      return 0;
-    }
-
-  /* Either of two environment variables can specify output of deps.
-     Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
-     where OUTPUT_FILE is the file to write deps info to
-     and DEPS_TARGET is the target to mention in the deps.  */
-
-  if (opts->print_deps == 0
-      && (getenv ("SUNPRO_DEPENDENCIES") != 0
-         || getenv ("DEPENDENCIES_OUTPUT") != 0)) {
-    char *spec = getenv ("DEPENDENCIES_OUTPUT");
-    char *s;
-    char *output_file;
-
-    if (spec == 0)
-      {
-       spec = getenv ("SUNPRO_DEPENDENCIES");
-       opts->print_deps = 2;
-      }
-    else
-      opts->print_deps = 1;
-
-    s = spec;
-    /* Find the space before the DEPS_TARGET, if there is one.  */
-    /* This should use index.  (mrs) */
-    while (*s != 0 && *s != ' ') s++;
-    if (*s != 0)
-      {
-       opts->deps_target = s + 1;
-       output_file = (char *) xmalloc (s - spec + 1);
-       bcopy (spec, output_file, s - spec);
-       output_file[s - spec] = 0;
-      }
-    else
-      {
-       opts->deps_target = 0;
-       output_file = spec;
-      }
-
-    opts->deps_file = output_file;
-    opts->print_deps_append = 1;
-  }
-
-  /* For -M, print the expected object file name
-     as the target of this Make-rule.  */
-  if (opts->print_deps)
-    {
-      pfile->deps_allocated_size = 200;
-      pfile->deps_buffer = (char *) xmalloc (pfile->deps_allocated_size);
-      pfile->deps_buffer[0] = 0;
-      pfile->deps_size = 0;
-      pfile->deps_column = 0;
-
-      if (opts->deps_target)
-       deps_output (pfile, opts->deps_target, ':');
-      else if (*opts->in_fname == 0)
-       deps_output (pfile, "-", ':');
-      else
-       {
-         char *p, *q, *r;
-         int len, x;
-         static char *known_suffixes[] = { ".c", ".C", ".s", ".S", ".m",
-                                    ".cc", ".cxx", ".cpp", ".cp",
-                                    ".c++", 0
-                                  };
-
-         /* Discard all directory prefixes from filename.  */
-         if ((q = rindex (opts->in_fname, '/')) != NULL
-#ifdef DIR_SEPARATOR
-             && (q = rindex (opts->in_fname, DIR_SEPARATOR)) != NULL
-#endif
-             )
-           ++q;
-         else
-           q = opts->in_fname;
-
-         /* Copy remainder to mungable area.  */
-         p = (char *) alloca (strlen(q) + 8);
-         strcpy (p, q);
-
-         /* Output P, but remove known suffixes.  */
-         len = strlen (p);
-         q = p + len;
-         /* Point to the filename suffix.  */
-         r = rindex (p, '.');
-         /* Compare against the known suffixes.  */
-         x = 0;
-         while (known_suffixes[x] != 0)
-           {
-             if (strncmp (known_suffixes[x], r, q - r) == 0)
-               {
-                 /* Make q point to the bit we're going to overwrite
-                    with an object suffix.  */
-                 q = r;
-                 break;
-               }
-             x++;
-           }
-
-         /* Supply our own suffix.  */
-#ifndef VMS
-         strcpy (q, ".o");
-#else
-         strcpy (q, ".obj");
-#endif
-
-         deps_output (pfile, p, ':');
-         deps_output (pfile, opts->in_fname, ' ');
-       }
-    }
-
-  /* Must call finclude() on the main input before processing
-     -include switches; otherwise the -included text winds up
-     after the main input. */
-  ih_fake = (struct include_hash *) xmalloc (sizeof (struct include_hash));
-  ih_fake->next = 0;
-  ih_fake->next_this_file = 0;
-  ih_fake->foundhere = ABSOLUTE_PATH;  /* well sort of ... */
-  ih_fake->name = fname;
-  ih_fake->control_macro = 0;
-  ih_fake->buf = (char *)-1;
-  ih_fake->limit = 0;
-  if (!finclude (pfile, f, ih_fake))
-    return 0;
-  output_line_command (pfile, 0, same_file);
-  pfile->only_seen_white = 2;
-
-  /* The -imacros files can be scanned now, but the -include files
-     have to be pushed onto the include stack and processed later,
-     in the main loop calling cpp_get_token.  That means the -include
-     files have to be processed in reverse order of the pending list,
-     which means the pending list has to be reversed again, which
-     means the -imacros files have to be done separately and first. */
-  
-  pfile->no_record_file++;
-  opts->no_output++;
-  for (pend = opts->pending; pend; pend = pend->next)
-    {
-      if (pend->cmd != NULL)
-        {
-         if (strcmp (pend->cmd, "-imacros") == 0)
-           {
-             int fd = open (pend->arg, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666);
-             if (fd < 0)
-               {
-                 cpp_perror_with_name (pfile, pend->arg);
-                 return 0;
-               }
-             if (!cpp_push_buffer (pfile, NULL, 0))
-               return 0;
-
-             ih_fake = (struct include_hash *)
-                 xmalloc (sizeof (struct include_hash));
-             ih_fake->next = 0;
-             ih_fake->next_this_file = 0;
-             ih_fake->foundhere = ABSOLUTE_PATH;  /* well sort of ... */
-             ih_fake->name = pend->arg;
-             ih_fake->control_macro = 0;
-             ih_fake->buf = (char *)-1;
-             ih_fake->limit = 0;
-             if (!finclude (pfile, fd, ih_fake))
-               cpp_scan_buffer (pfile);
-             free (ih_fake);
-           }
-       }
-    }
-  opts->no_output--;
-  opts->pending = nreverse_pending (opts->pending);
-  for (pend = opts->pending; pend; pend = pend->next)
-    {
-      if (pend->cmd != NULL)
-        {
-         if (strcmp (pend->cmd, "-include") == 0)
-           {
-             int fd = open (pend->arg, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666);
-             if (fd < 0)
-               {
-                 cpp_perror_with_name (pfile, pend->arg);
-                 return 0;
-               }
-             if (!cpp_push_buffer (pfile, NULL, 0))
-               return 0;
-
-             ih_fake = (struct include_hash *)
-                 xmalloc (sizeof (struct include_hash));
-             ih_fake->next = 0;
-             ih_fake->next_this_file = 0;
-             ih_fake->foundhere = ABSOLUTE_PATH;  /* well sort of ... */
-             ih_fake->name = pend->arg;
-             ih_fake->control_macro = 0;
-             ih_fake->buf = (char *)-1;
-             ih_fake->limit = 0;
-             if (finclude (pfile, fd, ih_fake))
-               output_line_command (pfile, 0, enter_file);
-           }
-       }
-    }
-  pfile->no_record_file--;
-
-  /* Free the pending list.  */
-  for (pend = opts->pending;  pend; )
-    {
-      struct cpp_pending *next = pend->next;
-      free (pend);
-      pend = next;
-    }
-  opts->pending = NULL;
-
-  return 1;
-}
-
-void
-cpp_reader_init (pfile)
-     cpp_reader *pfile;
-{
-  bzero ((char *) pfile, sizeof (cpp_reader));
-  pfile->get_token = cpp_get_token;
-
-  pfile->token_buffer_size = 200;
-  pfile->token_buffer = (U_CHAR *) xmalloc (pfile->token_buffer_size);
-  CPP_SET_WRITTEN (pfile, 0);
-
-  pfile->timebuf = NULL;
-  pfile->only_seen_white = 1;
-  pfile->buffer = CPP_NULL_BUFFER(pfile);
-  pfile->actual_dirs = NULL;
-}
-
-static struct cpp_pending *
-nreverse_pending (list)
-     struct cpp_pending *list;
-     
-{
-  register struct cpp_pending *prev = 0, *next, *pend;
-  for (pend = list;  pend;  pend = next)
-    {
-      next = pend->next;
-      pend->next = prev;
-      prev = pend;
-    }
-  return prev;
-}
-
-static void
-push_pending (pfile, cmd, arg)
-     cpp_reader *pfile;
-     char *cmd;
-     char *arg;
-{
-  struct cpp_pending *pend
-    = (struct cpp_pending *) xmalloc (sizeof (struct cpp_pending));
-  pend->cmd = cmd;
-  pend->arg = arg;
-  pend->next = CPP_OPTIONS (pfile)->pending;
-  CPP_OPTIONS (pfile)->pending = pend;
-}
-
-\f
-static void
-print_help ()
-{
-  printf ("Usage: %s [switches] input output\n", progname);
-  printf ("Switches:\n");
-  printf ("  -include <file>           Include the contents of <file> before other files\n");
-  printf ("  -imacros <file>           Accept definition of marcos in <file>\n");
-  printf ("  -iprefix <path>           Specify <path> as a prefix for next two options\n");
-  printf ("  -iwithprefix <dir>        Add <dir> to the end of the system include paths\n");
-  printf ("  -iwithprefixbefore <dir>  Add <dir> to the end of the main include paths\n");
-  printf ("  -isystem <dir>            Add <dir> to the start of the system include paths\n");
-  printf ("  -idirafter <dir>          Add <dir> to the end of the system include paths\n");
-  printf ("  -I <dir>                  Add <dir> to the end of the main include paths\n");
-  printf ("  -nostdinc                 Do not search the system include directories\n");
-  printf ("  -nostdinc++               Do not search the system include directories for C++\n");
-  printf ("  -o <file>                 Put output into <file>\n");
-  printf ("  -pedantic                 Issue all warnings demanded by strict ANSI C\n");
-  printf ("  -traditional              Follow K&R pre-processor behaviour\n");
-  printf ("  -trigraphs                Support ANSI C trigraphs\n");
-  printf ("  -lang-c                   Assume that the input sources are in C\n");
-  printf ("  -lang-c89                 Assume that the input sources are in C89\n");
-  printf ("  -lang-c++                 Assume that the input sources are in C++\n");
-  printf ("  -lang-objc                Assume that the input sources are in ObjectiveC\n");
-  printf ("  -lang-objc++              Assume that the input sources are in ObjectiveC++\n");
-  printf ("  -lang-asm                 Assume that the input sources are in assembler\n");
-  printf ("  -lang-chill               Assume that the input sources are in Chill\n");
-  printf ("  -std=<std name>           Specify the conformance standard; one of:\n");
-  printf ("                            gnu89, gnu9x, c89, c9x, iso9899:1990,\n");
-  printf ("                            iso9899:199409, iso9899:199x\n");
-
-  printf ("  -+                        Allow parsing of C++ style features\n");
-  printf ("  -w                        Inhibit warning messages\n");
-  printf ("  -Wtrigraphs               Warn if trigraphs are encountered\n");
-  printf ("  -Wno-trigraphs            Do not warn about trigraphs\n");
-  printf ("  -Wcomment{s}              Warn if one comment starts inside another\n");
-  printf ("  -Wno-comment{s}           Do not warn about comments\n");
-  printf ("  -Wtraditional             Warn if a macro argument is/would be turned into\n");
-  printf ("                             a string if -traditional is specified\n");
-  printf ("  -Wno-traditional          Do not warn about stringification\n");
-  printf ("  -Wundef                   Warn if an undefined macro is used by #if\n");
-  printf ("  -Wno-undef                Do not warn about testing undefined macros\n");
-  printf ("  -Wimport                  Warn about the use of the #import directive\n");
-  printf ("  -Wno-import               Do not warn about the use of #import\n");
-  printf ("  -Werror                   Treat all warnings as errors\n");
-  printf ("  -Wno-error                Do not treat warnings as errors\n");
-  printf ("  -Wall                     Enable all preprocessor warnings\n");
-  printf ("  -M                        Generate make dependencies\n");
-  printf ("  -MM                       As -M, but ignore system header files\n");
-  printf ("  -MD                       As -M, but put output in a .d file\n");
-  printf ("  -MMD                      As -MD, but ignore system header files\n");
-  printf ("  -MG                       Treat missing header file as generated files\n");
-  printf ("  -g                        Include #define and #undef directives in the output\n");
-  printf ("  -D<macro>                 Define a <macro> with string '1' as its value\n");
-  printf ("  -D<macro>=<val>           Define a <macro> with <val> as its value\n");
-  printf ("  -A<question> (<answer>)   Assert the <answer> to <question>\n");
-  printf ("  -U<macro>                 Undefine <macro> \n");
-  printf ("  -u or -undef              Do not predefine any macros\n");
-  printf ("  -v                        Display the version number\n");
-  printf ("  -H                        Print the name of header files as they are used\n");
-  printf ("  -C                        Do not discard comments\n");
-  printf ("  -dM                       Display a list of macro definitions active at end\n");
-  printf ("  -dD                       Preserve macro definitions in output\n");
-  printf ("  -dN                       As -dD except that only the names are preserved\n");
-  printf ("  -dI                       Include #include directives in the output\n");
-  printf ("  -ifoutput                 Describe skipped code blocks in output \n");
-  printf ("  -P                        Do not generate #line directives\n");
-  printf ("  -$                        Do not include '$' in identifiers\n");
-  printf ("  -remap                    Remap file names when including files.\n");
-  printf ("  -h or --help              Display this information\n");
-}
-\f
-
-/* Handle one command-line option in (argc, argv).
-   Can be called multiple times, to handle multiple sets of options.
-   Returns number of strings consumed.  */
-int
-cpp_handle_option (pfile, argc, argv)
-     cpp_reader *pfile;
-     int argc;
-     char **argv;
-{
-  struct cpp_options *opts = CPP_OPTIONS (pfile);
-  int i = 0;
-
-  if (user_label_prefix == NULL)
-    user_label_prefix = USER_LABEL_PREFIX;
-
-  if (argv[i][0] != '-') {
-    if (opts->out_fname != NULL)
-      {
-       print_help ();
-       cpp_fatal (pfile, "Too many arguments");
-      }
-    else if (opts->in_fname != NULL)
-      opts->out_fname = argv[i];
-    else
-      opts->in_fname = argv[i];
-  } else {
-    switch (argv[i][1]) {
-      
-    missing_filename:
-      cpp_fatal (pfile, "Filename missing after `%s' option", argv[i]);
-      return argc;
-    missing_dirname:
-      cpp_fatal (pfile, "Directory name missing after `%s' option", argv[i]);
-      return argc;
-      
-    case 'f':
-      if (!strcmp (argv[i], "-fleading-underscore"))
-       user_label_prefix = "_";
-      else if (!strcmp (argv[i], "-fno-leading-underscore"))
-       user_label_prefix = "";
-      break;
-
-    case 'I':                  /* Add directory to path for includes.  */
-      if (!strcmp (argv[i] + 2, "-"))
-        {
-         if (! opts->ignore_srcdir)
-           {
-             opts->ignore_srcdir = 1;
-             /* Don't use any preceding -I directories for #include <...>. */
-             opts->quote_include = opts->bracket_include;
-             opts->bracket_include = 0;
-           }
-       }
-      else
-       {
-         char *fname;
-         if (argv[i][2] != 0)
-           fname = argv[i] + 2;
-         else if (i + 1 == argc)
-           goto missing_dirname;
-         else
-           fname = argv[++i];
-         append_include_chain (pfile, &opts->bracket_include, fname, 0);
-       }
-      break;
-
-    case 'i':
-      /* Add directory to beginning of system include path, as a system
-        include directory. */
-      if (!strcmp (argv[i], "-isystem"))
-        {
-         if (i + 1 == argc)
-           goto missing_filename;
-         append_include_chain (pfile, &opts->system_include, argv[++i], 1);
-       }
-      /* Add directory to end of path for includes,
-        with the default prefix at the front of its name.  */
-      else if (!strcmp (argv[i], "-iwithprefix"))
-        {
-         char *fname;
-         if (i + 1 == argc)
-           goto missing_dirname;
-         ++i;
-
-         if (opts->include_prefix != 0)
-           {
-             fname = xmalloc (strlen (opts->include_prefix)
-                              + strlen (argv[i]) + 1);
-             strcpy (fname, opts->include_prefix);
-             strcat (fname, argv[i]);
-           }
-         else
-           {
-             fname = xmalloc (strlen (GCC_INCLUDE_DIR)
-                              + strlen (argv[i]) + 1);
-             strcpy (fname, GCC_INCLUDE_DIR);
-             /* Remove the `include' from /usr/local/lib/gcc.../include.  */
-             if (!strcmp (fname + strlen (fname) - 8, "/include"))
-               fname[strlen (fname) - 7] = 0;
-             strcat (fname, argv[i]);
-           }
-         
-         append_include_chain (pfile, &opts->system_include, fname, 0);
-      }
-      /* Add directory to main path for includes,
-        with the default prefix at the front of its name.  */
-      else if (!strcmp (argv[i], "-iwithprefix"))
-        {
-         char *fname;
-         if (i + 1 == argc)
-           goto missing_dirname;
-         ++i;
-
-         if (opts->include_prefix != 0)
-           {
-             fname = xmalloc (strlen (opts->include_prefix)
-                              + strlen (argv[i]) + 1);
-             strcpy (fname, opts->include_prefix);
-             strcat (fname, argv[i]);
-           }
-         else
-           {
-             fname = xmalloc (strlen (GCC_INCLUDE_DIR)
-                              + strlen (argv[i]) + 1);
-             strcpy (fname, GCC_INCLUDE_DIR);
-             /* Remove the `include' from /usr/local/lib/gcc.../include.  */
-             if (!strcmp (fname + strlen (fname) - 8, "/include"))
-               fname[strlen (fname) - 7] = 0;
-             strcat (fname, argv[i]);
-           }
-         
-         append_include_chain (pfile, &opts->bracket_include, fname, 0);
-        }
-      /* Add directory to end of path for includes.  */
-      else if (!strcmp (argv[i], "-idirafter"))
-        {
-         if (i + 1 == argc)
-           goto missing_dirname;
-         append_include_chain (pfile, &opts->after_include, argv[++i], 0);
-       }
-      else if (!strcmp (argv[i], "-include") || !strcmp (argv[i], "-imacros"))
-        {
-         if (i + 1 == argc)
-           goto missing_filename;
-         else
-           push_pending (pfile, argv[i], argv[i+1]), i++;
-        }
-      else if (!strcmp (argv[i], "-iprefix"))
-        {
-         if (i + 1 == argc)
-           goto missing_filename;
-         else
-             opts->include_prefix = argv[++i];
-       }
-      else if (!strcmp (argv[i], "-ifoutput"))
-       opts->output_conditionals = 1;
-
-      break;
-      
-    case 'o':
-      if (opts->out_fname != NULL)
-       {
-         cpp_fatal (pfile, "Output filename specified twice");
-         return argc;
-       }
-      if (i + 1 == argc)
-       goto missing_filename;
-      opts->out_fname = argv[++i];
-      if (!strcmp (opts->out_fname, "-"))
-       opts->out_fname = "";
-      break;
-      
-    case 'p':
-      if (!strcmp (argv[i], "-pedantic"))
-       CPP_PEDANTIC (pfile) = 1;
-      else if (!strcmp (argv[i], "-pedantic-errors")) {
-       CPP_PEDANTIC (pfile) = 1;
-       opts->pedantic_errors = 1;
-      }
-#if 0
-      else if (!strcmp (argv[i], "-pcp")) {
-       char *pcp_fname = argv[++i];
-       pcp_outfile = ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
-                      ? fopen (pcp_fname, "w")
-                      : fdopen (dup (fileno (stdout)), "w"));
-       if (pcp_outfile == 0)
-         cpp_pfatal_with_name (pfile, pcp_fname);
-       no_precomp = 1;
-      }
-#endif
-      break;
-      
-    case 't':
-      if (!strcmp (argv[i], "-traditional")) {
-       opts->traditional = 1;
-       opts->cplusplus_comments = 0;
-      } else if (!strcmp (argv[i], "-trigraphs")) {
-       if (!opts->chill)
-         opts->trigraphs = 1;
-      }
-      break;
-      
-    case 'l':
-      if (! strcmp (argv[i], "-lang-c"))
-       opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
-         opts->c9x = 1, opts->objc = 0;
-      if (! strcmp (argv[i], "-lang-c89"))
-       opts->cplusplus = 0, opts->cplusplus_comments = 0, opts->c89 = 1,
-         opts->c9x = 0, opts->objc = 0;
-      if (! strcmp (argv[i], "-lang-c++"))
-       opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
-         opts->c9x = 0, opts->objc = 0;
-      if (! strcmp (argv[i], "-lang-objc"))
-       opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
-         opts->c9x = 0, opts->objc = 1;
-      if (! strcmp (argv[i], "-lang-objc++"))
-       opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
-         opts->c9x = 0, opts->objc = 1;
-      if (! strcmp (argv[i], "-lang-asm"))
-       opts->lang_asm = 1;
-      if (! strcmp (argv[i], "-lint"))
-       opts->for_lint = 1;
-      if (! strcmp (argv[i], "-lang-chill"))
-       opts->objc = 0, opts->cplusplus = 0, opts->chill = 1,
-         opts->traditional = 1, opts->trigraphs = 0;
-      break;
-      
-    case '+':
-      opts->cplusplus = 1, opts->cplusplus_comments = 1;
-      break;
-
-    case 's':
-      if (!strcmp (argv[i], "-std=iso9899:1990")
-         || !strcmp (argv[i], "-std=iso9899:199409")
-         || !strcmp (argv[i], "-std=c89")
-         || !strcmp (argv[i], "-std=gnu89"))
-         opts->cplusplus = 0, opts->cplusplus_comments = 0,
-           opts->c89 = 1, opts->c9x = 0, opts->objc = 0;
-      else if (!strcmp (argv[i], "-std=iso9899:199x")
-              || !strcmp (argv[i], "-std=c9x")
-              || !strcmp (argv[i], "-std=gnu9x"))
-       opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
-         opts->c9x = 1, opts->objc = 0;
-      break;
-
-    case 'w':
-      opts->inhibit_warnings = 1;
-      break;
-      
-    case 'W':
-      if (!strcmp (argv[i], "-Wtrigraphs"))
-       opts->warn_trigraphs = 1;
-      else if (!strcmp (argv[i], "-Wno-trigraphs"))
-       opts->warn_trigraphs = 0;
-      else if (!strcmp (argv[i], "-Wcomment"))
-       opts->warn_comments = 1;
-      else if (!strcmp (argv[i], "-Wno-comment"))
-       opts->warn_comments = 0;
-      else if (!strcmp (argv[i], "-Wcomments"))
-       opts->warn_comments = 1;
-      else if (!strcmp (argv[i], "-Wno-comments"))
-       opts->warn_comments = 0;
-      else if (!strcmp (argv[i], "-Wtraditional"))
-       opts->warn_stringify = 1;
-      else if (!strcmp (argv[i], "-Wno-traditional"))
-       opts->warn_stringify = 0;
-      else if (!strcmp (argv[i], "-Wundef"))
-       opts->warn_undef = 1;
-      else if (!strcmp (argv[i], "-Wno-undef"))
-       opts->warn_undef = 0;
-      else if (!strcmp (argv[i], "-Wimport"))
-       opts->warn_import = 1;
-      else if (!strcmp (argv[i], "-Wno-import"))
-       opts->warn_import = 0;
-      else if (!strcmp (argv[i], "-Werror"))
-       opts->warnings_are_errors = 1;
-      else if (!strcmp (argv[i], "-Wno-error"))
-       opts->warnings_are_errors = 0;
-      else if (!strcmp (argv[i], "-Wall"))
-       {
-         opts->warn_trigraphs = 1;
-         opts->warn_comments = 1;
-       }
-      break;
-      
-    case 'M':
-      /* The style of the choices here is a bit mixed.
-        The chosen scheme is a hybrid of keeping all options in one string
-        and specifying each option in a separate argument:
-        -M|-MM|-MD file|-MMD file [-MG].  An alternative is:
-        -M|-MM|-MD file|-MMD file|-MG|-MMG; or more concisely:
-        -M[M][G][D file].  This is awkward to handle in specs, and is not
-        as extensible.  */
-      /* ??? -MG must be specified in addition to one of -M or -MM.
-        This can be relaxed in the future without breaking anything.
-        The converse isn't true.  */
-      
-      /* -MG isn't valid with -MD or -MMD.  This is checked for later.  */
-      if (!strcmp (argv[i], "-MG"))
-       {
-         opts->print_deps_missing_files = 1;
-         break;
-       }
-      if (!strcmp (argv[i], "-M"))
-       opts->print_deps = 2;
-      else if (!strcmp (argv[i], "-MM"))
-       opts->print_deps = 1;
-      else if (!strcmp (argv[i], "-MD"))
-       opts->print_deps = 2;
-      else if (!strcmp (argv[i], "-MMD"))
-       opts->print_deps = 1;
-      /* For -MD and -MMD options, write deps on file named by next arg.  */
-      if (!strcmp (argv[i], "-MD") || !strcmp (argv[i], "-MMD"))
-       {
-         if (i+1 == argc)
-           goto missing_filename;
-         opts->deps_file = argv[++i];
-       }
-      else
-       {
-         /* For -M and -MM, write deps on standard output
-            and suppress the usual output.  */
-         opts->no_output = 1;
-       }         
-      break;
-      
-    case 'd':
-      {
-       char *p = argv[i] + 2;
-       char c;
-       while ((c = *p++) != 0) {
-         /* Arg to -d specifies what parts of macros to dump */
-         switch (c) {
-         case 'M':
-           opts->dump_macros = dump_only;
-           opts->no_output = 1;
-           break;
-         case 'N':
-           opts->dump_macros = dump_names;
-           break;
-         case 'D':
-           opts->dump_macros = dump_definitions;
-           break;
-         case 'I':
-           opts->dump_includes = 1;
-           break;
-         }
-       }
-      }
-    break;
-    
-    case 'g':
-      if (argv[i][2] == '3')
-       opts->debug_output = 1;
-      break;
-      
-    case '-':
-      if (strcmp (argv[i], "--help") != 0)
-       return i;
-      print_help ();
-      break;
-       
-    case 'v':
-      cpp_notice ("GNU CPP version %s", version_string);
-#ifdef TARGET_VERSION
-      TARGET_VERSION;
-#endif
-      fprintf (stderr, "\n");
-      opts->verbose = 1;
-      break;
-      
-    case 'H':
-      opts->print_include_names = 1;
-      break;
-      
-    case 'D':
-      if (argv[i][2] != 0)
-       push_pending (pfile, "-D", argv[i] + 2);
-      else if (i + 1 == argc)
-       {
-         cpp_fatal (pfile, "Macro name missing after -D option");
-         return argc;
-       }
-      else
-       i++, push_pending (pfile, "-D", argv[i]);
-      break;
-      
-    case 'A':
-      {
-       char *p;
-       
-       if (argv[i][2] != 0)
-         p = argv[i] + 2;
-       else if (i + 1 == argc)
-         {
-           cpp_fatal (pfile, "Assertion missing after -A option");
-           return argc;
-         }
-       else
-         p = argv[++i];
-       
-       if (!strcmp (p, "-")) {
-         struct cpp_pending **ptr;
-         /* -A- eliminates all predefined macros and assertions.
-            Let's include also any that were specified earlier
-            on the command line.  That way we can get rid of any
-            that were passed automatically in from GCC.  */
-         opts->inhibit_predefs = 1;
-         for (ptr = &opts->pending; *ptr != NULL; )
-           {
-             struct cpp_pending *pend = *ptr;
-             if (pend->cmd && pend->cmd[0] == '-'
-                 && (pend->cmd[1] == 'D' || pend->cmd[1] == 'A'))
-               {
-                 *ptr = pend->next;
-                 free (pend);
-               }
-             else
-               ptr = &pend->next;
-           }
-       } else {
-         push_pending (pfile, "-A", p);
-       }
-      }
-    break;
-    
-    case 'U':          /* JF #undef something */
-      if (argv[i][2] != 0)
-       push_pending (pfile, "-U", argv[i] + 2);
-      else if (i + 1 == argc)
-       {
-         cpp_fatal (pfile, "Macro name missing after -U option");
-         return argc;
-       }
-      else
-       push_pending (pfile, "-U", argv[i+1]), i++;
-      break;
-      
-    case 'C':
-      opts->put_out_comments = 1;
-      break;
-      
-    case 'E':                  /* -E comes from cc -E; ignore it.  */
-      break;
-      
-    case 'P':
-      opts->no_line_commands = 1;
-      break;
-      
-    case '$':                  /* Don't include $ in identifiers.  */
-      opts->dollars_in_ident = 0;
-      break;
-      
-    case 'n':
-      if (!strcmp (argv[i], "-nostdinc"))
-       /* -nostdinc causes no default include directories.
-          You must specify all include-file directories with -I.  */
-       opts->no_standard_includes = 1;
-      else if (!strcmp (argv[i], "-nostdinc++"))
-       /* -nostdinc++ causes no default C++-specific include directories. */
-       opts->no_standard_cplusplus_includes = 1;
-#if 0
-      else if (!strcmp (argv[i], "-noprecomp"))
-       no_precomp = 1;
-#endif
-      break;
-      
-    case 'r':
-      if (!strcmp (argv[i], "-remap"))
-       opts->remap = 1;
-      break;
-      
-    case 'u':
-      /* Sun compiler passes undocumented switch "-undef".
-        Let's assume it means to inhibit the predefined symbols.  */
-      opts->inhibit_predefs = 1;
-      break;
-      
-    case '\0': /* JF handle '-' as file name meaning stdin or stdout */
-      if (opts->in_fname == NULL) {
-       opts->in_fname = "";
-       break;
-      } else if (opts->out_fname == NULL) {
-       opts->out_fname = "";
-       break;
-      }        /* else fall through into error */
-
-    default:
-      return i;
-    }
-  }
-
-  return i + 1;
-}
-
-/* Handle command-line options in (argc, argv).
-   Can be called multiple times, to handle multiple sets of options.
-   Returns if an unrecognized option is seen.
-   Returns number of strings consumed.  */
-
-int
-cpp_handle_options (pfile, argc, argv)
-     cpp_reader *pfile;
-     int argc;
-     char **argv;
-{
-  int i;
-  int strings_processed;
-  for (i = 0; i < argc; i += strings_processed)
-    {
-      strings_processed = cpp_handle_option (pfile, argc - i, argv + i);
-      if (strings_processed == 0)
-       break;
-    }
-  return i;
-}
-\f
-void
-cpp_finish (pfile)
-     cpp_reader *pfile;
-{
-  struct cpp_options *opts = CPP_OPTIONS (pfile);
-
-  if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != CPP_NULL_BUFFER (pfile))
-    cpp_fatal (pfile,
-              "cpplib internal error: buffers still stacked in cpp_finish");
-  cpp_pop_buffer (pfile);
-  
-  if (opts->print_deps)
-    {
-      /* Stream on which to print the dependency information.  */
-      FILE *deps_stream;
-
-      /* Don't actually write the deps file if compilation has failed.  */
-      if (pfile->errors == 0)
-       {
-         char *deps_mode = opts->print_deps_append ? "a" : "w";
-         if (opts->deps_file == 0)
-           deps_stream = stdout;
-         else if ((deps_stream = fopen (opts->deps_file, deps_mode)) == 0)
-           cpp_pfatal_with_name (pfile, opts->deps_file);
-         fputs (pfile->deps_buffer, deps_stream);
-         putc ('\n', deps_stream);
-         if (opts->deps_file)
-           {
-             if (ferror (deps_stream) || fclose (deps_stream) != 0)
-               cpp_fatal (pfile, "I/O error on output");
-           }
-       }
-    }
-
-#if 0
-  /* Debugging: dump statistics on the include hash table. */
-  {
-      struct include_hash *x;
-      int i, j;
-
-      for(i = 0; i < ALL_INCLUDE_HASHSIZE; i++)
-      {
-         x = pfile->all_include_files[i];
-         j = 0;
-         while(x)
-         {
-             j++;
-             x = x->next;
-         }
-         fprintf(stderr, "%d/%d ", i, j);
-      }
-      fputc('\n', stderr);
-  }
-#endif
-  
-}
-
-/* Free resources used by PFILE.
-   This is the cpp_reader 'finalizer' or 'destructor' (in C++ terminology).  */
-
-void
-cpp_cleanup (pfile)
-     cpp_reader *pfile;
-{
-  int i;
-  while (CPP_BUFFER (pfile) != CPP_NULL_BUFFER (pfile))
-    cpp_pop_buffer (pfile);
-
-  if (pfile->token_buffer)
-    {
-      free (pfile->token_buffer);
-      pfile->token_buffer = NULL;
-    }
-
-  if (pfile->deps_buffer)
-    {
-      free (pfile->deps_buffer);
-      pfile->deps_buffer = NULL;
-      pfile->deps_allocated_size = 0;
-    }
-
-  while (pfile->if_stack)
-    {
-      IF_STACK_FRAME *temp = pfile->if_stack;
-      pfile->if_stack = temp->next;
-      free (temp);
-    }
-
-  for (i = ALL_INCLUDE_HASHSIZE; --i >= 0; )
-    {
-      struct include_hash *imp = pfile->all_include_files[i];
-      while (imp)
-       {
-         struct include_hash *next = imp->next;
-#if 0
-         /* This gets freed elsewhere - I think. */
-         free (imp->name);
-#endif
-         free (imp);
-         imp = next;
-       }
-      pfile->all_include_files[i] = 0;
-    }
-
-  cpp_hash_cleanup (pfile);
-}
-\f
 /* Read an assertion into the token buffer, converting to
    canonical form: `#predicate(a n swe r)'  The next non-whitespace
    character to read should be the first letter of the predicate.
index 8a33eed..a943939 100644 (file)
@@ -637,11 +637,19 @@ struct definition {
   } args;
 };
 
-extern const unsigned char is_idstart[256];
-extern const unsigned char is_idchar[256];
-extern const unsigned char is_hor_space[256];
-extern const unsigned char is_space[256];
-extern const unsigned char trigraph_table[256];
+/* These tables are not really `const', but they are only modified at
+   initialization time, in a separate translation unit from the rest
+   of the library.  We let the rest of the library think they are `const'
+   to get better code and some additional sanity checks.  */
+#ifndef FAKE_CONST
+#define FAKE_CONST const
+#endif
+extern FAKE_CONST unsigned char is_idstart[256];
+extern FAKE_CONST unsigned char is_idchar[256];
+extern FAKE_CONST unsigned char is_hor_space[256];
+extern FAKE_CONST unsigned char is_space[256];
+extern FAKE_CONST unsigned char trigraph_table[256];
+#undef FAKE_CONST
 
 /* Stack of conditionals currently in progress
    (including both successful and failing conditionals).  */
@@ -667,8 +675,9 @@ typedef struct if_stack IF_STACK_FRAME;
 
 extern void cpp_buf_line_and_col PARAMS((cpp_buffer *, long *, long *));
 extern cpp_buffer* cpp_file_buffer PARAMS((cpp_reader *));
-extern void cpp_define PARAMS ((cpp_reader*, unsigned char *));
+extern void cpp_define PARAMS ((cpp_reader *, unsigned char *));
 extern void cpp_assert PARAMS ((cpp_reader *, unsigned char *));
+extern void cpp_undef  PARAMS ((cpp_reader *, unsigned char *));
 
 extern void cpp_error PVPROTO ((cpp_reader *, const char *, ...))
   ATTRIBUTE_PRINTF_2;
@@ -705,6 +714,16 @@ extern int scan_decls PARAMS ((cpp_reader *, int, char **));
 extern void skip_rest_of_line PARAMS ((cpp_reader *));
 extern void cpp_finish PARAMS ((cpp_reader *));
 
+extern void quote_string               PARAMS ((cpp_reader *, const char *));
+extern void cpp_expand_to_buffer       PARAMS ((cpp_reader *, U_CHAR *, int));
+extern void cpp_scan_buffer            PARAMS ((cpp_reader *));
+extern int check_macro_name            PARAMS ((cpp_reader *, U_CHAR *, int));
+
+/* Last arg to output_line_command.  */
+enum file_change_code {same_file, enter_file, leave_file};
+extern void output_line_command                PARAMS ((cpp_reader *, int,
+                                                enum file_change_code));
+
 /* From cpperror.c */
 extern void cpp_fatal PVPROTO ((cpp_reader *, const char *, ...))
   ATTRIBUTE_PRINTF_2;
@@ -729,9 +748,6 @@ extern int finclude                 PROTO ((cpp_reader *, int,
 extern void deps_output                        PROTO ((cpp_reader *, char *, int));
 extern struct include_hash *include_hash PROTO ((cpp_reader *, char *, int));
 
-/* cppinit.c */
-extern void initialize_char_syntax     PROTO ((int));
-
 #ifndef INCLUDE_LEN_FUDGE
 #define INCLUDE_LEN_FUDGE 0
 #endif