OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / libcpp / files.c
index 6a18d71..29ccf3b 100644 (file)
@@ -1,6 +1,7 @@
 /* Part of CPP library.  File handling.
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998,
 /* Part of CPP library.  File handling.
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005,
+   2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
    Written by Per Bothner, 1994.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
    Written by Per Bothner, 1994.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -9,7 +10,7 @@
 
 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
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
+Free Software Foundation; either version 3, or (at your option) any
 later version.
 
 This program is distributed in the hope that it will be useful,
 later version.
 
 This program is distributed in the hope that it will be useful,
@@ -18,14 +19,15 @@ 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
 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.  */
+along with this program; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 #include "cpplib.h"
 #include "internal.h"
 #include "mkdeps.h"
 
 #include "config.h"
 #include "system.h"
 #include "cpplib.h"
 #include "internal.h"
 #include "mkdeps.h"
+#include "obstack.h"
 #include "hashtab.h"
 #include "md5.h"
 #include <dirent.h>
 #include "hashtab.h"
 #include "md5.h"
 #include <dirent.h>
@@ -40,6 +42,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #endif
 
 #ifdef __DJGPP__
 #endif
 
 #ifdef __DJGPP__
+#include <io.h>
   /* For DJGPP redirected input is opened in text mode.  */
 #  define set_stdin_to_binary_mode() \
      if (! isatty (0)) setmode (0, O_BINARY)
   /* For DJGPP redirected input is opened in text mode.  */
 #  define set_stdin_to_binary_mode() \
      if (! isatty (0)) setmode (0, O_BINARY)
@@ -71,6 +74,10 @@ struct _cpp_file
   /* The contents of NAME after calling read_file().  */
   const uchar *buffer;
 
   /* The contents of NAME after calling read_file().  */
   const uchar *buffer;
 
+  /* Pointer to the real start of BUFFER.  read_file() might increment
+     BUFFER; when freeing, this this pointer must be used instead.  */
+  const uchar *buffer_start;
+
   /* The macro, if any, preventing re-inclusion.  */
   const cpp_hashnode *cmacro;
 
   /* The macro, if any, preventing re-inclusion.  */
   const cpp_hashnode *cmacro;
 
@@ -103,9 +110,6 @@ struct _cpp_file
 
   /* If BUFFER above contains the true contents of the file.  */
   bool buffer_valid;
 
   /* If BUFFER above contains the true contents of the file.  */
   bool buffer_valid;
-
-  /* File is a PCH (on return from find_include_file).  */
-  bool pch;
 };
 
 /* A singly-linked list for all searches for a given file name, with
 };
 
 /* A singly-linked list for all searches for a given file name, with
@@ -139,6 +143,7 @@ struct file_hash_entry
 {
   struct file_hash_entry *next;
   cpp_dir *start_dir;
 {
   struct file_hash_entry *next;
   cpp_dir *start_dir;
+  source_location location;
   union
   {
     _cpp_file *file;
   union
   {
     _cpp_file *file;
@@ -146,6 +151,21 @@ struct file_hash_entry
   } u;
 };
 
   } u;
 };
 
+/* Number of entries to put in a file_hash_entry pool.  */
+#define FILE_HASH_POOL_SIZE 127
+
+/* A file hash entry pool.  We allocate file_hash_entry object from
+   one of these.  */
+struct file_hash_entry_pool
+{
+  /* Number of entries used from this pool.  */
+  unsigned int file_hash_entries_used;
+  /* Next pool in the chain; used when freeing.  */
+  struct file_hash_entry_pool *next;
+  /* The memory pool.  */
+  struct file_hash_entry pool[FILE_HASH_POOL_SIZE];
+};
+
 static bool open_file (_cpp_file *file);
 static bool pch_open_file (cpp_reader *pfile, _cpp_file *file,
                           bool *invalid_pch);
 static bool open_file (_cpp_file *file);
 static bool pch_open_file (cpp_reader *pfile, _cpp_file *file,
                           bool *invalid_pch);
@@ -157,11 +177,11 @@ static bool should_stack_file (cpp_reader *, _cpp_file *file, bool import);
 static struct cpp_dir *search_path_head (cpp_reader *, const char *fname,
                                 int angle_brackets, enum include_type);
 static const char *dir_name_of_file (_cpp_file *file);
 static struct cpp_dir *search_path_head (cpp_reader *, const char *fname,
                                 int angle_brackets, enum include_type);
 static const char *dir_name_of_file (_cpp_file *file);
-static void open_file_failed (cpp_reader *pfile, _cpp_file *file);
-static struct file_hash_entry *search_cache (cpp_reader *pfile,
-                                            struct file_hash_entry *head,
+static void open_file_failed (cpp_reader *pfile, _cpp_file *file, int);
+static struct file_hash_entry *search_cache (struct file_hash_entry *head,
                                             const cpp_dir *start_dir);
 static _cpp_file *make_cpp_file (cpp_reader *, cpp_dir *, const char *fname);
                                             const cpp_dir *start_dir);
 static _cpp_file *make_cpp_file (cpp_reader *, cpp_dir *, const char *fname);
+static void destroy_cpp_file (_cpp_file *);
 static cpp_dir *make_cpp_dir (cpp_reader *, const char *dir_name, int sysp);
 static void allocate_file_hash_entries (cpp_reader *pfile);
 static struct file_hash_entry *new_file_hash_entry (cpp_reader *pfile);
 static cpp_dir *make_cpp_dir (cpp_reader *, const char *dir_name, int sysp);
 static void allocate_file_hash_entries (cpp_reader *pfile);
 static struct file_hash_entry *new_file_hash_entry (cpp_reader *pfile);
@@ -173,7 +193,6 @@ static void read_name_map (cpp_dir *dir);
 static char *remap_filename (cpp_reader *pfile, _cpp_file *file);
 static char *append_file_to_dir (const char *fname, cpp_dir *dir);
 static bool validate_pch (cpp_reader *, _cpp_file *file, const char *pchname);
 static char *remap_filename (cpp_reader *pfile, _cpp_file *file);
 static char *append_file_to_dir (const char *fname, cpp_dir *dir);
 static bool validate_pch (cpp_reader *, _cpp_file *file, const char *pchname);
-static int pchf_adder (void **slot, void *data);
 static int pchf_save_compare (const void *e1, const void *e2);
 static int pchf_compare (const void *d_p, const void *e_p);
 static bool check_file_against_entries (cpp_reader *, _cpp_file *, bool);
 static int pchf_save_compare (const void *e1, const void *e2);
 static int pchf_compare (const void *d_p, const void *e_p);
 static bool check_file_against_entries (cpp_reader *, _cpp_file *, bool);
@@ -226,6 +245,22 @@ open_file (_cpp_file *file)
       close (file->fd);
       file->fd = -1;
     }
       close (file->fd);
       file->fd = -1;
     }
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  else if (errno == EACCES)
+    {
+      /* On most UNIX systems, open succeeds on a directory.  Above,
+         we check if we have opened a directory and if so, set errno
+         to ENOENT.  However, on Windows, opening a directory
+         fails with EACCES.  We want to return ENOENT in that
+         case too.  */
+      if (stat (file->path, &file->st) == 0
+          && S_ISDIR (file->st.st_mode))
+        errno = ENOENT;
+      else
+       /* The call to stat may have reset errno.  */
+       errno = EACCES;
+    }
+#endif    
   else if (errno == ENOTDIR)
     errno = ENOENT;
 
   else if (errno == ENOTDIR)
     errno = ENOENT;
 
@@ -253,9 +288,15 @@ pch_open_file (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
   if (file->name[0] == '\0' || !pfile->cb.valid_pch)
     return false;
 
   if (file->name[0] == '\0' || !pfile->cb.valid_pch)
     return false;
 
+  /* If the file is not included as first include from either the toplevel
+     file or the command-line it is not a valid use of PCH.  */
+  if (pfile->all_files
+      && pfile->all_files->next_file)
+    return false;
+
   flen = strlen (path);
   len = flen + sizeof (extension);
   flen = strlen (path);
   len = flen + sizeof (extension);
-  pchname = xmalloc (len);
+  pchname = XNEWVEC (char, len);
   memcpy (pchname, path, flen);
   memcpy (pchname + flen, extension, sizeof (extension));
 
   memcpy (pchname, path, flen);
   memcpy (pchname + flen, extension, sizeof (extension));
 
@@ -279,7 +320,7 @@ pch_open_file (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
              if (dlen + plen > len)
                {
                  len += dlen + 64;
              if (dlen + plen > len)
                {
                  len += dlen + 64;
-                 pchname = xrealloc (pchname, len);
+                 pchname = XRESIZEVEC (char, pchname, len);
                }
              memcpy (pchname + plen, d->d_name, dlen);
              valid = validate_pch (pfile, file, pchname);
                }
              memcpy (pchname + plen, d->d_name, dlen);
              valid = validate_pch (pfile, file, pchname);
@@ -288,9 +329,7 @@ pch_open_file (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
            }
          closedir (pchdir);
        }
            }
          closedir (pchdir);
        }
-      if (valid)
-       file->pch = true;
-      else
+      if (!valid)
        *invalid_pch = true;
     }
 
        *invalid_pch = true;
     }
 
@@ -322,6 +361,16 @@ find_file_in_dir (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
 
   if (path)
     {
 
   if (path)
     {
+      hashval_t hv = htab_hash_string (path);
+      char *copy;
+      void **pp;
+
+      if (htab_find_with_hash (pfile->nonexistent_file_hash, path, hv) != NULL)
+       {
+         file->err_no = ENOENT;
+         return false;
+       }
+
       file->path = path;
       if (pch_open_file (pfile, file, invalid_pch))
        return true;
       file->path = path;
       if (pch_open_file (pfile, file, invalid_pch))
        return true;
@@ -331,11 +380,20 @@ find_file_in_dir (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
 
       if (file->err_no != ENOENT)
        {
 
       if (file->err_no != ENOENT)
        {
-         open_file_failed (pfile, file);
+         open_file_failed (pfile, file, 0);
          return true;
        }
 
          return true;
        }
 
+      /* We copy the path name onto an obstack partly so that we don't
+        leak the memory, but mostly so that we don't fragment the
+        heap.  */
+      copy = (char *) obstack_copy0 (&pfile->nonexistent_file_ob, path,
+                                    strlen (path));
       free (path);
       free (path);
+      pp = htab_find_slot_with_hash (pfile->nonexistent_file_hash,
+                                    copy, hv, INSERT);
+      *pp = copy;
+
       file->path = file->name;
     }
   else
       file->path = file->name;
     }
   else
@@ -391,11 +449,14 @@ _cpp_find_failed (_cpp_file *file)
    to open_file().
 */
 _cpp_file *
    to open_file().
 */
 _cpp_file *
-_cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool fake)
+_cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool fake, int angle_brackets)
 {
   struct file_hash_entry *entry, **hash_slot;
   _cpp_file *file;
   bool invalid_pch = false;
 {
   struct file_hash_entry *entry, **hash_slot;
   _cpp_file *file;
   bool invalid_pch = false;
+  bool saw_bracket_include = false;
+  bool saw_quote_include = false;
+  struct cpp_dir *found_in_cache = NULL;
 
   /* Ensure we get no confusion between cached files and directories.  */
   if (start_dir == NULL)
 
   /* Ensure we get no confusion between cached files and directories.  */
   if (start_dir == NULL)
@@ -407,7 +468,7 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f
                              INSERT);
 
   /* First check the cache before we resort to memory allocation.  */
                              INSERT);
 
   /* First check the cache before we resort to memory allocation.  */
-  entry = search_cache (pfile, *hash_slot, start_dir);
+  entry = search_cache (*hash_slot, start_dir);
   if (entry)
     return entry->u.file;
 
   if (entry)
     return entry->u.file;
 
@@ -423,9 +484,16 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f
       if (file->dir == NULL)
        {
          if (search_path_exhausted (pfile, fname, file))
       if (file->dir == NULL)
        {
          if (search_path_exhausted (pfile, fname, file))
-           return file;
+           {
+             /* Although this file must not go in the cache, because
+                the file found might depend on things (like the current file)
+                that aren't represented in the cache, it still has to go in
+                the list of all files so that #import works.  */
+             file->next_file = pfile->all_files;
+             pfile->all_files = file;
+             return file;
+           }
 
 
-         open_file_failed (pfile, file);
          if (invalid_pch)
            {
              cpp_error (pfile, CPP_DL_ERROR,
          if (invalid_pch)
            {
              cpp_error (pfile, CPP_DL_ERROR,
@@ -434,6 +502,24 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f
                cpp_error (pfile, CPP_DL_ERROR,
                           "use -Winvalid-pch for more information");
            }
                cpp_error (pfile, CPP_DL_ERROR,
                           "use -Winvalid-pch for more information");
            }
+         open_file_failed (pfile, file, angle_brackets);
+         break;
+       }
+
+      /* Only check the cache for the starting location (done above)
+        and the quote and bracket chain heads because there are no
+        other possible starting points for searches.  */
+      if (file->dir == pfile->bracket_include)
+       saw_bracket_include = true;
+      else if (file->dir == pfile->quote_include)
+       saw_quote_include = true;
+      else
+       continue;
+
+      entry = search_cache (*hash_slot, file->dir);
+      if (entry)
+       {
+         found_in_cache = file->dir;
          break;
        }
     }
          break;
        }
     }
@@ -452,40 +538,39 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f
       pfile->all_files = file;
     }
 
       pfile->all_files = file;
     }
 
-  /* If this file was found in the directory-of-the-current-file,
-     check whether that directory is reachable via one of the normal
-     search paths.  If so, we must record this entry as being
-     reachable that way, otherwise we will mistakenly reprocess this
-     file if it is included later from the normal search path.  */
-  if (file->dir && start_dir->next == pfile->quote_include)
-    {
-      cpp_dir *d;
-      cpp_dir *proper_start_dir = pfile->quote_include;
-
-      for (d = proper_start_dir;; d = d->next)
-       {
-         if (d == pfile->bracket_include)
-           proper_start_dir = d;
-         if (d == 0)
-           {
-             proper_start_dir = 0;
-             break;
-           }
-         /* file->dir->name will have a trailing slash.  */
-         if (!strncmp (d->name, file->dir->name, file->dir->len - 1))
-           break;
-       }
-      if (proper_start_dir)
-       start_dir = proper_start_dir;
-    }
-
   /* Store this new result in the hash table.  */
   entry = new_file_hash_entry (pfile);
   entry->next = *hash_slot;
   entry->start_dir = start_dir;
   /* Store this new result in the hash table.  */
   entry = new_file_hash_entry (pfile);
   entry->next = *hash_slot;
   entry->start_dir = start_dir;
+  entry->location = pfile->line_table->highest_location;
   entry->u.file = file;
   *hash_slot = entry;
 
   entry->u.file = file;
   *hash_slot = entry;
 
+  /* If we passed the quote or bracket chain heads, cache them also.
+     This speeds up processing if there are lots of -I options.  */
+  if (saw_bracket_include
+      && pfile->bracket_include != start_dir
+      && found_in_cache != pfile->bracket_include)
+    {
+      entry = new_file_hash_entry (pfile);
+      entry->next = *hash_slot;
+      entry->start_dir = pfile->bracket_include;
+      entry->location = pfile->line_table->highest_location;
+      entry->u.file = file;
+      *hash_slot = entry;
+    }
+  if (saw_quote_include
+      && pfile->quote_include != start_dir
+      && found_in_cache != pfile->quote_include)
+    {
+      entry = new_file_hash_entry (pfile);
+      entry->next = *hash_slot;
+      entry->start_dir = pfile->quote_include;
+      entry->location = pfile->line_table->highest_location;
+      entry->u.file = file;
+      *hash_slot = entry;
+    }
+
   return file;
 }
 
   return file;
 }
 
@@ -510,7 +595,7 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
       return false;
     }
 
       return false;
     }
 
-  regular = S_ISREG (file->st.st_mode);
+  regular = S_ISREG (file->st.st_mode) != 0;
   if (regular)
     {
       /* off_t might have a wider range than ssize_t - in other words,
   if (regular)
     {
       /* off_t might have a wider range than ssize_t - in other words,
@@ -535,7 +620,7 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
        the majority of C source files.  */
     size = 8 * 1024;
 
        the majority of C source files.  */
     size = 8 * 1024;
 
-  buf = xmalloc (size + 1);
+  buf = XNEWVEC (uchar, size + 1);
   total = 0;
   while ((count = read (file->fd, buf + total, size - total)) > 0)
     {
   total = 0;
   while ((count = read (file->fd, buf + total, size - total)) > 0)
     {
@@ -546,7 +631,7 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
          if (regular)
            break;
          size *= 2;
          if (regular)
            break;
          size *= 2;
-         buf = xrealloc (buf, size + 1);
+         buf = XRESIZEVEC (uchar, buf, size + 1);
        }
     }
 
        }
     }
 
@@ -560,8 +645,11 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
     cpp_error (pfile, CPP_DL_WARNING,
               "%s is shorter than expected", file->path);
 
     cpp_error (pfile, CPP_DL_WARNING,
               "%s is shorter than expected", file->path);
 
-  file->buffer = _cpp_convert_input (pfile, CPP_OPTION (pfile, input_charset),
-                                    buf, size, total, &file->st.st_size);
+  file->buffer = _cpp_convert_input (pfile,
+                                    CPP_OPTION (pfile, input_charset),
+                                    buf, size, total,
+                                    &file->buffer_start,
+                                    &file->st.st_size);
   file->buffer_valid = true;
 
   return true;
   file->buffer_valid = true;
 
   return true;
@@ -583,7 +671,7 @@ read_file (cpp_reader *pfile, _cpp_file *file)
 
   if (file->fd == -1 && !open_file (file))
     {
 
   if (file->fd == -1 && !open_file (file))
     {
-      open_file_failed (pfile, file);
+      open_file_failed (pfile, file, 0);
       return false;
     }
 
       return false;
     }
 
@@ -623,11 +711,12 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import)
     return false;
 
   /* Handle PCH files immediately; don't stack them.  */
     return false;
 
   /* Handle PCH files immediately; don't stack them.  */
-  if (file->pch)
+  if (file->pchname)
     {
     {
-      pfile->cb.read_pch (pfile, file->path, file->fd, file->pchname);
-      close (file->fd);
+      pfile->cb.read_pch (pfile, file->pchname, file->fd, file->path);
       file->fd = -1;
       file->fd = -1;
+      free ((void *) file->pchname);
+      file->pchname = NULL;
       return false;
     }
 
       return false;
     }
 
@@ -662,12 +751,38 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import)
       if ((import || f->once_only)
          && f->err_no == 0
          && f->st.st_mtime == file->st.st_mtime
       if ((import || f->once_only)
          && f->err_no == 0
          && f->st.st_mtime == file->st.st_mtime
-         && f->st.st_size == file->st.st_size
-         && read_file (pfile, f)
-         /* Size might have changed in read_file().  */
-         && f->st.st_size == file->st.st_size
-         && !memcmp (f->buffer, file->buffer, f->st.st_size))
-       break;
+         && f->st.st_size == file->st.st_size)
+       {
+         _cpp_file *ref_file;
+         bool same_file_p = false;
+
+         if (f->buffer && !f->buffer_valid)
+           {
+             /* We already have a buffer but it is not valid, because
+                the file is still stacked.  Make a new one.  */
+             ref_file = make_cpp_file (pfile, f->dir, f->name);
+             ref_file->path = f->path;
+           }
+         else
+           /* The file is not stacked anymore.  We can reuse it.  */
+           ref_file = f;
+
+         same_file_p = read_file (pfile, ref_file)
+                       /* Size might have changed in read_file().  */
+                       && ref_file->st.st_size == file->st.st_size
+                       && !memcmp (ref_file->buffer,
+                                   file->buffer,
+                                   file->st.st_size);
+
+         if (f->buffer && !f->buffer_valid)
+           {
+             ref_file->path = 0;
+             destroy_cpp_file (ref_file);
+           }
+
+         if (same_file_p)
+           break;
+       }
     }
 
   return f == NULL;
     }
 
   return f == NULL;
@@ -704,7 +819,8 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, bool import)
 
   /* Stack the buffer.  */
   buffer = cpp_push_buffer (pfile, file->buffer, file->st.st_size,
 
   /* Stack the buffer.  */
   buffer = cpp_push_buffer (pfile, file->buffer, file->st.st_size,
-                           CPP_OPTION (pfile, preprocessed));
+                           CPP_OPTION (pfile, preprocessed)
+                           && !CPP_OPTION (pfile, directives_only));
   buffer->file = file;
   buffer->sysp = sysp;
 
   buffer->file = file;
   buffer->sysp = sysp;
 
@@ -745,7 +861,8 @@ search_path_head (cpp_reader *pfile, const char *fname, int angle_brackets,
   /* For #include_next, skip in the search path past the dir in which
      the current file was found, but if it was found via an absolute
      path use the normal search logic.  */
   /* For #include_next, skip in the search path past the dir in which
      the current file was found, but if it was found via an absolute
      path use the normal search logic.  */
-  if (type == IT_INCLUDE_NEXT && file->dir)
+  if (type == IT_INCLUDE_NEXT && file->dir
+      && file->dir != &pfile->no_search_path)
     dir = file->dir->next;
   else if (angle_brackets)
     dir = pfile->bracket_include;
     dir = file->dir->next;
   else if (angle_brackets)
     dir = pfile->bracket_include;
@@ -775,7 +892,7 @@ dir_name_of_file (_cpp_file *file)
   if (!file->dir_name)
     {
       size_t len = lbasename (file->path) - file->path;
   if (!file->dir_name)
     {
       size_t len = lbasename (file->path) - file->path;
-      char *dir_name = xmalloc (len + 1);
+      char *dir_name = XNEWVEC (char, len + 1);
 
       memcpy (dir_name, file->path, len);
       dir_name[len] = '\0';
 
       memcpy (dir_name, file->path, len);
       dir_name[len] = '\0';
@@ -799,16 +916,17 @@ _cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets,
   if (!dir)
     return false;
 
   if (!dir)
     return false;
 
-  file = _cpp_find_file (pfile, fname, dir, false);
-
-  /* Compensate for the increment in linemap_add.  In the case of a
-     normal #include, we're currently at the start of the line
-     *following* the #include.  A separate source_location for this
-     location makes no sense (until we do the LC_LEAVE), and
-     complicates LAST_SOURCE_LINE_LOCATION.  This does not apply if we
-     found a PCH file (in which case linemap_add is not called) or we
-     were included from the command-line.  */
-  if (! file->pch && file->err_no == 0 && type != IT_CMDLINE)
+  file = _cpp_find_file (pfile, fname, dir, false, angle_brackets);
+
+  /* Compensate for the increment in linemap_add that occurs in
+     _cpp_stack_file.  In the case of a normal #include, we're
+     currently at the start of the line *following* the #include.  A
+     separate source_location for this location makes no sense (until
+     we do the LC_LEAVE), and complicates LAST_SOURCE_LINE_LOCATION.
+     This does not apply if we found a PCH file (in which case
+     linemap_add is not called) or we were included from the
+     command-line.  */
+  if (file->pchname == NULL && file->err_no == 0 && type != IT_CMDLINE)
     pfile->line_table->highest_location--;
 
   return _cpp_stack_file (pfile, file, type == IT_IMPORT);
     pfile->line_table->highest_location--;
 
   return _cpp_stack_file (pfile, file, type == IT_IMPORT);
@@ -816,62 +934,47 @@ _cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets,
 
 /* Could not open FILE.  The complication is dependency output.  */
 static void
 
 /* Could not open FILE.  The complication is dependency output.  */
 static void
-open_file_failed (cpp_reader *pfile, _cpp_file *file)
+open_file_failed (cpp_reader *pfile, _cpp_file *file, int angle_brackets)
 {
   int sysp = pfile->line_table->highest_line > 1 && pfile->buffer ? pfile->buffer->sysp : 0;
 {
   int sysp = pfile->line_table->highest_line > 1 && pfile->buffer ? pfile->buffer->sysp : 0;
-  bool print_dep = CPP_OPTION (pfile, deps.style) > !!sysp;
+  bool print_dep = CPP_OPTION (pfile, deps.style) > (angle_brackets || !!sysp);
 
   errno = file->err_no;
   if (print_dep && CPP_OPTION (pfile, deps.missing_files) && errno == ENOENT)
 
   errno = file->err_no;
   if (print_dep && CPP_OPTION (pfile, deps.missing_files) && errno == ENOENT)
-    deps_add_dep (pfile->deps, file->name);
+    {
+      deps_add_dep (pfile->deps, file->name);
+      /* If the preprocessor output (other than dependency information) is
+         being used, we must also flag an error.  */
+      if (CPP_OPTION (pfile, deps.need_preprocessor_output))
+       cpp_errno (pfile, CPP_DL_FATAL, file->path);
+    }
   else
     {
   else
     {
-      /* If we are outputting dependencies but not for this file then
-        don't error because we can still produce correct output.  */
-      if (CPP_OPTION (pfile, deps.style) && ! print_dep)
-       cpp_errno (pfile, CPP_DL_WARNING, file->path);
+      /* If we are not outputting dependencies, or if we are and dependencies
+         were requested for this file, or if preprocessor output is needed
+         in addition to dependency information, this is an error.
+
+         Otherwise (outputting dependencies but not for this file, and not
+         using the preprocessor output), we can still produce correct output
+         so it's only a warning.  */
+      if (CPP_OPTION (pfile, deps.style) == DEPS_NONE
+          || print_dep
+          || CPP_OPTION (pfile, deps.need_preprocessor_output))
+       cpp_errno (pfile, CPP_DL_FATAL, file->path);
       else
       else
-       cpp_errno (pfile, CPP_DL_ERROR, file->path);
+       cpp_errno (pfile, CPP_DL_WARNING, file->path);
     }
 }
 
 /* Search in the chain beginning at HEAD for a file whose search path
    started at START_DIR != NULL.  */
 static struct file_hash_entry *
     }
 }
 
 /* Search in the chain beginning at HEAD for a file whose search path
    started at START_DIR != NULL.  */
 static struct file_hash_entry *
-search_cache (cpp_reader *pfile, struct file_hash_entry *head,
-             const cpp_dir *start_dir)
+search_cache (struct file_hash_entry *head, const cpp_dir *start_dir)
 {
 {
-  struct file_hash_entry *p;
-
-  /* Look for a file that was found from a search starting at the
-     given location.  */
-  for (p = head; p; p = p->next)
-    if (p->start_dir == start_dir)
-      return p;
-
-  /* If the given location is for a search of the directory containing
-     the current file, check for a match starting at the base of the
-     quoted include chain.  */
-  if (start_dir->next == pfile->quote_include)
-    {
-      start_dir = pfile->quote_include;
-      for (p = head; p; p = p->next)
-       if (p->start_dir == start_dir)
-         return p;
-    }
+  while (head && head->start_dir != start_dir)
+    head = head->next;
 
 
-  /* If the given location is for a search from the base of the quoted
-     include chain, check for a match starting at the base of the
-     bracket include chain.  */
-  if (start_dir == pfile->quote_include)
-    {
-      start_dir = pfile->bracket_include;
-      for (p = head; p; p = p->next)
-       if (p->start_dir == start_dir)
-         return p;
-    }
-
-  return 0;
+  return head;
 }
 
 /* Allocate a new _cpp_file structure.  */
 }
 
 /* Allocate a new _cpp_file structure.  */
@@ -880,7 +983,7 @@ make_cpp_file (cpp_reader *pfile, cpp_dir *dir, const char *fname)
 {
   _cpp_file *file;
 
 {
   _cpp_file *file;
 
-  file = xcalloc (1, sizeof (_cpp_file));
+  file = XCNEW (_cpp_file);
   file->main_file = !pfile->buffer;
   file->fd = -1;
   file->dir = dir;
   file->main_file = !pfile->buffer;
   file->fd = -1;
   file->dir = dir;
@@ -889,6 +992,28 @@ make_cpp_file (cpp_reader *pfile, cpp_dir *dir, const char *fname)
   return file;
 }
 
   return file;
 }
 
+/* Release a _cpp_file structure.  */
+static void
+destroy_cpp_file (_cpp_file *file)
+{
+  free ((void *) file->buffer_start);
+  free ((void *) file->name);
+  free (file);
+}
+
+/* Release all the files allocated by this reader.  */
+static void
+destroy_all_cpp_files (cpp_reader *pfile)
+{
+  _cpp_file *iter = pfile->all_files;
+  while (iter)
+    {
+      _cpp_file *next = iter->next_file;
+      destroy_cpp_file (iter);
+      iter = next;
+    }
+}
+
 /* A hash of directory names.  The directory names are the path names
    of files which contain a #include "", the included file name is
    appended to this directories.
 /* A hash of directory names.  The directory names are the path names
    of files which contain a #include "", the included file name is
    appended to this directories.
@@ -903,7 +1028,7 @@ make_cpp_dir (cpp_reader *pfile, const char *dir_name, int sysp)
   cpp_dir *dir;
 
   hash_slot = (struct file_hash_entry **)
   cpp_dir *dir;
 
   hash_slot = (struct file_hash_entry **)
-    htab_find_slot_with_hash (pfile->file_hash, dir_name,
+    htab_find_slot_with_hash (pfile->dir_hash, dir_name,
                              htab_hash_string (dir_name),
                              INSERT);
 
                              htab_hash_string (dir_name),
                              INSERT);
 
@@ -912,7 +1037,7 @@ make_cpp_dir (cpp_reader *pfile, const char *dir_name, int sysp)
     if (entry->start_dir == NULL)
       return entry->u.dir;
 
     if (entry->start_dir == NULL)
       return entry->u.dir;
 
-  dir = xcalloc (1, sizeof (cpp_dir));
+  dir = XCNEW (cpp_dir);
   dir->next = pfile->quote_include;
   dir->name = (char *) dir_name;
   dir->len = strlen (dir_name);
   dir->next = pfile->quote_include;
   dir->name = (char *) dir_name;
   dir->len = strlen (dir_name);
@@ -923,6 +1048,7 @@ make_cpp_dir (cpp_reader *pfile, const char *dir_name, int sysp)
   entry = new_file_hash_entry (pfile);
   entry->next = *hash_slot;
   entry->start_dir = NULL;
   entry = new_file_hash_entry (pfile);
   entry->next = *hash_slot;
   entry->start_dir = NULL;
+  entry->location = pfile->line_table->highest_location;
   entry->u.dir = dir;
   *hash_slot = entry;
 
   entry->u.dir = dir;
   *hash_slot = entry;
 
@@ -933,20 +1059,35 @@ make_cpp_dir (cpp_reader *pfile, const char *dir_name, int sysp)
 static void
 allocate_file_hash_entries (cpp_reader *pfile)
 {
 static void
 allocate_file_hash_entries (cpp_reader *pfile)
 {
-  pfile->file_hash_entries_used = 0;
-  pfile->file_hash_entries_allocated = 127;
-  pfile->file_hash_entries = xmalloc
-    (pfile->file_hash_entries_allocated * sizeof (struct file_hash_entry));
+  struct file_hash_entry_pool *pool = XNEW (struct file_hash_entry_pool);
+  pool->file_hash_entries_used = 0;
+  pool->next = pfile->file_hash_entries;
+  pfile->file_hash_entries = pool;
 }
 
 /* Return a new file hash entry.  */
 static struct file_hash_entry *
 new_file_hash_entry (cpp_reader *pfile)
 {
 }
 
 /* Return a new file hash entry.  */
 static struct file_hash_entry *
 new_file_hash_entry (cpp_reader *pfile)
 {
-  if (pfile->file_hash_entries_used == pfile->file_hash_entries_allocated)
+  unsigned int idx;
+  if (pfile->file_hash_entries->file_hash_entries_used == FILE_HASH_POOL_SIZE)
     allocate_file_hash_entries (pfile);
 
     allocate_file_hash_entries (pfile);
 
-  return &pfile->file_hash_entries[pfile->file_hash_entries_used++];
+  idx = pfile->file_hash_entries->file_hash_entries_used++;
+  return &pfile->file_hash_entries->pool[idx];
+}
+
+/* Free the file hash entry pools.  */
+static void
+free_file_hash_entries (cpp_reader *pfile)
+{
+  struct file_hash_entry_pool *iter = pfile->file_hash_entries;
+  while (iter)
+    {
+      struct file_hash_entry_pool *next = iter->next;
+      free (iter);
+      iter = next;
+    }
 }
 
 /* Returns TRUE if a file FNAME has ever been successfully opened.
 }
 
 /* Returns TRUE if a file FNAME has ever been successfully opened.
@@ -957,8 +1098,8 @@ cpp_included (cpp_reader *pfile, const char *fname)
 {
   struct file_hash_entry *entry;
 
 {
   struct file_hash_entry *entry;
 
-  entry = htab_find_with_hash (pfile->file_hash, fname,
-                              htab_hash_string (fname));
+  entry = (struct file_hash_entry *)
+     htab_find_with_hash (pfile->file_hash, fname, htab_hash_string (fname));
 
   while (entry && (entry->start_dir == NULL || entry->u.file->err_no))
     entry = entry->next;
 
   while (entry && (entry->start_dir == NULL || entry->u.file->err_no))
     entry = entry->next;
@@ -966,6 +1107,25 @@ cpp_included (cpp_reader *pfile, const char *fname)
   return entry != NULL;
 }
 
   return entry != NULL;
 }
 
+/* Returns TRUE if a file FNAME has ever been successfully opened
+   before LOCATION.  This routine is not intended to correctly handle
+   filenames aliased by links or redundant . or .. traversals etc.  */
+bool
+cpp_included_before (cpp_reader *pfile, const char *fname,
+                    source_location location)
+{
+  struct file_hash_entry *entry;
+
+  entry = (struct file_hash_entry *)
+     htab_find_with_hash (pfile->file_hash, fname, htab_hash_string (fname));
+
+  while (entry && (entry->start_dir == NULL || entry->u.file->err_no
+                  || entry->location > location))
+    entry = entry->next;
+
+  return entry != NULL;
+}
+
 /* Calculate the hash value of a file hash entry P.  */
 
 static hashval_t
 /* Calculate the hash value of a file hash entry P.  */
 
 static hashval_t
@@ -994,7 +1154,15 @@ file_hash_eq (const void *p, const void *q)
   else
     hname = entry->u.dir->name;
 
   else
     hname = entry->u.dir->name;
 
-  return strcmp (hname, fname) == 0;
+  return filename_cmp (hname, fname) == 0;
+}
+
+/* Compare entries in the nonexistent file hash table.  These are just
+   strings.  */
+static int
+nonexistent_file_hash_eq (const void *p, const void *q)
+{
+  return filename_cmp ((const char *) p, (const char *) q) == 0;
 }
 
 /* Initialize everything in this source file.  */
 }
 
 /* Initialize everything in this source file.  */
@@ -1003,7 +1171,15 @@ _cpp_init_files (cpp_reader *pfile)
 {
   pfile->file_hash = htab_create_alloc (127, file_hash_hash, file_hash_eq,
                                        NULL, xcalloc, free);
 {
   pfile->file_hash = htab_create_alloc (127, file_hash_hash, file_hash_eq,
                                        NULL, xcalloc, free);
+  pfile->dir_hash = htab_create_alloc (127, file_hash_hash, file_hash_eq,
+                                       NULL, xcalloc, free);
   allocate_file_hash_entries (pfile);
   allocate_file_hash_entries (pfile);
+  pfile->nonexistent_file_hash = htab_create_alloc (127, htab_hash_string,
+                                                   nonexistent_file_hash_eq,
+                                                   NULL, xcalloc, free);
+  _obstack_begin (&pfile->nonexistent_file_ob, 0, 0,
+                 (void *(*) (long)) xmalloc,
+                 (void (*) (void *)) free);
 }
 
 /* Finalize everything in this source file.  */
 }
 
 /* Finalize everything in this source file.  */
@@ -1011,13 +1187,29 @@ void
 _cpp_cleanup_files (cpp_reader *pfile)
 {
   htab_delete (pfile->file_hash);
 _cpp_cleanup_files (cpp_reader *pfile)
 {
   htab_delete (pfile->file_hash);
+  htab_delete (pfile->dir_hash);
+  htab_delete (pfile->nonexistent_file_hash);
+  obstack_free (&pfile->nonexistent_file_ob, 0);
+  free_file_hash_entries (pfile);
+  destroy_all_cpp_files (pfile);
+}
+
+/* Make the parser forget about files it has seen.  This can be useful
+   for resetting the parser to start another run.  */
+void
+cpp_clear_file_cache (cpp_reader *pfile)
+{
+  _cpp_cleanup_files (pfile);
+  pfile->file_hash_entries = NULL;
+  pfile->all_files = NULL;
+  _cpp_init_files (pfile);
 }
 
 /* Enter a file name in the hash for the sake of cpp_included.  */
 void
 _cpp_fake_include (cpp_reader *pfile, const char *fname)
 {
 }
 
 /* Enter a file name in the hash for the sake of cpp_included.  */
 void
 _cpp_fake_include (cpp_reader *pfile, const char *fname)
 {
-  _cpp_find_file (pfile, fname, pfile->buffer->file->dir, true);
+  _cpp_find_file (pfile, fname, pfile->buffer->file->dir, true, 0);
 }
 
 /* Not everyone who wants to set system-header-ness on a buffer can
 }
 
 /* Not everyone who wants to set system-header-ness on a buffer can
@@ -1028,13 +1220,12 @@ cpp_make_system_header (cpp_reader *pfile, int syshdr, int externc)
 {
   int flags = 0;
   const struct line_maps *line_table = pfile->line_table;
 {
   int flags = 0;
   const struct line_maps *line_table = pfile->line_table;
-  const struct line_map *map = &line_table->maps[line_table->used-1];
-
+  const struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
   /* 1 = system header, 2 = system header to be treated as C.  */
   if (syshdr)
     flags = 1 + (externc != 0);
   pfile->buffer->sysp = flags;
   /* 1 = system header, 2 = system header to be treated as C.  */
   if (syshdr)
     flags = 1 + (externc != 0);
   pfile->buffer->sysp = flags;
-  _cpp_do_file_change (pfile, LC_RENAME, map->to_file,
+  _cpp_do_file_change (pfile, LC_RENAME, ORDINARY_MAP_FILE_NAME (map),
                       SOURCE_LINE (map, pfile->line_table->highest_line), flags);
 }
 
                       SOURCE_LINE (map, pfile->line_table->highest_line), flags);
 }
 
@@ -1048,12 +1239,19 @@ cpp_change_file (cpp_reader *pfile, enum lc_reason reason,
   _cpp_do_file_change (pfile, reason, new_name, 1, 0);
 }
 
   _cpp_do_file_change (pfile, reason, new_name, 1, 0);
 }
 
+struct report_missing_guard_data
+{
+  const char **paths;
+  size_t count;
+};
+
 /* Callback function for htab_traverse.  */
 static int
 /* Callback function for htab_traverse.  */
 static int
-report_missing_guard (void **slot, void *b)
+report_missing_guard (void **slot, void *d)
 {
   struct file_hash_entry *entry = (struct file_hash_entry *) *slot;
 {
   struct file_hash_entry *entry = (struct file_hash_entry *) *slot;
-  int *bannerp = (int *) b;
+  struct report_missing_guard_data *data
+    = (struct report_missing_guard_data *) d;
 
   /* Skip directories.  */
   if (entry->start_dir != NULL)
 
   /* Skip directories.  */
   if (entry->start_dir != NULL)
@@ -1061,21 +1259,28 @@ report_missing_guard (void **slot, void *b)
       _cpp_file *file = entry->u.file;
 
       /* We don't want MI guard advice for the main file.  */
       _cpp_file *file = entry->u.file;
 
       /* We don't want MI guard advice for the main file.  */
-      if (file->cmacro == NULL && file->stack_count == 1 && !file->main_file)
+      if (!file->once_only && file->cmacro == NULL
+         && file->stack_count == 1 && !file->main_file)
        {
        {
-         if (*bannerp == 0)
+         if (data->paths == NULL)
            {
            {
-             fputs (_("Multiple include guards may be useful for:\n"),
-                    stderr);
-             *bannerp = 1;
+             data->paths = XCNEWVEC (const char *, data->count);
+             data->count = 0;
            }
 
            }
 
-         fputs (entry->u.file->path, stderr);
-         putc ('\n', stderr);
+         data->paths[data->count++] = file->path;
        }
     }
 
        }
     }
 
-  return 0;
+  /* Keep traversing the hash table.  */
+  return 1;
+}
+
+/* Comparison function for qsort.  */
+static int
+report_missing_guard_cmp (const void *p1, const void *p2)
+{
+  return strcmp (*(const char *const *) p1, *(const char *const *) p2);
 }
 
 /* Report on all files that might benefit from a multiple include guard.
 }
 
 /* Report on all files that might benefit from a multiple include guard.
@@ -1083,9 +1288,29 @@ report_missing_guard (void **slot, void *b)
 void
 _cpp_report_missing_guards (cpp_reader *pfile)
 {
 void
 _cpp_report_missing_guards (cpp_reader *pfile)
 {
-  int banner = 0;
+  struct report_missing_guard_data data;
+
+  data.paths = NULL;
+  data.count = htab_elements (pfile->file_hash);
+  htab_traverse (pfile->file_hash, report_missing_guard, &data);
 
 
-  htab_traverse (pfile->file_hash, report_missing_guard, &banner);
+  if (data.paths != NULL)
+    {
+      size_t i;
+
+      /* Sort the paths to avoid outputting them in hash table
+        order.  */
+      qsort (data.paths, data.count, sizeof (const char *),
+            report_missing_guard_cmp);
+      fputs (_("Multiple include guards may be useful for:\n"),
+            stderr);
+      for (i = 0; i < data.count; i++)
+       {
+         fputs (data.paths[i], stderr);
+         putc ('\n', stderr);
+       }
+      free (data.paths);
+    }
 }
 
 /* Locate HEADER, and determine whether it is newer than the current
 }
 
 /* Locate HEADER, and determine whether it is newer than the current
@@ -1102,7 +1327,7 @@ _cpp_compare_file_date (cpp_reader *pfile, const char *fname,
   if (!dir)
     return -1;
 
   if (!dir)
     return -1;
 
-  file = _cpp_find_file (pfile, fname, dir, false);
+  file = _cpp_find_file (pfile, fname, dir, false, angle_brackets);
   if (file->err_no)
     return -1;
 
   if (file->err_no)
     return -1;
 
@@ -1136,13 +1361,29 @@ _cpp_pop_file_buffer (cpp_reader *pfile, _cpp_file *file)
   /* Invalidate control macros in the #including file.  */
   pfile->mi_valid = false;
 
   /* Invalidate control macros in the #including file.  */
   pfile->mi_valid = false;
 
-  if (file->buffer)
+  if (file->buffer_start)
     {
     {
-      free ((void *) file->buffer);
+      free ((void *) file->buffer_start);
+      file->buffer_start = NULL;
       file->buffer = NULL;
       file->buffer = NULL;
+      file->buffer_valid = false;
     }
 }
 
     }
 }
 
+/* Return the file name associated with FILE.  */
+const char *
+_cpp_get_file_name (_cpp_file *file)
+{
+  return file->name;
+}
+
+/* Inteface to file statistics record in _cpp_file structure. */
+struct stat *
+_cpp_get_file_stat (_cpp_file *file)
+{
+    return &file->st;
+}
+
 /* Set the include chain for "" to QUOTE, for <> to BRACKET.  If
    QUOTE_IGNORES_SOURCE_DIR, then "" includes do not look in the
    directory of the including file.
 /* Set the include chain for "" to QUOTE, for <> to BRACKET.  If
    QUOTE_IGNORES_SOURCE_DIR, then "" includes do not look in the
    directory of the including file.
@@ -1175,9 +1416,9 @@ append_file_to_dir (const char *fname, cpp_dir *dir)
 
   dlen = dir->len;
   flen = strlen (fname);
 
   dlen = dir->len;
   flen = strlen (fname);
-  path = xmalloc (dlen + 1 + flen + 1);
+  path = XNEWVEC (char, dlen + 1 + flen + 1);
   memcpy (path, dir->name, dlen);
   memcpy (path, dir->name, dlen);
-  if (dlen && path[dlen - 1] != '/')
+  if (dlen && !IS_DIR_SEPARATOR (path[dlen - 1]))
     path[dlen++] = '/';
   memcpy (&path[dlen], fname, flen + 1);
 
     path[dlen++] = '/';
   memcpy (&path[dlen], fname, flen + 1);
 
@@ -1193,7 +1434,7 @@ read_filename_string (int ch, FILE *f)
   int len;
 
   len = 20;
   int len;
 
   len = 20;
-  set = alloc = xmalloc (len + 1);
+  set = alloc = XNEWVEC (char, len + 1);
   if (! is_space (ch))
     {
       *set++ = ch;
   if (! is_space (ch))
     {
       *set++ = ch;
@@ -1202,7 +1443,7 @@ read_filename_string (int ch, FILE *f)
          if (set - alloc == len)
            {
              len *= 2;
          if (set - alloc == len)
            {
              len *= 2;
-             alloc = xrealloc (alloc, len + 1);
+             alloc = XRESIZEVEC (char, alloc, len + 1);
              set = alloc + len / 2;
            }
          *set++ = ch;
              set = alloc + len / 2;
            }
          *set++ = ch;
@@ -1223,14 +1464,14 @@ read_name_map (cpp_dir *dir)
   size_t len, count = 0, room = 9;
 
   len = dir->len;
   size_t len, count = 0, room = 9;
 
   len = dir->len;
-  name = alloca (len + sizeof (FILE_NAME_MAP_FILE) + 1);
+  name = (char *) alloca (len + sizeof (FILE_NAME_MAP_FILE) + 1);
   memcpy (name, dir->name, len);
   memcpy (name, dir->name, len);
-  if (len && name[len - 1] != '/')
+  if (len && !IS_DIR_SEPARATOR (name[len - 1]))
     name[len++] = '/';
   strcpy (name + len, FILE_NAME_MAP_FILE);
   f = fopen (name, "r");
 
     name[len++] = '/';
   strcpy (name + len, FILE_NAME_MAP_FILE);
   f = fopen (name, "r");
 
-  dir->name_map = xmalloc (room * sizeof (char *));
+  dir->name_map = XNEWVEC (const char *, room);
 
   /* Silently return NULL if we cannot open.  */
   if (f)
 
   /* Silently return NULL if we cannot open.  */
   if (f)
@@ -1247,7 +1488,7 @@ read_name_map (cpp_dir *dir)
          if (count + 2 > room)
            {
              room += 8;
          if (count + 2 > room)
            {
              room += 8;
-             dir->name_map = xrealloc (dir->name_map, room * sizeof (char *));
+             dir->name_map = XRESIZEVEC (const char *, dir->name_map, room);
            }
 
          dir->name_map[count] = read_filename_string (ch, f);
            }
 
          dir->name_map[count] = read_filename_string (ch, f);
@@ -1296,15 +1537,23 @@ remap_filename (cpp_reader *pfile, _cpp_file *file)
        read_name_map (dir);
 
       for (index = 0; dir->name_map[index]; index += 2)
        read_name_map (dir);
 
       for (index = 0; dir->name_map[index]; index += 2)
-       if (!strcmp (dir->name_map[index], fname))
+       if (!filename_cmp (dir->name_map[index], fname))
            return xstrdup (dir->name_map[index + 1]);
            return xstrdup (dir->name_map[index + 1]);
-
+      if (IS_ABSOLUTE_PATH (fname))
+       return NULL;
       p = strchr (fname, '/');
       p = strchr (fname, '/');
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+      {
+       char *p2 = strchr (fname, '\\');
+       if (!p || (p > p2))
+         p = p2;
+      }
+#endif
       if (!p || p == fname)
        return NULL;
 
       len = dir->len + (p - fname + 1);
       if (!p || p == fname)
        return NULL;
 
       len = dir->len + (p - fname + 1);
-      new_dir = xmalloc (len + 1);
+      new_dir = XNEWVEC (char, len + 1);
       memcpy (new_dir, dir->name, dir->len);
       memcpy (new_dir + dir->len, fname, p - fname + 1);
       new_dir[len] = '\0';
       memcpy (new_dir, dir->name, dir->len);
       memcpy (new_dir + dir->len, fname, p - fname + 1);
       new_dir[len] = '\0';
@@ -1397,6 +1646,16 @@ cpp_get_prev (cpp_buffer *b)
    that's OK.  The code does rely on having entries with the same size
    next to each other.  */
 
    that's OK.  The code does rely on having entries with the same size
    next to each other.  */
 
+struct pchf_entry {
+  /* The size of this file.  This is used to save running a MD5 checksum
+     if the sizes don't match.  */
+  off_t size;
+  /* The MD5 checksum of this file.  */
+  unsigned char sum[16];
+  /* Is this file to be included only once?  */
+  bool once_only;
+};
+
 struct pchf_data {
   /* Number of pchf_entry structures.  */
   size_t count;
 struct pchf_data {
   /* Number of pchf_entry structures.  */
   size_t count;
@@ -1406,51 +1665,59 @@ struct pchf_data {
      the structure if we're processing a regular #include.  */
   bool have_once_only;
 
      the structure if we're processing a regular #include.  */
   bool have_once_only;
 
-  struct pchf_entry {
-    /* The size of this file.  This is used to save running a MD5 checksum
-       if the sizes don't match.  */
-    off_t size;
-    /* The MD5 checksum of this file.  */
-    unsigned char sum[16];
-    /* Is this file to be included only once?  */
-    bool once_only;
-  } entries[1];
+  struct pchf_entry entries[1];
 };
 
 static struct pchf_data *pchf;
 
 };
 
 static struct pchf_data *pchf;
 
-/* Data for pchf_addr.  */
-struct pchf_adder_info
+/* A qsort ordering function for pchf_entry structures.  */
+
+static int
+pchf_save_compare (const void *e1, const void *e2)
 {
 {
-  cpp_reader *pfile;
-  struct pchf_data *d;
-};
+  return memcmp (e1, e2, sizeof (struct pchf_entry));
+}
 
 
-/* A hash traversal function to add entries into DATA->D.  */
+/* Create and write to F a pchf_data structure.  */
 
 
-static int
-pchf_adder (void **slot, void *data)
+bool
+_cpp_save_file_entries (cpp_reader *pfile, FILE *fp)
 {
 {
-  struct file_hash_entry *h = (struct file_hash_entry *) *slot;
-  struct pchf_adder_info *i = (struct pchf_adder_info *) data;
+  size_t count = 0;
+  struct pchf_data *result;
+  size_t result_size;
+  _cpp_file *f;
+
+  for (f = pfile->all_files; f; f = f->next_file)
+    ++count;
 
 
-  if (h->start_dir != NULL && h->u.file->stack_count != 0)
+  result_size = (sizeof (struct pchf_data)
+                + sizeof (struct pchf_entry) * (count - 1));
+  result = XCNEWVAR (struct pchf_data, result_size);
+
+  result->count = 0;
+  result->have_once_only = false;
+
+  for (f = pfile->all_files; f; f = f->next_file)
     {
     {
-      struct pchf_data *d = i->d;
-      _cpp_file *f = h->u.file;
-      size_t count = d->count++;
+      size_t count;
 
       /* This should probably never happen, since if a read error occurred
         the PCH file shouldn't be written...  */
       if (f->dont_read || f->err_no)
 
       /* This should probably never happen, since if a read error occurred
         the PCH file shouldn't be written...  */
       if (f->dont_read || f->err_no)
-       return 1;
+       continue;
 
 
-      d->entries[count].once_only = f->once_only;
+      if (f->stack_count == 0)
+       continue;
+
+      count = result->count++;
+
+      result->entries[count].once_only = f->once_only;
       /* |= is avoided in the next line because of an HP C compiler bug */
       /* |= is avoided in the next line because of an HP C compiler bug */
-      d->have_once_only = d->have_once_only | f->once_only; 
+      result->have_once_only = result->have_once_only | f->once_only;
       if (f->buffer_valid)
       if (f->buffer_valid)
-         md5_buffer ((const char *)f->buffer,
-                     f->st.st_size, d->entries[count].sum);
+       md5_buffer ((const char *)f->buffer,
+                   f->st.st_size, result->entries[count].sum);
       else
        {
          FILE *ff;
       else
        {
          FILE *ff;
@@ -1458,48 +1725,16 @@ pchf_adder (void **slot, void *data)
 
          if (!open_file (f))
            {
 
          if (!open_file (f))
            {
-             open_file_failed (i->pfile, f);
-             return 0;
+             open_file_failed (pfile, f, 0);
+             return false;
            }
          ff = fdopen (f->fd, "rb");
            }
          ff = fdopen (f->fd, "rb");
-         md5_stream (ff, d->entries[count].sum);
+         md5_stream (ff, result->entries[count].sum);
          fclose (ff);
          f->fd = oldfd;
        }
          fclose (ff);
          f->fd = oldfd;
        }
-      d->entries[count].size = f->st.st_size;
+      result->entries[count].size = f->st.st_size;
     }
     }
-  return 1;
-}
-
-/* A qsort ordering function for pchf_entry structures.  */
-
-static int
-pchf_save_compare (const void *e1, const void *e2)
-{
-  return memcmp (e1, e2, sizeof (struct pchf_entry));
-}
-
-/* Create and write to F a pchf_data structure.  */
-
-bool
-_cpp_save_file_entries (cpp_reader *pfile, FILE *f)
-{
-  size_t count = 0;
-  struct pchf_data *result;
-  size_t result_size;
-  struct pchf_adder_info pai;
-
-  count = htab_elements (pfile->file_hash);
-  result_size = (sizeof (struct pchf_data)
-                + sizeof (struct pchf_entry) * (count - 1));
-  result = xcalloc (result_size, 1);
-
-  result->count = 0;
-  result->have_once_only = false;
-
-  pai.pfile = pfile;
-  pai.d = result;
-  htab_traverse (pfile->file_hash, pchf_adder, &pai);
 
   result_size = (sizeof (struct pchf_data)
                  + sizeof (struct pchf_entry) * (result->count - 1));
 
   result_size = (sizeof (struct pchf_data)
                  + sizeof (struct pchf_entry) * (result->count - 1));
@@ -1507,7 +1742,7 @@ _cpp_save_file_entries (cpp_reader *pfile, FILE *f)
   qsort (result->entries, result->count, sizeof (struct pchf_entry),
         pchf_save_compare);
 
   qsort (result->entries, result->count, sizeof (struct pchf_entry),
         pchf_save_compare);
 
-  return fwrite (result, result_size, 1, f) == 1;
+  return fwrite (result, result_size, 1, fp) == 1;
 }
 
 /* Read the pchf_data structure from F.  */
 }
 
 /* Read the pchf_data structure from F.  */
@@ -1521,7 +1756,7 @@ _cpp_read_file_entries (cpp_reader *pfile ATTRIBUTE_UNUSED, FILE *f)
        != 1)
     return false;
 
        != 1)
     return false;
 
-  pchf = xmalloc (sizeof (struct pchf_data)
+  pchf = XNEWVAR (struct pchf_data, sizeof (struct pchf_data)
                  + sizeof (struct pchf_entry) * (d.count - 1));
   memcpy (pchf, &d, sizeof (struct pchf_data) - sizeof (struct pchf_entry));
   if (fread (pchf->entries, sizeof (struct pchf_entry), d.count, f)
                  + sizeof (struct pchf_entry) * (d.count - 1));
   memcpy (pchf, &d, sizeof (struct pchf_data) - sizeof (struct pchf_entry));
   if (fread (pchf->entries, sizeof (struct pchf_entry), d.count, f)