unaligned-memcpy-2.c (dest): Initialize to ensure alignment.
[gcc.git] / libcpp / files.c
index 833421805900c1bba0c77774c4787ab9b6a065f8..5c5a0b9b5146e4ff171e133885cb158a17c9ba02 100644 (file)
@@ -1,6 +1,5 @@
 /* Part of CPP library.  File handling.
-   Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1986-2013 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
@@ -9,7 +8,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
-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,
@@ -18,14 +17,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
-along with this program; if not, write to the Free Software
-Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "obstack.h"
 #include "hashtab.h"
 #include "md5.h"
 #include <dirent.h>
@@ -72,6 +72,10 @@ struct _cpp_file
   /* 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;
 
@@ -105,8 +109,8 @@ struct _cpp_file
   /* 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;
+  /* If this file is implicitly preincluded.  */
+  bool implicit_preinclude;
 };
 
 /* A singly-linked list for all searches for a given file name, with
@@ -140,6 +144,7 @@ struct file_hash_entry
 {
   struct file_hash_entry *next;
   cpp_dir *start_dir;
+  source_location location;
   union
   {
     _cpp_file *file;
@@ -147,6 +152,21 @@ struct file_hash_entry
   } 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);
@@ -226,6 +246,22 @@ open_file (_cpp_file *file)
       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;
 
@@ -253,6 +289,14 @@ pch_open_file (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
   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
+      && !(pfile->all_files->implicit_preinclude
+          || pfile->all_files->next_file->implicit_preinclude))
+    return false;
+
   flen = strlen (path);
   len = flen + sizeof (extension);
   pchname = XNEWVEC (char, len);
@@ -288,9 +332,7 @@ pch_open_file (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
            }
          closedir (pchdir);
        }
-      if (valid)
-       file->pch = true;
-      else
+      if (!valid)
        *invalid_pch = true;
     }
 
@@ -302,6 +344,25 @@ pch_open_file (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
   return valid;
 }
 
+/* Canonicalize the path to FILE.  Return the canonical form if it is
+   shorter, otherwise return NULL.  This function does NOT free the
+   memory pointed by FILE.  */
+
+static char *
+maybe_shorter_path (const char * file)
+{
+  char * file2 = lrealpath (file);
+  if (file2 && strlen (file2) < strlen (file))
+    {
+      return file2;
+    }
+  else 
+    {
+      free (file2);
+      return NULL;
+    }
+}
+
 /* Try to open the path FILE->name appended to FILE->dir.  This is
    where remap and PCH intercept the file lookup process.  Return true
    if the file was found, whether or not the open was successful.
@@ -322,6 +383,30 @@ find_file_in_dir (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
 
   if (path)
     {
+      hashval_t hv;
+      char *copy;
+      void **pp;
+
+      /* We try to canonicalize system headers.  */
+      if (CPP_OPTION (pfile, canonical_system_headers) && file->dir->sysp)
+       {
+         char * canonical_path = maybe_shorter_path (path);
+         if (canonical_path)
+           {
+             /* The canonical path was newly allocated.  Let's free the
+                non-canonical one.  */
+             free (path);
+             path = canonical_path;
+           }
+       }
+
+      hv = htab_hash_string (path);
+      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;
@@ -335,7 +420,16 @@ find_file_in_dir (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
          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);
+      pp = htab_find_slot_with_hash (pfile->nonexistent_file_hash,
+                                    copy, hv, INSERT);
+      *pp = copy;
+
       file->path = file->name;
     }
   else
@@ -389,29 +483,38 @@ _cpp_find_failed (_cpp_file *file)
    descriptor.  FD can be -1 if the file was found in the cache and
    had previously been closed.  To open it again pass the return value
    to open_file().
+
+   If IMPLICIT_PREINCLUDE then it is OK for the file to be missing.
+   If present, it is OK for a precompiled header to be included after
+   it.
 */
 _cpp_file *
-_cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool fake, int angle_brackets)
+_cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir,
+               bool fake, int angle_brackets, bool implicit_preinclude)
 {
-  struct file_hash_entry *entry, **hash_slot;
+  struct file_hash_entry *entry;
+  void **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)
     cpp_error (pfile, CPP_DL_ICE, "NULL directory in find_file");
 
-  hash_slot = (struct file_hash_entry **)
-    htab_find_slot_with_hash (pfile->file_hash, fname,
-                             htab_hash_string (fname),
-                             INSERT);
+  hash_slot
+    = htab_find_slot_with_hash (pfile->file_hash, fname,
+                               htab_hash_string (fname), INSERT);
 
   /* First check the cache before we resort to memory allocation.  */
-  entry = search_cache (*hash_slot, start_dir);
+  entry = search_cache ((struct file_hash_entry *) *hash_slot, start_dir);
   if (entry)
     return entry->u.file;
 
   file = make_cpp_file (pfile, start_dir, fname);
+  file->implicit_preinclude = implicit_preinclude;
 
   /* Try each path in the include chain.  */
   for (; !fake ;)
@@ -430,10 +533,20 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f
                 the list of all files so that #import works.  */
              file->next_file = pfile->all_files;
              pfile->all_files = file;
+             if (*hash_slot == NULL)
+               {
+                 /* If *hash_slot is NULL, the above htab_find_slot_with_hash
+                    call just created the slot, but we aren't going to store
+                    there anything, so need to remove the newly created entry.
+                    htab_clear_slot requires that it is non-NULL, so store
+                    there some non-NULL pointer, htab_clear_slot will
+                    overwrite it immediately.  */
+                 *hash_slot = file;
+                 htab_clear_slot (pfile->file_hash, hash_slot);
+               }
              return file;
            }
 
-         open_file_failed (pfile, file, angle_brackets);
          if (invalid_pch)
            {
              cpp_error (pfile, CPP_DL_ERROR,
@@ -442,19 +555,39 @@ _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");
            }
+         if (implicit_preinclude)
+           {
+             free ((char *) file->name);
+             free (file);
+             if (*hash_slot == NULL)
+               {
+                 /* See comment on the above htab_clear_slot call.  */
+                 *hash_slot = file;
+                 htab_clear_slot (pfile->file_hash, hash_slot);
+               }
+             return NULL;
+           }
+         else
+           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
-         && file->dir != pfile->quote_include)
+      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);
+      entry = search_cache ((struct file_hash_entry *) *hash_slot, file->dir);
       if (entry)
-       break;
+       {
+         found_in_cache = file->dir;
+         break;
+       }
     }
 
   if (entry)
@@ -473,10 +606,36 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f
 
   /* Store this new result in the hash table.  */
   entry = new_file_hash_entry (pfile);
-  entry->next = *hash_slot;
+  entry->next = (struct file_hash_entry *) *hash_slot;
   entry->start_dir = start_dir;
+  entry->location = pfile->line_table->highest_location;
   entry->u.file = file;
-  *hash_slot = entry;
+  *hash_slot = (void *) 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 = (struct file_hash_entry *) *hash_slot;
+      entry->start_dir = pfile->bracket_include;
+      entry->location = pfile->line_table->highest_location;
+      entry->u.file = file;
+      *hash_slot = (void *) entry;
+    }
+  if (saw_quote_include
+      && pfile->quote_include != start_dir
+      && found_in_cache != pfile->quote_include)
+    {
+      entry = new_file_hash_entry (pfile);
+      entry->next = (struct file_hash_entry *) *hash_slot;
+      entry->start_dir = pfile->quote_include;
+      entry->location = pfile->line_table->highest_location;
+      entry->u.file = file;
+      *hash_slot = (void *) entry;
+    }
 
   return file;
 }
@@ -502,7 +661,7 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
       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,
@@ -527,7 +686,11 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
        the majority of C source files.  */
     size = 8 * 1024;
 
-  buf = XNEWVEC (uchar, size + 1);
+  /* The + 16 here is space for the final '\n' and 15 bytes of padding,
+     used to quiet warnings from valgrind or Address Sanitizer, when the
+     optimized lexer accesses aligned 16-byte memory chunks, including
+     the bytes after the malloced, area, and stops lexing on '\n'.  */
+  buf = XNEWVEC (uchar, size + 16);
   total = 0;
   while ((count = read (file->fd, buf + total, size - total)) > 0)
     {
@@ -538,13 +701,14 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
          if (regular)
            break;
          size *= 2;
-         buf = XRESIZEVEC (uchar, buf, size + 1);
+         buf = XRESIZEVEC (uchar, buf, size + 16);
        }
     }
 
   if (count < 0)
     {
       cpp_errno (pfile, CPP_DL_ERROR, file->path);
+      free (buf);
       return false;
     }
 
@@ -552,8 +716,11 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
     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 + 16, total,
+                                    &file->buffer_start,
+                                    &file->st.st_size);
   file->buffer_valid = true;
 
   return true;
@@ -615,11 +782,12 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import)
     return false;
 
   /* Handle PCH files immediately; don't stack them.  */
-  if (file->pch)
+  if (file->pchname)
     {
       pfile->cb.read_pch (pfile, file->pchname, file->fd, file->path);
-      close (file->fd);
       file->fd = -1;
+      free ((void *) file->pchname);
+      file->pchname = NULL;
       return false;
     }
 
@@ -722,9 +890,11 @@ _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,
-                           CPP_OPTION (pfile, preprocessed));
+                           CPP_OPTION (pfile, preprocessed)
+                           && !CPP_OPTION (pfile, directives_only));
   buffer->file = file;
   buffer->sysp = sysp;
+  buffer->to_free = file->buffer_start;
 
   /* Initialize controlling macro state.  */
   pfile->mi_valid = true;
@@ -763,7 +933,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.  */
-  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;
@@ -817,16 +988,21 @@ _cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets,
   if (!dir)
     return false;
 
-  file = _cpp_find_file (pfile, fname, dir, false, angle_brackets);
+  file = _cpp_find_file (pfile, fname, dir, false, angle_brackets,
+                        type == IT_DEFAULT);
+  if (type == IT_DEFAULT && file == NULL)
+    return 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)
+  /* 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 && type != IT_DEFAULT)
     pfile->line_table->highest_location--;
 
   return _cpp_stack_file (pfile, file, type == IT_IMPORT);
@@ -841,15 +1017,28 @@ open_file_failed (cpp_reader *pfile, _cpp_file *file, int angle_brackets)
 
   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
     {
-      /* 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
-       cpp_errno (pfile, CPP_DL_ERROR, file->path);
+       cpp_errno (pfile, CPP_DL_WARNING, file->path);
     }
 }
 
@@ -883,12 +1072,24 @@ make_cpp_file (cpp_reader *pfile, cpp_dir *dir, const char *fname)
 static void
 destroy_cpp_file (_cpp_file *file)
 {
-  if (file->buffer)
-    free ((void *) file->buffer);
+  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.
@@ -923,6 +1124,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->location = pfile->line_table->highest_location;
   entry->u.dir = dir;
   *hash_slot = entry;
 
@@ -933,20 +1135,35 @@ make_cpp_dir (cpp_reader *pfile, const char *dir_name, int sysp)
 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 = XNEWVEC (struct file_hash_entry,
-                                      pfile->file_hash_entries_allocated);
+  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)
 {
-  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);
 
-  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.
@@ -966,6 +1183,25 @@ cpp_included (cpp_reader *pfile, const char *fname)
   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
@@ -994,7 +1230,15 @@ file_hash_eq (const void *p, const void *q)
   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.  */
@@ -1006,6 +1250,12 @@ _cpp_init_files (cpp_reader *pfile)
   pfile->dir_hash = htab_create_alloc (127, file_hash_hash, file_hash_eq,
                                        NULL, xcalloc, free);
   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.  */
@@ -1014,13 +1264,28 @@ _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)
 {
-  _cpp_find_file (pfile, fname, pfile->buffer->file->dir, true, 0);
+  _cpp_find_file (pfile, fname, pfile->buffer->file->dir, true, 0, false);
 }
 
 /* Not everyone who wants to set system-header-ness on a buffer can
@@ -1031,13 +1296,12 @@ cpp_make_system_header (cpp_reader *pfile, int syshdr, int externc)
 {
   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;
-  _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);
 }
 
@@ -1051,12 +1315,19 @@ cpp_change_file (cpp_reader *pfile, enum lc_reason reason,
   _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
-report_missing_guard (void **slot, void *b)
+report_missing_guard (void **slot, void *d)
 {
   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)
@@ -1064,21 +1335,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.  */
-      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.
@@ -1086,9 +1364,29 @@ report_missing_guard (void **slot, void *b)
 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
@@ -1105,7 +1403,7 @@ _cpp_compare_file_date (cpp_reader *pfile, const char *fname,
   if (!dir)
     return -1;
 
-  file = _cpp_find_file (pfile, fname, dir, false, angle_brackets);
+  file = _cpp_find_file (pfile, fname, dir, false, angle_brackets, false);
   if (file->err_no)
     return -1;
 
@@ -1126,10 +1424,20 @@ cpp_push_include (cpp_reader *pfile, const char *fname)
   return _cpp_stack_include (pfile, fname, false, IT_CMDLINE);
 }
 
+/* Pushes the given file, implicitly included at the start of a
+   compilation, onto the buffer stack but without any errors if the
+   file is not found.  Returns nonzero if successful.  */
+bool
+cpp_push_default_include (cpp_reader *pfile, const char *fname)
+{
+  return _cpp_stack_include (pfile, fname, true, IT_DEFAULT);
+}
+
 /* Do appropriate cleanup when a file INC's buffer is popped off the
    input stack.  */
 void
-_cpp_pop_file_buffer (cpp_reader *pfile, _cpp_file *file)
+_cpp_pop_file_buffer (cpp_reader *pfile, _cpp_file *file,
+                     const unsigned char *to_free)
 {
   /* Record the inclusion-preventing macro, which could be NULL
      meaning no controlling macro.  */
@@ -1139,14 +1447,25 @@ _cpp_pop_file_buffer (cpp_reader *pfile, _cpp_file *file)
   /* Invalidate control macros in the #including file.  */
   pfile->mi_valid = false;
 
-  if (file->buffer)
+  if (to_free)
     {
-      free ((void *) file->buffer);
-      file->buffer = NULL;
-      file->buffer_valid = false;
+      if (to_free == file->buffer_start)
+       {
+         file->buffer_start = NULL;
+         file->buffer = NULL;
+         file->buffer_valid = false;
+       }
+      free ((void *) to_free);
     }
 }
 
+/* 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)
@@ -1188,7 +1507,7 @@ append_file_to_dir (const char *fname, cpp_dir *dir)
   flen = strlen (fname);
   path = XNEWVEC (char, dlen + 1 + flen + 1);
   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);
 
@@ -1236,7 +1555,7 @@ read_name_map (cpp_dir *dir)
   len = dir->len;
   name = (char *) alloca (len + sizeof (FILE_NAME_MAP_FILE) + 1);
   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");
@@ -1307,10 +1626,18 @@ remap_filename (cpp_reader *pfile, _cpp_file *file)
        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]);
-
+      if (IS_ABSOLUTE_PATH (fname))
+       return NULL;
       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;
 
@@ -1449,6 +1776,7 @@ _cpp_save_file_entries (cpp_reader *pfile, FILE *fp)
   struct pchf_data *result;
   size_t result_size;
   _cpp_file *f;
+  bool ret;
 
   for (f = pfile->all_files; f; f = f->next_file)
     ++count;
@@ -1488,6 +1816,7 @@ _cpp_save_file_entries (cpp_reader *pfile, FILE *fp)
          if (!open_file (f))
            {
              open_file_failed (pfile, f, 0);
+             free (result);
              return false;
            }
          ff = fdopen (f->fd, "rb");
@@ -1504,7 +1833,9 @@ _cpp_save_file_entries (cpp_reader *pfile, FILE *fp)
   qsort (result->entries, result->count, sizeof (struct pchf_entry),
         pchf_save_compare);
 
-  return fwrite (result, result_size, 1, fp) == 1;
+  ret = fwrite (result, result_size, 1, fp) == 1;
+  free (result);
+  return ret;
 }
 
 /* Read the pchf_data structure from F.  */