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
{
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. */
errno = ENOENT;
+ close (file->fd);
+ file->fd = -1;
}
file->err_no = errno;
/* Not in cache? */
if (! inc->buffer)
{
- /* Mark a regular, zero-length file never-reread. Zero-length
- files are stacked the first time, 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);
- else if (read_include_file (pfile, inc))
+ 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 (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)
else
#endif
{
- buf = (U_CHAR *) xmalloc (size);
+ buf = (U_CHAR *) xmalloc (size + 1);
offset = 0;
while (offset < size)
{
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))
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;
}
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;
}
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
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;
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));
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;