[multiple changes]
authorZack Weinberg <zack@rabi.phys.columbia.edu>
Thu, 29 Oct 1998 11:54:13 +0000 (11:54 +0000)
committerDave Brolley <brolley@gcc.gnu.org>
Thu, 29 Oct 1998 11:54:13 +0000 (06:54 -0500)
1998-10-28 16:10 -0500 Zack Weinberg  <zack@rabi.phys.columbia.edu>
 * c-lang.c: Declare extern char *yy_cur if USE_CPPLIB.
   (lang_init): Call check_newline always.
 * c-lex.c (init_parse) [USE_CPPLIB=1]: After calling
   cpp_start_read, set yy_cur and yy_lim to read from
   parse_in.token_buffer, so that we'll see the first #line
   directive.
 * cpplib.c (cpp_start_read): finclude the main input file
   before processing -include/-imacros.  Process -imacros and
   -include separately, and handle -include by stacking a
   buffer for the file in question as if it'd been #included.
 * toplev.c (documented_lang_options) Recognize -H when
   USE_CPPLIB is on.
1998-10-28 16:09 -0500 Zack Weinberg  <zack@rabi.phys.columbia.edu>
 * cpplib.c: Merge do_once into do_pragma.  Break file handling
   code out of do_include.
   Move append_include_chain, deps_output,
   file_cleanup, redundant_include_p, import_hash,
   lookup_import, add_import, read_filename_string, read_name_map,
   open_include_file, finclude, safe_read to cppfiles.c.
   Move prototypes for deps_output, append_include_chain,
   finclude to cpplib.h.  Move definition of struct
   file_name_list there also.
 * cppfiles.c: New file.  Contains all the above functions
   broken out of cpplib.c; also hack_vms_include_specification
   from cccp.c and find_include_file, a new function broken out of
   do_include.
 * Makefile.in (cppmain): Depend on cppfiles.o.
   (fix-header): Likewise.
   (cppfiles.o): New target.
 * configure.in (--enable-c-cpplib): Add cppfiles.o to
   extra_c_objs.  Add ../cppfiles.o to extra_cxx_objs.

From-SVN: r23424

gcc/ChangeLog
gcc/Makefile.in
gcc/c-lang.c
gcc/c-lex.c
gcc/cppfiles.c [new file with mode: 0644]
gcc/cpplib.c
gcc/cpplib.h
gcc/toplev.c

index b01e4eaf05842419d86d3c7d7b7f8d1c74d8bc88..8eb81d2c43fe0ecca5322631e23fb87c10f2320c 100644 (file)
@@ -86,6 +86,44 @@ Wed Oct 28 16:46:07 1998  Andreas Schwab  <schwab@issan.cs.uni-dortmund.de>
        (purge_addressof_replacements): New variable.
        (purge_addressof): Clear it at end.
 
+1998-10-28 16:10 -0500 Zack Weinberg  <zack@rabi.phys.columbia.edu>
+
+        * c-lang.c: Declare extern char *yy_cur if USE_CPPLIB.
+          (lang_init): Call check_newline always.
+        * c-lex.c (init_parse) [USE_CPPLIB=1]: After calling
+          cpp_start_read, set yy_cur and yy_lim to read from
+          parse_in.token_buffer, so that we'll see the first #line
+          directive.
+        * cpplib.c (cpp_start_read): finclude the main input file
+          before processing -include/-imacros.  Process -imacros and
+          -include separately, and handle -include by stacking a
+          buffer for the file in question as if it'd been #included.
+        * toplev.c (documented_lang_options) Recognize -H when
+          USE_CPPLIB is on.
+
+1998-10-28 16:09 -0500 Zack Weinberg  <zack@rabi.phys.columbia.edu>
+
+        * cpplib.c: Merge do_once into do_pragma.  Break file handling
+          code out of do_include.
+          Move append_include_chain, deps_output,
+          file_cleanup, redundant_include_p, import_hash,
+          lookup_import, add_import, read_filename_string, read_name_map,
+          open_include_file, finclude, safe_read to cppfiles.c.
+          Move prototypes for deps_output, append_include_chain,
+          finclude to cpplib.h.  Move definition of struct
+          file_name_list there also.
+
+        * cppfiles.c: New file.  Contains all the above functions
+          broken out of cpplib.c; also hack_vms_include_specification
+          from cccp.c and find_include_file, a new function broken out of
+          do_include.
+
+        * Makefile.in (cppmain): Depend on cppfiles.o.
+          (fix-header): Likewise.
+          (cppfiles.o): New target.
+        * configure.in (--enable-c-cpplib): Add cppfiles.o to
+          extra_c_objs.  Add ../cppfiles.o to extra_cxx_objs.
+
 Wed Oct 28 14:06:49 1998  Jim Wilson  <wilson@cygnus.com>
 
        * dwarfout.c (dwarfout_file_scope_decl): If DECL_CONTEXT, don't abort
index 62eed7f068a3f9309d48058869b3d208f6126e5c..c407d28bfb69fc17f619d6457b2f5502ec98ecd6 100644 (file)
@@ -1881,7 +1881,7 @@ cccp.o: cccp.c $(CONFIG_H) pcp.h version.c config.status system.h gansidecl.h \
          -DTOOL_INCLUDE_DIR=\"$(tooldir)/include\" \
          -c `echo $(srcdir)/cccp.c | sed 's,^\./,,'`
 
-LIBCPP_OBJS =  cpplib.o cpphash.o cppalloc.o cpperror.o cppexp.o \
+LIBCPP_OBJS =  cpplib.o cpphash.o cppalloc.o cpperror.o cppexp.o cppfiles.o \
                cppulp.o prefix.o version.o mbchar.o @extra_cpp_objs@
 
 libcpp.a: $(LIBCPP_OBJS)
@@ -1907,6 +1907,8 @@ cpperror.o: cpperror.c $(CONFIG_H) cpplib.h system.h gansidecl.h
 
 cppexp.o: cppexp.c $(CONFIG_H) cpplib.h system.h gansidecl.h
 
+cppfiles.o: cppfiles.c $(CONFIG_H) cpplib.h system.h gansidecl.h
+
 cpphash.o: cpphash.c cpplib.h cpphash.h $(CONFIG_H) system.h gansidecl.h
 
 cppalloc.o: cppalloc.c $(CONFIG_H) cpplib.h system.h gansidecl.h
index 8a5fd6bbfefb6ff414308e3f78396a7f2e468e08..6e04bd76f8b23d3ff8e7103bb54a57789480437f 100644 (file)
@@ -28,6 +28,10 @@ Boston, MA 02111-1307, USA.  */
 #include "toplev.h"
 #include "output.h"
 
+#if USE_CPPLIB
+extern char *yy_cur;
+#endif
+
 /* Each of the functions defined here
    is an alternative to a function in objc-actions.c.  */
    
@@ -47,12 +51,15 @@ lang_init_options ()
 void
 lang_init ()
 {
-#if !USE_CPPLIB
   /* the beginning of the file is a new line; check for # */
   /* With luck, we discover the real source file's name from that
      and put it in input_filename.  */
+#if !USE_CPPLIB
   ungetc (check_newline (), finput);
-#endif
+#else
+  check_newline ();
+  yy_cur--;
+#endif 
 }
 
 void
index 10e91216f665c44eeb9da935f979a15c5f20449e..b6d8295606c21bbb8b1cdecb17f0011d11d3b03f 100644 (file)
@@ -194,12 +194,14 @@ init_parse (filename)
   init_lex ();
 
 #if USE_CPPLIB
-  yy_cur = "\n";
-  yy_lim = yy_cur+1;
-
   parse_in.show_column = 1;
   if (! cpp_start_read (&parse_in, filename))
     abort ();
+
+  /* cpp_start_read always puts at least one line directive into the
+     token buffer.  We must arrange to read it out here. */
+  yy_cur = parse_in.token_buffer;
+  yy_lim = CPP_PWRITTEN (&parse_in);
 #endif
 
   return filename;
diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c
new file mode 100644 (file)
index 0000000..559cc11
--- /dev/null
@@ -0,0 +1,1023 @@
+/* Part of CPP library.  (include file handling)
+   Copyright (C) 1986, 87, 89, 92 - 95, 1998 Free Software Foundation, Inc.
+   Written by Per Bothner, 1994.
+   Based on CCCP program by Paul Rubin, June 1986
+   Adapted to ANSI C, Richard Stallman, Jan 1987
+   Split out of cpplib.c, Zack Weinberg, Oct 1998
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them.   Help stamp out software-hoarding!  */
+
+#include "config.h"
+#include "system.h"
+#include "gansidecl.h"
+#include "cpplib.h"
+
+/* The entry points to this file are: find_include_file, finclude,
+   append_include_chain, deps_output, and file_cleanup.
+   file_cleanup is only called through CPP_BUFFER(pfile)->cleanup,
+   so it's static anyway. */
+
+static void add_import                 PROTO ((cpp_reader *, int, char *));
+static int lookup_import               PROTO ((cpp_reader *, char *,
+                                               struct file_name_list *));
+static int redundant_include_p         PROTO ((cpp_reader *, char *));
+static struct file_name_map *read_name_map     PROTO ((cpp_reader *, char *));
+static char *read_filename_string      PROTO ((int, FILE *));
+static int open_include_file           PROTO ((cpp_reader *, char *,
+                                               struct file_name_list *));
+static int safe_read                   PROTO ((int, char *, int));
+
+/* Not safe to prototype these. */
+extern char *xmalloc();
+extern char *xrealloc();
+
+/* Append a chain of `struct file_name_list's
+   to the end of the main include chain.
+   FIRST is the beginning of the chain to append, and LAST is the end.  */
+
+void
+append_include_chain (pfile, first, last)
+     cpp_reader *pfile;
+     struct file_name_list *first, *last;
+{
+  struct cpp_options *opts = CPP_OPTIONS (pfile);
+  struct file_name_list *dir;
+
+  if (!first || !last)
+    return;
+
+  if (opts->include == 0)
+    opts->include = first;
+  else
+    opts->last_include->next = first;
+
+  if (opts->first_bracket_include == 0)
+    opts->first_bracket_include = first;
+
+  for (dir = first; ; dir = dir->next) {
+    int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
+    if (len > pfile->max_include_len)
+      pfile->max_include_len = len;
+    if (dir == last)
+      break;
+  }
+
+  last->next = NULL;
+  opts->last_include = last;
+}
+
+/* Add output to `deps_buffer' for the -M switch.
+   STRING points to the text to be output.
+   SPACER is ':' for targets, ' ' for dependencies, zero for text
+   to be inserted literally.  */
+
+void
+deps_output (pfile, string, spacer)
+     cpp_reader *pfile;
+     char *string;
+     int spacer;
+{
+  int size;
+
+  if (!*string)
+    return;
+
+#ifdef VMS
+  hack_vms_include_specification (string);
+#endif
+
+  size = strlen (string);
+
+#ifndef MAX_OUTPUT_COLUMNS
+#define MAX_OUTPUT_COLUMNS 72
+#endif
+  if (spacer
+      && pfile->deps_column > 0
+      && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS)
+    {
+      deps_output (pfile, " \\\n  ", 0);
+      pfile->deps_column = 0;
+    }
+
+  if (pfile->deps_size + size + 8 > pfile->deps_allocated_size)
+    {
+      pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2;
+      pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer,
+                                             pfile->deps_allocated_size);
+    }
+  if (spacer == ' ' && pfile->deps_column > 0)
+    pfile->deps_buffer[pfile->deps_size++] = ' ';
+  bcopy (string, &pfile->deps_buffer[pfile->deps_size], size);
+  pfile->deps_size += size;
+  pfile->deps_column += size;
+  if (spacer == ':')
+    pfile->deps_buffer[pfile->deps_size++] = ':';
+  pfile->deps_buffer[pfile->deps_size] = 0;
+}
+
+static int
+file_cleanup (pbuf, pfile)
+     cpp_buffer *pbuf;
+     cpp_reader *pfile ATTRIBUTE_UNUSED;
+{
+  if (pbuf->buf)
+    {
+      free (pbuf->buf);
+      pbuf->buf = 0;
+    }
+  return 0;
+}
+
+int
+find_include_file (pfile, fbeg, flen, fname,
+                  importing, search_start, foundhere)
+     cpp_reader *pfile;
+     char *fbeg;
+     unsigned long flen;
+     char *fname;
+     int importing;
+     struct file_name_list *search_start;
+     struct file_name_list **foundhere;
+{
+  struct file_name_list *searchptr;
+  int f;
+    
+  /* If specified file name is absolute, just open it.  */
+
+  if (*fbeg == '/')
+  {
+    strcpy (fname, fbeg);
+#ifdef VMS
+    hack_vms_include_specification (fname);
+#endif
+    if (redundant_include_p (pfile, fname))
+      return -2;
+    if (importing)
+      f = lookup_import (pfile, fname, NULL_PTR);
+    else
+      f = open_include_file (pfile, fname, NULL_PTR);
+    if (f == -2)
+      return -2;       /* Already included this file */
+  }
+  else
+  {
+    /* Search directory path, trying to open the file.
+       Copy each filename tried into FNAME.  */
+
+    for (searchptr = search_start; searchptr; searchptr = searchptr->next)
+    {
+      unsigned int l = 0;
+      if (searchptr->fname)
+      {
+       /* The empty string in a search path is ignored.
+          This makes it possible to turn off entirely
+          a standard piece of the list.  */
+       if (searchptr->fname[0] == 0)
+         continue;
+
+       l = strlen (searchptr->fname);
+
+       bcopy (searchptr->fname, fname, l);
+       fname[l++] = '/';
+      }
+
+      bcopy (fbeg, &fname[l], flen);
+      fname[flen+l] = '\0';
+#ifdef VMS
+      hack_vms_include_specification (fname);
+#endif /* VMS */
+      /* ??? There are currently 3 separate mechanisms for avoiding processing
+        of redundant include files: #import, #pragma once, and
+        redundant_include_p.  It would be nice if they were unified.  */
+      if (redundant_include_p (pfile, fname))
+       return -2;
+      if (importing)
+       f = lookup_import (pfile, fname, searchptr);
+      else
+       f = open_include_file (pfile, fname, searchptr);
+      if (f == -2)
+       return -2;                      /* Already included this file */
+#ifdef EACCES
+      else if (f == -1 && errno == EACCES)
+       cpp_warning (pfile, "Header file %s exists, but is not readable",
+                    fname);
+#endif
+      if (f >= 0)
+       break;
+    }
+  }
+
+  if (f < 0)
+    {
+      /* A file that was not found.  */
+      bcopy (fbeg, fname, flen);
+      fname[flen] = 0;
+
+      return -1;
+    }
+  else
+    {
+      /* Check to see if this include file is a once-only include file.
+        If so, give up.  */
+
+      struct file_name_list *ptr;
+
+      for (ptr = pfile->dont_repeat_files; ptr; ptr = ptr->next)
+         if (!strcmp (ptr->fname, fname))
+           {
+             close (f);
+             return -2;                /* This file was once'd.  */
+           }
+    }
+
+    /* Record file on "seen" list for #import.  */
+    add_import (pfile, f, fname);
+
+    *foundhere = searchptr;
+    return f;
+}
+
+/* Return nonzero if there is no need to include file NAME
+   because it has already been included and it contains a conditional
+   to make a repeated include do nothing.  */
+
+static int
+redundant_include_p (pfile, name)
+     cpp_reader *pfile;
+     char *name;
+{
+  struct file_name_list *l = pfile->all_include_files;
+  for (; l; l = l->next)
+    if (! strcmp (name, l->fname)
+       && l->control_macro
+       && cpp_lookup (pfile, l->control_macro, -1, -1))
+      return 1;
+  return 0;
+}
+
+
+
+/* Maintain and search list of included files, for #import.  */
+
+/* Hash a file name for import_hash_table.  */
+
+static int 
+import_hash (f)
+     char *f;
+{
+  int val = 0;
+
+  while (*f) val += *f++;
+  return (val%IMPORT_HASH_SIZE);
+}
+
+/* Search for file FILENAME in import_hash_table.
+   Return -2 if found, either a matching name or a matching inode.
+   Otherwise, open the file and return a file descriptor if successful
+   or -1 if unsuccessful.  */
+
+static int
+lookup_import (pfile, filename, searchptr)
+     cpp_reader *pfile;
+     char *filename;
+     struct file_name_list *searchptr;
+{
+  struct import_file *i;
+  int h;
+  int hashval;
+  struct stat sb;
+  int fd;
+
+  hashval = import_hash (filename);
+
+  /* Attempt to find file in list of already included files */
+  i = pfile->import_hash_table[hashval];
+
+  while (i) {
+    if (!strcmp (filename, i->name))
+      return -2;               /* return found */
+    i = i->next;
+  }
+  /* Open it and try a match on inode/dev */
+  fd = open_include_file (pfile, filename, searchptr);
+  if (fd < 0)
+    return fd;
+  fstat (fd, &sb);
+  for (h = 0; h < IMPORT_HASH_SIZE; h++) {
+    i = pfile->import_hash_table[h];
+    while (i) {
+      /* Compare the inode and the device.
+        Supposedly on some systems the inode is not a scalar.  */
+      if (!bcmp ((char *) &i->inode, (char *) &sb.st_ino, sizeof (sb.st_ino))
+         && i->dev == sb.st_dev) {
+        close (fd);
+        return -2;             /* return found */
+      }
+      i = i->next;
+    }
+  }
+  return fd;                   /* Not found, return open file */
+}
+
+/* Add the file FNAME, open on descriptor FD, to import_hash_table.  */
+
+static void
+add_import (pfile, fd, fname)
+     cpp_reader *pfile;
+     int fd;
+     char *fname;
+{
+  struct import_file *i;
+  int hashval;
+  struct stat sb;
+
+  hashval = import_hash (fname);
+  fstat (fd, &sb);
+  i = (struct import_file *)xmalloc (sizeof (struct import_file));
+  i->name = (char *)xmalloc (strlen (fname)+1);
+  strcpy (i->name, fname);
+  bcopy ((char *) &sb.st_ino, (char *) &i->inode, sizeof (sb.st_ino));
+  i->dev = sb.st_dev;
+  i->next = pfile->import_hash_table[hashval];
+  pfile->import_hash_table[hashval] = i;
+}
+
+/* The file_name_map structure holds a mapping of file names for a
+   particular directory.  This mapping is read from the file named
+   FILE_NAME_MAP_FILE in that directory.  Such a file can be used to
+   map filenames on a file system with severe filename restrictions,
+   such as DOS.  The format of the file name map file is just a series
+   of lines with two tokens on each line.  The first token is the name
+   to map, and the second token is the actual name to use.  */
+
+struct file_name_map
+{
+  struct file_name_map *map_next;
+  char *map_from;
+  char *map_to;
+};
+
+#define FILE_NAME_MAP_FILE "header.gcc"
+
+/* Read a space delimited string of unlimited length from a stdio
+   file.  */
+
+static char *
+read_filename_string (ch, f)
+     int ch;
+     FILE *f;
+{
+  char *alloc, *set;
+  int len;
+
+  len = 20;
+  set = alloc = xmalloc (len + 1);
+  if (! is_space[ch])
+    {
+      *set++ = ch;
+      while ((ch = getc (f)) != EOF && ! is_space[ch])
+       {
+         if (set - alloc == len)
+           {
+             len *= 2;
+             alloc = xrealloc (alloc, len + 1);
+             set = alloc + len / 2;
+           }
+         *set++ = ch;
+       }
+    }
+  *set = '\0';
+  ungetc (ch, f);
+  return alloc;
+}
+
+/* This structure holds a linked list of file name maps, one per directory.  */
+
+struct file_name_map_list
+{
+  struct file_name_map_list *map_list_next;
+  char *map_list_name;
+  struct file_name_map *map_list_map;
+};
+
+/* Read the file name map file for DIRNAME.  */
+
+static struct file_name_map *
+read_name_map (pfile, dirname)
+     cpp_reader *pfile;
+     char *dirname;
+{
+  register struct file_name_map_list *map_list_ptr;
+  char *name;
+  FILE *f;
+
+  for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
+       map_list_ptr = map_list_ptr->map_list_next)
+    if (! strcmp (map_list_ptr->map_list_name, dirname))
+      return map_list_ptr->map_list_map;
+
+  map_list_ptr = ((struct file_name_map_list *)
+                 xmalloc (sizeof (struct file_name_map_list)));
+  map_list_ptr->map_list_name = savestring (dirname);
+  map_list_ptr->map_list_map = NULL;
+
+  name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
+  strcpy (name, dirname);
+  if (*dirname)
+    strcat (name, "/");
+  strcat (name, FILE_NAME_MAP_FILE);
+  f = fopen (name, "r");
+  if (!f)
+    map_list_ptr->map_list_map = NULL;
+  else
+    {
+      int ch;
+      int dirlen = strlen (dirname);
+
+      while ((ch = getc (f)) != EOF)
+       {
+         char *from, *to;
+         struct file_name_map *ptr;
+
+         if (is_space[ch])
+           continue;
+         from = read_filename_string (ch, f);
+         while ((ch = getc (f)) != EOF && is_hor_space[ch])
+           ;
+         to = read_filename_string (ch, f);
+
+         ptr = ((struct file_name_map *)
+                xmalloc (sizeof (struct file_name_map)));
+         ptr->map_from = from;
+
+         /* Make the real filename absolute.  */
+         if (*to == '/')
+           ptr->map_to = to;
+         else
+           {
+             ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
+             strcpy (ptr->map_to, dirname);
+             ptr->map_to[dirlen] = '/';
+             strcpy (ptr->map_to + dirlen + 1, to);
+             free (to);
+           }         
+
+         ptr->map_next = map_list_ptr->map_list_map;
+         map_list_ptr->map_list_map = ptr;
+
+         while ((ch = getc (f)) != '\n')
+           if (ch == EOF)
+             break;
+       }
+      fclose (f);
+    }
+  
+  map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
+  CPP_OPTIONS (pfile)->map_list = map_list_ptr;
+
+  return map_list_ptr->map_list_map;
+}  
+
+/* Try to open include file FILENAME.  SEARCHPTR is the directory
+   being tried from the include file search path.  This function maps
+   filenames on file systems based on information read by
+   read_name_map.  */
+
+static int
+open_include_file (pfile, filename, searchptr)
+     cpp_reader *pfile;
+     char *filename;
+     struct file_name_list *searchptr;
+{
+  if (CPP_OPTIONS (pfile)->remap)
+    {
+      register struct file_name_map *map;
+      register char *from;
+      char *p, *dir;
+
+      if (searchptr && ! searchptr->got_name_map)
+       {
+         searchptr->name_map = read_name_map (pfile,
+                                              searchptr->fname
+                                              ? searchptr->fname : ".");
+         searchptr->got_name_map = 1;
+       }
+
+      /* First check the mapping for the directory we are using.  */
+      if (searchptr && searchptr->name_map)
+       {
+         from = filename;
+         if (searchptr->fname)
+           from += strlen (searchptr->fname) + 1;
+         for (map = searchptr->name_map; map; map = map->map_next)
+           {
+             if (! strcmp (map->map_from, from))
+               {
+                 /* Found a match.  */
+                 return open (map->map_to, O_RDONLY, 0666);
+               }
+           }
+       }
+
+      /* Try to find a mapping file for the particular directory we are
+        looking in.  Thus #include <sys/types.h> will look up sys/types.h
+        in /usr/include/header.gcc and look up types.h in
+        /usr/include/sys/header.gcc.  */
+      p = rindex (filename, '/');
+      if (! p)
+       p = filename;
+      if (searchptr
+         && searchptr->fname
+         && strlen (searchptr->fname) == (size_t) (p - filename)
+         && ! strncmp (searchptr->fname, filename, p - filename))
+       {
+         /* FILENAME is in SEARCHPTR, which we've already checked.  */
+         return open (filename, O_RDONLY, 0666);
+       }
+
+      if (p == filename)
+       {
+         dir = ".";
+         from = filename;
+       }
+      else
+       {
+         dir = (char *) alloca (p - filename + 1);
+         bcopy (filename, dir, p - filename);
+         dir[p - filename] = '\0';
+         from = p + 1;
+       }
+      for (map = read_name_map (pfile, dir); map; map = map->map_next)
+       if (! strcmp (map->map_from, from))
+         return open (map->map_to, O_RDONLY, 0666);
+    }
+
+  return open (filename, O_RDONLY, 0666);
+}
+
+/* Process the contents of include file FNAME, already open on descriptor F,
+   with output to OP.
+   SYSTEM_HEADER_P is 1 if this file resides in any one of the known
+   "system" include directories (as decided by the `is_system_include'
+   function above).
+   DIRPTR is the link in the dir path through which this file was found,
+   or 0 if the file name was absolute or via the current directory.
+   Return 1 on success, 0 on failure.
+
+   The caller is responsible for the cpp_push_buffer.  */
+
+int
+finclude (pfile, f, fname, system_header_p, dirptr)
+     cpp_reader *pfile;
+     int f;
+     char *fname;
+     int system_header_p;
+     struct file_name_list *dirptr;
+{
+  struct stat st;
+  size_t st_size;
+  long i;
+  int length;
+  cpp_buffer *fp;                      /* For input stack frame */
+#if 0
+  int missing_newline = 0;
+#endif
+
+  if (fstat (f, &st) < 0)
+    {
+      cpp_perror_with_name (pfile, fname);
+      close (f);
+      cpp_pop_buffer (pfile);
+      return 0;
+    }
+
+  fp = CPP_BUFFER (pfile);
+  fp->nominal_fname = fp->fname = fname;
+#if 0
+  fp->length = 0;
+#endif
+  fp->dir = dirptr;
+  fp->system_header_p = system_header_p;
+  fp->lineno = 1;
+  fp->colno = 1;
+  fp->cleanup = file_cleanup;
+
+  if (S_ISREG (st.st_mode)) {
+    st_size = (size_t) st.st_size;
+    if (st_size != st.st_size || st_size + 2 < st_size) {
+      cpp_error (pfile, "file `%s' too large", fname);
+      close (f);
+      return 0;
+    }
+    fp->buf = (U_CHAR *) xmalloc (st_size + 2);
+    fp->alimit = fp->buf + st_size + 2;
+    fp->cur = fp->buf;
+
+    /* Read the file contents, knowing that st_size is an upper bound
+       on the number of bytes we can read.  */
+    length = safe_read (f, fp->buf, st_size);
+    fp->rlimit = fp->buf + length;
+    if (length < 0) goto nope;
+  }
+  else if (S_ISDIR (st.st_mode)) {
+    cpp_error (pfile, "directory `%s' specified in #include", fname);
+    close (f);
+    return 0;
+  } else {
+    /* Cannot count its file size before reading.
+       First read the entire file into heap and
+       copy them into buffer on stack.  */
+
+    size_t bsize = 2000;
+
+    st_size = 0;
+    fp->buf = (U_CHAR *) xmalloc (bsize + 2);
+
+    for (;;) {
+      i = safe_read (f, fp->buf + st_size, bsize - st_size);
+      if (i < 0)
+       goto nope;      /* error! */
+      st_size += i;
+      if (st_size != bsize)
+       break;  /* End of file */
+      bsize *= 2;
+      fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
+    }
+    fp->cur = fp->buf;
+    length = st_size;
+  }
+
+  if ((length > 0 && fp->buf[length - 1] != '\n')
+      /* Backslash-newline at end is not good enough.  */
+      || (length > 1 && fp->buf[length - 2] == '\\')) {
+    fp->buf[length++] = '\n';
+#if 0
+    missing_newline = 1;
+#endif
+  }
+  fp->buf[length] = '\0';
+  fp->rlimit = fp->buf + length;
+
+  /* Close descriptor now, so nesting does not use lots of descriptors.  */
+  close (f);
+
+  /* Must do this before calling trigraph_pcp, so that the correct file name
+     will be printed in warning messages.  */
+
+  pfile->input_stack_listing_current = 0;
+
+#if 0
+  if (!no_trigraphs)
+    trigraph_pcp (fp);
+#endif
+
+#if 0
+  rescan (op, 0);
+
+  if (missing_newline)
+    fp->lineno--;
+
+  if (CPP_PEDANTIC (pfile) && missing_newline)
+    pedwarn ("file does not end in newline");
+
+  indepth--;
+  input_file_stack_tick++;
+  free (fp->buf);
+#endif
+  return 1;
+
+ nope:
+
+  cpp_perror_with_name (pfile, fname);
+  close (f);
+  free (fp->buf);
+  return 1;
+}
+
+/* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
+   retrying if necessary.  If MAX_READ_LEN is defined, read at most
+   that bytes at a time.  Return a negative value if an error occurs,
+   otherwise return the actual number of bytes read,
+   which must be LEN unless end-of-file was reached.  */
+
+static int
+safe_read (desc, ptr, len)
+     int desc;
+     char *ptr;
+     int len;
+{
+  int left, rcount, nchars;
+
+  left = len;
+  while (left > 0) {
+    rcount = left;
+#ifdef MAX_READ_LEN
+    if (rcount > MAX_READ_LEN)
+      rcount = MAX_READ_LEN;
+#endif
+    nchars = read (desc, ptr, rcount);
+    if (nchars < 0)
+      {
+#ifdef EINTR
+       if (errno == EINTR)
+         continue;
+#endif
+       return nchars;
+      }
+    if (nchars == 0)
+      break;
+    ptr += nchars;
+    left -= nchars;
+  }
+  return len - left;
+}
+
+#ifdef VMS
+
+/* Under VMS we need to fix up the "include" specification filename.
+
+   Rules for possible conversions
+
+       fullname                tried paths
+
+       name                    name
+       ./dir/name              [.dir]name
+       /dir/name               dir:name
+       /name                   [000000]name, name
+       dir/name                dir:[000000]name, dir:name, dir/name
+       dir1/dir2/name          dir1:[dir2]name, dir1:[000000.dir2]name
+       path:/name              path:[000000]name, path:name
+       path:/dir/name          path:[000000.dir]name, path:[dir]name
+       path:dir/name           path:[dir]name
+       [path]:[dir]name        [path.dir]name
+       path/[dir]name          [path.dir]name
+
+   The path:/name input is constructed when expanding <> includes. */
+
+
+static void
+hack_vms_include_specification (fullname)
+     char *fullname;
+{
+  register char *basename, *unixname, *local_ptr, *first_slash;
+  int f, check_filename_before_returning, must_revert;
+  char Local[512];
+
+  check_filename_before_returning = 0;
+  must_revert = 0;
+  /* See if we can find a 1st slash. If not, there's no path information.  */
+  first_slash = index (fullname, '/');
+  if (first_slash == 0)
+    return 0;                          /* Nothing to do!!! */
+
+  /* construct device spec if none given.  */
+
+  if (index (fullname, ':') == 0)
+    {
+
+      /* If fullname has a slash, take it as device spec.  */
+
+      if (first_slash == fullname)
+       {
+         first_slash = index (fullname+1, '/');        /* 2nd slash ? */
+         if (first_slash)
+           *first_slash = ':';                         /* make device spec  */
+         for (basename = fullname; *basename != 0; basename++)
+           *basename = *(basename+1);                  /* remove leading slash  */
+       }
+      else if ((first_slash[-1] != '.')                /* keep ':/', './' */
+           && (first_slash[-1] != ':')
+           && (first_slash[-1] != ']'))        /* or a vms path  */
+       {
+         *first_slash = ':';
+       }
+      else if ((first_slash[1] == '[')         /* skip './' in './[dir'  */
+           && (first_slash[-1] == '.'))
+       fullname += 2;
+    }
+
+  /* Get part after first ':' (basename[-1] == ':')
+     or last '/' (basename[-1] == '/').  */
+
+  basename = base_name (fullname);
+
+  local_ptr = Local;                   /* initialize */
+
+  /* We are trying to do a number of things here.  First of all, we are
+     trying to hammer the filenames into a standard format, such that later
+     processing can handle them.
+     
+     If the file name contains something like [dir.], then it recognizes this
+     as a root, and strips the ".]".  Later processing will add whatever is
+     needed to get things working properly.
+     
+     If no device is specified, then the first directory name is taken to be
+     a device name (or a rooted logical).  */
+
+  /* Point to the UNIX filename part (which needs to be fixed!)
+     but skip vms path information.
+     [basename != fullname since first_slash != 0].  */
+
+  if ((basename[-1] == ':')            /* vms path spec.  */
+      || (basename[-1] == ']')
+      || (basename[-1] == '>'))
+    unixname = basename;
+  else
+    unixname = fullname;
+
+  if (*unixname == '/')
+    unixname++;
+
+  /* If the directory spec is not rooted, we can just copy
+     the UNIX filename part and we are done.  */
+
+  if (((basename - fullname) > 1)
+     && (  (basename[-1] == ']')
+        || (basename[-1] == '>')))
+    {
+      if (basename[-2] != '.')
+       {
+
+       /* The VMS part ends in a `]', and the preceding character is not a `.'.
+          -> PATH]:/name (basename = '/name', unixname = 'name')
+          We strip the `]', and then splice the two parts of the name in the
+          usual way.  Given the default locations for include files in cccp.c,
+          we will only use this code if the user specifies alternate locations
+          with the /include (-I) switch on the command line.  */
+
+         basename -= 1;        /* Strip "]" */
+         unixname--;           /* backspace */
+       }
+      else
+       {
+
+       /* The VMS part has a ".]" at the end, and this will not do.  Later
+          processing will add a second directory spec, and this would be a syntax
+          error.  Thus we strip the ".]", and thus merge the directory specs.
+          We also backspace unixname, so that it points to a '/'.  This inhibits the
+          generation of the 000000 root directory spec (which does not belong here
+          in this case).  */
+
+         basename -= 2;        /* Strip ".]" */
+         unixname--;           /* backspace */
+       }
+    }
+
+  else
+
+    {
+
+      /* We drop in here if there is no VMS style directory specification yet.
+         If there is no device specification either, we make the first dir a
+         device and try that.  If we do not do this, then we will be essentially
+         searching the users default directory (as if they did a #include "asdf.h").
+        
+         Then all we need to do is to push a '[' into the output string. Later
+         processing will fill this in, and close the bracket.  */
+
+      if ((unixname != fullname)       /* vms path spec found.  */
+        && (basename[-1] != ':'))
+       *local_ptr++ = ':';             /* dev not in spec.  take first dir */
+
+      *local_ptr++ = '[';              /* Open the directory specification */
+    }
+
+    if (unixname == fullname)          /* no vms dir spec.  */
+      {
+       must_revert = 1;
+       if ((first_slash != 0)          /* unix dir spec.  */
+           && (*unixname != '/')       /* not beginning with '/'  */
+           && (*unixname != '.'))      /* or './' or '../'  */
+         *local_ptr++ = '.';           /* dir is local !  */
+      }
+
+  /* at this point we assume that we have the device spec, and (at least
+     the opening "[" for a directory specification.  We may have directories
+     specified already.
+
+     If there are no other slashes then the filename will be
+     in the "root" directory.  Otherwise, we need to add
+     directory specifications.  */
+
+  if (index (unixname, '/') == 0)
+    {
+      /* if no directories specified yet and none are following.  */
+      if (local_ptr[-1] == '[')
+       {
+         /* Just add "000000]" as the directory string */
+         strcpy (local_ptr, "000000]");
+         local_ptr += strlen (local_ptr);
+         check_filename_before_returning = 1; /* we might need to fool with this later */
+       }
+    }
+  else
+    {
+
+      /* As long as there are still subdirectories to add, do them.  */
+      while (index (unixname, '/') != 0)
+       {
+         /* If this token is "." we can ignore it
+              if it's not at the beginning of a path.  */
+         if ((unixname[0] == '.') && (unixname[1] == '/'))
+           {
+             /* remove it at beginning of path.  */
+             if (  ((unixname == fullname)             /* no device spec  */
+                   && (fullname+2 != basename))        /* starts with ./ */
+                                                       /* or  */
+                || ((basename[-1] == ':')              /* device spec  */
+                   && (unixname-1 == basename)))       /* and ./ afterwards  */
+               *local_ptr++ = '.';                     /* make '[.' start of path.  */
+             unixname += 2;
+             continue;
+           }
+
+         /* Add a subdirectory spec. Do not duplicate "." */
+         if (  local_ptr[-1] != '.'
+            && local_ptr[-1] != '['
+            && local_ptr[-1] != '<')
+           *local_ptr++ = '.';
+
+         /* If this is ".." then the spec becomes "-" */
+         if (  (unixname[0] == '.')
+            && (unixname[1] == '.')
+            && (unixname[2] == '/'))
+           {
+             /* Add "-" and skip the ".." */
+             if ((local_ptr[-1] == '.')
+                 && (local_ptr[-2] == '['))
+               local_ptr--;                    /* prevent [.-  */
+             *local_ptr++ = '-';
+             unixname += 3;
+             continue;
+           }
+
+         /* Copy the subdirectory */
+         while (*unixname != '/')
+           *local_ptr++= *unixname++;
+
+         unixname++;                   /* Skip the "/" */
+       }
+
+      /* Close the directory specification */
+      if (local_ptr[-1] == '.')                /* no trailing periods */
+       local_ptr--;
+
+      if (local_ptr[-1] == '[')                /* no dir needed */
+       local_ptr--;
+      else
+       *local_ptr++ = ']';
+    }
+
+  /* Now add the filename.  */
+
+  while (*unixname)
+    *local_ptr++ = *unixname++;
+  *local_ptr = 0;
+
+  /* Now append it to the original VMS spec.  */
+
+  strcpy ((must_revert==1)?fullname:basename, Local);
+
+  /* If we put a [000000] in the filename, try to open it first. If this fails,
+     remove the [000000], and return that name.  This provides flexibility
+     to the user in that they can use both rooted and non-rooted logical names
+     to point to the location of the file.  */
+
+  if (check_filename_before_returning)
+    {
+      f = open (fullname, O_RDONLY, 0666);
+      if (f >= 0)
+       {
+         /* The file name is OK as it is, so return it as is.  */
+         close (f);
+         return 1;
+       }
+
+      /* The filename did not work.  Try to remove the [000000] from the name,
+        and return it.  */
+
+      basename = index (fullname, '[');
+      local_ptr = index (fullname, ']') + 1;
+      strcpy (basename, local_ptr);            /* this gets rid of it */
+
+    }
+
+  return 1;
+}
+#endif /* VMS */
index c726c3c813c375616eee87148d9df2a6a2baf421..e8d2e09d1c69a0f996848bf2ec81075fbfd17767 100644 (file)
@@ -89,9 +89,6 @@ extern char *update_path PARAMS ((char *, char *));
 #ifndef STANDARD_INCLUDE_DIR
 #define STANDARD_INCLUDE_DIR "/usr/include"
 #endif
-#ifndef INCLUDE_LEN_FUDGE
-#define INCLUDE_LEN_FUDGE 0
-#endif
 
 /* Symbols to predefine.  */
 
@@ -200,10 +197,6 @@ char *xmalloc ();
 extern void cpp_hash_cleanup PARAMS ((cpp_reader *));
 
 static char *my_strerror               PROTO ((int));
-static void add_import                 PROTO ((cpp_reader *, int, char *));
-static void append_include_chain       PROTO ((cpp_reader *,
-                                               struct file_name_list *,
-                                               struct file_name_list *));
 static void make_assertion             PROTO ((cpp_reader *, char *, U_CHAR *));
 static void path_include               PROTO ((cpp_reader *, char *));
 static void initialize_builtins                PROTO ((cpp_reader *));
@@ -211,38 +204,27 @@ static void initialize_char_syntax        PROTO ((struct cpp_options *));
 #if 0
 static void trigraph_pcp ();
 #endif
-static int finclude                    PROTO ((cpp_reader *, int, char *,
-                                               int, struct file_name_list *));
 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 lookup_import               PROTO ((cpp_reader *, char *,
-                                               struct file_name_list *));
-static int redundant_include_p         PROTO ((cpp_reader *, char *));
-static int is_system_include           PROTO ((cpp_reader *, char *));
-static struct file_name_map *read_name_map     PROTO ((cpp_reader *, char *));
-static char *read_filename_string      PROTO ((int, FILE *));
-static int open_include_file           PROTO ((cpp_reader *, char *,
-                                               struct file_name_list *));
 static int check_macro_name            PROTO ((cpp_reader *, U_CHAR *, char *));
 static int compare_defs                        PROTO ((cpp_reader *,
                                                DEFINITION *, DEFINITION *));
 static int compare_token_lists         PROTO ((struct arglist *,
                                                struct arglist *));
+static int is_system_include           PROTO ((cpp_reader *, char *));
 static HOST_WIDE_INT eval_if_expression        PROTO ((cpp_reader *, U_CHAR *, int));
 static int change_newlines             PROTO ((U_CHAR *, int));
 static struct arglist *read_token_list PROTO ((cpp_reader *, int *));
 static void free_token_list            PROTO ((struct arglist *));
-static int safe_read                   PROTO ((int, char *, int));
 static void push_macro_expansion PARAMS ((cpp_reader *,
                                          U_CHAR *, int, HASHNODE *));
 static struct cpp_pending *nreverse_pending PARAMS ((struct cpp_pending *));
 extern char *xrealloc ();
 static char *xcalloc                   PROTO ((unsigned, unsigned));
-static char *savestring                        PROTO ((char *));
 
 static void conditional_skip           PROTO ((cpp_reader *, int,
                                               enum node_type, U_CHAR *));
@@ -260,25 +242,6 @@ extern HOST_WIDE_INT cpp_parse_expr PARAMS ((cpp_reader *));
 extern char *version_string;
 extern struct tm *localtime ();
 \f
-struct file_name_list
-  {
-    struct file_name_list *next;
-    char *fname;
-    /* If the following is nonzero, it is a macro name.
-       Don't include the file again if that macro is defined.  */
-    U_CHAR *control_macro;
-    /* If the following is nonzero, it is a C-language system include
-       directory.  */
-    int c_system_include_path;
-    /* Mapping of file names for this directory.  */
-    struct file_name_map *name_map;
-    /* Non-zero if name_map is valid.  */
-    int got_name_map;
-  };
-
-/* If a buffer's dir field is SELF_DIR_DUMMY, it means the file was found
-   via the same directory as the file that #included it.  */
-#define SELF_DIR_DUMMY ((struct file_name_list *) (~0))
 
 /* #include "file" looks in source file dir, then stack.  */
 /* #include <file> just looks in the stack.  */
@@ -366,7 +329,6 @@ static int do_endif PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR
 #ifdef SCCS_DIRECTIVE
 static int do_sccs PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
 #endif
-static int do_once PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
 static int do_assert PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
 static int do_unassert PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
 static int do_warning PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
@@ -403,13 +365,13 @@ static struct directive directive_table[] = {
 };
 \f
 /* table to tell if char can be part of a C identifier.  */
-U_CHAR is_idchar[256];
+U_CHAR is_idchar[256] = { 0 };
 /* table to tell if char can be first char of a c identifier.  */
-U_CHAR is_idstart[256];
+U_CHAR is_idstart[256] = { 0 };
 /* table to tell if c is horizontal space.  */
-U_CHAR is_hor_space[256];
+U_CHAR is_hor_space[256] = { 0 };
 /* table to tell if c is horizontal or vertical space.  */
-static U_CHAR is_space[256];
+U_CHAR is_space[256] = { 0 };
 
 /* Initialize syntactic classifications of characters.  */
 
@@ -615,85 +577,7 @@ make_assertion (pfile, option, str)
       cpp_pop_buffer (pfile);
     }
 }
-\f
-/* Append a chain of `struct file_name_list's
-   to the end of the main include chain.
-   FIRST is the beginning of the chain to append, and LAST is the end.  */
-
-static void
-append_include_chain (pfile, first, last)
-     cpp_reader *pfile;
-     struct file_name_list *first, *last;
-{
-  struct cpp_options *opts = CPP_OPTIONS (pfile);
-  struct file_name_list *dir;
-
-  if (!first || !last)
-    return;
 
-  if (opts->include == 0)
-    opts->include = first;
-  else
-    opts->last_include->next = first;
-
-  if (opts->first_bracket_include == 0)
-    opts->first_bracket_include = first;
-
-  for (dir = first; ; dir = dir->next) {
-    int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
-    if (len > pfile->max_include_len)
-      pfile->max_include_len = len;
-    if (dir == last)
-      break;
-  }
-
-  last->next = NULL;
-  opts->last_include = last;
-}
-\f
-/* Add output to `deps_buffer' for the -M switch.
-   STRING points to the text to be output.
-   SPACER is ':' for targets, ' ' for dependencies, zero for text
-   to be inserted literally.  */
-
-static void
-deps_output (pfile, string, spacer)
-     cpp_reader *pfile;
-     char *string;
-     int spacer;
-{
-  int size = strlen (string);
-
-  if (size == 0)
-    return;
-
-#ifndef MAX_OUTPUT_COLUMNS
-#define MAX_OUTPUT_COLUMNS 72
-#endif
-  if (spacer
-      && pfile->deps_column > 0
-      && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS)
-    {
-      deps_output (pfile, " \\\n  ", 0);
-      pfile->deps_column = 0;
-    }
-
-  if (pfile->deps_size + size + 8 > pfile->deps_allocated_size)
-    {
-      pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2;
-      pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer,
-                                             pfile->deps_allocated_size);
-    }
-  if (spacer == ' ' && pfile->deps_column > 0)
-    pfile->deps_buffer[pfile->deps_size++] = ' ';
-  bcopy (string, &pfile->deps_buffer[pfile->deps_size], size);
-  pfile->deps_size += size;
-  pfile->deps_column += size;
-  if (spacer == ':')
-    pfile->deps_buffer[pfile->deps_size++] = ':';
-  pfile->deps_buffer[pfile->deps_size] = 0;
-}
-\f
 /* Given a colon-separated list of file names PATH,
    add all the names to the search path for include files.  */
 
@@ -806,19 +690,6 @@ macro_cleanup (pbuf, pfile)
   return 0;
 }
 
-int
-file_cleanup (pbuf, pfile)
-     cpp_buffer *pbuf;
-     cpp_reader *pfile ATTRIBUTE_UNUSED;
-{
-  if (pbuf->buf)
-    {
-      free (pbuf->buf);
-      pbuf->buf = 0;
-    }
-  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 ' '.
@@ -3077,29 +2948,21 @@ do_include (pfile, keyword, unused1, unused2)
 {
   int importing = (keyword->type == T_IMPORT);
   int skip_dirs = (keyword->type == T_INCLUDE_NEXT);
+  int angle_brackets = 0;      /* 0 for "...", 1 for <...> */
   char *fname;         /* Dynamically allocated fname buffer */
-  char *pcftry;
-  U_CHAR *fbeg, *fend;         /* Beginning and end of fname */
+  char *fbeg, *fend;           /* Beginning and end of fname */
+  long flen;
+
   enum cpp_token token;
 
   /* Chain of dirs to search */
   struct file_name_list *search_start = CPP_OPTIONS (pfile)->include;
-  struct file_name_list dsp[1];        /* First in chain, if #include "..." */
-  struct file_name_list *searchptr = 0;
+  struct file_name_list dsp;   /* First in chain, if #include "..." */
+  struct file_name_list *foundhere, *ptr;
+  
   long old_written = CPP_WRITTEN (pfile);
 
-  int flen;
-
-  int f;                       /* file number */
-
-  int angle_brackets = 0;      /* 0 for "...", 1 for <...> */
-  char *pcfbuf;
-#if 0
-  int pcf = -1;
-  char *pcfbuflimit;
-#endif
-  int pcfnum;
-  f= -1;                       /* JF we iz paranoid! */
+  int fd;
 
   if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
     {
@@ -3133,9 +2996,9 @@ do_include (pfile, keyword, unused1, unused2)
 
   if (token == CPP_STRING)
     {
-      /* FIXME - check no trailing garbage */
       fbeg = pfile->token_buffer + old_written + 1;
       fend = CPP_PWRITTEN (pfile) - 1;
+      *fend = '\0';
       if (fbeg[-1] == '<')
        {
          angle_brackets = 1;
@@ -3159,8 +3022,8 @@ do_include (pfile, keyword, unused1, unused2)
                {
                  /* Found a named file.  Figure out dir of the file,
                     and put it in front of the search list.  */
-                 dsp[0].next = search_start;
-                 search_start = dsp;
+                 dsp.next = search_start;
+                 search_start = &dsp;
 #ifndef VMS
                  ep = rindex (nam, '/');
 #else                          /* VMS */
@@ -3172,17 +3035,17 @@ do_include (pfile, keyword, unused1, unused2)
                  if (ep != NULL)
                    {
                      n = ep - nam;
-                     dsp[0].fname = (char *) alloca (n + 1);
-                     strncpy (dsp[0].fname, nam, n);
-                     dsp[0].fname[n] = '\0';
+                     dsp.fname = (char *) alloca (n + 1);
+                     strncpy (dsp.fname, nam, n);
+                     dsp.fname[n] = '\0';
                      if (n + INCLUDE_LEN_FUDGE > pfile->max_include_len)
                        pfile->max_include_len = n + INCLUDE_LEN_FUDGE;
                    }
                  else
                    {
-                     dsp[0].fname = 0; /* Current directory */
+                     dsp.fname = 0; /* Current directory */
                    }
-                 dsp[0].got_name_map = 0;
+                 dsp.got_name_map = 0;
                  break;
                }
            }
@@ -3202,6 +3065,11 @@ do_include (pfile, keyword, unused1, unused2)
       /* If -I-, start with the first -I dir after the -I-.  */
       if (CPP_OPTIONS (pfile)->first_bracket_include)
        search_start = CPP_OPTIONS (pfile)->first_bracket_include;
+
+      /* 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);
     }
@@ -3215,14 +3083,11 @@ do_include (pfile, keyword, unused1, unused2)
       return 0;
     }
 
-  *fend = 0;
-
   token = get_directive_token (pfile);
   if (token != CPP_VSPACE)
     {
       cpp_error (pfile, "junk at end of `#include'");
-      while (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP)
-       token = get_directive_token (pfile);
+      skip_rest_of_line (pfile);
     }
 
   /* For #include_next, skip in the search path
@@ -3255,127 +3120,57 @@ do_include (pfile, keyword, unused1, unused2)
 
   /* Allocate this permanently, because it gets stored in the definitions
      of macros.  */
-  fname = (char *) xmalloc (pfile->max_include_len + flen + 4);
   /* + 2 above for slash and terminating null.  */
-  /* + 2 added for '.h' on VMS (to support '#include filename') */
+  fname = (char *) xmalloc (pfile->max_include_len + flen + 2);
 
-  /* If specified file name is absolute, just open it.  */
+  fd = find_include_file (pfile, fbeg, flen, fname,
+                         importing, search_start, &foundhere);
 
-  if (*fbeg == '/') {
-    strncpy (fname, fbeg, flen);
-    fname[flen] = 0;
-    if (redundant_include_p (pfile, fname))
+  if (fd == -2)
+    {
+      free (fname);
       return 0;
-    if (importing)
-      f = lookup_import (pfile, fname, NULL_PTR);
-    else
-      f = open_include_file (pfile, fname, NULL_PTR);
-    if (f == -2)
-      return 0;                /* Already included this file */
-  } else {
-    /* Search directory path, trying to open the file.
-       Copy each filename tried into FNAME.  */
-
-    for (searchptr = search_start; searchptr; searchptr = searchptr->next) {
-      if (searchptr->fname) {
-       /* The empty string in a search path is ignored.
-          This makes it possible to turn off entirely
-          a standard piece of the list.  */
-       if (searchptr->fname[0] == 0)
-         continue;
-       strcpy (fname, searchptr->fname);
-       strcat (fname, "/");
-       fname[strlen (fname) + flen] = 0;
-      } else {
-       fname[0] = 0;
-      }
-      strncat (fname, fbeg, flen);
-#ifdef VMS
-      /* Change this 1/2 Unix 1/2 VMS file specification into a
-         full VMS file specification */
-      if (searchptr->fname && (searchptr->fname[0] != 0)) {
-       /* Fix up the filename */
-       hack_vms_include_specification (fname);
-      } else {
-       /* This is a normal VMS filespec, so use it unchanged.  */
-       strncpy (fname, fbeg, flen);
-       fname[flen] = 0;
-       /* if it's '#include filename', add the missing .h */
-       if (index(fname,'.')==NULL) {
-         strcat (fname, ".h");
-       }
-      }
-#endif /* VMS */
-      /* ??? There are currently 3 separate mechanisms for avoiding processing
-        of redundant include files: #import, #pragma once, and
-        redundant_include_p.  It would be nice if they were unified.  */
-      if (redundant_include_p (pfile, fname))
-       return 0;
-      if (importing)
-       f = lookup_import (pfile, fname, searchptr);
-      else
-       f = open_include_file (pfile, fname, searchptr);
-      if (f == -2)
-       return 0;                       /* Already included this file */
-#ifdef EACCES
-      else if (f == -1 && errno == EACCES)
-       cpp_warning (pfile, "Header file %s exists, but is not readable",
-                    fname);
-#endif
-      if (f >= 0)
-       break;
     }
-  }
-
-  if (f < 0)
+  
+  if (fd == -1)
     {
-      /* A file that was not found.  */
-      strncpy (fname, fbeg, flen);
-      fname[flen] = 0;
-      /* If generating dependencies and -MG was specified, we assume missing
-        files are leaf files, living in the same directory as the source file
-        or other similar place; these missing files may be generated from
-        other files and may not exist yet (eg: y.tab.h).  */
-
-      if (CPP_OPTIONS(pfile)->print_deps_missing_files
-         && CPP_PRINT_DEPS (pfile)
-         > (angle_brackets || (pfile->system_include_depth > 0)))
-       {
-         /* If it was requested as a system header file,
-            then assume it belongs in the first place to look for such.  */
-         if (angle_brackets)
+      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
            {
-             for (searchptr = search_start; searchptr;
-                  searchptr = searchptr->next)
-               {
-                 if (searchptr->fname)
+             /* If requested as a system header, assume it belongs in
+                the first system header directory. */
+             if (CPP_OPTIONS (pfile)->first_bracket_include)
+               ptr = CPP_OPTIONS (pfile)->first_bracket_include;
+             else
+               ptr = CPP_OPTIONS (pfile)->include;
+             for (; ptr; ptr = ptr->next)
+                 if (ptr->fname)
                    {
                      char *p;
 
-                     if (searchptr->fname[0] == 0)
+                     if (ptr->fname[0] == 0)
                        continue;
-                     p = (char *) alloca (strlen (searchptr->fname)
+                     p = (char *) alloca (strlen (ptr->fname)
                                           + strlen (fname) + 2);
-                     strcpy (p, searchptr->fname);
+                     strcpy (p, ptr->fname);
                      strcat (p, "/");
                      strcat (p, fname);
                      deps_output (pfile, p, ' ');
                      break;
                    }
-               }
-           }
-         else
-           {
-             /* Otherwise, omit the directory, as if the file existed
-                in the directory with the source.  */
-             deps_output (pfile, fname, ' ');
            }
        }
-      /* 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.*/
+      /* 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))))
@@ -3384,26 +3179,19 @@ do_include (pfile, keyword, unused1, unused2)
        cpp_error_from_errno (pfile, fname);
       else
        cpp_error (pfile, "No include path in which to find %s", fname);
-    }
-  else {
-    /* Check to see if this include file is a once-only include file.
-       If so, give up.  */
 
-    struct file_name_list *ptr;
-
-    for (ptr = pfile->dont_repeat_files; ptr; ptr = ptr->next) {
-      if (!strcmp (ptr->fname, fname)) {
-       close (f);
-        return 0;                              /* This file was once'd.  */
-      }
+      free (fname);
+      return 0;
     }
 
-    for (ptr = pfile->all_include_files; ptr; ptr = ptr->next) {
-      if (!strcmp (ptr->fname, fname))
-        break;                         /* This file was included before.  */
-    }
+  /* If we get here, we have a file to process. */
 
-    if (ptr == 0) {
+  for (ptr = pfile->all_include_files; ptr; ptr = ptr->next)
+    if (!strcmp (ptr->fname, fname))
+      break;                           /* This file was included before.  */
+
+  if (ptr == 0)
+    {
       /* This is the first time for this file.  */
       /* Add it to list of files included.  */
 
@@ -3419,95 +3207,38 @@ do_include (pfile, keyword, unused1, unused2)
       if (CPP_PRINT_DEPS (pfile)
          > (angle_brackets || (pfile->system_include_depth > 0)))
        deps_output (pfile, fname, ' ');
-    }   
-
-    /* Handle -H option.  */
-    if (CPP_OPTIONS(pfile)->print_include_names)
-      {
-       cpp_buffer *buf = CPP_BUFFER (pfile);
-       while ((buf = CPP_PREV_BUFFER (buf)) != CPP_NULL_BUFFER (pfile))
-         putc ('.', stderr);
-       fprintf (stderr, "%s\n", fname);
-      }
-
-    if (angle_brackets)
-      pfile->system_include_depth++;
-
-    /* Actually process the file.  */
-
-    /* Record file on "seen" list for #import.  */
-    add_import (pfile, f, fname);
-
-    pcftry = (char *) alloca (strlen (fname) + 30);
-    pcfbuf = 0;
-    pcfnum = 0;
-
-#if 0
-    if (!no_precomp)
-      {
-       struct stat stat_f;
-
-       fstat (f, &stat_f);
-
-       do {
-         sprintf (pcftry, "%s%d", fname, pcfnum++);
+    }
 
-         pcf = open (pcftry, O_RDONLY, 0666);
-         if (pcf != -1)
-           {
-             struct stat s;
+  /* Handle -H option.  */
+  if (CPP_OPTIONS(pfile)->print_include_names)
+    {
+      cpp_buffer *buf = CPP_BUFFER (pfile);
+      while ((buf = CPP_PREV_BUFFER (buf)) != CPP_NULL_BUFFER (pfile))
+       putc ('.', stderr);
+      fprintf (stderr, "%s\n", fname);
+    }
 
-             fstat (pcf, &s);
-             if (bcmp ((char *) &stat_f.st_ino, (char *) &s.st_ino,
-                       sizeof (s.st_ino))
-                 || stat_f.st_dev != s.st_dev)
-               {
-                 pcfbuf = check_precompiled (pcf, fname, &pcfbuflimit);
-                 /* Don't need it any more.  */
-                 close (pcf);
-               }
-             else
-               {
-                 /* Don't need it at all.  */
-                 close (pcf);
-                 break;
-               }
-           }
-       } while (pcf != -1 && !pcfbuf);
-      }
-#endif
-    
-    /* Actually process the file */
-    if (cpp_push_buffer (pfile, NULL, 0) == NULL)
+  /* Actually process the file */
+  if (cpp_push_buffer (pfile, NULL, 0) == NULL)
+    {
+      close (fd);
+      free (fname);
       return 0;
-    if (finclude (pfile, f, fname, is_system_include (pfile, fname),
-                 searchptr != dsp ? searchptr : SELF_DIR_DUMMY))
-      {
-       output_line_command (pfile, 0, enter_file);
-       pfile->only_seen_white = 2;
-      }
+    }
 
-    if (angle_brackets)
-      pfile->system_include_depth--;
-  }
-  return 0;
-}
+  if (angle_brackets)
+    pfile->system_include_depth++;
 
-/* Return nonzero if there is no need to include file NAME
-   because it has already been included and it contains a conditional
-   to make a repeated include do nothing.  */
+  if (finclude (pfile, fd, fname, is_system_include (pfile, fname),
+               foundhere != &dsp ? foundhere : SELF_DIR_DUMMY))
+    {
+      output_line_command (pfile, 0, enter_file);
+      pfile->only_seen_white = 2;
+    }
+  
+  if (angle_brackets)
+    pfile->system_include_depth--;
 
-static int
-redundant_include_p (pfile, name)
-     cpp_reader *pfile;
-     char *name;
-{
-  struct file_name_list *l = pfile->all_include_files;
-  for (; l; l = l->next)
-    if (! strcmp (name, l->fname)
-       && l->control_macro
-       && cpp_lookup (pfile, l->control_macro, -1, -1))
-      return 1;
   return 0;
 }
 
@@ -3546,7 +3277,6 @@ is_system_include (pfile, filename)
   return 0;
 }
 
-\f
 /*
  * Install a name in the assertion hash table.
  *
@@ -3911,38 +3641,6 @@ do_warning (pfile, keyword, buf, limit)
   return 0;
 }
 
-/* Remember the name of the current file being read from so that we can
-   avoid ever including it again.  */
-
-static int
-do_once (pfile, keyword, unused1, unused2)
-     cpp_reader *pfile;
-     struct directive *keyword ATTRIBUTE_UNUSED;
-     U_CHAR *unused1 ATTRIBUTE_UNUSED, *unused2 ATTRIBUTE_UNUSED;
-{
-  cpp_buffer *ip = NULL;
-  struct file_name_list *new;
-
-  for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
-    {
-      if (ip == CPP_NULL_BUFFER (pfile))
-       return 0;
-      if (ip->fname != NULL)
-       break;
-    }
-
-    
-  new = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
-  new->next = pfile->dont_repeat_files;
-  pfile->dont_repeat_files = new;
-  new->fname = savestring (ip->fname);
-  new->control_macro = 0;
-  new->got_name_map = 0;
-  new->c_system_include_path = 0;
-
-  return 0;
-}
-
 /* Report program identification.  */
 
 static int
@@ -3973,13 +3671,32 @@ do_pragma (pfile, keyword, buf, limit)
 {
   while (*buf == ' ' || *buf == '\t')
     buf++;
-  if (!strncmp (buf, "once", 4)) {
-    /* Allow #pragma once in system headers, since that's not the user's
-       fault.  */
-    if (!CPP_BUFFER (pfile)->system_header_p)
-      cpp_warning (pfile, "`#pragma once' is obsolete");
-    do_once (pfile, NULL, NULL, NULL);
-  }
+  if (!strncmp (buf, "once", 4))
+    {
+      cpp_buffer *ip = NULL;
+      struct file_name_list *new;
+
+      /* Allow #pragma once in system headers, since that's not the user's
+        fault.  */
+      if (!CPP_BUFFER (pfile)->system_header_p)
+       cpp_warning (pfile, "`#pragma once' is obsolete");
+      
+      for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
+        {
+         if (ip == CPP_NULL_BUFFER (pfile))
+           return 0;
+         if (ip->fname != NULL)
+           break;
+       }
+      
+      new = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
+      new->next = pfile->dont_repeat_files;
+      new->fname = savestring (ip->fname);
+      new->control_macro = 0;
+      new->got_name_map = 0;
+      new->c_system_include_path = 0;
+      pfile->dont_repeat_files = new;
+    }
 
   if (!strncmp (buf, "implementation", 14)) {
     /* Be quiet about `#pragma implementation' for a file only if it hasn't
@@ -5271,444 +4988,6 @@ parse_name (pfile, c)
   return 1;
 }
 
-\f
-/* Maintain and search list of included files, for #import.  */
-
-/* Hash a file name for import_hash_table.  */
-
-static int 
-import_hash (f)
-     char *f;
-{
-  int val = 0;
-
-  while (*f) val += *f++;
-  return (val%IMPORT_HASH_SIZE);
-}
-
-/* Search for file FILENAME in import_hash_table.
-   Return -2 if found, either a matching name or a matching inode.
-   Otherwise, open the file and return a file descriptor if successful
-   or -1 if unsuccessful.  */
-
-static int
-lookup_import (pfile, filename, searchptr)
-     cpp_reader *pfile;
-     char *filename;
-     struct file_name_list *searchptr;
-{
-  struct import_file *i;
-  int h;
-  int hashval;
-  struct stat sb;
-  int fd;
-
-  hashval = import_hash (filename);
-
-  /* Attempt to find file in list of already included files */
-  i = pfile->import_hash_table[hashval];
-
-  while (i) {
-    if (!strcmp (filename, i->name))
-      return -2;               /* return found */
-    i = i->next;
-  }
-  /* Open it and try a match on inode/dev */
-  fd = open_include_file (pfile, filename, searchptr);
-  if (fd < 0)
-    return fd;
-  fstat (fd, &sb);
-  for (h = 0; h < IMPORT_HASH_SIZE; h++) {
-    i = pfile->import_hash_table[h];
-    while (i) {
-      /* Compare the inode and the device.
-        Supposedly on some systems the inode is not a scalar.  */
-      if (!bcmp ((char *) &i->inode, (char *) &sb.st_ino, sizeof (sb.st_ino))
-         && i->dev == sb.st_dev) {
-        close (fd);
-        return -2;             /* return found */
-      }
-      i = i->next;
-    }
-  }
-  return fd;                   /* Not found, return open file */
-}
-
-/* Add the file FNAME, open on descriptor FD, to import_hash_table.  */
-
-static void
-add_import (pfile, fd, fname)
-     cpp_reader *pfile;
-     int fd;
-     char *fname;
-{
-  struct import_file *i;
-  int hashval;
-  struct stat sb;
-
-  hashval = import_hash (fname);
-  fstat (fd, &sb);
-  i = (struct import_file *)xmalloc (sizeof (struct import_file));
-  i->name = (char *)xmalloc (strlen (fname)+1);
-  strcpy (i->name, fname);
-  bcopy ((char *) &sb.st_ino, (char *) &i->inode, sizeof (sb.st_ino));
-  i->dev = sb.st_dev;
-  i->next = pfile->import_hash_table[hashval];
-  pfile->import_hash_table[hashval] = i;
-}
-\f
-/* The file_name_map structure holds a mapping of file names for a
-   particular directory.  This mapping is read from the file named
-   FILE_NAME_MAP_FILE in that directory.  Such a file can be used to
-   map filenames on a file system with severe filename restrictions,
-   such as DOS.  The format of the file name map file is just a series
-   of lines with two tokens on each line.  The first token is the name
-   to map, and the second token is the actual name to use.  */
-
-struct file_name_map
-{
-  struct file_name_map *map_next;
-  char *map_from;
-  char *map_to;
-};
-
-#define FILE_NAME_MAP_FILE "header.gcc"
-
-/* Read a space delimited string of unlimited length from a stdio
-   file.  */
-
-static char *
-read_filename_string (ch, f)
-     int ch;
-     FILE *f;
-{
-  char *alloc, *set;
-  int len;
-
-  len = 20;
-  set = alloc = xmalloc (len + 1);
-  if (! is_space[ch])
-    {
-      *set++ = ch;
-      while ((ch = getc (f)) != EOF && ! is_space[ch])
-       {
-         if (set - alloc == len)
-           {
-             len *= 2;
-             alloc = xrealloc (alloc, len + 1);
-             set = alloc + len / 2;
-           }
-         *set++ = ch;
-       }
-    }
-  *set = '\0';
-  ungetc (ch, f);
-  return alloc;
-}
-
-/* This structure holds a linked list of file name maps, one per directory.  */
-
-struct file_name_map_list
-{
-  struct file_name_map_list *map_list_next;
-  char *map_list_name;
-  struct file_name_map *map_list_map;
-};
-
-/* Read the file name map file for DIRNAME.  */
-
-static struct file_name_map *
-read_name_map (pfile, dirname)
-     cpp_reader *pfile;
-     char *dirname;
-{
-  register struct file_name_map_list *map_list_ptr;
-  char *name;
-  FILE *f;
-
-  for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
-       map_list_ptr = map_list_ptr->map_list_next)
-    if (! strcmp (map_list_ptr->map_list_name, dirname))
-      return map_list_ptr->map_list_map;
-
-  map_list_ptr = ((struct file_name_map_list *)
-                 xmalloc (sizeof (struct file_name_map_list)));
-  map_list_ptr->map_list_name = savestring (dirname);
-  map_list_ptr->map_list_map = NULL;
-
-  name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
-  strcpy (name, dirname);
-  if (*dirname)
-    strcat (name, "/");
-  strcat (name, FILE_NAME_MAP_FILE);
-  f = fopen (name, "r");
-  if (!f)
-    map_list_ptr->map_list_map = NULL;
-  else
-    {
-      int ch;
-      int dirlen = strlen (dirname);
-
-      while ((ch = getc (f)) != EOF)
-       {
-         char *from, *to;
-         struct file_name_map *ptr;
-
-         if (is_space[ch])
-           continue;
-         from = read_filename_string (ch, f);
-         while ((ch = getc (f)) != EOF && is_hor_space[ch])
-           ;
-         to = read_filename_string (ch, f);
-
-         ptr = ((struct file_name_map *)
-                xmalloc (sizeof (struct file_name_map)));
-         ptr->map_from = from;
-
-         /* Make the real filename absolute.  */
-         if (*to == '/')
-           ptr->map_to = to;
-         else
-           {
-             ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
-             strcpy (ptr->map_to, dirname);
-             ptr->map_to[dirlen] = '/';
-             strcpy (ptr->map_to + dirlen + 1, to);
-             free (to);
-           }         
-
-         ptr->map_next = map_list_ptr->map_list_map;
-         map_list_ptr->map_list_map = ptr;
-
-         while ((ch = getc (f)) != '\n')
-           if (ch == EOF)
-             break;
-       }
-      fclose (f);
-    }
-  
-  map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
-  CPP_OPTIONS (pfile)->map_list = map_list_ptr;
-
-  return map_list_ptr->map_list_map;
-}  
-
-/* Try to open include file FILENAME.  SEARCHPTR is the directory
-   being tried from the include file search path.  This function maps
-   filenames on file systems based on information read by
-   read_name_map.  */
-
-static int
-open_include_file (pfile, filename, searchptr)
-     cpp_reader *pfile;
-     char *filename;
-     struct file_name_list *searchptr;
-{
-  if (CPP_OPTIONS (pfile)->remap)
-    {
-      register struct file_name_map *map;
-      register char *from;
-      char *p, *dir;
-
-      if (searchptr && ! searchptr->got_name_map)
-       {
-         searchptr->name_map = read_name_map (pfile,
-                                              searchptr->fname
-                                              ? searchptr->fname : ".");
-         searchptr->got_name_map = 1;
-       }
-
-      /* First check the mapping for the directory we are using.  */
-      if (searchptr && searchptr->name_map)
-       {
-         from = filename;
-         if (searchptr->fname)
-           from += strlen (searchptr->fname) + 1;
-         for (map = searchptr->name_map; map; map = map->map_next)
-           {
-             if (! strcmp (map->map_from, from))
-               {
-                 /* Found a match.  */
-                 return open (map->map_to, O_RDONLY, 0666);
-               }
-           }
-       }
-
-      /* Try to find a mapping file for the particular directory we are
-        looking in.  Thus #include <sys/types.h> will look up sys/types.h
-        in /usr/include/header.gcc and look up types.h in
-        /usr/include/sys/header.gcc.  */
-      p = rindex (filename, '/');
-      if (! p)
-       p = filename;
-      if (searchptr
-         && searchptr->fname
-         && strlen (searchptr->fname) == (size_t) (p - filename)
-         && ! strncmp (searchptr->fname, filename, p - filename))
-       {
-         /* FILENAME is in SEARCHPTR, which we've already checked.  */
-         return open (filename, O_RDONLY, 0666);
-       }
-
-      if (p == filename)
-       {
-         dir = ".";
-         from = filename;
-       }
-      else
-       {
-         dir = (char *) alloca (p - filename + 1);
-         bcopy (filename, dir, p - filename);
-         dir[p - filename] = '\0';
-         from = p + 1;
-       }
-      for (map = read_name_map (pfile, dir); map; map = map->map_next)
-       if (! strcmp (map->map_from, from))
-         return open (map->map_to, O_RDONLY, 0666);
-    }
-
-  return open (filename, O_RDONLY, 0666);
-}
-
-/* Process the contents of include file FNAME, already open on descriptor F,
-   with output to OP.
-   SYSTEM_HEADER_P is 1 if this file resides in any one of the known
-   "system" include directories (as decided by the `is_system_include'
-   function above).
-   DIRPTR is the link in the dir path through which this file was found,
-   or 0 if the file name was absolute or via the current directory.
-   Return 1 on success, 0 on failure.
-
-   The caller is responsible for the cpp_push_buffer.  */
-
-static int
-finclude (pfile, f, fname, system_header_p, dirptr)
-     cpp_reader *pfile;
-     int f;
-     char *fname;
-     int system_header_p;
-     struct file_name_list *dirptr;
-{
-  struct stat st;
-  size_t st_size;
-  long i;
-  int length;
-  cpp_buffer *fp;                      /* For input stack frame */
-#if 0
-  int missing_newline = 0;
-#endif
-
-  if (fstat (f, &st) < 0)
-    {
-      cpp_perror_with_name (pfile, fname);
-      close (f);
-      cpp_pop_buffer (pfile);
-      return 0;
-    }
-
-  fp = CPP_BUFFER (pfile);
-  fp->nominal_fname = fp->fname = fname;
-#if 0
-  fp->length = 0;
-#endif
-  fp->dir = dirptr;
-  fp->system_header_p = system_header_p;
-  fp->lineno = 1;
-  fp->colno = 1;
-  fp->cleanup = file_cleanup;
-
-  if (S_ISREG (st.st_mode)) {
-    st_size = (size_t) st.st_size;
-    if (st_size != st.st_size || st_size + 2 < st_size) {
-      cpp_error (pfile, "file `%s' too large", fname);
-      close (f);
-      return 0;
-    }
-    fp->buf = (U_CHAR *) xmalloc (st_size + 2);
-    fp->alimit = fp->buf + st_size + 2;
-    fp->cur = fp->buf;
-
-    /* Read the file contents, knowing that st_size is an upper bound
-       on the number of bytes we can read.  */
-    length = safe_read (f, fp->buf, st_size);
-    fp->rlimit = fp->buf + length;
-    if (length < 0) goto nope;
-  }
-  else if (S_ISDIR (st.st_mode)) {
-    cpp_error (pfile, "directory `%s' specified in #include", fname);
-    close (f);
-    return 0;
-  } else {
-    /* Cannot count its file size before reading.
-       First read the entire file into heap and
-       copy them into buffer on stack.  */
-
-    size_t bsize = 2000;
-
-    st_size = 0;
-    fp->buf = (U_CHAR *) xmalloc (bsize + 2);
-
-    for (;;) {
-      i = safe_read (f, fp->buf + st_size, bsize - st_size);
-      if (i < 0)
-       goto nope;      /* error! */
-      st_size += i;
-      if (st_size != bsize)
-       break;  /* End of file */
-      bsize *= 2;
-      fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
-    }
-    fp->cur = fp->buf;
-    length = st_size;
-  }
-
-  if ((length > 0 && fp->buf[length - 1] != '\n')
-      /* Backslash-newline at end is not good enough.  */
-      || (length > 1 && fp->buf[length - 2] == '\\')) {
-    fp->buf[length++] = '\n';
-#if 0
-    missing_newline = 1;
-#endif
-  }
-  fp->buf[length] = '\0';
-  fp->rlimit = fp->buf + length;
-
-  /* Close descriptor now, so nesting does not use lots of descriptors.  */
-  close (f);
-
-  /* Must do this before calling trigraph_pcp, so that the correct file name
-     will be printed in warning messages.  */
-
-  pfile->input_stack_listing_current = 0;
-
-#if 0
-  if (!no_trigraphs)
-    trigraph_pcp (fp);
-#endif
-
-#if 0
-  rescan (op, 0);
-
-  if (missing_newline)
-    fp->lineno--;
-
-  if (CPP_PEDANTIC (pfile) && missing_newline)
-    pedwarn ("file does not end in newline");
-
-  indepth--;
-  input_file_stack_tick++;
-  free (fp->buf);
-#endif
-  return 1;
-
- nope:
-
-  cpp_perror_with_name (pfile, fname);
-  close (f);
-  free (fp->buf);
-  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.)
@@ -6143,18 +5422,27 @@ cpp_start_read (pfile, fname)
     trigraph_pcp (fp);
 #endif
 
-  /* Avoid a #line 0 if -include files are present. */
-  CPP_BUFFER (pfile)->lineno = 1;
+  /* Must call finclude() on the main input before processing
+     -include switches; otherwise the -included text winds up
+     after the main input. */
+  if (!finclude (pfile, f, fname, 0, NULL_PTR))
+    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. */
   
-  /* Scan the -include and -imacros files before the main input. */
-
   pfile->no_record_file++;
-  for (pend = opts->pending;  pend;  pend = pend->next)
+  for (pend = opts->pending; pend; pend = pend->next)
     {
       if (pend->cmd != NULL)
         {
-         if (strcmp (pend->cmd, "-include") == 0)
+         if (strcmp (pend->cmd, "-imacros") == 0)
            {
              int fd = open (pend->arg, O_RDONLY, 0666);
              if (fd < 0)
@@ -6164,13 +5452,19 @@ cpp_start_read (pfile, fname)
                }
              if (!cpp_push_buffer (pfile, NULL, 0))
                return 0;
+             opts->no_output++;
              if (finclude (pfile, fd, pend->arg, 0, NULL_PTR))
-               {
-                 output_line_command (pfile, 0, enter_file);
-                 cpp_scan_buffer (pfile);
-               }
+               cpp_scan_buffer (pfile);
+             opts->no_output--;
            }
-         else if (strcmp (pend->cmd, "-imacros") == 0)
+       }
+    }
+  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, 0666);
              if (fd < 0)
@@ -6178,12 +5472,10 @@ cpp_start_read (pfile, fname)
                  cpp_perror_with_name (pfile, pend->arg);
                  return 0;
                }
-             opts->no_output++;
              if (!cpp_push_buffer (pfile, NULL, 0))
                return 0;
              if (finclude (pfile, fd, pend->arg, 0, NULL_PTR))
-               cpp_scan_buffer (pfile);
-             opts->no_output--;
+               output_line_command (pfile, 0, enter_file);
            }
        }
     }
@@ -6198,19 +5490,6 @@ cpp_start_read (pfile, fname)
     }
   opts->pending = NULL;
 
-#if 0
-  /* Scan the input, processing macros and directives.  */
-
-  rescan (&outbuf, 0);
-
-  if (missing_newline)
-    fp->lineno--;
-
-  if (CPP_PEDANTIC (pfile) && missing_newline)
-    pedwarn ("file does not end in newline");
-
-#endif
-  finclude (pfile, f, fname, 0, NULL_PTR);
   return 1;
 }
 
@@ -7309,45 +6588,11 @@ free_token_list (tokens)
     tokens = next;
   }
 }
-\f
-/* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
-   retrying if necessary.  If MAX_READ_LEN is defined, read at most
-   that bytes at a time.  Return a negative value if an error occurs,
-   otherwise return the actual number of bytes read,
-   which must be LEN unless end-of-file was reached.  */
-
-static int
-safe_read (desc, ptr, len)
-     int desc;
-     char *ptr;
-     int len;
-{
-  int left, rcount, nchars;
-
-  left = len;
-  while (left > 0) {
-    rcount = left;
-#ifdef MAX_READ_LEN
-    if (rcount > MAX_READ_LEN)
-      rcount = MAX_READ_LEN;
-#endif
-    nchars = read (desc, ptr, rcount);
-    if (nchars < 0)
-      {
-#ifdef EINTR
-       if (errno == EINTR)
-         continue;
-#endif
-       return nchars;
-      }
-    if (nchars == 0)
-      break;
-    ptr += nchars;
-    left -= nchars;
-  }
-  return len - left;
-}
 
+/* FIXME: savestring() should be renamed strdup() and both should
+   be moved into cppalloc.c.  We can't do that right now because
+   then we'd get multiple-symbol clashes with toplev.c and several
+   other people. */
 static char *
 xcalloc (number, size)
      unsigned number, size;
@@ -7358,7 +6603,7 @@ xcalloc (number, size)
   return ptr;
 }
 
-static char *
+char *
 savestring (input)
      char *input;
 {
index ab63719c4c8f8c88c9334589ae6f842375bf6bf1..3ff0c9214bfcf8eb23992ac64142d12d98c46026 100644 (file)
@@ -510,6 +510,27 @@ struct cpp_options {
 #define CPP_PEDANTIC(PFILE) (CPP_OPTIONS (PFILE)->pedantic)
 #define CPP_PRINT_DEPS(PFILE) (CPP_OPTIONS (PFILE)->print_deps)
 
+struct file_name_list
+  {
+    struct file_name_list *next;
+    char *fname;
+    /* If the following is nonzero, it is a macro name.
+       Don't include the file again if that macro is defined.  */
+    U_CHAR *control_macro;
+    /* If the following is nonzero, it is a C-language system include
+       directory.  */
+    int c_system_include_path;
+    /* Mapping of file names for this directory.  */
+    struct file_name_map *name_map;
+    /* Non-zero if name_map is valid.  */
+    int got_name_map;
+  };
+
+/* If a buffer's dir field is SELF_DIR_DUMMY, it means the file was found
+   via the same directory as the file that #included it.  */
+#define SELF_DIR_DUMMY ((struct file_name_list *) (~0))
+
+    
 /* Name under which this program was invoked.  */
 
 extern char *progname;
@@ -623,6 +644,8 @@ struct definition {
 };
 
 extern unsigned char is_idchar[256];
+extern unsigned char is_hor_space[256];
+extern unsigned char is_space[256];
 
 /* Stack of conditionals currently in progress
    (including both successful and failing conditionals).  */
@@ -685,6 +708,25 @@ extern void cpp_pfatal_with_name PROTO ((cpp_reader *, const char *));
 extern void cpp_file_line_for_message PROTO ((cpp_reader *, char *, int, int));
 extern void cpp_print_containing_files PROTO ((cpp_reader *));
 
+/* In cppfiles.c */
+extern void append_include_chain       PROTO ((cpp_reader *,
+                                               struct file_name_list *,
+                                               struct file_name_list *));
+extern int finclude                    PROTO ((cpp_reader *, int, char *,
+                                               int, struct file_name_list *));
+extern int find_include_file           PROTO ((cpp_reader *, char *,
+                                               unsigned long, char *, int,
+                                               struct file_name_list *,
+                                               struct file_name_list **));
+extern void deps_output                        PROTO ((cpp_reader *, char *, int));
+
+/* Bleargh. */
+extern char *savestring                        PROTO ((char *));
+#ifndef INCLUDE_LEN_FUDGE
+#define INCLUDE_LEN_FUDGE 0
+#endif
+
+    
 #ifdef __cplusplus
 }
 #endif
index 5acb8f014b2ec29ebdc9dc98f70b460d0e1d07c0..acf3d431aa7e5cd25d8a52624805ab7a7b77c4d7 100644 (file)
@@ -1058,6 +1058,7 @@ documented_lang_options[] =
   { "-D", "" },
   { "-I", "" },
   { "-U", "" },
+  { "-H", "" },
   { "-idirafter", "" },
   { "-imacros", "" },
   { "-include", "" },