OSDN Git Service

* reload1.c (move2add_last_cc0): New.
[pf3gnuchains/gcc-fork.git] / gcc / cppfiles.c
index 85c9b6e..1ff34ff 100644 (file)
@@ -1,6 +1,6 @@
 /* Part of CPP library.  (include file handling)
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 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
@@ -22,11 +22,24 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include <dirent.h>
+#include "coretypes.h"
+#include "tm.h"
 #include "cpplib.h"
 #include "cpphash.h"
 #include "intl.h"
 #include "mkdeps.h"
 #include "splay-tree.h"
+#ifdef ENABLE_VALGRIND_CHECKING
+# ifdef HAVE_MEMCHECK_H
+# include <memcheck.h>
+# else
+# include <valgrind.h>
+# endif
+#else
+/* Avoid #ifdef:s when we can help it.  */
+#define VALGRIND_DISCARD(x)
+#endif
 
 #ifdef HAVE_MMAP_FILE
 # include <sys/mman.h>
@@ -77,11 +90,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #undef strcmp
 
 /* This structure is used for the table of all includes.  */
-struct include_file
-{
+struct include_file {
   const char *name;            /* actual path name of file */
+  const char *header_name;     /* the original header found */
   const cpp_hashnode *cmacro;  /* macro, if any, preventing reinclusion.  */
-  const struct search_path *foundhere;
+  const struct cpp_path *foundhere;
                                /* location in search path where file was
                                   found, for #include_next and sysp.  */
   const unsigned char *buffer; /* pointer to cached file contents */
@@ -91,6 +104,13 @@ struct include_file
   unsigned short include_count;        /* number of times file has been read */
   unsigned short refcnt;       /* number of stacked buffers using this file */
   unsigned char mapped;                /* file buffer is mmapped */
+  unsigned char pch;           /* 0: file not known to be a PCH.
+                                  1: file is a PCH 
+                                     (on return from find_include_file).
+                                  2: file is not and never will be a valid
+                                     precompiled header.
+                                  3: file is always a valid precompiled
+                                     header.  */
 };
 
 /* Variable length record files on VMS will have a stat size that includes
@@ -106,23 +126,29 @@ struct include_file
    included again.  If it's NEVER_REREAD, the file is never to be
    included again.  Otherwise it is a macro hashnode, and the file is
    to be included again if the macro is defined.  */
-#define NEVER_REREAD ((const cpp_hashnode *)-1)
+#define NEVER_REREAD ((const cpp_hashnode *) -1)
 #define DO_NOT_REREAD(inc) \
 ((inc)->cmacro && ((inc)->cmacro == NEVER_REREAD \
                   || (inc)->cmacro->type == NT_MACRO))
 #define NO_INCLUDE_PATH ((struct include_file *) -1)
+#define INCLUDE_PCH_P(F) (((F)->pch & 1) != 0)
 
 static struct file_name_map *read_name_map
                                PARAMS ((cpp_reader *, const char *));
 static char *read_filename_string PARAMS ((int, FILE *));
 static char *remap_filename    PARAMS ((cpp_reader *, char *,
-                                        struct search_path *));
-static struct search_path *search_from PARAMS ((cpp_reader *,
+                                        struct cpp_path *));
+static struct cpp_path *search_from PARAMS ((cpp_reader *,
                                                enum include_type));
 static struct include_file *
        find_include_file PARAMS ((cpp_reader *, const cpp_token *,
                                   enum include_type));
 static struct include_file *open_file PARAMS ((cpp_reader *, const char *));
+static struct include_file *validate_pch PARAMS ((cpp_reader *,
+                                                 const char *,
+                                                 const char *));
+static struct include_file *open_file_pch PARAMS ((cpp_reader *, 
+                                                  const char *));
 static int read_include_file   PARAMS ((cpp_reader *, struct include_file *));
 static bool stack_include_file PARAMS ((cpp_reader *, struct include_file *));
 static void purge_cache        PARAMS ((struct include_file *));
@@ -131,7 +157,7 @@ static int report_missing_guard             PARAMS ((splay_tree_node, void *));
 static splay_tree_node find_or_create_entry PARAMS ((cpp_reader *,
                                                     const char *));
 static void handle_missing_header PARAMS ((cpp_reader *, const char *, int));
-static int remove_component_p  PARAMS ((const char *));
+static int remove_component_p PARAMS ((const char *));
 
 /* Set up the splay tree we use to store information about all the
    file names seen in this compilation.  We also have entries for each
@@ -139,7 +165,7 @@ static int remove_component_p       PARAMS ((const char *));
    don't try to open it again in future.
 
    The key of each node is the file name, after processing by
-   _cpp_simplify_pathname.  The path name may or may not be absolute.
+   cpp_simplify_path.  The path name may or may not be absolute.
    The path string has been malloced, as is automatically freed by
    registering free () as the splay tree key deletion function.
 
@@ -168,7 +194,7 @@ static void
 destroy_node (v)
      splay_tree_value v;
 {
-  struct include_file *f = (struct include_file *)v;
+  struct include_file *f = (struct include_file *) v;
 
   if (f)
     {
@@ -186,8 +212,7 @@ _cpp_never_reread (file)
 }
 
 /* Lookup a filename, which is simplified after making a copy, and
-   create an entry if none exists.  errno is nonzero iff a (reported)
-   stat() error occurred during simplification.  */
+   create an entry if none exists.  */
 static splay_tree_node
 find_or_create_entry (pfile, fname)
      cpp_reader *pfile;
@@ -197,7 +222,7 @@ find_or_create_entry (pfile, fname)
   struct include_file *file;
   char *name = xstrdup (fname);
 
-  _cpp_simplify_pathname (name);
+  cpp_simplify_path (name);
   node = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name);
   if (node)
     free (name);
@@ -205,6 +230,7 @@ find_or_create_entry (pfile, fname)
     {
       file = xcnew (struct include_file);
       file->name = name;
+      file->header_name = name;
       file->err_no = errno;
       node = splay_tree_insert (pfile->all_include_files,
                                (splay_tree_key) file->name,
@@ -299,6 +325,91 @@ open_file (pfile, filename)
   return 0;
 }
 
+static struct include_file *
+validate_pch (pfile, filename, pchname)
+     cpp_reader *pfile;
+     const char *filename;
+     const char *pchname;
+{
+  struct include_file * file;
+  
+  file = open_file (pfile, pchname);
+  if (file == NULL)
+    return NULL;
+  if ((file->pch & 2) == 0)
+    file->pch = pfile->cb.valid_pch (pfile, pchname, file->fd);
+  if (INCLUDE_PCH_P (file))
+    {
+      char *f = xstrdup (filename);
+      cpp_simplify_path (f);
+      file->header_name = f;
+      return file;
+    }
+  close (file->fd);
+  file->fd = -1;
+  return NULL;
+}
+
+
+/* Like open_file, but also look for a precompiled header if (a) one exists
+   and (b) it is valid.  */
+static struct include_file *
+open_file_pch (pfile, filename)
+     cpp_reader *pfile;
+     const char *filename;
+{
+  if (filename[0] != '\0'
+      && pfile->cb.valid_pch != NULL)
+    {
+      size_t namelen = strlen (filename);
+      char *pchname = alloca (namelen + 5);
+      struct include_file * file;
+      splay_tree_node nd;
+      
+      memcpy (pchname, filename, namelen);
+      memcpy (pchname + namelen, ".gch", 5);
+
+      nd = find_or_create_entry (pfile, pchname);
+      file = (struct include_file *) nd->value;
+
+      if (file != NULL)
+       {
+         if (stat (file->name, &file->st) == 0 && S_ISDIR (file->st.st_mode))
+           {
+             DIR * thedir;
+             struct dirent *d;
+             size_t subname_len = namelen + 64;
+             char *subname = xmalloc (subname_len);
+             
+             thedir = opendir (pchname);
+             if (thedir == NULL)
+               return NULL;
+             memcpy (subname, pchname, namelen + 4);
+             subname[namelen+4] = '/';
+             while ((d = readdir (thedir)) != NULL)
+               {
+                 if (strlen (d->d_name) + namelen + 7 > subname_len)
+                   {
+                     subname_len = strlen (d->d_name) + namelen + 64;
+                     subname = xrealloc (subname, subname_len);
+                   }
+                 strcpy (subname + namelen + 5, d->d_name);
+                 file = validate_pch (pfile, filename, subname);
+                 if (file)
+                   break;
+               }
+             closedir (thedir);
+             free (subname);
+           }
+         else
+           file = validate_pch (pfile, filename, pchname);
+         if (file)
+           return file;
+       }
+    }
+  return open_file (pfile, filename);
+}
+
 /* Place the file referenced by INC into a new buffer on the buffer
    stack, unless there are errors, or the file is not re-included
    because of e.g. multiple-include guards.  Returns true if a buffer
@@ -318,9 +429,21 @@ stack_include_file (pfile, inc)
   sysp = MAX ((pfile->map ? pfile->map->sysp : 0),
              (inc->foundhere ? inc->foundhere->sysp : 0));
 
-  /* For -M, add the file to the dependencies on its first inclusion.  */
-  if (CPP_OPTION (pfile, print_deps) > sysp && !inc->include_count)
-    deps_add_dep (pfile->deps, inc->name);
+  /* Add the file to the dependencies on its first inclusion.  */
+  if (CPP_OPTION (pfile, deps.style) > !!sysp && !inc->include_count)
+    {
+      if (pfile->buffer || CPP_OPTION (pfile, deps.ignore_main_file) == 0)
+       deps_add_dep (pfile->deps, inc->name);
+    }
+
+  /* PCH files get dealt with immediately.  */
+  if (INCLUDE_PCH_P (inc))
+    {
+      pfile->cb.read_pch (pfile, inc->name, inc->fd, inc->header_name);
+      close (inc->fd);
+      inc->fd = -1;
+      return false;
+    }
 
   /* Not in cache?  */
   if (! inc->buffer)
@@ -350,7 +473,7 @@ stack_include_file (pfile, inc)
   fp->inc = inc;
   fp->inc->refcnt++;
 
-  /* Initialise controlling macro state.  */
+  /* Initialize controlling macro state.  */
   pfile->mi_valid = true;
   pfile->mi_cmacro = 0;
 
@@ -413,8 +536,13 @@ read_include_file (pfile, inc)
       if (SHOULD_MMAP (size, pagesize))
        {
          buf = (uchar *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0);
-         if (buf == (uchar *)-1)
+         if (buf == (uchar *) -1)
            goto perror_fail;
+
+         /* We must tell Valgrind that the byte at buf[size] is actually
+            readable.  Discard the handle to avoid handle leak.  */
+         VALGRIND_DISCARD (VALGRIND_MAKE_READABLE (buf + size, 1));
+
          inc->mapped = 1;
        }
       else
@@ -495,7 +623,14 @@ purge_cache (inc)
     {
 #if MMAP_THRESHOLD
       if (inc->mapped)
-       munmap ((PTR) inc->buffer, inc->st.st_size);
+       {
+         /* Undo the previous annotation for the
+            known-zero-byte-after-mmap.  Discard the handle to avoid
+            handle leak.  */
+         VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (inc->buffer
+                                                   + inc->st.st_size, 1));
+         munmap ((PTR) inc->buffer, inc->st.st_size);
+       }
       else
 #endif
        free ((PTR) inc->buffer);
@@ -510,7 +645,7 @@ cpp_included (pfile, fname)
      cpp_reader *pfile;
      const char *fname;
 {
-  struct search_path *path;
+  struct cpp_path *path;
   char *name, *n;
   splay_tree_node nd;
 
@@ -523,7 +658,7 @@ cpp_included (pfile, fname)
 
   /* Search directory path for the file.  */
   name = (char *) alloca (strlen (fname) + pfile->max_include_len + 2);
-  for (path = CPP_OPTION (pfile, quote_include); path; path = path->next)
+  for (path = pfile->quote_include; path; path = path->next)
     {
       memcpy (name, path->name, path->len);
       name[path->len] = '/';
@@ -552,12 +687,12 @@ find_include_file (pfile, header, type)
      enum include_type type;
 {
   const char *fname = (const char *) header->val.str.text;
-  struct search_path *path;
+  struct cpp_path *path;
   struct include_file *file;
   char *name, *n;
 
   if (IS_ABSOLUTE_PATHNAME (fname))
-    return open_file (pfile, fname);
+    return open_file_pch (pfile, fname);
 
   /* 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
@@ -565,7 +700,7 @@ find_include_file (pfile, header, type)
   if (type == IT_INCLUDE_NEXT && pfile->buffer->inc->foundhere)
     path = pfile->buffer->inc->foundhere->next;
   else if (header->type == CPP_HEADER_NAME)
-    path = CPP_OPTION (pfile, bracket_include);
+    path = pfile->bracket_include;
   else
     path = search_from (pfile, type);
 
@@ -593,7 +728,7 @@ find_include_file (pfile, header, type)
       else
        n = name;
 
-      file = open_file (pfile, n);
+      file = open_file_pch (pfile, n);
       if (file)
        {
          file->foundhere = path;
@@ -621,6 +756,18 @@ cpp_make_system_header (pfile, syshdr, externc)
                       SOURCE_LINE (pfile->map, pfile->line), flags);
 }
 
+/* Allow the client to change the current file.  Used by the front end
+   to achieve pseudo-file names like <built-in>.
+   If REASON is LC_LEAVE, then NEW_NAME must be NULL.  */
+void
+cpp_change_file (pfile, reason, new_name)
+     cpp_reader *pfile;
+     enum lc_reason reason;
+     const char *new_name;
+{
+  _cpp_do_file_change (pfile, reason, new_name, 1, 0);
+}
+
 /* Report on all files that might benefit from a multiple include guard.
    Triggered by -H.  */
 void
@@ -639,7 +786,7 @@ report_missing_guard (n, b)
      void *b;
 {
   struct include_file *f = (struct include_file *) n->value;
-  int *bannerp = (int *)b;
+  int *bannerp = (int *) b;
 
   if (f && f->cmacro == 0 && f->include_count == 1)
     {
@@ -655,7 +802,7 @@ report_missing_guard (n, b)
 }
 
 /* Create a dependency for file FNAME, or issue an error message as
-   appropriate.  ANGLE_BRACKETS is non-zero if the file was bracketed
+   appropriate.  ANGLE_BRACKETS is nonzero if the file was bracketed
    like <..>.  */
 static void
 handle_missing_header (pfile, fname, angle_brackets)
@@ -663,9 +810,10 @@ handle_missing_header (pfile, fname, angle_brackets)
      const char *fname;
      int angle_brackets;
 {
-  int print_dep = CPP_PRINT_DEPS(pfile) > (angle_brackets || pfile->map->sysp);
+  bool print_dep
+    = CPP_OPTION (pfile, deps.style) > (angle_brackets || pfile->map->sysp);
 
-  if (CPP_OPTION (pfile, print_deps_missing_files) && print_dep)
+  if (CPP_OPTION (pfile, deps.missing_files) && print_dep)
     deps_add_dep (pfile->deps, fname);
   /* If -M was specified, then don't count this as an error, because
      we can still produce correct output.  Otherwise, we can't produce
@@ -673,7 +821,7 @@ handle_missing_header (pfile, fname, angle_brackets)
      the missing file, and we don't know what directory this missing
      file exists in.  */
   else
-    cpp_errno (pfile, CPP_PRINT_DEPS (pfile) && ! print_dep
+    cpp_errno (pfile, CPP_OPTION (pfile, deps.style) && ! print_dep
               ? DL_WARNING: DL_ERROR, fname);
 }
 
@@ -734,6 +882,9 @@ _cpp_read_file (pfile, fname)
      cpp_reader *pfile;
      const char *fname;
 {
+  /* This uses open_file, because we don't allow a PCH to be used as
+     the toplevel compilation (that would prevent re-compiling an
+     existing PCH without deleting it first).  */
   struct include_file *f = open_file (pfile, fname);
 
   if (f == NULL)
@@ -745,6 +896,24 @@ _cpp_read_file (pfile, fname)
   return stack_include_file (pfile, f);
 }
 
+/* Pushes the given file onto the buffer stack.  Returns nonzero if
+   successful.  */
+bool
+cpp_push_include (pfile, filename)
+     cpp_reader *pfile;
+     const char *filename;
+{
+  cpp_token header;
+
+  header.type = CPP_STRING;
+  header.val.str.text = (const unsigned char *) filename;
+  header.val.str.len = strlen (filename);
+  /* Make the command line directive take up a line.  */
+  pfile->line++;
+
+  return _cpp_execute_include (pfile, &header, IT_CMDLINE);
+}
+
 /* Do appropriate cleanup when a file INC's buffer is popped off the
    input stack.  */
 void
@@ -771,7 +940,7 @@ _cpp_pop_file_buffer (pfile, inc)
 
    If we're handling -include or -imacros, use the "" chain, but with
    the preprocessor's cwd prepended.  */
-static struct search_path *
+static struct cpp_path *
 search_from (pfile, type)
      cpp_reader *pfile;
      enum include_type type;
@@ -783,9 +952,9 @@ search_from (pfile, type)
   if (type == IT_CMDLINE)
     goto use_cwd;
 
-  /* Ignore the current file's directory if -I- was given.  */
-  if (CPP_OPTION (pfile, ignore_srcdir))
-    return CPP_OPTION (pfile, quote_include);
+  /* Ignore the current file's directory?  */
+  if (pfile->quote_ignores_source_dir)
+    return pfile->quote_include;
 
   if (! buffer->search_cached)
     {
@@ -797,14 +966,14 @@ search_from (pfile, type)
        {
          /* We don't guarantee NAME is null-terminated.  This saves
             allocating and freeing memory.  Drop a trailing '/'.  */
-         buffer->dir.name = buffer->inc->name;
+         buffer->dir.name = (char *) buffer->inc->name;
          if (dlen > 1)
            dlen--;
        }
       else
        {
        use_cwd:
-         buffer->dir.name = ".";
+         buffer->dir.name = (char *) ".";
          dlen = 1;
        }
 
@@ -812,7 +981,7 @@ search_from (pfile, type)
        pfile->max_include_len = dlen;
 
       buffer->dir.len = dlen;
-      buffer->dir.next = CPP_OPTION (pfile, quote_include);
+      buffer->dir.next = pfile->quote_include;
       buffer->dir.sysp = pfile->map->sysp;
     }
 
@@ -826,8 +995,7 @@ search_from (pfile, type)
    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 {
   struct file_name_map *map_next;
   char *map_from;
   char *map_to;
@@ -847,10 +1015,10 @@ read_filename_string (ch, f)
 
   len = 20;
   set = alloc = xmalloc (len + 1);
-  if (! is_space(ch))
+  if (! is_space (ch))
     {
       *set++ = ch;
-      while ((ch = getc (f)) != EOF && ! is_space(ch))
+      while ((ch = getc (f)) != EOF && ! is_space (ch))
        {
          if (set - alloc == len)
            {
@@ -867,8 +1035,7 @@ read_filename_string (ch, f)
 }
 
 /* This structure holds a linked list of file name maps, one per directory.  */
-struct file_name_map_list
-{
+struct file_name_map_list {
   struct file_name_map_list *map_list_next;
   char *map_list_name;
   struct file_name_map *map_list_map;
@@ -908,17 +1075,16 @@ read_name_map (pfile, dirname)
   if (f)
     {
       int ch;
-      int dirlen = strlen (dirname);
 
       while ((ch = getc (f)) != EOF)
        {
          char *from, *to;
          struct file_name_map *ptr;
 
-         if (is_space(ch))
+         if (is_space (ch))
            continue;
          from = read_filename_string (ch, f);
-         while ((ch = getc (f)) != EOF && is_hspace(ch))
+         while ((ch = getc (f)) != EOF && is_hspace (ch))
            ;
          to = read_filename_string (ch, f);
 
@@ -931,10 +1097,7 @@ read_name_map (pfile, dirname)
            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);
+             ptr->map_to = concat (dirname, "/", to, NULL);
              free (to);
            }
 
@@ -961,7 +1124,7 @@ static char *
 remap_filename (pfile, name, loc)
      cpp_reader *pfile;
      char *name;
-     struct search_path *loc;
+     struct cpp_path *loc;
 {
   struct file_name_map *map;
   const char *from, *p;
@@ -1010,6 +1173,33 @@ remap_filename (pfile, name, loc)
   return name;
 }
 
+/* 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.
+
+   If BRACKET does not lie in the QUOTE chain, it is set to QUOTE.  */
+void
+cpp_set_include_chains (pfile, quote, bracket, quote_ignores_source_dir)
+     cpp_reader *pfile;
+     cpp_path *quote, *bracket;
+     int quote_ignores_source_dir;
+{
+  pfile->quote_include = quote;
+  pfile->bracket_include = quote;
+  pfile->quote_ignores_source_dir = quote_ignores_source_dir;
+  pfile->max_include_len = 0;
+
+  for (; quote; quote = quote->next)
+    {
+      quote->name_map = NULL;
+      quote->len = strlen (quote->name);
+      if (quote->len > pfile->max_include_len)
+       pfile->max_include_len = quote->len;
+      if (quote == bracket)
+       pfile->bracket_include = bracket;
+    }
+}
+
 /* Returns true if it is safe to remove the final component of path,
    when it is followed by a ".." component.  We use lstat to avoid
    symlinks if we have it.  If not, we can still catch errors with
@@ -1050,9 +1240,9 @@ remove_component_p (path)
    Guarantees no trailing slashes.  All transforms reduce the length
    of the string.  Returns PATH.  errno is 0 if no error occurred;
    nonzero if an error occurred when using stat () or lstat ().  */
-char *
-_cpp_simplify_pathname (path)
-     char *path;
+void
+cpp_simplify_path (path)
+     char *path ATTRIBUTE_UNUSED;
 {
 #ifndef VMS
   char *from, *to;
@@ -1062,7 +1252,7 @@ _cpp_simplify_pathname (path)
   errno = 0;
   /* Don't overflow the empty path by putting a '.' in it below.  */
   if (*path == '\0')
-    return path;
+    return;
 
 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
   /* Convert all backslashes to slashes.  */
@@ -1158,10 +1348,7 @@ _cpp_simplify_pathname (path)
   if (to == path)
     *to++ = '.';
   *to = '\0';
-
-  return path;
-#else /* VMS  */
+#else  /* VMS */
   errno = 0;
-  return path;
 #endif /* !VMS  */
 }