diff options
author | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-06-21 18:33:51 +0000 |
---|---|---|
committer | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-06-21 18:33:51 +0000 |
commit | c95d8aaa18938a46f022ce74ac75b21ef1e98bad (patch) | |
tree | eb5aadb8fbe401846a1ceb69f99c1b4e7af8d929 /gcc/cppfiles.c | |
parent | 5ba7b7e9d0549acfe9d7b3ba07d8a20b2c1d7ae6 (diff) | |
download | gcc-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.c | 990 |
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; |