Commit a58d32c2 by Zack Weinberg Committed by Zack Weinberg

cppfiles.c: Move all default-#defines to top of file.

	* cppfiles.c: Move all default-#defines to top of file.
	(open_include_file): Replace by lookup_include_file.
	(read_with_read, read_file): Merged into read_include_file.
	(stack_include_file, purge_cache): New functions.
	(close_cached_fd): Delete.
	(lookup_include_file, read_include_file, _cpp_pop_file_buffer):
	Cache the in-memory buffer, not the file descriptor.

	* cpphash.h (struct include_file): Add buffer, st, refcnt,
	mapped fields.
	(xcnew): New utility macro.
	(DO_NOT_REREAD, NEVER_REREAD): Move up by struct include_file.
	* cpplib.h (struct cpp_buffer): Remove mapped field.

	* cpplex.c (parse_string): Accept backslash space newline as a
	line continuation.
	(lex_line): Likewise.
	(_cpp_get_token): Remove hard limit on macro nesting.

testsuite:
	* gcc.dg/cpp/backslash.c: New test.

From-SVN: r36347
parent 4ba01ed2
2000-09-11 Zack Weinberg <zack@wolery.cumb.org>
* cppfiles.c: Move all default-#defines to top of file.
(open_include_file): Replace by lookup_include_file.
(read_with_read, read_file): Merged into read_include_file.
(stack_include_file, purge_cache): New functions.
(close_cached_fd): Delete.
(lookup_include_file, read_include_file, _cpp_pop_file_buffer):
Cache the in-memory buffer, not the file descriptor.
* cpphash.h (struct include_file): Add buffer, st, refcnt,
mapped fields.
(xcnew): New utility macro.
(DO_NOT_REREAD, NEVER_REREAD): Move up by struct include_file.
* cpplib.h (struct cpp_buffer): Remove mapped field.
2000-09-11 Zack Weinberg <zack@wolery.cumb.org>
* cpplex.c (parse_string): Accept backslash space newline as a
line continuation.
(lex_line): Likewise.
(_cpp_get_token): Remove hard limit on macro nesting.
2000-09-12 Philipp Thomas <pthomas@suse.de> 2000-09-12 Philipp Thomas <pthomas@suse.de>
* aclocal.m4 (AM_WITH_NLS): Don't force use of included gettext. * aclocal.m4 (AM_WITH_NLS): Don't force use of included gettext.
......
...@@ -43,6 +43,22 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ...@@ -43,6 +43,22 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
# define O_BINARY 0 # define O_BINARY 0
#endif #endif
#ifndef INCLUDE_LEN_FUDGE
# define INCLUDE_LEN_FUDGE 0
#endif
/* If errno is inspected immediately after a system call fails, it will be
nonzero, and no error number will ever be zero. */
#ifndef ENOENT
# define ENOENT 0
#endif
#ifndef ENOTDIR
# define ENOTDIR 0
#endif
#ifndef ENOMEM
# define ENOMEM 0
#endif
/* Suppress warning about function macros used w/o arguments in traditional /* Suppress warning about function macros used w/o arguments in traditional
C. It is unlikely that glibc's strcmp macro helps this file at all. */ C. It is unlikely that glibc's strcmp macro helps this file at all. */
#undef strcmp #undef strcmp
...@@ -57,24 +73,18 @@ static struct file_name_list *actual_directory ...@@ -57,24 +73,18 @@ static struct file_name_list *actual_directory
static struct include_file *find_include_file static struct include_file *find_include_file
PARAMS ((cpp_reader *, const char *, PARAMS ((cpp_reader *, const char *,
struct file_name_list *)); struct file_name_list *));
static struct include_file *open_include_file static struct include_file *lookup_include_file
PARAMS ((cpp_reader *, const char *)); PARAMS ((cpp_reader *, const char *));
static int read_include_file PARAMS ((cpp_reader *, struct include_file *)); static int read_include_file PARAMS ((cpp_reader *, struct include_file *));
static ssize_t read_with_read PARAMS ((cpp_buffer *, int, ssize_t)); static int stack_include_file PARAMS ((cpp_reader *, struct include_file *));
static ssize_t read_file PARAMS ((cpp_buffer *, int, ssize_t)); static void purge_cache PARAMS ((struct include_file *));
static void destroy_include_file_node PARAMS ((splay_tree_value)); static void destroy_include_file_node PARAMS ((splay_tree_value));
static int close_cached_fd PARAMS ((splay_tree_node, void *));
static int report_missing_guard PARAMS ((splay_tree_node, void *)); static int report_missing_guard PARAMS ((splay_tree_node, void *));
#if 0 #if 0
static void hack_vms_include_specification PARAMS ((char *)); static void hack_vms_include_specification PARAMS ((char *));
#endif #endif
#ifndef INCLUDE_LEN_FUDGE
#define INCLUDE_LEN_FUDGE 0
#endif
/* We use a splay tree to store information about all the include /* We use a splay tree to store information about all the include
files seen in this compilation. The key of each tree node is the files seen in this compilation. The key of each tree node is the
physical path to the file. The value is 0 if the file does not physical path to the file. The value is 0 if the file does not
...@@ -87,26 +97,11 @@ destroy_include_file_node (v) ...@@ -87,26 +97,11 @@ destroy_include_file_node (v)
struct include_file *f = (struct include_file *)v; struct include_file *f = (struct include_file *)v;
if (f) if (f)
{ {
if (f->fd != -1) purge_cache (f);
close (f->fd);
free (f); free (f);
} }
} }
static int
close_cached_fd (n, dummy)
splay_tree_node n;
void *dummy ATTRIBUTE_UNUSED;
{
struct include_file *f = (struct include_file *)n->value;
if (f && f->fd != -1)
{
close (f->fd);
f->fd = -1;
}
return 0;
}
void void
_cpp_init_includes (pfile) _cpp_init_includes (pfile)
cpp_reader *pfile; cpp_reader *pfile;
...@@ -124,48 +119,24 @@ _cpp_cleanup_includes (pfile) ...@@ -124,48 +119,24 @@ _cpp_cleanup_includes (pfile)
splay_tree_delete (pfile->all_include_files); splay_tree_delete (pfile->all_include_files);
} }
/* Given a filename, look it up and possibly open it. If the file /* Given a file name, look it up in the cache; if there is no entry,
does not exist, return NULL. If the file does exist but doesn't create one. Returns 0 if the file doesn't exist or is
need to be reread, return an include_file entry with fd == -1. inaccessible, otherwise the cache entry. */
If it needs to be (re)read, return an include_file entry with
fd a file descriptor open on the file. */
static struct include_file * static struct include_file *
open_include_file (pfile, filename) lookup_include_file (pfile, filename)
cpp_reader *pfile; cpp_reader *pfile;
const char *filename; const char *filename;
{ {
splay_tree_node nd; splay_tree_node nd;
struct include_file *file = 0; struct include_file *file = 0;
int fd; int fd;
struct stat st;
nd = splay_tree_lookup (pfile->all_include_files, nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) filename);
(splay_tree_key) filename);
if (nd) if (nd)
{ return (struct include_file *)nd->value;
if (nd->value == 0)
return 0;
file = (struct include_file *)nd->value;
if (DO_NOT_REREAD (file))
{
if (file->fd != -1)
{
close (file->fd);
file->fd = -1;
}
return file;
}
/* File descriptors are cached for files that might be reread. */
if (file->fd != -1)
{
lseek (file->fd, 0, SEEK_SET);
return file;
}
}
/* We used to open files in nonblocking mode, but that caused more /* We used to open files in nonblocking mode, but that caused more
problems than it solved. Do take care not to acquire a problems than it solved. Do take care not to acquire a
...@@ -180,67 +151,224 @@ open_include_file (pfile, filename) ...@@ -180,67 +151,224 @@ open_include_file (pfile, filename)
ourselves. ourselves.
Special case: the empty string is translated to stdin. */ Special case: the empty string is translated to stdin. */
retry:
if (filename[0] == '\0') if (filename[0] == '\0')
fd = 0; fd = 0;
else else
fd = open (filename, O_RDONLY|O_NOCTTY|O_BINARY, 0666); fd = open (filename, O_RDONLY|O_NOCTTY|O_BINARY, 0666);
if (fd == -1) if (fd == -1)
goto fail;
if (fstat (fd, &st) < 0)
goto fail;
file = xcnew (struct include_file);
file->name = xstrdup (filename);
file->st = st;
file->fd = fd;
/* If the file is plain and zero length, mark it never-reread now. */
if (S_ISREG (st.st_mode) && st.st_size == 0)
file->cmacro = NEVER_REREAD;
splay_tree_insert (pfile->all_include_files,
(splay_tree_key) file->name, (splay_tree_value) file);
return file;
fail:
/* Don't issue an error message if the file doesn't exist. */
if (errno != ENOENT && errno != ENOTDIR)
cpp_error_from_errno (pfile, filename);
/* Create a negative node for this path. */
splay_tree_insert (pfile->all_include_files,
(splay_tree_key) xstrdup (filename), 0);
return 0;
}
/* Place the file referenced by INC into a new buffer on PFILE's stack.
Return 1 if successful, 0 if not. */
static int
stack_include_file (pfile, inc)
cpp_reader *pfile;
struct include_file *inc;
{
cpp_buffer *fp;
if (DO_NOT_REREAD (inc))
return 0;
if (inc->buffer == NULL)
if (read_include_file (pfile, inc) == 0)
return 0;
fp = cpp_push_buffer (pfile, NULL, 0);
if (fp == 0)
return 0;
fp->inc = inc;
fp->nominal_fname = inc->name;
fp->buf = inc->buffer;
fp->rlimit = fp->buf + inc->st.st_size;
fp->cur = fp->buf;
fp->lineno = 1;
fp->line_base = fp->buf;
/* The ->actual_dir field is only used when ignore_srcdir is not in effect;
see do_include */
if (!CPP_OPTION (pfile, ignore_srcdir))
fp->actual_dir = actual_directory (pfile, inc->name);
fp->inc->refcnt++;
pfile->include_depth++;
pfile->input_stack_listing_current = 0;
if (pfile->cb.enter_file)
(*pfile->cb.enter_file) (pfile);
return 1;
}
/* Read the file referenced by INC into the file cache.
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.
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;
#if MMAP_THRESHOLD
static int pagesize = -1;
#endif
if (S_ISREG (inc->st.st_mode))
{ {
#ifdef EACCES /* off_t might have a wider range than ssize_t - in other words,
if (errno == EACCES) 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 2GB needs to rethink
their coding style.) Some systems (e.g. AIX 4.1) define
SSIZE_MAX to be much smaller than the actual range of the
type. Use INTTYPE_MAXIMUM unconditionally to ensure this
does not bite us. */
if (inc->st.st_size > INTTYPE_MAXIMUM (ssize_t))
{ {
cpp_error (pfile, "included file \"%s\" exists but is not readable", cpp_error (pfile, "%s is too large", inc->name);
filename); goto fail;
} }
size = inc->st.st_size;
#if MMAP_THRESHOLD
if (pagesize == -1)
pagesize = getpagesize ();
if (size / pagesize >= MMAP_THRESHOLD)
{
buf = (U_CHAR *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0);
if (buf == (U_CHAR *)-1)
goto perror_fail;
inc->mapped = 1;
}
else
#endif #endif
if (0
#ifdef EMFILE
|| errno == EMFILE
#endif
#ifdef ENFILE
|| errno == ENFILE
#endif
)
{ {
/* Too many files open. Close all cached file descriptors and buf = (U_CHAR *) xmalloc (size);
try again. */ offset = 0;
splay_tree_foreach (pfile->all_include_files, close_cached_fd, 0); while (offset < size)
goto retry; {
count = read (inc->fd, buf + offset, size - offset);
if (count < 0)
goto perror_fail;
if (count == 0)
{
cpp_warning (pfile, "%s is shorter than expected", inc->name);
break;
}
offset += count;
}
inc->mapped = 0;
}
}
else if (S_ISBLK (inc->st.st_mode))
{
cpp_error (pfile, "%s is a block device", inc->name);
goto fail;
}
else if (S_ISDIR (inc->st.st_mode))
{
cpp_error (pfile, "%s is a directory", inc->name);
goto fail;
}
else
{
/* 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. */
size = 8 * 1024;
buf = (U_CHAR *) xmalloc (size);
offset = 0;
while ((count = read (inc->fd, buf + offset, size - offset)) > 0)
{
offset += count;
if (offset == size)
buf = xrealloc (buf, (size *= 2));
} }
if (count < 0)
goto perror_fail;
/* Nonexistent or inaccessible file. Create a negative node for it. */ if (offset == 0)
if (nd)
{ {
cpp_ice (pfile, free (buf);
"node for '%s' exists, open failed, error '%s', value %lx\n", return 0;
filename, strerror (errno), nd->value);
destroy_include_file_node (nd->value);
} }
splay_tree_insert (pfile->all_include_files,
(splay_tree_key) xstrdup (filename), 0); if (offset < size)
return 0; buf = xrealloc (buf, offset);
inc->st.st_size = offset;
} }
/* If we haven't seen this file before, create a positive node for it. */ close (inc->fd);
if (!nd) inc->buffer = buf;
inc->fd = -1;
return 1;
perror_fail:
cpp_error_from_errno (pfile, inc->name);
fail:
/* Do not try to read this file again. */
close (inc->fd);
inc->fd = -1;
inc->cmacro = NEVER_REREAD;
return 0;
}
static void
purge_cache (inc)
struct include_file *inc;
{
if (inc->buffer)
{ {
file = xnew (struct include_file); if (inc->mapped)
file->cmacro = 0; munmap ((caddr_t) inc->buffer, inc->st.st_size);
file->include_count = 0; else
file->sysp = 0; free ((PTR) inc->buffer);
file->foundhere = 0; inc->buffer = NULL;
file->name = xstrdup (filename);
splay_tree_insert (pfile->all_include_files,
(splay_tree_key) file->name,
(splay_tree_value) file);
} }
file->fd = fd;
file->date = (time_t) -1;
return file;
} }
/* Return 1 if the file named by FNAME has been included before in /* Return 1 if the file named by FNAME has been included before in
...@@ -282,8 +410,7 @@ cpp_included (pfile, fname) ...@@ -282,8 +410,7 @@ cpp_included (pfile, fname)
/* Search for include file FNAME in the include chain starting at /* Search for include file FNAME in the include chain starting at
SEARCH_START. Return 0 if there is no such file (or it's un-openable), SEARCH_START. Return 0 if there is no such file (or it's un-openable),
otherwise an include_file structure, possibly with a file descriptor otherwise an include_file structure. */
open on the file. */
static struct include_file * static struct include_file *
find_include_file (pfile, fname, search_start) find_include_file (pfile, fname, search_start)
...@@ -296,7 +423,7 @@ find_include_file (pfile, fname, search_start) ...@@ -296,7 +423,7 @@ find_include_file (pfile, fname, search_start)
struct include_file *file; struct include_file *file;
if (fname[0] == '/') if (fname[0] == '/')
return open_include_file (pfile, fname); return lookup_include_file (pfile, fname);
/* Search directory path for the file. */ /* Search directory path for the file. */
name = (char *) alloca (strlen (fname) + pfile->max_include_len name = (char *) alloca (strlen (fname) + pfile->max_include_len
...@@ -310,7 +437,7 @@ find_include_file (pfile, fname, search_start) ...@@ -310,7 +437,7 @@ find_include_file (pfile, fname, search_start)
if (CPP_OPTION (pfile, remap)) if (CPP_OPTION (pfile, remap))
name = remap_filename (pfile, name, path); name = remap_filename (pfile, name, path);
file = open_include_file (pfile, name); file = lookup_include_file (pfile, name);
if (file) if (file)
{ {
file->sysp = path->sysp; file->sysp = path->sysp;
...@@ -321,9 +448,9 @@ find_include_file (pfile, fname, search_start) ...@@ -321,9 +448,9 @@ find_include_file (pfile, fname, search_start)
return 0; return 0;
} }
/* #line uses this to save artificial file names. We have to try /* #line uses this to save artificial file names. We have to stat the
opening the file because an all_include_files entry is always file because an all_include_files entry is always either + or -,
either + or -, there's no 'I don't know' value. */ there's no 'I don't know' value. */
const char * const char *
_cpp_fake_include (pfile, fname) _cpp_fake_include (pfile, fname)
cpp_reader *pfile; cpp_reader *pfile;
...@@ -335,7 +462,14 @@ _cpp_fake_include (pfile, fname) ...@@ -335,7 +462,14 @@ _cpp_fake_include (pfile, fname)
file = find_include_file (pfile, fname, CPP_OPTION (pfile, quote_include)); file = find_include_file (pfile, fname, CPP_OPTION (pfile, quote_include));
if (file) if (file)
return file->name; {
if (file->fd > 0)
{
close (file->fd);
file->fd = -1;
}
return file->name;
}
name = xstrdup (fname); name = xstrdup (fname);
_cpp_simplify_pathname (name); _cpp_simplify_pathname (name);
...@@ -453,31 +587,28 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start, angle_brackets) ...@@ -453,31 +587,28 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start, angle_brackets)
if (inc) if (inc)
{ {
if (inc->fd == -1)
return;
/* For -M, add the file to the dependencies on its first inclusion. */ /* For -M, add the file to the dependencies on its first inclusion. */
if (!inc->include_count && PRINT_THIS_DEP (pfile, angle_brackets)) if (!inc->include_count && PRINT_THIS_DEP (pfile, angle_brackets))
deps_add_dep (pfile->deps, inc->name); deps_add_dep (pfile->deps, inc->name);
inc->include_count++; inc->include_count++;
/* Handle -H option. */
if (CPP_OPTION (pfile, print_include_names))
{
cpp_buffer *fp = CPP_BUFFER (pfile);
while ((fp = CPP_PREV_BUFFER (fp)) != NULL)
putc ('.', stderr);
fprintf (stderr, " %s\n", inc->name);
}
/* Actually process the file. */ /* Actually process the file. */
if (no_reinclude) if (stack_include_file (pfile, inc))
inc->cmacro = NEVER_REREAD;
if (read_include_file (pfile, inc))
{ {
if (angle_brackets) if (angle_brackets)
pfile->system_include_depth++; pfile->system_include_depth++;
if (no_reinclude)
inc->cmacro = NEVER_REREAD;
/* Handle -H option. */
if (CPP_OPTION (pfile, print_include_names))
{
cpp_buffer *fp = CPP_BUFFER (pfile);
while ((fp = CPP_PREV_BUFFER (fp)) != NULL)
putc ('.', stderr);
fprintf (stderr, " %s\n", inc->name);
}
} }
return; return;
} }
...@@ -552,23 +683,13 @@ _cpp_compare_file_date (pfile, f, len, angle_brackets) ...@@ -552,23 +683,13 @@ _cpp_compare_file_date (pfile, f, len, angle_brackets)
if (!inc) if (!inc)
return -1; return -1;
if (inc->fd >= 0) if (inc->fd > 0)
{ {
struct stat source;
if (fstat (inc->fd, &source) < 0)
{
close (inc->fd);
inc->fd = -1;
return -1;
}
inc->date = source.st_mtime;
close (inc->fd); close (inc->fd);
inc->fd = -1; inc->fd = -1;
} }
if (inc->date == (time_t)-1 || current_include->date == (time_t)-1)
return -1; return inc->st.st_mtime > current_include->st.st_mtime;
return inc->date > current_include->date;
} }
...@@ -584,7 +705,7 @@ cpp_read_file (pfile, fname) ...@@ -584,7 +705,7 @@ cpp_read_file (pfile, fname)
if (fname == NULL) if (fname == NULL)
fname = ""; fname = "";
f = open_include_file (pfile, fname); f = lookup_include_file (pfile, fname);
if (f == NULL) if (f == NULL)
{ {
...@@ -592,188 +713,7 @@ cpp_read_file (pfile, fname) ...@@ -592,188 +713,7 @@ cpp_read_file (pfile, fname)
return 0; return 0;
} }
return read_include_file (pfile, f); return stack_include_file (pfile, f);
}
/* Read the file referenced by INC into a new buffer on PFILE's stack.
Return 1 if successful, 0 if not. */
static int
read_include_file (pfile, inc)
cpp_reader *pfile;
struct include_file *inc;
{
struct stat st;
ssize_t length;
cpp_buffer *fp;
int fd = inc->fd;
fp = cpp_push_buffer (pfile, NULL, 0);
if (fp == 0)
goto push_fail;
if (fd < 0 || fstat (fd, &st) < 0)
goto perror_fail;
/* These must be set right away. */
inc->date = st.st_mtime;
fp->inc = inc;
fp->nominal_fname = inc->name;
/* 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. */
if (S_ISREG (st.st_mode))
{
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 2GB needs to rethink
their coding style.) Some systems (e.g. AIX 4.1) define
SSIZE_MAX to be much smaller than the actual range of the
type. Use INTTYPE_MAXIMUM unconditionally to ensure this
does not bite us. */
if (st.st_size > INTTYPE_MAXIMUM (ssize_t))
{
cpp_error (pfile, "%s is too large", inc->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", inc->name);
}
else if (S_ISBLK (st.st_mode))
{
cpp_error (pfile, "%s is a block device", inc->name);
goto fail;
}
else if (S_ISDIR (st.st_mode))
{
cpp_error (pfile, "%s is a directory", inc->name);
goto fail;
}
else
{
/* 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;
}
if (length == 0)
inc->cmacro = NEVER_REREAD;
fp->rlimit = fp->buf + length;
fp->cur = fp->buf;
fp->lineno = 1;
fp->line_base = fp->buf;
/* The ->actual_dir field is only used when ignore_srcdir is not in effect;
see do_include */
if (!CPP_OPTION (pfile, ignore_srcdir))
fp->actual_dir = actual_directory (pfile, inc->name);
pfile->include_depth++;
pfile->input_stack_listing_current = 0;
if (pfile->cb.enter_file)
(*pfile->cb.enter_file) (pfile);
return 1;
perror_fail:
cpp_error_from_errno (pfile, inc->name);
/* Do not try to read this file again. */
if (fd != -1)
close (fd);
inc->fd = -1;
inc->cmacro = NEVER_REREAD;
fail:
cpp_pop_buffer (pfile);
push_fail:
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;
} }
/* Do appropriate cleanup when a file buffer is popped off the input /* Do appropriate cleanup when a file buffer is popped off the input
...@@ -797,21 +737,9 @@ _cpp_pop_file_buffer (pfile, buf) ...@@ -797,21 +737,9 @@ _cpp_pop_file_buffer (pfile, buf)
} }
pfile->input_stack_listing_current = 0; pfile->input_stack_listing_current = 0;
/* Discard file buffer. XXX Would be better to cache these instead inc->refcnt--;
of the file descriptors. */ if (inc->refcnt == 0 && DO_NOT_REREAD (inc))
#ifdef HAVE_MMAP_FILE purge_cache (inc);
if (buf->mapped)
munmap ((caddr_t) buf->buf, buf->rlimit - buf->buf);
else
#endif
free ((PTR) buf->buf);
/* If the file will not be included again, close it. */
if (DO_NOT_REREAD (inc))
{
close (inc->fd);
inc->fd = -1;
}
} }
/* The file_name_map structure holds a mapping of file names for a /* The file_name_map structure holds a mapping of file names for a
......
...@@ -115,12 +115,24 @@ struct include_file ...@@ -115,12 +115,24 @@ struct include_file
const struct file_name_list *foundhere; const struct file_name_list *foundhere;
/* location in search path where file was /* location in search path where file was
found, for #include_next */ found, for #include_next */
int fd; /* file descriptor possibly open on 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) */
unsigned short include_count; /* number of times file has been read */ unsigned short include_count; /* number of times file has been read */
unsigned short sysp; /* file is a system header */ unsigned short refcnt; /* number of stacked buffers using this file */
time_t date; /* modification date of file, if known */ unsigned char sysp; /* file is a system header */
unsigned char mapped; /* file buffer is mmapped */
}; };
/* 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
to be included again if the macro is not defined. */
#define NEVER_REREAD ((const cpp_hashnode *)-1)
#define DO_NOT_REREAD(inc) \
((inc)->cmacro && \
((inc)->cmacro == NEVER_REREAD || (inc)->cmacro->type != T_VOID))
/* Special nodes - identifiers with predefined significance. /* Special nodes - identifiers with predefined significance.
Note that the array length of dirs[] must be kept in sync with Note that the array length of dirs[] must be kept in sync with
cpplib.c's dtable[]. */ cpplib.c's dtable[]. */
...@@ -133,16 +145,6 @@ struct spec_nodes ...@@ -133,16 +145,6 @@ struct spec_nodes
cpp_hashnode *dirs[19]; /* 19 directives counting #sccs */ cpp_hashnode *dirs[19]; /* 19 directives counting #sccs */
}; };
/* 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
to be included again if the macro is not defined. */
#define NEVER_REREAD ((const cpp_hashnode *)-1)
#define DO_NOT_REREAD(inc) \
((inc)->cmacro && \
((inc)->cmacro == NEVER_REREAD || (inc)->cmacro->type != T_VOID))
/* Character classes. /* Character classes.
If the definition of `numchar' looks odd to you, please look up the If the definition of `numchar' looks odd to you, please look up the
definition of a pp-number in the C standard [section 6.4.8 of C99]. definition of a pp-number in the C standard [section 6.4.8 of C99].
...@@ -293,6 +295,7 @@ extern void _cpp_init_internal_pragmas PARAMS ((cpp_reader *)); ...@@ -293,6 +295,7 @@ extern void _cpp_init_internal_pragmas PARAMS ((cpp_reader *));
/* Utility routines and macros. */ /* Utility routines and macros. */
#define xnew(T) (T *) xmalloc (sizeof(T)) #define xnew(T) (T *) xmalloc (sizeof(T))
#define xcnew(T) (T *) xcalloc (1, sizeof(T))
#define xnewvec(T, N) (T *) xmalloc (sizeof(T) * (N)) #define xnewvec(T, N) (T *) xmalloc (sizeof(T) * (N))
#define xcnewvec(T, N) (T *) xcalloc (N, sizeof(T)) #define xcnewvec(T, N) (T *) xcalloc (N, sizeof(T))
#define xobnew(O, T) (T *) obstack_alloc (O, sizeof(T)) #define xobnew(O, T) (T *) obstack_alloc (O, sizeof(T))
......
...@@ -1106,12 +1106,23 @@ parse_string (pfile, list, token, terminator) ...@@ -1106,12 +1106,23 @@ parse_string (pfile, list, token, terminator)
if (is_vspace (c)) if (is_vspace (c))
{ {
/* Drop a backslash newline, and continue. */ /* Drop a backslash newline, and continue. */
U_CHAR *old = namebuf;
while (namebuf > list->namebuf && is_hspace (namebuf[-1]))
namebuf--;
if (namebuf > list->namebuf && namebuf[-1] == '\\') if (namebuf > list->namebuf && namebuf[-1] == '\\')
{ {
handle_newline (cur, buffer->rlimit, c); handle_newline (cur, buffer->rlimit, c);
namebuf--; namebuf--;
if (old[-1] != '\\')
{
buffer->cur = cur;
cpp_warning (pfile,
"backslash and newline separated by space");
}
continue; continue;
} }
else
namebuf = old;
cur--; cur--;
...@@ -1516,37 +1527,40 @@ lex_line (pfile, list) ...@@ -1516,37 +1527,40 @@ lex_line (pfile, list)
handle_newline (cur, buffer->rlimit, c); handle_newline (cur, buffer->rlimit, c);
if (PREV_TOKEN_TYPE == CPP_BACKSLASH) if (PREV_TOKEN_TYPE == CPP_BACKSLASH)
{ {
if (IMMED_TOKEN ()) /* backslash space newline is still treated as backslash-newline;
{ we think this is standard conforming, with some reservations
/* Remove the escaped newline. Then continue to process about actually _using_ the weasel words in C99 5.1.1.2
any interrupted name or number. */ (translation phase 1 is allowed to do whatever it wants to
cur_token--; your input as long as it's documented). */
/* Backslash-newline may not be immediately followed by if (! IMMED_TOKEN ())
EOF (C99 5.1.1.2). */
if (cur >= buffer->rlimit)
{
cpp_pedwarn (pfile, "backslash-newline at end of file");
break;
}
if (IMMED_TOKEN ())
{
cur_token--;
if (cur_token->type == CPP_NAME)
goto continue_name;
else if (cur_token->type == CPP_NUMBER)
goto continue_number;
cur_token++;
}
/* Remember whitespace setting. */
flags = cur_token->flags;
break;
}
else
{ {
buffer->cur = cur; buffer->cur = cur;
cpp_warning (pfile, cpp_warning (pfile,
"backslash and newline separated by space"); "backslash and newline separated by space");
} }
/* Remove the escaped newline. Then continue to process
any interrupted name or number. */
cur_token--;
/* Backslash-newline may not be immediately followed by
EOF (C99 5.1.1.2). */
if (cur >= buffer->rlimit)
{
cpp_pedwarn (pfile, "backslash-newline at end of file");
break;
}
if (IMMED_TOKEN ())
{
cur_token--;
if (cur_token->type == CPP_NAME)
goto continue_name;
else if (cur_token->type == CPP_NUMBER)
goto continue_number;
cur_token++;
}
/* Remember whitespace setting. */
flags = cur_token->flags;
break;
} }
else if (MIGHT_BE_DIRECTIVE ()) else if (MIGHT_BE_DIRECTIVE ())
{ {
...@@ -3187,12 +3201,6 @@ _cpp_get_token (pfile) ...@@ -3187,12 +3201,6 @@ _cpp_get_token (pfile)
if (is_macro_disabled (pfile, node->value.expansion, token)) if (is_macro_disabled (pfile, node->value.expansion, token))
return token; return token;
if (pfile->cur_context > CPP_STACK_MAX)
{
cpp_error (pfile, "macros nested too deep invoking '%s'", node->name);
return token;
}
if (push_macro_context (pfile, token)) if (push_macro_context (pfile, token))
return token; return token;
/* else loop */ /* else loop */
......
...@@ -246,9 +246,6 @@ struct cpp_buffer ...@@ -246,9 +246,6 @@ struct cpp_buffer
or for -Wtraditional, and only once per file (otherwise it would or for -Wtraditional, and only once per file (otherwise it would
be far too noisy). */ be far too noisy). */
char warned_cplusplus_comments; char warned_cplusplus_comments;
/* True if this buffer's data is mmapped. */
char mapped;
}; };
struct file_name_map_list; struct file_name_map_list;
......
2000-09-11 Zack Weinberg <zack@wolery.cumb.org>
* gcc.dg/cpp/backslash.c: New test.
2000-09-11 Alexandre Oliva <aoliva@redhat.com> 2000-09-11 Alexandre Oliva <aoliva@redhat.com>
* gcc.c-torture/execute/20000910-1.c: New test. * gcc.c-torture/execute/20000910-1.c: New test.
......
/* Test backslash newline with and without trailing spaces. */
#define alpha(a, b, c) \
a, \
b, \
c
/* Note the trailing whitespace on the next three lines. */
#define beta(a, b, c) \
a, \
b, \
c
/* { dg-warning "separated by space" "space" { target *-*-* } 9 } */
/* { dg-warning "separated by space" "tab" { target *-*-* } 10 } */
/* { dg-warning "separated by space" "space and tab" { target *-*-* } 11 } */
int x[] = {
alpha(1, 2, 3),
beta(4, 5, 6)
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment