aboutsummaryrefslogtreecommitdiff
path: root/gcc/cppfiles.c
diff options
context:
space:
mode:
authorZack Weinberg <zack@wolery.cumb.org>2000-05-28 05:56:38 +0000
committerZack Weinberg <zack@gcc.gnu.org>2000-05-28 05:56:38 +0000
commitf8f769ea4e694c516b9631ae8f2215cc6d5fb96f (patch)
tree2f5db92bd0f352a3b3a9f86ac6b719d86650e290 /gcc/cppfiles.c
parente79f71f73dd44748c28d7f94b29d293722345e26 (diff)
downloadgcc-f8f769ea4e694c516b9631ae8f2215cc6d5fb96f.zip
gcc-f8f769ea4e694c516b9631ae8f2215cc6d5fb96f.tar.gz
gcc-f8f769ea4e694c516b9631ae8f2215cc6d5fb96f.tar.bz2
cppfiles.c: Read files in, using mmap if possible, then prescan them separately.
* cppfiles.c: Read files in, using mmap if possible, then prescan them separately. (read_file, read_with_read): New functions. * cpplex.c: Don't define UCHAR_MAX. (_cpp_read_and_prescan): Rename to _cpp_prescan. Don't read the file here. * cppinit.c (handle_option): Automatically define __cplusplus, __OBJC__, __ASEEMBLER__, _LANGUAGE_FORTRAN here when we see the respective -lang switch. * cpphash.h (enum node_type, struct hashnode, _cpp_lookup prototype): Move to... * cpplib.h: ... here. Rename struct hashnode to struct cpp_hashnode and give it a typedef. Rename _cpp_lookup to cpp_lookup. Add 'fe_value' slot, a union tree_node *. From-SVN: r34228
Diffstat (limited to 'gcc/cppfiles.c')
-rw-r--r--gcc/cppfiles.c140
1 files changed, 113 insertions, 27 deletions
diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c
index 395976f..2955902 100644
--- a/gcc/cppfiles.c
+++ b/gcc/cppfiles.c
@@ -28,6 +28,17 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "intl.h"
#include "mkdeps.h"
+#ifdef HAVE_MMAP_FILE
+# include <sys/mman.h>
+# ifndef MMAP_THRESHOLD
+# define MMAP_THRESHOLD 3 /* Minimum page count to mmap the file. */
+# endif
+
+#else /* No MMAP_FILE */
+# undef MMAP_THRESHOLD
+# define MMAP_THRESHOLD 0
+#endif
+
static IHASH *redundant_include_p PARAMS ((cpp_reader *, IHASH *,
struct file_name_list *));
static IHASH *make_IHASH PARAMS ((const char *, const char *,
@@ -45,8 +56,10 @@ static int eq_IHASH PARAMS ((const void *, const void *));
static int find_include_file PARAMS ((cpp_reader *, const char *,
struct file_name_list *,
IHASH **, int *));
-static int read_include_file PARAMS ((cpp_reader *, int, IHASH *));
static inline int open_include_file PARAMS ((cpp_reader *, const char *));
+static int read_include_file PARAMS ((cpp_reader *, int, IHASH *));
+static ssize_t read_with_read PARAMS ((cpp_buffer *, int, ssize_t));
+static ssize_t read_file PARAMS ((cpp_buffer *, int, ssize_t));
#if 0
static void hack_vms_include_specification PARAMS ((char *));
@@ -678,8 +691,7 @@ read_include_file (pfile, fd, ihash)
IHASH *ihash;
{
struct stat st;
- size_t st_size;
- long length;
+ ssize_t length;
cpp_buffer *fp;
fp = cpp_push_buffer (pfile, NULL, 0);
@@ -690,35 +702,37 @@ read_include_file (pfile, fd, ihash)
if (fstat (fd, &st) < 0)
goto perror_fail;
- /* If fd points to a plain file, we know how big it is, so we can
- allocate the buffer all at once. If fd is a pipe or terminal, we
- can't. Most C source files are 4k or less, so we guess that. If
- fd is something weird, like a directory, we don't want to read it
- at all.
+ /* If fd points to a plain file, we might be able to mmap it; we can
+ definitely allocate the buffer all at once. If fd is a pipe or
+ terminal, we can't do either. If fd is something weird, like a
+ block device or a directory, we don't want to read it at all.
Unfortunately, different systems use different st.st_mode values
for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and
zero the entire struct stat except a couple fields. Hence we don't
even try to figure out what something is, except for plain files,
- directories, and block devices.
-
- In all cases, read_and_prescan will resize the buffer if it
- turns out there's more data than we thought. */
+ directories, and block devices. */
if (S_ISREG (st.st_mode))
{
- /* off_t might have a wider range than size_t - in other words,
+ ssize_t st_size;
+
+ /* off_t might have a wider range than ssize_t - in other words,
the max size of a file might be bigger than the address
space. We can't handle a file that large. (Anyone with
- a single source file bigger than 4GB needs to rethink
+ a single source file bigger than 2GB needs to rethink
their coding style.) */
- st_size = (size_t) st.st_size;
- if ((unsigned HOST_WIDEST_INT) st_size
- != (unsigned HOST_WIDEST_INT) st.st_size)
+ if (st.st_size > SSIZE_MAX)
{
- cpp_error (pfile, "file `%s' is too large", ihash->name);
+ cpp_error (pfile, "%s is too large", ihash->name);
goto fail;
}
+ st_size = st.st_size;
+ length = read_file (fp, fd, st_size);
+ if (length == -1)
+ goto perror_fail;
+ if (length < st_size)
+ cpp_warning (pfile, "%s is shorter than expected\n", ihash->name);
}
else if (S_ISBLK (st.st_mode))
{
@@ -732,25 +746,28 @@ read_include_file (pfile, fd, ihash)
}
else
{
- /* We don't know how big this is. 4k is a decent first guess. */
- st_size = 4096;
+ /* 8 kilobytes is a sensible starting size. It ought to be
+ bigger than the kernel pipe buffer, and it's definitely
+ bigger than the majority of C source files. */
+ length = read_with_read (fp, fd, 8 * 1024);
+ if (length == -1)
+ goto perror_fail;
}
- /* Read the file, converting end-of-line characters and trigraphs
- (if enabled). */
+ /* These must be set before prescan. */
fp->ihash = ihash;
fp->nominal_fname = ihash->name;
- length = _cpp_read_and_prescan (pfile, fp, fd, st_size);
- if (length < 0)
- goto fail;
+
if (length == 0)
ihash->control_macro = U""; /* never re-include */
+ else
+ /* Temporary - I hope. */
+ length = _cpp_prescan (pfile, fp, length);
- close (fd);
fp->rlimit = fp->buf + length;
fp->cur = fp->buf;
if (ihash->foundhere != ABSOLUTE_PATH)
- fp->system_header_p = ihash->foundhere->sysp;
+ fp->system_header_p = ihash->foundhere->sysp;
fp->lineno = 1;
fp->line_base = fp->buf;
@@ -761,6 +778,7 @@ read_include_file (pfile, fd, ihash)
pfile->input_stack_listing_current = 0;
pfile->only_seen_white = 2;
+ close (fd);
return 1;
perror_fail:
@@ -772,6 +790,74 @@ read_include_file (pfile, fd, ihash)
return 0;
}
+static ssize_t
+read_file (fp, fd, size)
+ cpp_buffer *fp;
+ int fd;
+ ssize_t size;
+{
+ static int pagesize = -1;
+
+ if (size == 0)
+ return 0;
+
+ if (pagesize == -1)
+ pagesize = getpagesize ();
+
+#if MMAP_THRESHOLD
+ if (size / pagesize >= MMAP_THRESHOLD)
+ {
+ const U_CHAR *result
+ = (const U_CHAR *) mmap (0, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (result != (const U_CHAR *)-1)
+ {
+ fp->buf = result;
+ fp->mapped = 1;
+ return size;
+ }
+ }
+ /* If mmap fails, try read. If there's really a problem, read will
+ fail too. */
+#endif
+
+ return read_with_read (fp, fd, size);
+}
+
+static ssize_t
+read_with_read (fp, fd, size)
+ cpp_buffer *fp;
+ int fd;
+ ssize_t size;
+{
+ ssize_t offset, count;
+ U_CHAR *buf;
+
+ buf = (U_CHAR *) xmalloc (size);
+ offset = 0;
+ while ((count = read (fd, buf + offset, size - offset)) > 0)
+ {
+ offset += count;
+ if (offset == size)
+ buf = xrealloc (buf, (size *= 2));
+ }
+ if (count < 0)
+ {
+ free (buf);
+ return -1;
+ }
+ if (offset == 0)
+ {
+ free (buf);
+ return 0;
+ }
+
+ if (offset < size)
+ buf = xrealloc (buf, offset);
+ fp->buf = buf;
+ fp->mapped = 0;
+ return offset;
+}
+
/* Given a path FNAME, extract the directory component and place it
onto the actual_dirs list. Return a pointer to the allocated
file_name_list structure. These structures are used to implement