OSDN Git Service

Segher Boessenkool <segher@koffie.nl>
[pf3gnuchains/gcc-fork.git] / gcc / cppfiles.c
index 38780ad..203619f 100644 (file)
@@ -22,11 +22,20 @@ 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
+#include <valgrind.h>
+#else
+/* Avoid #ifdef:s when we can help it.  */
+#define VALGRIND_DISCARD(x)
+#endif
 
 #ifdef HAVE_MMAP_FILE
 # include <sys/mman.h>
@@ -77,9 +86,9 @@ 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;
                                /* location in search path where file was
@@ -91,6 +100,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,11 +122,12 @@ 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 *));
@@ -123,6 +140,11 @@ 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 *));
@@ -168,7 +190,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)
     {
@@ -205,6 +227,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,
@@ -250,7 +273,7 @@ open_file (pfile, filename)
   /* Don't reopen an idempotent file.  */
   if (DO_NOT_REREAD (file))
     return file;
-      
+
   /* Don't reopen one which is already loaded.  */
   if (file->buffer != NULL)
     return file;
@@ -270,7 +293,15 @@ open_file (pfile, filename)
      Special case: the empty string is translated to stdin.  */
 
   if (filename[0] == '\0')
-    file->fd = 0;
+    {
+      file->fd = 0;
+#ifdef __DJGPP__
+      /* For DJGPP redirected input is opened in text mode. Change it
+         to binary mode.  */
+      if (! isatty (file->fd))
+       setmode (file->fd, O_BINARY);
+#endif
+    }
   else
     file->fd = open (file->name, O_RDONLY | O_NOCTTY | O_BINARY, 0666);
 
@@ -291,6 +322,89 @@ 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))
+    {
+      file->header_name = _cpp_simplify_pathname (xstrdup (filename));
+      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, ".pch", 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
@@ -310,9 +424,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)
@@ -342,7 +468,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;
 
@@ -405,8 +531,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
@@ -487,7 +618,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);
@@ -512,7 +650,7 @@ cpp_included (pfile, fname)
       nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) fname);
       return (nd && nd->value);
     }
-      
+
   /* 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)
@@ -549,7 +687,7 @@ find_include_file (pfile, header, type)
   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
@@ -585,7 +723,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;
@@ -631,7 +769,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)
     {
@@ -647,7 +785,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)
@@ -655,40 +793,18 @@ 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);
-
-  if (CPP_OPTION (pfile, print_deps_missing_files) && print_dep)
-    {
-      if (!angle_brackets || IS_ABSOLUTE_PATHNAME (fname))
-       deps_add_dep (pfile->deps, fname);
-      else
-       {
-         /* If requested as a system header, assume it belongs in
-            the first system header directory.  */
-         struct search_path *ptr = CPP_OPTION (pfile, bracket_include);
-         char *p;
-         int len = 0, fname_len = strlen (fname);
-
-         if (ptr)
-           len = ptr->len;
+  bool print_dep
+    = CPP_OPTION (pfile, deps.style) > (angle_brackets || pfile->map->sysp);
 
-         p = (char *) alloca (len + fname_len + 2);
-         if (len)
-           {
-             memcpy (p, ptr->name, len);
-             p[len++] = '/';
-           }
-         memcpy (p + len, fname, fname_len + 1);
-         deps_add_dep (pfile->deps, p);
-       }
-    }
+  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
      correct output, because there may be dependencies we need inside
      the missing file, and we don't know what directory this missing
      file exists in.  */
   else
-    cpp_errno (pfile, CPP_PRINT_DEPS (pfile) && ! print_dep
+    cpp_errno (pfile, CPP_OPTION (pfile, deps.style) && ! print_dep
               ? DL_WARNING: DL_ERROR, fname);
 }
 
@@ -727,7 +843,7 @@ _cpp_compare_file_date (pfile, header)
      const cpp_token *header;
 {
   struct include_file *inc = find_include_file (pfile, header, 0);
-  
+
   if (inc == NULL || inc == NO_INCLUDE_PATH)
     return -1;
 
@@ -736,7 +852,7 @@ _cpp_compare_file_date (pfile, header)
       close (inc->fd);
       inc->fd = -1;
     }
-    
+
   return inc->st.st_mtime > pfile->buffer->inc->st.st_mtime;
 }
 
@@ -749,6 +865,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)
@@ -761,14 +880,12 @@ _cpp_read_file (pfile, fname)
 }
 
 /* Do appropriate cleanup when a file INC's buffer is popped off the
-   input stack.  Push the next -include file, if any remain.  */
-bool
+   input stack.  */
+void
 _cpp_pop_file_buffer (pfile, inc)
      cpp_reader *pfile;
      struct include_file *inc;
 {
-  bool pushed = false;
-
   /* Record the inclusion-preventing macro, which could be NULL
      meaning no controlling macro.  */
   if (pfile->mi_valid && inc->cmacro == NULL)
@@ -780,18 +897,6 @@ _cpp_pop_file_buffer (pfile, inc)
   inc->refcnt--;
   if (inc->refcnt == 0 && DO_NOT_REREAD (inc))
     purge_cache (inc);
-
-  /* Don't generate a callback for popping the main file.  */
-  if (pfile->buffer)
-    {
-      _cpp_do_file_change (pfile, LC_LEAVE, 0, 0, 0);
-
-      /* Finally, push the next -included file, if any.  */
-      if (!pfile->buffer->prev)
-       pushed = _cpp_push_next_buffer (pfile);
-    }
-
-  return pushed;
 }
 
 /* Returns the first place in the include chain to start searching for
@@ -855,8 +960,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;
@@ -876,10 +980,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)
            {
@@ -896,8 +1000,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;
@@ -937,17 +1040,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);
 
@@ -960,12 +1062,9 @@ 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);
-           }         
+           }
 
          ptr->map_next = map_list_ptr->map_list_map;
          map_list_ptr->map_list_map = ptr;
@@ -976,13 +1075,13 @@ read_name_map (pfile, dirname)
        }
       fclose (f);
     }
-  
+
   /* Add this information to the cache.  */
   map_list_ptr->map_list_next = CPP_OPTION (pfile, map_list);
   CPP_OPTION (pfile, map_list) = map_list_ptr;
 
   return map_list_ptr->map_list_map;
-}  
+}
 
 /* Remap an unsimplified path NAME based on the file_name_map (if any)
    for LOC.  */
@@ -1007,10 +1106,10 @@ remap_filename (pfile, name, loc)
       if (! loc->name_map)
        return name;
     }
-  
+
   /* This works since NAME has not been simplified yet.  */
   from = name + loc->len + 1;
-  
+
   for (map = loc->name_map; map; map = map->map_next)
     if (!strcmp (map->map_from, from))
       return map->map_to;
@@ -1031,7 +1130,7 @@ remap_filename (pfile, name, loc)
   memcpy (dir, name, p - name);
   dir[p - name] = '\0';
   from = p + 1;
-  
+
   for (map = read_name_map (pfile, dir); map; map = map->map_next)
     if (! strcmp (map->map_from, from))
       return map->map_to;
@@ -1081,7 +1180,7 @@ remove_component_p (path)
    nonzero if an error occurred when using stat () or lstat ().  */
 char *
 _cpp_simplify_pathname (path)
-    char *path;
+     char *path;
 {
 #ifndef VMS
   char *from, *to;
@@ -1097,7 +1196,7 @@ _cpp_simplify_pathname (path)
   /* Convert all backslashes to slashes.  */
   for (from = path; *from; from++)
     if (*from == '\\') *from = '/';
-    
+
   /* Skip over leading drive letter if present.  */
   if (ISALPHA (path[0]) && path[1] == ':')
     from = to = &path[2];
@@ -1106,7 +1205,7 @@ _cpp_simplify_pathname (path)
 #else
   from = to = path;
 #endif
-    
+
   /* Remove redundant leading /s.  */
   if (*from == '/')
     {
@@ -1181,7 +1280,7 @@ _cpp_simplify_pathname (path)
       if (move_base)
        base = to;
     }
-    
+
   /* Change the empty string to "." so that it is not treated as stdin.
      Null terminate.  */
   if (to == path)