/* Part of CPP library. (include file handling)
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 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
# ifndef MMAP_THRESHOLD
# define MMAP_THRESHOLD 3 /* Minimum page count to mmap the file. */
# endif
+# if MMAP_THRESHOLD
+# define TEST_THRESHOLD(size, pagesize) \
+ (size / pagesize >= MMAP_THRESHOLD && (size % pagesize) != 0)
+ /* 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. */
+# ifndef __CYGWIN__
+# define SHOULD_MMAP(size, pagesize) TEST_THRESHOLD (size, pagesize)
+# else
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+ /* Cygwin can't correctly emulate mmap under Windows 9x style systems so
+ disallow use of mmap on those systems. Windows 9x does not zero fill
+ memory at EOF and beyond, as required. */
+# define SHOULD_MMAP(size, pagesize) ((GetVersion() & 0x80000000) \
+ ? 0 : TEST_THRESHOLD (size, pagesize))
+# endif
+# endif
#else /* No MMAP_FILE */
# undef MMAP_THRESHOLD
};
/* 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. */
+ 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)
Returns an include_file structure with an open file descriptor on
success, or NULL on failure. */
-
static struct include_file *
open_file (pfile, filename)
cpp_reader *pfile;
{
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;
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 bool
stack_include_file (pfile, inc)
cpp_reader *pfile;
/* 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;
}
/* Generate the call back. */
filename = inc->name;
if (*filename == '\0')
- filename = _("<stdin>");
+ filename = "<stdin>";
_cpp_do_file_change (pfile, LC_ENTER, filename, 1, sysp);
return true;
and block devices.
FIXME: Flush file cache and try again if we run out of memory. */
-
static int
read_include_file (pfile, inc)
cpp_reader *pfile;
struct include_file *inc;
{
ssize_t size, offset, count;
- U_CHAR *buf;
+ uchar *buf;
#if MMAP_THRESHOLD
static int pagesize = -1;
#endif
does not bite us. */
if (inc->st.st_size > INTTYPE_MAXIMUM (ssize_t))
{
- cpp_error (pfile, "%s is too large", inc->name);
+ cpp_error (pfile, DL_ERROR, "%s is too large", inc->name);
goto fail;
}
size = inc->st.st_size;
if (pagesize == -1)
pagesize = getpagesize ();
- if (size / pagesize >= MMAP_THRESHOLD)
+ if (SHOULD_MMAP (size, pagesize))
{
- buf = (U_CHAR *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0);
- if (buf == (U_CHAR *)-1)
+ buf = (uchar *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0);
+ if (buf == (uchar *)-1)
goto perror_fail;
inc->mapped = 1;
}
else
#endif
{
- buf = (U_CHAR *) xmalloc (size);
+ buf = (uchar *) xmalloc (size + 1);
offset = 0;
while (offset < size)
{
if (count == 0)
{
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;
+ cpp_error (pfile, DL_WARNING,
+ "%s is shorter than expected", inc->name);
+ size = offset;
+ buf = xrealloc (buf, size + 1);
+ inc->st.st_size = size;
break;
}
offset += count;
}
+ /* The lexer requires that the buffer be NUL-terminated. */
+ buf[size] = '\0';
}
}
else if (S_ISBLK (inc->st.st_mode))
{
- cpp_error (pfile, "%s is a block device", inc->name);
+ cpp_error (pfile, DL_ERROR, "%s is a block device", inc->name);
goto fail;
}
else
bigger than the majority of C source files. */
size = 8 * 1024;
- buf = (U_CHAR *) xmalloc (size);
+ buf = (uchar *) 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;
}
return 0;
perror_fail:
- cpp_error_from_errno (pfile, inc->name);
+ cpp_errno (pfile, DL_ERROR, inc->name);
fail:
return 1;
}
+/* Drop INC's buffer from memory, if we are unlikely to need it again. */
static void
purge_cache (inc)
struct include_file *inc;
un-openable), in which case an error code will be in errno. If
there is no include path to use it returns NO_INCLUDE_PATH,
otherwise an include_file structure. If this request originates
- from a #include_next directive, set INCLUDE_NEXT to true. */
-
+ from a directive of TYPE #include_next, set INCLUDE_NEXT to true. */
static struct include_file *
find_include_file (pfile, header, type)
cpp_reader *pfile;
if (path == NULL)
{
- cpp_error (pfile, "No include path in which to find %s", fname);
+ cpp_error (pfile, DL_ERROR, "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
(PTR) &banner);
}
+/* Callback function for splay_tree_foreach(). */
static int
report_missing_guard (n, b)
splay_tree_node n;
return 0;
}
-/* Create a dependency, or issue an error message as appropriate. */
+/* Create a dependency for file FNAME, or issue an error message as
+ appropriate. ANGLE_BRACKETS is non-zero if the file was bracketed
+ like <..>. */
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_diagnostic_with_errno ()
- for both of these cases. */
- else if (CPP_PRINT_DEPS (pfile) && ! print_dep)
- cpp_warning (pfile, "%s: %s", fname, xstrerror (errno));
+ file exists in. */
else
- cpp_error_from_errno (pfile, fname);
+ cpp_errno (pfile, CPP_PRINT_DEPS (pfile) && ! print_dep
+ ? DL_WARNING: DL_ERROR, fname);
}
-/* Handles #include-family directives, and the command line -imacros
- and -include. Returns true if a buffer was stacked. */
+/* Handles #include-family directives (distinguished by TYPE),
+ including HEADER, and the command line -imacros and -include.
+ Returns true if a buffer was stacked. */
bool
_cpp_execute_include (pfile, header, type)
cpp_reader *pfile;
if (f == NULL)
{
- cpp_error_from_errno (pfile, fname);
+ cpp_errno (pfile, DL_ERROR, fname);
return false;
}
return stack_include_file (pfile, f);
}
-/* Do appropriate cleanup when a file buffer is popped off the input
- stack. Push the next -include file, if any remain. */
+/* Do appropriate cleanup when a file INC's buffer is popped off the
+ input stack. */
void
_cpp_pop_file_buffer (pfile, inc)
cpp_reader *pfile;
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
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 *map_next;
#define FILE_NAME_MAP_FILE "header.gcc"
/* Read a space delimited string of unlimited length from a stdio
- file. */
-
+ file F. */
static char *
read_filename_string (ch, f)
int ch;
}
/* This structure holds a linked list of file name maps, one per directory. */
-
struct file_name_map_list
{
struct file_name_map_list *map_list_next;
};
/* Read the file name map file for DIRNAME. */
-
static struct file_name_map *
read_name_map (pfile, dirname)
cpp_reader *pfile;
/* We know p != name as absolute paths don't call remap_filename. */
if (p == name)
- cpp_ice (pfile, "absolute file name in remap_filename");
+ cpp_error (pfile, DL_ICE, "absolute file name in remap_filename");
dir = (char *) alloca (p - name + 1);
memcpy (dir, name, p - name);
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;