OSDN Git Service

* lib/prune.exp (prune_gcc_output): Also handle "In member
[pf3gnuchains/gcc-fork.git] / gcc / cppfiles.c
index e242e92..33801d6 100644 (file)
@@ -67,11 +67,21 @@ struct include_file
   const unsigned char *buffer; /* pointer to cached file contents */
   struct stat st;              /* copy of stat(2) data for file */
   int fd;                      /* fd open on file (short term storage only) */
+  int err_no;                  /* errno obtained if opening a file failed */
   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 */
 };
 
+/* Variable length record files on VMS will have a stat size that includes
+   record control characters that won't be included in the read size. */
+#ifdef VMS
+# define FAB_C_VAR 2 /* variable length records (see Starlet fabdef.h) */
+# define STAT_SIZE_TOO_BIG(ST) ((ST).st_fab_rfm == FAB_C_VAR)
+#else
+# define STAT_SIZE_TOO_BIG(ST) 0
+#endif
+
 /* The cmacro works like this: If it's NULL, the file is to be
    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
@@ -94,7 +104,7 @@ static struct include_file *
                                   enum include_type));
 static struct include_file *open_file PARAMS ((cpp_reader *, const char *));
 static int read_include_file   PARAMS ((cpp_reader *, struct include_file *));
-static void stack_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 *));
 static void destroy_node       PARAMS ((splay_tree_value));
 static int report_missing_guard                PARAMS ((splay_tree_node, void *));
@@ -175,6 +185,7 @@ find_or_create_entry (pfile, fname)
     {
       file = xcnew (struct include_file);
       file->name = name;
+      file->err_no = errno;
       node = splay_tree_insert (pfile->all_include_files,
                                (splay_tree_key) file->name,
                                (splay_tree_value) file);
@@ -210,18 +221,18 @@ open_file (pfile, filename)
   splay_tree_node nd = find_or_create_entry (pfile, filename);
   struct include_file *file = (struct include_file *) nd->value;
 
-  if (errno)
-    file->fd = -2;
-
-  /* Don't retry opening if we failed previously.  */
-  if (file->fd == -2)
-    return 0;
+  if (file->err_no)
+    {
+      /* Ugh.  handle_missing_header () needs errno to be set.  */
+      errno = file->err_no;
+      return 0;
+    }
 
-  /* Don't reopen an idempotent file. */
+  /* Don't reopen an idempotent file.  */
   if (DO_NOT_REREAD (file))
     return file;
       
-  /* Don't reopen one which is already loaded. */
+  /* Don't reopen one which is already loaded.  */
   if (file->buffer != NULL)
     return file;
 
@@ -246,100 +257,84 @@ open_file (pfile, filename)
 
   if (file->fd != -1 && fstat (file->fd, &file->st) == 0)
     {
+      if (!S_ISDIR (file->st.st_mode))
+       return file;
+
       /* If it's a directory, we return null and continue the search
         as the file we're looking for may appear elsewhere in the
         search path.  */
-      if (S_ISDIR (file->st.st_mode))
-       errno = ENOENT;
-      else
-       {
-         /* Mark a regular, zero-length file never-reread now.  */
-         if (S_ISREG (file->st.st_mode) && file->st.st_size == 0)
-           {
-             _cpp_never_reread (file);
-             close (file->fd);
-             file->fd = -1;
-           }
-
-         return file;
-       }
+      errno = ENOENT;
+      close (file->fd);
+      file->fd = -1;
     }
 
-  /* Don't issue an error message if the file doesn't exist.  */
-  if (errno != ENOENT && errno != ENOTDIR)
-    cpp_error_from_errno (pfile, file->name);
-
-  /* Create a negative node for this path, and return null.  */
-  file->fd = -2;
-
+  file->err_no = errno;
   return 0;
 }
 
-/* Place the file referenced by INC into a new buffer on PFILE's
-   stack.  If there are errors, or the file should not be re-included,
-   a null (zero-length) buffer is pushed.  */
+/* 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
+   is stacked.  */
 
-static void
+static bool
 stack_include_file (pfile, inc)
      cpp_reader *pfile;
      struct include_file *inc;
 {
-  size_t len = 0;
   cpp_buffer *fp;
-  int sysp, deps_sysp;
+  int sysp;
+  const char *filename;
+
+  if (DO_NOT_REREAD (inc))
+    return false;
 
-  /* We'll try removing deps_sysp after the release of 3.0.  */
-  deps_sysp = pfile->system_include_depth != 0;
-  sysp = MAX ((pfile->buffer ? pfile->buffer->sysp : 0),
+  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) > deps_sysp && !inc->include_count)
+  if (CPP_OPTION (pfile, print_deps) > sysp && !inc->include_count)
     deps_add_dep (pfile->deps, inc->name);
 
   /* Not in cache?  */
-  if (! DO_NOT_REREAD (inc) && ! inc->buffer)
+  if (! inc->buffer)
     {
-      /* If an error occurs, do not try to read this file again.  */
       if (read_include_file (pfile, inc))
+       {
+         /* If an error occurs, do not try to read this file again.  */
+         _cpp_never_reread (inc);
+         return false;
+       }
+      /* Mark a regular, zero-length file never-reread.  We read it,
+        NUL-terminate it, and stack it once, so preprocessing a main
+        file of zero length does not raise an error.  */
+      if (S_ISREG (inc->st.st_mode) && inc->st.st_size == 0)
        _cpp_never_reread (inc);
       close (inc->fd);
       inc->fd = -1;
     }
 
-  if (! DO_NOT_REREAD (inc))
-    {
-      len = inc->st.st_size;
-      if (pfile->buffer)
-       {
-         /* We don't want MI guard advice for the main file.  */
-         inc->include_count++;
-
-         /* Handle -H option.  */
-         if (CPP_OPTION (pfile, print_include_names))
-           {
-             for (fp = pfile->buffer; fp; fp = fp->prev)
-               putc ('.', stderr);
-             fprintf (stderr, " %s\n", inc->name);
-           }
-       }
-    }
+  if (pfile->buffer)
+    /* We don't want MI guard advice for the main file.  */
+    inc->include_count++;
 
   /* Push a buffer.  */
-  fp = cpp_push_buffer (pfile, inc->buffer, len, BUF_FILE, inc->name);
+  fp = cpp_push_buffer (pfile, inc->buffer, inc->st.st_size,
+                       /* from_stage3 */ CPP_OPTION (pfile, preprocessed), 0);
   fp->inc = inc;
   fp->inc->refcnt++;
-  fp->sysp = sysp;
 
   /* Initialise controlling macro state.  */
-  pfile->mi_state = MI_OUTSIDE;
+  pfile->mi_valid = true;
   pfile->mi_cmacro = 0;
-  pfile->include_depth++;
 
   /* Generate the call back.  */
-  fp->lineno = 0;
-  _cpp_do_file_change (pfile, FC_ENTER, 0, 0);
-  fp->lineno = 1;
+  filename = inc->name;
+  if (*filename == '\0')
+    filename = _("<stdin>");
+  _cpp_do_file_change (pfile, LC_ENTER, filename, 1, sysp);
+
+  return true;
 }
 
 /* Read the file referenced by INC into the file cache.
@@ -390,7 +385,13 @@ read_include_file (pfile, inc)
       if (pagesize == -1)
        pagesize = getpagesize ();
 
-      if (size / pagesize >= MMAP_THRESHOLD)
+      /* Use mmap if the file is big enough to be worth it (controlled
+        by MMAP_THRESHOLD) and if we can safely count on there being
+        at least one readable NUL byte after the end of the file's
+        contents.  This is true for all tested operating systems when
+        the file size is not an exact multiple of the page size.  */
+      if (size / pagesize >= MMAP_THRESHOLD
+         && (size % pagesize) != 0)
        {
          buf = (U_CHAR *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0);
          if (buf == (U_CHAR *)-1)
@@ -400,7 +401,7 @@ read_include_file (pfile, inc)
       else
 #endif
        {
-         buf = (U_CHAR *) xmalloc (size);
+         buf = (U_CHAR *) xmalloc (size + 1);
          offset = 0;
          while (offset < size)
            {
@@ -409,11 +410,17 @@ read_include_file (pfile, inc)
                goto perror_fail;
              if (count == 0)
                {
-                 cpp_warning (pfile, "%s is shorter than expected", inc->name);
+                 if (!STAT_SIZE_TOO_BIG (inc->st))
+                   cpp_warning
+                     (pfile, "%s is shorter than expected", inc->name);
+                 buf = xrealloc (buf, offset);
+                 inc->st.st_size = offset;
                  break;
                }
              offset += count;
            }
+         /* The lexer requires that the buffer be NUL-terminated.  */
+         buf[size] = '\0';
        }
     }
   else if (S_ISBLK (inc->st.st_mode))
@@ -428,19 +435,25 @@ read_include_file (pfile, inc)
         bigger than the majority of C source files.  */
       size = 8 * 1024;
 
-      buf = (U_CHAR *) xmalloc (size);
+      buf = (U_CHAR *) xmalloc (size + 1);
       offset = 0;
       while ((count = read (inc->fd, buf + offset, size - offset)) > 0)
        {
          offset += count;
          if (offset == size)
-           buf = xrealloc (buf, (size *= 2));
+           {
+             size *= 2;
+             buf = xrealloc (buf, size + 1);
+           }
        }
       if (count < 0)
        goto perror_fail;
 
-      if (offset < size)
-       buf = xrealloc (buf, offset);
+      if (offset + 1 < size)
+       buf = xrealloc (buf, offset + 1);
+
+      /* The lexer requires that the buffer be NUL-terminated.  */
+      buf[offset] = '\0';
       inc->st.st_size = offset;
     }
 
@@ -538,7 +551,7 @@ find_include_file (pfile, header, type)
 
   if (path == NULL)
     {
-      cpp_error (pfile, "No include path in which to find %s", fname);
+      cpp_error (pfile, "no include path in which to find %s", fname);
       return NO_INCLUDE_PATH;
     }
 
@@ -546,9 +559,14 @@ find_include_file (pfile, header, type)
   name = (char *) alloca (strlen (fname) + pfile->max_include_len + 2);
   for (; path; path = path->next)
     {
-      memcpy (name, path->name, path->len);
-      name[path->len] = '/';
-      strcpy (&name[path->len + 1], fname);
+      int len = path->len;
+      memcpy (name, path->name, len);
+      /* Don't turn / into // or // into ///; // may be a namespace
+        escape.  */
+      if (name[len-1] == '/')
+       len--;
+      name[len] = '/';
+      strcpy (&name[len + 1], fname);
       if (CPP_OPTION (pfile, remap))
        n = remap_filename (pfile, name, path);
       else
@@ -578,9 +596,8 @@ cpp_make_system_header (pfile, syshdr, externc)
   /* 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, FC_RENAME, pfile->buffer->nominal_fname,
-                      pfile->buffer->lineno);
+  _cpp_do_file_change (pfile, LC_RENAME, pfile->map->to_file,
+                      SOURCE_LINE (pfile->map, pfile->line), flags);
 }
 
 /* Report on all files that might benefit from a multiple include guard.
@@ -615,16 +632,14 @@ report_missing_guard (n, b)
   return 0;
 }
 
-/* Create a dependency, or issue an error message as appropriate.   */
+/* Create a dependency, or issue an error message as appropriate.  */
 static void
 handle_missing_header (pfile, fname, angle_brackets)
      cpp_reader *pfile;
      const char *fname;
      int angle_brackets;
 {
-  /* We will try making the RHS pfile->buffer->sysp after 3.0.  */
-  int print_dep = CPP_PRINT_DEPS(pfile) > (angle_brackets
-                                          || pfile->system_include_depth);
+  int print_dep = CPP_PRINT_DEPS(pfile) > (angle_brackets || pfile->map->sysp);
 
   if (CPP_OPTION (pfile, print_deps_missing_files) && print_dep)
     {
@@ -655,7 +670,7 @@ handle_missing_header (pfile, fname, angle_brackets)
      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.  FIXME: Use a future cpp_diagnotic_with_errno ()
+     file exists in.  FIXME: Use a future cpp_diagnostic_with_errno ()
      for both of these cases.  */
   else if (CPP_PRINT_DEPS (pfile) && ! print_dep)
     cpp_warning (pfile, "%s: %s", fname, xstrerror (errno));
@@ -663,13 +678,15 @@ handle_missing_header (pfile, fname, angle_brackets)
     cpp_error_from_errno (pfile, fname);
 }
 
-/* Returns non-zero if a buffer was stacked.  */
-int
+/* Handles #include-family directives, and the command line -imacros
+   and -include.  Returns true if a buffer was stacked.  */
+bool
 _cpp_execute_include (pfile, header, type)
      cpp_reader *pfile;
      const cpp_token *header;
      enum include_type type;
 {
+  bool stacked = false;
   struct include_file *inc = find_include_file (pfile, header, type);
 
   if (inc == 0)
@@ -677,18 +694,13 @@ _cpp_execute_include (pfile, header, type)
                           header->type == CPP_HEADER_NAME);
   else if (inc != NO_INCLUDE_PATH)
     {
-      if (header->type == CPP_HEADER_NAME)
-       pfile->system_include_depth++;
-
-      stack_include_file (pfile, inc);
+      stacked = stack_include_file (pfile, inc);
 
       if (type == IT_IMPORT)
        _cpp_never_reread (inc);
-
-      return 1;
     }
 
-  return 0;
+  return stacked;
 }
 
 /* Locate HEADER, and determine whether it is newer than the current
@@ -714,9 +726,10 @@ _cpp_compare_file_date (pfile, header)
 }
 
 
-/* Push an input buffer and load it up with the contents of FNAME.
-   If FNAME is "", read standard input.  */
-int
+/* Push an input buffer and load it up with the contents of FNAME.  If
+   FNAME is "", read standard input.  Return true if a buffer was
+   stacked.  */
+bool
 _cpp_read_file (pfile, fname)
      cpp_reader *pfile;
      const char *fname;
@@ -726,38 +739,40 @@ _cpp_read_file (pfile, fname)
   if (f == NULL)
     {
       cpp_error_from_errno (pfile, fname);
-      return 0;
+      return false;
     }
 
-  stack_include_file (pfile, f);
-  return 1;
+  return stack_include_file (pfile, f);
 }
 
 /* Do appropriate cleanup when a file buffer is popped off the input
-   stack.  */
+   stack.  Push the next -include file, if any remain.  */
 void
-_cpp_pop_file_buffer (pfile, buf)
+_cpp_pop_file_buffer (pfile, inc)
      cpp_reader *pfile;
-     cpp_buffer *buf;
+     struct include_file *inc;
 {
-  struct include_file *inc = buf->inc;
-
-  if (pfile->system_include_depth)
-    pfile->system_include_depth--;
-  if (pfile->include_depth)
-    pfile->include_depth--;
-
   /* Record the inclusion-preventing macro, which could be NULL
-     meaning no controlling macro, if we haven't got it already.  */
-  if (pfile->mi_state == MI_OUTSIDE && inc->cmacro == NULL)
+     meaning no controlling macro.  */
+  if (pfile->mi_valid && inc->cmacro == NULL)
     inc->cmacro = pfile->mi_cmacro;
 
   /* Invalidate control macros in the #including file.  */
-  pfile->mi_state = MI_FAILED;
+  pfile->mi_valid = false;
 
   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)
+       _cpp_push_next_buffer (pfile);
+    }
 }
 
 /* Returns the first place in the include chain to start searching for
@@ -791,8 +806,7 @@ search_from (pfile, type)
       if (dlen)
        {
          /* We don't guarantee NAME is null-terminated.  This saves
-            allocating and freeing memory, and duplicating it when faking
-            buffers in cpp_push_buffer.  Drop a trailing '/'.  */
+            allocating and freeing memory.  Drop a trailing '/'.  */
          buffer->dir.name = buffer->inc->name;
          if (dlen > 1)
            dlen--;
@@ -809,7 +823,7 @@ search_from (pfile, type)
 
       buffer->dir.len = dlen;
       buffer->dir.next = CPP_OPTION (pfile, quote_include);
-      buffer->dir.sysp = buffer->sysp;
+      buffer->dir.sysp = pfile->map->sysp;
     }
 
   return &buffer->dir;
@@ -880,7 +894,7 @@ read_name_map (pfile, dirname)
      cpp_reader *pfile;
      const char *dirname;
 {
-  register struct file_name_map_list *map_list_ptr;
+  struct file_name_map_list *map_list_ptr;
   char *name;
   FILE *f;
 
@@ -1027,6 +1041,12 @@ remove_component_p (path)
   result = stat (path, &s);
 #endif
 
+  /* There's no guarantee that errno will be unchanged, even on
+     success.  Cygwin's lstat(), for example, will often set errno to
+     ENOSYS.  In case of success, reset errno to zero.  */
+  if (result == 0)
+    errno = 0;
+
   return result == 0 && S_ISDIR (s.st_mode);
 }
 
@@ -1060,11 +1080,11 @@ _cpp_simplify_pathname (path)
     return path;
 
 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
-  /* Convert all backslashes to slashes. */
+  /* Convert all backslashes to slashes.  */
   for (from = path; *from; from++)
     if (*from == '\\') *from = '/';
     
-  /* Skip over leading drive letter if present. */
+  /* Skip over leading drive letter if present.  */
   if (ISALPHA (path[0]) && path[1] == ':')
     from = to = &path[2];
   else