summaryrefslogtreecommitdiff
path: root/gcc/cppfiles.c
diff options
context:
space:
mode:
authorzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>2000-06-21 18:33:51 +0000
committerzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>2000-06-21 18:33:51 +0000
commitc95d8aaa18938a46f022ce74ac75b21ef1e98bad (patch)
treeeb5aadb8fbe401846a1ceb69f99c1b4e7af8d929 /gcc/cppfiles.c
parent5ba7b7e9d0549acfe9d7b3ba07d8a20b2c1d7ae6 (diff)
downloadgcc-c95d8aaa18938a46f022ce74ac75b21ef1e98bad.tar.gz
* cppfiles.c: Include splay-tree.h, not hashtab.h.
(redundant_include_p, make_IHASH, hash_IHASH, eq_IHASH): Delete. (destroy_include_file_node): New. (_cpp_init_include_hash): Rename _cpp_init_include_table. Create a splay tree, not a hash table. (open_include_file): Look up the path in the include table, do the multiple include optimization here, etc. (cpp_included): Walk the path. (find_include_file): Just walk the path calling open_include_file, or call it directly for an absolute path. (_cpp_fake_ihash): Rename _cpp_fake_include and update for new scheme. (read_include_file): Update for new scheme. Don't close the file unless reading fails. (_cpp_execute_include, cpp_read_file): Tweak for new scheme. * cpphash.h (struct ihash, NEVER_REINCLUDE): Delete. (struct include_file): New. (NEVER_REREAD, DO_NOT_REREAD, CPP_IN_SYSTEM_HEADER): New macros. (CPP_PEDANTIC, CPP_WTRADITIONAL): Update. Update prototypes. * cppinit.c: Include splay-tree.h. (cpp_reader_init, cpp_cleanup): Update. * cpplib.h (struct cpp_buffer): Change ihash field to 'struct include_file *inc'. Remove system_header_p. (struct cpp_reader): Change all_include_files to a struct splay_tree_s *. * cpplex.c: Update all references to cpp_buffer->ihash and/or cpp_buffer->system_header_p. (cpp_pop_buffer): Close file here, only if DO_NOT_REREAD. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@34636 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cppfiles.c')
-rw-r--r--gcc/cppfiles.c990
1 files changed, 465 insertions, 525 deletions
diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c
index 55250aeda07..422a123a1e0 100644
--- a/gcc/cppfiles.c
+++ b/gcc/cppfiles.c
@@ -22,11 +22,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
-#include "hashtab.h"
#include "cpplib.h"
#include "cpphash.h"
#include "intl.h"
#include "mkdeps.h"
+#include "splay-tree.h"
#ifdef HAVE_MMAP_FILE
# include <sys/mman.h>
@@ -43,10 +43,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
# define O_BINARY 0
#endif
-static IHASH *redundant_include_p PARAMS ((IHASH *, struct file_name_list *));
-static IHASH *make_IHASH PARAMS ((const char *, const char *,
- struct file_name_list *,
- unsigned int, IHASH **));
static struct file_name_map *read_name_map
PARAMS ((cpp_reader *, const char *));
static char *read_filename_string PARAMS ((int, FILE *));
@@ -54,485 +50,265 @@ static char *remap_filename PARAMS ((cpp_reader *, char *,
struct file_name_list *));
static struct file_name_list *actual_directory
PARAMS ((cpp_reader *, const char *));
-static unsigned int hash_IHASH PARAMS ((const void *));
-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 inline int open_include_file PARAMS ((cpp_reader *, const char *));
-static int read_include_file PARAMS ((cpp_reader *, int, IHASH *));
+static struct include_file *find_include_file
+ PARAMS ((cpp_reader *, const char *,
+ struct file_name_list *));
+static struct include_file *open_include_file
+ PARAMS ((cpp_reader *, const char *));
+static int read_include_file PARAMS ((cpp_reader *, struct include_file *));
static ssize_t read_with_read PARAMS ((cpp_buffer *, int, ssize_t));
static ssize_t read_file PARAMS ((cpp_buffer *, int, ssize_t));
+static void destroy_include_file_node PARAMS ((splay_tree_value));
+
#if 0
static void hack_vms_include_specification PARAMS ((char *));
#endif
-/* Initial size of include hash table. */
-#define IHASHSIZE 50
-
#ifndef INCLUDE_LEN_FUDGE
#define INCLUDE_LEN_FUDGE 0
#endif
-/* Calculate hash of an IHASH entry. */
-static unsigned int
-hash_IHASH (x)
- const void *x;
-{
- const IHASH *i = (const IHASH *)x;
- return i->hash;
-}
+/* 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
+ physical path to the file. The value is 0 if the file does not
+ exist, or a struct include_file pointer. */
-/* Compare an existing IHASH structure with a potential one. */
-static int
-eq_IHASH (x, y)
- const void *x;
- const void *y;
+static void
+destroy_include_file_node (v)
+ splay_tree_value v;
{
- const char *a = ((const IHASH *)x)->nshort;
- const char *b = ((const IHASH *)y)->nshort;
- return !strcmp (a, b);
+ struct include_file *f = (struct include_file *)v;
+ if (f)
+ {
+ if (f->fd != -1)
+ close (f->fd);
+ free (f);
+ }
}
-/* Init the hash table. In here so it can see the hash and eq functions. */
void
-_cpp_init_include_hash (pfile)
+_cpp_init_include_table (pfile)
cpp_reader *pfile;
{
pfile->all_include_files
- = htab_create (IHASHSIZE, hash_IHASH, eq_IHASH, free);
+ = splay_tree_new ((splay_tree_compare_fn) strcmp,
+ (splay_tree_delete_key_fn) free,
+ destroy_include_file_node);
}
-/* Return 0 if the file pointed to by IHASH has never been included before,
- -1 if it has been included before and need not be again,
- or a pointer to an IHASH entry which is the file to be reread.
- "Never before" is with respect to the position in ILIST.
+/* Given a filename, look it up and possibly open it. If the file
+ does not exist, return NULL. If the file does exist but doesn't
+ need to be reread, return an include_file entry with fd == -1.
+ If it needs to be (re)read, return an include_file entry with
+ fd a file descriptor open on the file. */
- This will not detect redundancies involving odd uses of the
- `current directory' rule for "" includes. They aren't quite
- pathological, but I think they are rare enough not to worry about.
- The simplest example is:
+static struct include_file *
+open_include_file (pfile, filename)
+ cpp_reader *pfile;
+ const char *filename;
+{
+ splay_tree_node nd;
+ struct include_file *file = 0;
+ int fd;
- top.c:
- #include "a/a.h"
- #include "b/b.h"
+ nd = splay_tree_lookup (pfile->all_include_files,
+ (splay_tree_key) filename);
- a/a.h:
- #include "../b/b.h"
+ if (nd)
+ {
+ if (nd->value == 0)
+ return 0;
- and the problem is that for `current directory' includes,
- ihash->foundhere is not on any of the global include chains,
- so the test below (i->foundhere == l) may be false even when
- the directories are in fact the same. */
+ file = (struct include_file *)nd->value;
-static IHASH *
-redundant_include_p (ihash, ilist)
- IHASH *ihash;
- struct file_name_list *ilist;
-{
- struct file_name_list *l;
- IHASH *i;
+ if (DO_NOT_REREAD (file))
+ {
+ if (file->fd != -1)
+ {
+ close (file->fd);
+ file->fd = -1;
+ }
+ return file;
+ }
- if (! ihash->foundhere)
- return 0;
+ /* File descriptors are cached for files that might be reread. */
+ if (file->fd != -1)
+ {
+ lseek (file->fd, 0, SEEK_SET);
+ return file;
+ }
+ }
- for (i = ihash; i; i = i->next_this_file)
- for (l = ilist; l; l = l->next)
- if (i->foundhere == l)
- /* The cmacro works like this: If it's NULL, the file is to
- be included again. If it's NEVER_REINCLUDE, 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. */
- return (i->cmacro
- && (i->cmacro == NEVER_REINCLUDE
- || i->cmacro->type != T_VOID))
- ? (IHASH *)-1 : i;
+ /* We used to open files in nonblocking mode, but that caused more
+ problems than it solved. Do take care not to acquire a
+ controlling terminal by mistake (this can't happen on sane
+ systems, but paranoia is a virtue).
- return 0;
-}
+ Use the three-argument form of open even though we aren't
+ specifying O_CREAT, to defend against broken system headers.
-/* Return 1 if the file named by FNAME has been included before in
- any context, 0 otherwise. */
-int
-cpp_included (pfile, fname)
- cpp_reader *pfile;
- const char *fname;
-{
- IHASH dummy, *ptr;
- dummy.nshort = fname;
- dummy.hash = _cpp_calc_hash ((const U_CHAR *)fname, strlen (fname));
- ptr = htab_find_with_hash (pfile->all_include_files,
- (const void *)&dummy, dummy.hash);
- return (ptr != NULL);
-}
+ O_BINARY tells some runtime libraries (notably DJGPP) not to do
+ newline translation; we can handle DOS line breaks just fine
+ ourselves.
-/* Create an IHASH entry and insert it in SLOT. */
-static IHASH *
-make_IHASH (name, fname, path, hash, slot)
- const char *name, *fname;
- struct file_name_list *path;
- unsigned int hash;
- IHASH **slot;
-{
- IHASH *ih;
- if (path == ABSOLUTE_PATH)
- {
- ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name));
- ih->nshort = ih->name;
- }
+ Special case: the empty string is translated to stdin. */
+ if (filename[0] == '\0')
+ fd = 0;
else
+ fd = open (filename, O_RDONLY|O_NOCTTY|O_BINARY, 0666);
+
+ if (fd == -1)
{
- char *s;
-
- if ((s = strstr (name, fname)) != NULL)
+#ifdef EACCES
+ if (errno == EACCES)
{
- ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name));
- ih->nshort = ih->name + (s - name);
+ cpp_error (pfile, "included file `%s' exists but is not readable",
+ filename);
}
- else
+#endif
+ /* Nonexistent or inaccessible file. Create a negative node for it. */
+ if (nd)
{
- ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name)
- + strlen (fname) + 1);
- ih->nshort = ih->name + strlen (name) + 1;
- strcpy ((char *)ih->nshort, fname);
+ cpp_ice (pfile,
+ "node for '%s' exists, open failed, error '%s', value %lx\n",
+ filename, strerror (errno), nd->value);
+ destroy_include_file_node (nd->value);
}
+ splay_tree_insert (pfile->all_include_files,
+ (splay_tree_key) xstrdup (filename), 0);
+ return 0;
}
- strcpy ((char *)ih->name, name);
- ih->foundhere = path;
- ih->cmacro = NULL;
- ih->hash = hash;
- ih->next_this_file = *slot;
- *slot = ih;
- return ih;
-}
-
-/* Centralize calls to open(2) here. This provides a hook for future
- changes which might, e.g. look for and open a precompiled version
- of the header. It also means all the magic currently associated
- with calling open is in one place, and if we ever need more, it'll
- be in one place too.
-
- We used to open files in nonblocking mode, but that caused more
- problems than it solved. Do take care not to acquire a controlling
- terminal by mistake (this can't happen on sane systems, but
- paranoia is a virtue).
- Use the three-argument form of open even though we aren't
- specifying O_CREAT, to defend against broken system headers.
-
- O_BINARY tells some runtime libraries (notably DJGPP) not to do
- newline translation; we can handle DOS line breaks just fine
- ourselves. */
+ /* If we haven't seen this file before, create a positive node for it. */
+ if (!nd)
+ {
+ file = xnew (struct include_file);
+ file->cmacro = 0;
+ file->before = 0;
+ file->sysp = 0;
+ file->foundhere = 0;
+ file->name = xstrdup (filename);
+ splay_tree_insert (pfile->all_include_files,
+ (splay_tree_key) file->name,
+ (splay_tree_value) file);
+ }
-static inline int
-open_include_file (pfile, filename)
- cpp_reader *pfile ATTRIBUTE_UNUSED;
- const char *filename;
-{
- return open (filename, O_RDONLY|O_NOCTTY|O_BINARY, 0666);
+ file->fd = fd;
+ return file;
}
-/* Search for include file FNAME in the include chain starting at
- SEARCH_START. Return -2 if this file doesn't need to be included
- (because it was included already and it's marked idempotent),
- -1 if an error occurred, or a file descriptor open on the file.
- *IHASH is set to point to the include hash entry for this file, and
- *BEFORE is set to 1 if the file was included before (but needs to be read
- again). */
-static int
-find_include_file (pfile, fname, search_start, ihash, before)
+/* Return 1 if the file named by FNAME has been included before in
+ any context, 0 otherwise. */
+int
+cpp_included (pfile, fname)
cpp_reader *pfile;
const char *fname;
- struct file_name_list *search_start;
- IHASH **ihash;
- int *before;
{
struct file_name_list *path;
- IHASH *ih, **slot;
- IHASH dummy;
- int f;
char *name;
+ splay_tree_node nd;
- dummy.nshort = fname;
- dummy.hash = _cpp_calc_hash ((const U_CHAR *)fname, strlen (fname));
- path = (fname[0] == '/') ? ABSOLUTE_PATH : search_start;
- slot = (IHASH **) htab_find_slot_with_hash (pfile->all_include_files,
- (const void *) &dummy,
- dummy.hash, INSERT);
-
- if (*slot && (ih = redundant_include_p (*slot, path)))
- {
- if (ih == (IHASH *)-1)
- return -2;
-
- *before = 1;
- *ihash = ih;
- return open_include_file (pfile, ih->name);
- }
-
- if (path == ABSOLUTE_PATH)
+ if (fname[0] == '/')
{
- name = (char *) fname;
- f = open_include_file (pfile, name);
+ /* Just look it up. */
+ nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) fname);
+ return (nd && nd->value);
}
- else
+
+ /* Search directory path for the file. */
+ name = (char *) alloca (strlen (fname) + pfile->max_include_len
+ + 2 + INCLUDE_LEN_FUDGE);
+ for (path = CPP_OPTION (pfile, quote_include); path; path = path->next)
{
- /* Search directory path, trying to open the file. */
- name = (char *) alloca (strlen (fname) + pfile->max_include_len
- + 2 + INCLUDE_LEN_FUDGE);
- do
- {
- memcpy (name, path->name, path->nlen);
- name[path->nlen] = '/';
- strcpy (&name[path->nlen+1], fname);
- _cpp_simplify_pathname (name);
- if (CPP_OPTION (pfile, remap))
- name = remap_filename (pfile, name, path);
-
- f = open_include_file (pfile, name);
-#ifdef EACCES
- if (f == -1 && errno == EACCES)
- {
- cpp_error (pfile,
- "included file `%s' exists but is not readable",
- name);
- return -1;
- }
-#endif
- if (f >= 0)
- break;
- path = path->next;
- }
- while (path);
+ memcpy (name, path->name, path->nlen);
+ name[path->nlen] = '/';
+ strcpy (&name[path->nlen+1], fname);
+ _cpp_simplify_pathname (name);
+ if (CPP_OPTION (pfile, remap))
+ name = remap_filename (pfile, name, path);
+
+ nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name);
+ if (nd && nd->value)
+ return 1;
}
- if (f == -1)
- return -1;
-
- ih = make_IHASH (name, fname, path, dummy.hash, slot);
- *before = 0;
- *ihash = ih;
- return f;
+ return 0;
}
-/* Create a dummy IHASH entry for FNAME, and return its name pointer.
- This is used by #line. */
-const char *
-_cpp_fake_ihash (pfile, fname)
+/* 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),
+ otherwise an include_file structure, possibly with a file descriptor
+ open on the file. */
+
+static struct include_file *
+find_include_file (pfile, fname, search_start)
cpp_reader *pfile;
const char *fname;
+ struct file_name_list *search_start;
{
- IHASH *ih, **slot;
- IHASH dummy;
-
- dummy.nshort = fname;
- dummy.hash = _cpp_calc_hash ((const U_CHAR *)fname, strlen (fname));
- slot = (IHASH **) htab_find_slot_with_hash (pfile->all_include_files,
- (const void *) &dummy,
- dummy.hash, INSERT);
- if (*slot)
- return (*slot)->name;
- ih = make_IHASH (fname, 0, ABSOLUTE_PATH, dummy.hash, slot);
- return ih->name;
-}
-
-
-/* The file_name_map structure holds a mapping of file names for a
- particular directory. This mapping is read from the file named
- FILE_NAME_MAP_FILE in that directory. Such a file can be used to
- map filenames on a file system with severe filename restrictions,
- 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;
- char *map_from;
- char *map_to;
-};
-
-#define FILE_NAME_MAP_FILE "header.gcc"
-
-/* Read a space delimited string of unlimited length from a stdio
- file. */
-
-static char *
-read_filename_string (ch, f)
- int ch;
- FILE *f;
-{
- char *alloc, *set;
- int len;
+ struct file_name_list *path;
+ char *name;
+ struct include_file *file;
- len = 20;
- set = alloc = xmalloc (len + 1);
- if (! is_space(ch))
+ if (fname[0] == '/')
+ return open_include_file (pfile, fname);
+
+ /* Search directory path for the file. */
+ name = (char *) alloca (strlen (fname) + pfile->max_include_len
+ + 2 + INCLUDE_LEN_FUDGE);
+ for (path = search_start; path; path = path->next)
{
- *set++ = ch;
- while ((ch = getc (f)) != EOF && ! is_space(ch))
+ memcpy (name, path->name, path->nlen);
+ name[path->nlen] = '/';
+ strcpy (&name[path->nlen+1], fname);
+ _cpp_simplify_pathname (name);
+ if (CPP_OPTION (pfile, remap))
+ name = remap_filename (pfile, name, path);
+
+ file = open_include_file (pfile, name);
+ if (file)
{
- if (set - alloc == len)
- {
- len *= 2;
- alloc = xrealloc (alloc, len + 1);
- set = alloc + len / 2;
- }
- *set++ = ch;
+ file->sysp = path->sysp;
+ file->foundhere = path;
+ return file;
}
}
- *set = '\0';
- ungetc (ch, f);
- return alloc;
+ return 0;
}
-/* 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;
- char *map_list_name;
- struct file_name_map *map_list_map;
-};
-
-/* Read the file name map file for DIRNAME. */
-
-static struct file_name_map *
-read_name_map (pfile, dirname)
+/* #line uses this to save artificial file names. We have to try
+ opening the file because an all_include_files entry is always
+ either + or -, there's no 'I don't know' value. */
+const char *
+_cpp_fake_include (pfile, fname)
cpp_reader *pfile;
- const char *dirname;
+ const char *fname;
{
- register struct file_name_map_list *map_list_ptr;
+ splay_tree_node nd;
+ struct include_file *file;
char *name;
- FILE *f;
- for (map_list_ptr = CPP_OPTION (pfile, map_list); map_list_ptr;
- map_list_ptr = map_list_ptr->map_list_next)
- if (! strcmp (map_list_ptr->map_list_name, dirname))
- return map_list_ptr->map_list_map;
+ file = find_include_file (pfile, fname, CPP_OPTION (pfile, quote_include));
+ if (file)
+ return file->name;
- map_list_ptr = ((struct file_name_map_list *)
- xmalloc (sizeof (struct file_name_map_list)));
- map_list_ptr->map_list_name = xstrdup (dirname);
+ name = xstrdup (fname);
+ _cpp_simplify_pathname (name);
- name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
- strcpy (name, dirname);
- if (*dirname)
- strcat (name, "/");
- strcat (name, FILE_NAME_MAP_FILE);
- f = fopen (name, "r");
- if (!f)
- map_list_ptr->map_list_map = (struct file_name_map *)-1;
- else
+ /* We cannot just blindly insert a node, because there's still the
+ chance that the node already exists but isn't on the search path. */
+ nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name);
+ if (nd)
{
- int ch;
- int dirlen = strlen (dirname);
-
- while ((ch = getc (f)) != EOF)
- {
- char *from, *to;
- struct file_name_map *ptr;
-
- if (is_space(ch))
- continue;
- from = read_filename_string (ch, f);
- while ((ch = getc (f)) != EOF && is_hspace(ch))
- ;
- to = read_filename_string (ch, f);
-
- ptr = ((struct file_name_map *)
- xmalloc (sizeof (struct file_name_map)));
- ptr->map_from = from;
-
- /* Make the real filename absolute. */
- if (*to == '/')
- ptr->map_to = to;
- else
- {
- ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
- strcpy (ptr->map_to, dirname);
- ptr->map_to[dirlen] = '/';
- strcpy (ptr->map_to + dirlen + 1, to);
- free (to);
- }
-
- ptr->map_next = map_list_ptr->map_list_map;
- map_list_ptr->map_list_map = ptr;
-
- while ((ch = getc (f)) != '\n')
- if (ch == EOF)
- break;
- }
- fclose (f);
+ free (name);
+ return (const char *) nd->key;
}
-
- map_list_ptr->map_list_next = CPP_OPTION (pfile, map_list);
- CPP_OPTION (pfile, map_list) = map_list_ptr;
-
- return map_list_ptr->map_list_map;
-}
-
-/* Remap NAME based on the file_name_map (if any) for LOC. */
-
-static char *
-remap_filename (pfile, name, loc)
- cpp_reader *pfile;
- char *name;
- struct file_name_list *loc;
-{
- struct file_name_map *map;
- const char *from, *p, *dir;
-
- if (! loc->name_map)
- loc->name_map = read_name_map (pfile,
- loc->name
- ? loc->name : ".");
-
- if (loc->name_map == (struct file_name_map *)-1)
- return name;
-
- from = name + strlen (loc->name) + 1;
-
- for (map = loc->name_map; map; map = map->map_next)
- if (!strcmp (map->map_from, from))
- return map->map_to;
- /* Try to find a mapping file for the particular directory we are
- looking in. Thus #include <sys/types.h> will look up sys/types.h
- in /usr/include/header.gcc and look up types.h in
- /usr/include/sys/header.gcc. */
- p = strrchr (name, '/');
- if (!p)
- p = name;
- if (loc && loc->name
- && strlen (loc->name) == (size_t) (p - name)
- && !strncmp (loc->name, name, p - name))
- /* FILENAME is in SEARCHPTR, which we've already checked. */
- return name;
-
- if (p == name)
- {
- dir = ".";
- from = name;
- }
- else
- {
- char * newdir = (char *) alloca (p - name + 1);
- memcpy (newdir, name, p - name);
- newdir[p - name] = '\0';
- dir = newdir;
- from = p + 1;
- }
-
- for (map = read_name_map (pfile, dir); map; map = map->map_next)
- if (! strcmp (map->map_from, name))
- return map->map_to;
-
- return name;
+ splay_tree_insert (pfile->all_include_files, (splay_tree_key) name, 0);
+ return (const char *)name;
}
-
+#define PRINT_THIS_DEP(p, b) (CPP_PRINT_DEPS(p) > (b||p->system_include_depth))
void
_cpp_execute_include (pfile, f, len, no_reinclude, search_start)
cpp_reader *pfile;
@@ -541,11 +317,9 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start)
int no_reinclude;
struct file_name_list *search_start;
{
- IHASH *ihash;
+ struct include_file *inc;
char *fname = (char *)f;
- int fd;
int angle_brackets = fname[0] == '<';
- int before;
if (!search_start)
{
@@ -568,83 +342,80 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start)
len -= 2;
fname[len] = '\0';
- fd = find_include_file (pfile, fname, search_start, &ihash, &before);
+ inc = find_include_file (pfile, fname, search_start);
- if (fd == -2)
- return;
-
- if (fd == -1)
+ if (inc)
{
- if (CPP_OPTION (pfile, print_deps_missing_files)
- && CPP_PRINT_DEPS (pfile) > (angle_brackets ||
- (pfile->system_include_depth > 0)))
- {
- if (!angle_brackets)
- deps_add_dep (pfile->deps, fname);
- else
- {
- char *p;
- struct file_name_list *ptr;
- /* If requested as a system header, assume it belongs in
- the first system header directory. */
- if (CPP_OPTION (pfile, bracket_include))
- ptr = CPP_OPTION (pfile, bracket_include);
- else
- ptr = CPP_OPTION (pfile, quote_include);
-
- p = (char *) alloca (strlen (ptr->name)
- + strlen (fname) + 2);
- if (*ptr->name != '\0')
- {
- strcpy (p, ptr->name);
- strcat (p, "/");
- }
- strcat (p, fname);
- deps_add_dep (pfile->deps, p);
- }
+ if (inc->fd == -1)
+ return;
+
+ /* For -M, add the file to the dependencies on its first inclusion. */
+ if (!inc->before && PRINT_THIS_DEP (pfile, angle_brackets))
+ deps_add_dep (pfile->deps, inc->name);
+ inc->before = 1;
+
+ /* 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);
}
- /* If -M was specified, and this header file won't be added to
- the dependency list, then don't count this as an error,
- because 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. */
- else if (CPP_PRINT_DEPS (pfile)
- && (CPP_PRINT_DEPS (pfile)
- <= (angle_brackets || (pfile->system_include_depth > 0))))
- cpp_warning (pfile, "No include path in which to find %s", fname);
- else
- cpp_error_from_errno (pfile, fname);
+ /* Actually process the file. */
+ if (no_reinclude)
+ inc->cmacro = NEVER_REREAD;
+
+ if (read_include_file (pfile, inc))
+ {
+ if (angle_brackets)
+ pfile->system_include_depth++;
+ }
return;
}
-
- /* For -M, add the file to the dependencies on its first inclusion. */
- if (!before && (CPP_PRINT_DEPS (pfile)
- > (angle_brackets || (pfile->system_include_depth > 0))))
- deps_add_dep (pfile->deps, ihash->name);
-
- /* Handle -H option. */
- if (CPP_OPTION (pfile, print_include_names))
+
+ if (CPP_OPTION (pfile, print_deps_missing_files)
+ && PRINT_THIS_DEP (pfile, angle_brackets))
{
- cpp_buffer *fp = CPP_BUFFER (pfile);
- while ((fp = CPP_PREV_BUFFER (fp)) != NULL)
- putc ('.', stderr);
- fprintf (stderr, " %s\n", ihash->name);
- }
+ if (!angle_brackets)
+ deps_add_dep (pfile->deps, fname);
+ else
+ {
+ char *p;
+ struct file_name_list *ptr;
+ /* If requested as a system header, assume it belongs in
+ the first system header directory. */
+ if (CPP_OPTION (pfile, bracket_include))
+ ptr = CPP_OPTION (pfile, bracket_include);
+ else
+ ptr = CPP_OPTION (pfile, quote_include);
- /* Actually process the file. */
- if (no_reinclude)
- ihash->cmacro = NEVER_REINCLUDE;
-
- if (read_include_file (pfile, fd, ihash))
- {
- if (angle_brackets)
- pfile->system_include_depth++;
+ p = (char *) alloca (strlen (ptr->name)
+ + strlen (fname) + 2);
+ if (*ptr->name != '\0')
+ {
+ strcpy (p, ptr->name);
+ strcat (p, "/");
+ }
+ strcat (p, fname);
+ _cpp_simplify_pathname (p);
+ deps_add_dep (pfile->deps, p);
+ }
}
+ /* If -M was specified, and this header file won't be added to
+ the dependency list, then don't count this as an error,
+ because 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. */
+ else if (CPP_PRINT_DEPS (pfile)
+ && ! PRINT_THIS_DEP (pfile, angle_brackets))
+ cpp_warning (pfile, "No include path in which to find %s", fname);
+ else
+ cpp_error_from_errno (pfile, fname);
}
-
/* Push an input buffer and load it up with the contents of FNAME.
If FNAME is "" or NULL, read standard input. */
int
@@ -652,53 +423,28 @@ cpp_read_file (pfile, fname)
cpp_reader *pfile;
const char *fname;
{
- IHASH *ih, **slot;
- IHASH dummy;
- int f;
+ struct include_file *f;
if (fname == NULL)
fname = "";
- dummy.nshort = fname;
- /* _cpp_calc_hash doesn't like zero-length strings. */
- if (*fname == 0)
- dummy.hash = 0;
- else
- dummy.hash = _cpp_calc_hash ((const U_CHAR *)fname, strlen (fname));
- slot = (IHASH **) htab_find_slot_with_hash (pfile->all_include_files,
- (const void *) &dummy,
- dummy.hash, INSERT);
- if (*slot && (ih = redundant_include_p (*slot, ABSOLUTE_PATH)))
- {
- if (ih == (IHASH *) -1)
- return 1; /* Already included. */
- }
- else
- ih = make_IHASH (fname, 0, ABSOLUTE_PATH, dummy.hash, slot);
-
- if (*fname == '\0')
- f = 0;
- else
- f = open_include_file (pfile, fname);
+ f = open_include_file (pfile, fname);
- return read_include_file (pfile, f, ih);
+ return read_include_file (pfile, f);
}
-/* Read the contents of FD into the buffer on the top of PFILE's stack.
- IHASH points to the include hash entry for the file associated with
- FD.
-
- The caller is responsible for the cpp_push_buffer. */
+/* 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, fd, ihash)
+read_include_file (pfile, inc)
cpp_reader *pfile;
- int fd;
- IHASH *ihash;
+ struct include_file *inc;
{
struct stat st;
ssize_t length;
cpp_buffer *fp;
+ int fd = inc->fd;
fp = cpp_push_buffer (pfile, NULL, 0);
@@ -733,7 +479,7 @@ read_include_file (pfile, fd, ihash)
does not bite us. */
if (st.st_size > INTTYPE_MAXIMUM (ssize_t))
{
- cpp_error (pfile, "%s is too large", ihash->name);
+ cpp_error (pfile, "%s is too large", inc->name);
goto fail;
}
st_size = st.st_size;
@@ -741,16 +487,16 @@ read_include_file (pfile, fd, ihash)
if (length == -1)
goto perror_fail;
if (length < st_size)
- cpp_warning (pfile, "%s is shorter than expected\n", ihash->name);
+ 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", ihash->name);
+ 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", ihash->name);
+ cpp_error (pfile, "%s is a directory", inc->name);
goto fail;
}
else
@@ -764,38 +510,38 @@ read_include_file (pfile, fd, ihash)
}
/* These must be set before prescan. */
- fp->ihash = ihash;
- fp->nominal_fname = ihash->name;
+ fp->inc = inc;
+ fp->nominal_fname = inc->name;
if (length == 0)
- ihash->cmacro = NEVER_REINCLUDE;
+ inc->cmacro = NEVER_REREAD;
else
/* Temporary - I hope. */
length = _cpp_prescan (pfile, fp, length);
fp->rlimit = fp->buf + length;
fp->cur = fp->buf;
- if (ihash->foundhere != ABSOLUTE_PATH)
- fp->system_header_p = ihash->foundhere->sysp;
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, ihash->name);
+ fp->actual_dir = actual_directory (pfile, inc->name);
pfile->input_stack_listing_current = 0;
pfile->only_seen_white = 2;
- close (fd);
return 1;
perror_fail:
- cpp_error_from_errno (pfile, ihash->name);
+ cpp_error_from_errno (pfile, inc->name);
+ /* Do not try to read this file again. */
+ close (fd);
+ inc->fd = -1;
+ inc->cmacro = NEVER_REREAD;
fail:
cpp_pop_buffer (pfile);
push_fail:
- close (fd);
return 0;
}
@@ -867,6 +613,200 @@ read_with_read (fp, fd, size)
return offset;
}
+/* The file_name_map structure holds a mapping of file names for a
+ particular directory. This mapping is read from the file named
+ FILE_NAME_MAP_FILE in that directory. Such a file can be used to
+ map filenames on a file system with severe filename restrictions,
+ 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;
+ char *map_from;
+ char *map_to;
+};
+
+#define FILE_NAME_MAP_FILE "header.gcc"
+
+/* Read a space delimited string of unlimited length from a stdio
+ file. */
+
+static char *
+read_filename_string (ch, f)
+ int ch;
+ FILE *f;
+{
+ char *alloc, *set;
+ int len;
+
+ len = 20;
+ set = alloc = xmalloc (len + 1);
+ if (! is_space(ch))
+ {
+ *set++ = ch;
+ while ((ch = getc (f)) != EOF && ! is_space(ch))
+ {
+ if (set - alloc == len)
+ {
+ len *= 2;
+ alloc = xrealloc (alloc, len + 1);
+ set = alloc + len / 2;
+ }
+ *set++ = ch;
+ }
+ }
+ *set = '\0';
+ ungetc (ch, f);
+ return alloc;
+}
+
+/* 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;
+ char *map_list_name;
+ struct file_name_map *map_list_map;
+};
+
+/* Read the file name map file for DIRNAME. */
+
+static struct file_name_map *
+read_name_map (pfile, dirname)
+ cpp_reader *pfile;
+ const char *dirname;
+{
+ register struct file_name_map_list *map_list_ptr;
+ char *name;
+ FILE *f;
+
+ for (map_list_ptr = CPP_OPTION (pfile, map_list); map_list_ptr;
+ map_list_ptr = map_list_ptr->map_list_next)
+ if (! strcmp (map_list_ptr->map_list_name, dirname))
+ return map_list_ptr->map_list_map;
+
+ map_list_ptr = ((struct file_name_map_list *)
+ xmalloc (sizeof (struct file_name_map_list)));
+ map_list_ptr->map_list_name = xstrdup (dirname);
+
+ name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
+ strcpy (name, dirname);
+ if (*dirname)
+ strcat (name, "/");
+ strcat (name, FILE_NAME_MAP_FILE);
+ f = fopen (name, "r");
+ if (!f)
+ map_list_ptr->map_list_map = (struct file_name_map *)-1;
+ else
+ {
+ int ch;
+ int dirlen = strlen (dirname);
+
+ while ((ch = getc (f)) != EOF)
+ {
+ char *from, *to;
+ struct file_name_map *ptr;
+
+ if (is_space(ch))
+ continue;
+ from = read_filename_string (ch, f);
+ while ((ch = getc (f)) != EOF && is_hspace(ch))
+ ;
+ to = read_filename_string (ch, f);
+
+ ptr = ((struct file_name_map *)
+ xmalloc (sizeof (struct file_name_map)));
+ ptr->map_from = from;
+
+ /* Make the real filename absolute. */
+ if (*to == '/')
+ ptr->map_to = to;
+ else
+ {
+ ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
+ strcpy (ptr->map_to, dirname);
+ ptr->map_to[dirlen] = '/';
+ strcpy (ptr->map_to + dirlen + 1, to);
+ free (to);
+ }
+
+ ptr->map_next = map_list_ptr->map_list_map;
+ map_list_ptr->map_list_map = ptr;
+
+ while ((ch = getc (f)) != '\n')
+ if (ch == EOF)
+ break;
+ }
+ fclose (f);
+ }
+
+ map_list_ptr->map_list_next = CPP_OPTION (pfile, map_list);
+ CPP_OPTION (pfile, map_list) = map_list_ptr;
+
+ return map_list_ptr->map_list_map;
+}
+
+/* Remap NAME based on the file_name_map (if any) for LOC. */
+
+static char *
+remap_filename (pfile, name, loc)
+ cpp_reader *pfile;
+ char *name;
+ struct file_name_list *loc;
+{
+ struct file_name_map *map;
+ const char *from, *p, *dir;
+
+ if (! loc->name_map)
+ loc->name_map = read_name_map (pfile,
+ loc->name
+ ? loc->name : ".");
+
+ if (loc->name_map == (struct file_name_map *)-1)
+ return name;
+
+ from = name + strlen (loc->name) + 1;
+
+ for (map = loc->name_map; map; map = map->map_next)
+ if (!strcmp (map->map_from, from))
+ return map->map_to;
+
+ /* Try to find a mapping file for the particular directory we are
+ looking in. Thus #include <sys/types.h> will look up sys/types.h
+ in /usr/include/header.gcc and look up types.h in
+ /usr/include/sys/header.gcc. */
+ p = strrchr (name, '/');
+ if (!p)
+ p = name;
+ if (loc && loc->name
+ && strlen (loc->name) == (size_t) (p - name)
+ && !strncmp (loc->name, name, p - name))
+ /* FILENAME is in SEARCHPTR, which we've already checked. */
+ return name;
+
+ if (p == name)
+ {
+ dir = ".";
+ from = name;
+ }
+ else
+ {
+ char * newdir = (char *) alloca (p - name + 1);
+ memcpy (newdir, name, p - name);
+ newdir[p - name] = '\0';
+ dir = newdir;
+ from = p + 1;
+ }
+
+ for (map = read_name_map (pfile, dir); map; map = map->map_next)
+ if (! strcmp (map->map_from, name))
+ return map->map_to;
+
+ return name;
+}
+
/* 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
@@ -919,7 +859,7 @@ actual_directory (pfile, fname)
x->nlen = dlen;
x->next = CPP_OPTION (pfile, quote_include);
x->alloc = pfile->actual_dirs;
- x->sysp = CPP_BUFFER (pfile)->system_header_p;
+ x->sysp = CPP_BUFFER (pfile)->inc->sysp;
x->name_map = NULL;
pfile->actual_dirs = x;