From: Zack Weinberg Date: Wed, 25 Nov 1998 11:56:54 +0000 (+0000) Subject: cpplib.h: Delete struct import_file. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0b3d776a4260dc4dbecb16a0cd63aec58c96bb7d;p=gcc.git cpplib.h: Delete struct import_file. Wed Nov 25 14:54:46 1998 Zack Weinberg * cpplib.h: Delete struct import_file. Add ihash element to struct cpp_buffer. Delete dont_repeat_files and import_hash_table elements from cpp_reader; change all_include_files to a hash table. Delete all foobar_include / last_foobar_include elements from struct cpp_options; put back four such: quote_include, bracket_include, system_include, after_include. Redo struct file_name_list completely. Add new structure type include_hash. Add prototypes for merge_include_chains and include_hash. Change prototypes for finclude, find_include_file, and append_include_chain to match changes below. * cppfiles.c (simplify_pathname, include_hash, remap_filename, merge_include_chains): New functions. (add_import, lookup_import, open_include_file): Removed. (INO_T_EQ): Define this (copied from cccp.c). (hack_vms_include_specification): Remove all calls and #if 0 out the definition. It was being called incorrectly and at the wrong times. Until a VMSie can look at this, it's better to not pretend to support it. (append_include_chain): Change calling convention; now takes only one directory at a time, and sets up the data structure itself. (redundant_include_p): Rewritten - this is now used for all include redundancy, whether by #ifndef, #import, or #pragma once. Looks up things in the include hash table. (file_cleanup): Decrement pfile->system_include_depth here if it's >0. (find_include_file): Calling convention changed; now passes around a struct include_hash instead of 3 separate parameters. Guts ripped out and replaced with new include_hash mechanism. (finclude): Calling convention changed as for find_include_file. Error exits pulled out-of-line. Reformat. (safe_read): Return a long, not an int. (deps_output): Don't recurse. * cpplib.c (is_system_include): Deleted. (path_include): Fix up call to append_include_chain. (do_include): Fix up calls to find_include_file and finclude. Clean up dependency output a bit. Shorten obnoxiously lengthy #import warning message. Don't decrement pfile->system_include_depth here. (do_pragma): Understand the include_hash structure. Reformat. (do_endif): Correct handling of control macros. Understand the include_hash. (cpp_start_read): Fix up calls to finclude. Call merge_include_chains. (cpp_handle_option): Fix up calls to append_include_chain. Understand the four partial include chains. (cpp_finish): Add debugging code (#if 0-ed out) for the include_hash. (cpp_cleanup): Free the include_hash, not the import hash and the all_include and dont_repeat lists which no longer exist. From-SVN: r23857 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fdf4b63c26e..b684e5bfc2c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,59 @@ +Wed Nov 25 14:54:46 1998 Zack Weinberg + + * cpplib.h: Delete struct import_file. Add ihash element to + struct cpp_buffer. Delete dont_repeat_files and + import_hash_table elements from cpp_reader; change + all_include_files to a hash table. Delete all foobar_include + / last_foobar_include elements from struct cpp_options; put + back four such: quote_include, bracket_include, + system_include, after_include. Redo struct file_name_list + completely. Add new structure type include_hash. Add + prototypes for merge_include_chains and include_hash. Change + prototypes for finclude, find_include_file, and + append_include_chain to match changes below. + + * cppfiles.c (simplify_pathname, include_hash, + remap_filename, merge_include_chains): New functions. + (add_import, lookup_import, open_include_file): Removed. + (INO_T_EQ): Define this (copied from cccp.c). + (hack_vms_include_specification): Remove all calls and #if 0 + out the definition. It was being called incorrectly and at + the wrong times. Until a VMSie can look at this, it's better + to not pretend to support it. + (append_include_chain): Change calling convention; now takes + only one directory at a time, and sets up the data structure + itself. + (redundant_include_p): Rewritten - this is now used for all + include redundancy, whether by #ifndef, #import, or #pragma + once. Looks up things in the include hash table. + (file_cleanup): Decrement pfile->system_include_depth here if + it's >0. + (find_include_file): Calling convention changed; now passes + around a struct include_hash instead of 3 separate parameters. + Guts ripped out and replaced with new include_hash mechanism. + (finclude): Calling convention changed as for + find_include_file. Error exits pulled out-of-line. Reformat. + (safe_read): Return a long, not an int. + (deps_output): Don't recurse. + + * cpplib.c (is_system_include): Deleted. + (path_include): Fix up call to append_include_chain. + (do_include): Fix up calls to find_include_file and finclude. + Clean up dependency output a bit. Shorten obnoxiously lengthy + #import warning message. Don't decrement + pfile->system_include_depth here. + (do_pragma): Understand the include_hash structure. Reformat. + (do_endif): Correct handling of control macros. Understand + the include_hash. + (cpp_start_read): Fix up calls to finclude. Call + merge_include_chains. + (cpp_handle_option): Fix up calls to append_include_chain. + Understand the four partial include chains. + (cpp_finish): Add debugging code (#if 0-ed out) for the + include_hash. + (cpp_cleanup): Free the include_hash, not the import hash and + the all_include and dont_repeat lists which no longer exist. + Wed Nov 25 11:26:19 1998 Jeffrey A Law (law@cygnus.com) * toplev.c (no_new_pseudos): Define. diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c index 94562ab9acb..b0e20825a12 100644 --- a/gcc/cppfiles.c +++ b/gcc/cppfiles.c @@ -28,333 +28,447 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "cpplib.h" /* The entry points to this file are: find_include_file, finclude, - append_include_chain, deps_output, and file_cleanup. + include_hash, append_include_chain, deps_output, and file_cleanup. file_cleanup is only called through CPP_BUFFER(pfile)->cleanup, so it's static anyway. */ -static void add_import PROTO ((cpp_reader *, int, char *)); -static int lookup_import PROTO ((cpp_reader *, char *, +static struct include_hash *redundant_include_p + PROTO ((cpp_reader *, + struct include_hash *, struct file_name_list *)); -static int redundant_include_p PROTO ((cpp_reader *, char *)); static struct file_name_map *read_name_map PROTO ((cpp_reader *, char *)); static char *read_filename_string PROTO ((int, FILE *)); -static int open_include_file PROTO ((cpp_reader *, char *, +static char *remap_filename PROTO ((cpp_reader *, char *, struct file_name_list *)); -static int safe_read PROTO ((int, char *, int)); +static long safe_read PROTO ((int, char *, int)); +static void simplify_pathname PROTO ((char *)); + +#if 0 +static void hack_vms_include_specification PROTO ((char *)); +#endif /* Not safe to prototype these. */ extern char *xmalloc(); extern char *xrealloc(); -/* Append a chain of `struct file_name_list's - to the end of the main include chain. - FIRST is the beginning of the chain to append, and LAST is the end. */ +/* Windows does not natively support inodes, and neither does MSDOS. + VMS has non-numeric inodes. */ +#ifdef VMS +#define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a))) +#elif (defined _WIN32 && !defined CYGWIN) || defined __MSDOS__ +#define INO_T_EQ(a, b) 0 +#else +#define INO_T_EQ(a, b) ((a) == (b)) +#endif +/* Append an entry for dir DIR to list LIST, simplifying it if + possible. SYS says whether this is a system include directory. + *** DIR is modified in place. It must be writable and permanently + allocated. LIST is a pointer to the head pointer, because we actually + *prepend* the dir, and reverse the list later (in merge_include_chains). */ void -append_include_chain (pfile, first, last) +append_include_chain (pfile, list, dir, sysp) cpp_reader *pfile; - struct file_name_list *first, *last; + struct file_name_list **list; + char *dir; + int sysp; { - struct cpp_options *opts = CPP_OPTIONS (pfile); - struct file_name_list *dir; - - if (!first || !last) - return; - - if (opts->include == 0) - opts->include = first; - else - opts->last_include->next = first; + struct file_name_list *new; + struct stat st; + unsigned int len; - if (opts->first_bracket_include == 0) - opts->first_bracket_include = first; + dir = savestring (dir); + simplify_pathname (dir); + if (stat (dir, &st)) + { + /* Dirs that don't exist are silently ignored. */ + if (errno != ENOENT) + cpp_perror_with_name (pfile, dir); + return; + } - for (dir = first; ; dir = dir->next) { - int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE; - if (len > pfile->max_include_len) - pfile->max_include_len = len; - if (dir == last) - break; - } + if (!S_ISDIR (st.st_mode)) + { + cpp_message (pfile, 1, "%s: %s: Not a directory", progname, dir); + return; + } - last->next = NULL; - opts->last_include = last; + len = strlen(dir); + if (len > pfile->max_include_len) + pfile->max_include_len = len; + + new = (struct file_name_list *)xmalloc (sizeof (struct file_name_list)); + new->name = dir; + new->nlen = len; + new->next = *list; + new->ino = st.st_ino; + new->dev = st.st_dev; + new->sysp = sysp; + new->name_map = NULL; + + *list = new; } -/* Add output to `deps_buffer' for the -M switch. - STRING points to the text to be output. - SPACER is ':' for targets, ' ' for dependencies, zero for text - to be inserted literally. */ +/* Merge the four include chains together in the order quote, bracket, + system, after. Remove duplicate dirs (as determined by + INO_T_EQ()). The system_include and after_include chains are never + referred to again after this function; all access is through the + bracket_include path. + + For the future: Check if the directory is empty (but + how?) and possibly preload the include hash. */ void -deps_output (pfile, string, spacer) - cpp_reader *pfile; - char *string; - int spacer; +merge_include_chains (opts) + struct cpp_options *opts; { - int size; - - if (!*string) - return; - -#ifdef VMS - hack_vms_include_specification (string); -#endif - - size = strlen (string); - -#ifndef MAX_OUTPUT_COLUMNS -#define MAX_OUTPUT_COLUMNS 72 -#endif - if (spacer - && pfile->deps_column > 0 - && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS) + struct file_name_list *prev, *next, *cur, *other; + struct file_name_list *quote, *brack, *systm, *after; + struct file_name_list *qtail, *btail, *stail, *atail; + + qtail = opts->quote_include; + btail = opts->bracket_include; + stail = opts->system_include; + atail = opts->after_include; + + /* Nreverse the four lists. */ + prev = 0; + for (cur = qtail; cur; cur = next) { - deps_output (pfile, " \\\n ", 0); - pfile->deps_column = 0; + next = cur->next; + cur->next = prev; + prev = cur; } + quote = prev; - if (pfile->deps_size + size + 8 > pfile->deps_allocated_size) + prev = 0; + for (cur = btail; cur; cur = next) { - pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2; - pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer, - pfile->deps_allocated_size); + next = cur->next; + cur->next = prev; + prev = cur; } - if (spacer == ' ' && pfile->deps_column > 0) - pfile->deps_buffer[pfile->deps_size++] = ' '; - bcopy (string, &pfile->deps_buffer[pfile->deps_size], size); - pfile->deps_size += size; - pfile->deps_column += size; - if (spacer == ':') - pfile->deps_buffer[pfile->deps_size++] = ':'; - pfile->deps_buffer[pfile->deps_size] = 0; -} + brack = prev; -static int -file_cleanup (pbuf, pfile) - cpp_buffer *pbuf; - cpp_reader *pfile ATTRIBUTE_UNUSED; -{ - if (pbuf->buf) + prev = 0; + for (cur = stail; cur; cur = next) { - free (pbuf->buf); - pbuf->buf = 0; + next = cur->next; + cur->next = prev; + prev = cur; } - return 0; -} + systm = prev; -int -find_include_file (pfile, fbeg, flen, fname, - importing, search_start, foundhere) - cpp_reader *pfile; - char *fbeg; - unsigned long flen; - char *fname; - int importing; - struct file_name_list *search_start; - struct file_name_list **foundhere; -{ - struct file_name_list *searchptr; - int f; - - /* If specified file name is absolute, just open it. */ + prev = 0; + for (cur = atail; cur; cur = next) + { + next = cur->next; + cur->next = prev; + prev = cur; + } + after = prev; - if (*fbeg == '/') - { - strcpy (fname, fbeg); -#ifdef VMS - hack_vms_include_specification (fname); -#endif - if (redundant_include_p (pfile, fname)) - return -2; - if (importing) - f = lookup_import (pfile, fname, NULL_PTR); - else - f = open_include_file (pfile, fname, NULL_PTR); - if (f == -2) - return -2; /* Already included this file */ - } + /* Paste together bracket, system, and after include chains. */ + if (stail) + stail->next = after; else - { - /* Search directory path, trying to open the file. - Copy each filename tried into FNAME. */ - - for (searchptr = search_start; searchptr; searchptr = searchptr->next) - { - unsigned int l = 0; - if (searchptr->fname) - { - /* The empty string in a search path is ignored. - This makes it possible to turn off entirely - a standard piece of the list. */ - if (searchptr->fname[0] == 0) - continue; + systm = after; + if (btail) + btail->next = systm; + else + brack = systm; - l = strlen (searchptr->fname); + /* This is a bit tricky. + First we drop dupes from the quote-include list. + Then we drop dupes from the bracket-include list. + Finally, if qtail and brack are the same directory, + we cut out qtail. - bcopy (searchptr->fname, fname, l); - fname[l++] = '/'; - } + We can't just merge the lists and then uniquify them because + then we may lose directories from the <> search path that should + be there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however + safe to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written + -Ibar -I- -Ifoo -Iquux. */ - bcopy (fbeg, &fname[l], flen); - fname[flen+l] = '\0'; -#ifdef VMS - hack_vms_include_specification (fname); -#endif /* VMS */ - /* ??? There are currently 3 separate mechanisms for avoiding processing - of redundant include files: #import, #pragma once, and - redundant_include_p. It would be nice if they were unified. */ - if (redundant_include_p (pfile, fname)) - return -2; - if (importing) - f = lookup_import (pfile, fname, searchptr); - else - f = open_include_file (pfile, fname, searchptr); - if (f == -2) - return -2; /* Already included this file */ -#ifdef EACCES - else if (f == -1 && errno == EACCES) - cpp_warning (pfile, "Header file %s exists, but is not readable", - fname); -#endif - if (f >= 0) - break; + for (cur = quote; cur; cur = cur->next) + { + for (other = quote; other != cur; other = other->next) + if (INO_T_EQ (cur->ino, other->ino) + && cur->dev == other->dev) + { + prev->next = cur->next; + free (cur->name); + free (cur); + cur = prev; + break; + } + prev = cur; } - } + qtail = prev; - if (f < 0) + for (cur = brack; cur; cur = cur->next) { - /* A file that was not found. */ - bcopy (fbeg, fname, flen); - fname[flen] = 0; - - return -1; + for (other = brack; other != cur; other = other->next) + if (INO_T_EQ (cur->ino, other->ino) + && cur->dev == other->dev) + { + prev->next = cur->next; + free (cur->name); + free (cur); + cur = prev; + break; + } + prev = cur; } - else - { - /* Check to see if this include file is a once-only include file. - If so, give up. */ - - struct file_name_list *ptr; - for (ptr = pfile->dont_repeat_files; ptr; ptr = ptr->next) - if (!strcmp (ptr->fname, fname)) + if (quote) + { + if (INO_T_EQ (qtail->ino, brack->ino) && qtail->dev == brack->dev) + { + if (quote == qtail) + { + free (quote->name); + free (quote); + quote = brack; + } + else { - close (f); - return -2; /* This file was once'd. */ + cur = quote; + while (cur->next != qtail) + cur = cur->next; + cur->next = brack; + free (qtail->name); + free (qtail); } + } + else + qtail->next = brack; } + else + quote = brack; - /* Record file on "seen" list for #import. */ - add_import (pfile, f, fname); - - *foundhere = searchptr; - return f; + opts->quote_include = quote; + opts->bracket_include = brack; + opts->system_include = NULL; + opts->after_include = NULL; } -/* Return nonzero if there is no need to include file NAME - because it has already been included and it contains a conditional - to make a repeated include do nothing. */ +/* Look up or add an entry to the table of all includes. This table + is indexed by the name as it appears in the #include line. The + ->next_this_file chain stores all different files with the same + #include name (there are at least three ways this can happen). The + hash function could probably be improved a bit. */ -static int -redundant_include_p (pfile, name) +struct include_hash * +include_hash (pfile, fname, add) cpp_reader *pfile; - char *name; + char *fname; + int add; { - struct file_name_list *l = pfile->all_include_files; - for (; l; l = l->next) - if (! strcmp (name, l->fname) - && l->control_macro - && cpp_lookup (pfile, l->control_macro, -1, -1)) - return 1; - return 0; -} + unsigned int hash = 0; + struct include_hash *l, *m; + char *f = fname; + while (*f) + hash += *f++; + l = pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE]; + m = 0; + for (; l; m = l, l = l->next) + if (!strcmp (l->nshort, fname)) + return l; -/* Maintain and search list of included files, for #import. */ + if (!add) + return 0; + + l = (struct include_hash *) xmalloc (sizeof (struct include_hash)); + l->next = NULL; + l->next_this_file = NULL; + l->foundhere = NULL; + l->buf = NULL; + l->limit = NULL; + if (m) + m->next = l; + else + pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE] = l; + + return l; +} -/* Hash a file name for import_hash_table. */ +/* 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. -static int -import_hash (f) - char *f; -{ - int val = 0; + 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: - while (*f) val += *f++; - return (val%IMPORT_HASH_SIZE); -} + top.c: + #include "a/a.h" + #include "b/b.h" -/* Search for file FILENAME in import_hash_table. - Return -2 if found, either a matching name or a matching inode. - Otherwise, open the file and return a file descriptor if successful - or -1 if unsuccessful. */ + a/a.h: + #include "../b/b.h" -static int -lookup_import (pfile, filename, searchptr) + 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. */ + +static struct include_hash * +redundant_include_p (pfile, ihash, ilist) cpp_reader *pfile; - char *filename; - struct file_name_list *searchptr; + struct include_hash *ihash; + struct file_name_list *ilist; { - struct import_file *i; - int h; - int hashval; - struct stat sb; - int fd; + struct file_name_list *l; + struct include_hash *i; - hashval = import_hash (filename); + if (! ihash->foundhere) + return 0; - /* Attempt to find file in list of already included files */ - i = pfile->import_hash_table[hashval]; + for (i = ihash; i; i = i->next_this_file) + for (l = ilist; l; l = l->next) + if (i->foundhere == l) + /* The control_macro works like this: If it's NULL, the file + is to be included again. If it's "", the file is never to + be included again. If it's a string, the file is not to be + included again if the string is the name of a defined macro. */ + return (i->control_macro + && (i->control_macro[0] == '\0' + || cpp_lookup (pfile, i->control_macro, -1, -1))) + ? (struct include_hash *)-1 : i; - while (i) { - if (!strcmp (filename, i->name)) - return -2; /* return found */ - i = i->next; - } - /* Open it and try a match on inode/dev */ - fd = open_include_file (pfile, filename, searchptr); - if (fd < 0) - return fd; - fstat (fd, &sb); - for (h = 0; h < IMPORT_HASH_SIZE; h++) { - i = pfile->import_hash_table[h]; - while (i) { - /* Compare the inode and the device. - Supposedly on some systems the inode is not a scalar. */ - if (!bcmp ((char *) &i->inode, (char *) &sb.st_ino, sizeof (sb.st_ino)) - && i->dev == sb.st_dev) { - close (fd); - return -2; /* return found */ - } - i = i->next; - } - } - return fd; /* Not found, return open file */ + return 0; } -/* Add the file FNAME, open on descriptor FD, to import_hash_table. */ +static int +file_cleanup (pbuf, pfile) + cpp_buffer *pbuf; + cpp_reader *pfile; +{ + if (pbuf->buf) + { + free (pbuf->buf); + pbuf->buf = 0; + } + if (pfile->system_include_depth) + pfile->system_include_depth--; + return 0; +} -static void -add_import (pfile, fd, fname) +/* 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 1 if the file was included before (but needs to be read + again). */ +int +find_include_file (pfile, fname, search_start, ihash, before) cpp_reader *pfile; - int fd; char *fname; + struct file_name_list *search_start; + struct include_hash **ihash; + int *before; { - struct import_file *i; - int hashval; - struct stat sb; - - hashval = import_hash (fname); - fstat (fd, &sb); - i = (struct import_file *)xmalloc (sizeof (struct import_file)); - i->name = (char *)xmalloc (strlen (fname)+1); - strcpy (i->name, fname); - bcopy ((char *) &sb.st_ino, (char *) &i->inode, sizeof (sb.st_ino)); - i->dev = sb.st_dev; - i->next = pfile->import_hash_table[hashval]; - pfile->import_hash_table[hashval] = i; + struct file_name_list *l; + struct include_hash *ih, *jh; + int f, len; + char *name; + + ih = include_hash (pfile, fname, 1); + jh = redundant_include_p (pfile, ih, + fname[0] == '/' ? ABSOLUTE_PATH : search_start); + + if (jh != 0) + { + *before = 1; + *ihash = jh; + + if (jh == (struct include_hash *)-1) + return -2; + else + return open (jh->name, O_RDONLY, 0666); + } + + if (ih->foundhere) + /* A file is already known by this name, but it's not the same file. + Allocate another include_hash block and add it to the next_this_file + chain. */ + { + jh = (struct include_hash *)xmalloc (sizeof (struct include_hash)); + while (ih->next_this_file) ih = ih->next_this_file; + + ih->next_this_file = jh; + jh = ih; + ih = ih->next_this_file; + + ih->next = NULL; + ih->next_this_file = NULL; + ih->buf = NULL; + ih->limit = NULL; + } + *before = 0; + *ihash = ih; + ih->nshort = savestring (fname); + ih->control_macro = NULL; + + /* If the pathname is absolute, just open it. */ + if (fname[0] == '/') + { + ih->foundhere = ABSOLUTE_PATH; + ih->name = ih->nshort; + return open (ih->name, O_RDONLY, 0666); + } + + /* Search directory path, trying to open the file. */ + + /* The first entry in the search list may be a buffer-specific entry, + and its directory name may be longer than max_include_len. Adjust + as appropriate. */ + if (pfile->max_include_len < search_start->nlen) + pfile->max_include_len = search_start->nlen; + len = strlen (fname); + name = xmalloc (len + pfile->max_include_len + 2 + INCLUDE_LEN_FUDGE); + + for (l = search_start; l; l = l->next) + { + bcopy (l->name, name, l->nlen); + name[l->nlen] = '/'; + strcpy (&name[l->nlen+1], fname); + simplify_pathname (name); + if (CPP_OPTIONS (pfile)->remap) + name = remap_filename (pfile, name, l); + + f = open (name, O_RDONLY, 0666); +#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) + { + ih->foundhere = l; + ih->name = xrealloc (name, strlen (name)+1); + return f; + } + } + + if (jh) + { + jh->next_this_file = NULL; + free (ih); + } + free (name); + *ihash = (struct include_hash *)-1; + return -1; } /* The file_name_map structure holds a mapping of file names for a @@ -434,7 +548,6 @@ read_name_map (pfile, dirname) map_list_ptr = ((struct file_name_map_list *) xmalloc (sizeof (struct file_name_map_list))); map_list_ptr->map_list_name = savestring (dirname); - map_list_ptr->map_list_map = NULL; name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2); strcpy (name, dirname); @@ -443,7 +556,7 @@ read_name_map (pfile, dirname) strcat (name, FILE_NAME_MAP_FILE); f = fopen (name, "r"); if (!f) - map_list_ptr->map_list_map = NULL; + map_list_ptr->map_list_map = (struct file_name_map *)-1; else { int ch; @@ -493,220 +606,192 @@ read_name_map (pfile, dirname) return map_list_ptr->map_list_map; } -/* Try to open include file FILENAME. SEARCHPTR is the directory - being tried from the include file search path. This function maps - filenames on file systems based on information read by - read_name_map. */ +/* Remap NAME based on the file_name_map (if any) for LOC. */ -static int -open_include_file (pfile, filename, searchptr) +static char * +remap_filename (pfile, name, loc) cpp_reader *pfile; - char *filename; - struct file_name_list *searchptr; + char *name; + struct file_name_list *loc; { - if (CPP_OPTIONS (pfile)->remap) - { - register struct file_name_map *map; - register char *from; - char *p, *dir; - - if (searchptr && ! searchptr->got_name_map) - { - searchptr->name_map = read_name_map (pfile, - searchptr->fname - ? searchptr->fname : "."); - searchptr->got_name_map = 1; - } - - /* First check the mapping for the directory we are using. */ - if (searchptr && searchptr->name_map) - { - from = filename; - if (searchptr->fname) - from += strlen (searchptr->fname) + 1; - for (map = searchptr->name_map; map; map = map->map_next) - { - if (! strcmp (map->map_from, from)) - { - /* Found a match. */ - return open (map->map_to, O_RDONLY, 0666); - } - } - } + struct file_name_map *map; + char *from; + char *p, *dir; - /* Try to find a mapping file for the particular directory we are - looking in. Thus #include will look up sys/types.h - in /usr/include/header.gcc and look up types.h in - /usr/include/sys/header.gcc. */ - p = rindex (filename, '/'); - if (! p) - p = filename; - if (searchptr - && searchptr->fname - && strlen (searchptr->fname) == (size_t) (p - filename) - && ! strncmp (searchptr->fname, filename, p - filename)) - { - /* FILENAME is in SEARCHPTR, which we've already checked. */ - return open (filename, O_RDONLY, 0666); - } + if (! loc->name_map) + loc->name_map = read_name_map (pfile, + loc->name + ? loc->name : "."); - if (p == filename) - { - dir = "."; - from = filename; - } - else - { - dir = (char *) alloca (p - filename + 1); - bcopy (filename, dir, p - filename); - dir[p - filename] = '\0'; - from = p + 1; - } - for (map = read_name_map (pfile, dir); map; map = map->map_next) - if (! strcmp (map->map_from, from)) - return open (map->map_to, O_RDONLY, 0666); + 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 will look up sys/types.h + in /usr/include/header.gcc and look up types.h in + /usr/include/sys/header.gcc. */ + p = rindex (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 + { + dir = (char *) alloca (p - name + 1); + bcopy (name, dir, p - name); + dir[p - name] = '\0'; + 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 open (filename, O_RDONLY, 0666); + return name; } -/* Process the contents of include file FNAME, already open on descriptor F, - with output to OP. - SYSTEM_HEADER_P is 1 if this file resides in any one of the known - "system" include directories (as decided by the `is_system_include' - function above). - DIRPTR is the link in the dir path through which this file was found, - or 0 if the file name was absolute or via the current directory. - Return 1 on success, 0 on failure. +/* 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. */ int -finclude (pfile, f, fname, system_header_p, dirptr) +finclude (pfile, fd, ihash) cpp_reader *pfile; - int f; - char *fname; - int system_header_p; - struct file_name_list *dirptr; + int fd; + struct include_hash *ihash; { struct stat st; size_t st_size; - long i; - int length; - cpp_buffer *fp; /* For input stack frame */ -#if 0 - int missing_newline = 0; -#endif - - if (fstat (f, &st) < 0) - { - cpp_perror_with_name (pfile, fname); - close (f); - cpp_pop_buffer (pfile); - return 0; - } + long i, length; + cpp_buffer *fp; + if (fstat (fd, &st) < 0) + goto perror_fail; + fp = CPP_BUFFER (pfile); - fp->nominal_fname = fp->fname = fname; -#if 0 - fp->length = 0; -#endif - fp->dir = dirptr; - fp->system_header_p = system_header_p; + fp->nominal_fname = fp->fname = ihash->name; + fp->ihash = ihash; + fp->system_header_p = (ihash->foundhere != ABSOLUTE_PATH + && ihash->foundhere->sysp); fp->lineno = 1; fp->colno = 1; fp->cleanup = file_cleanup; - if (S_ISREG (st.st_mode)) { - st_size = (size_t) st.st_size; - if (st_size != st.st_size || st_size + 2 < st_size) { - cpp_error (pfile, "file `%s' too large", fname); - close (f); - return 0; - } - fp->buf = (U_CHAR *) xmalloc (st_size + 2); - fp->alimit = fp->buf + st_size + 2; - fp->cur = fp->buf; - - /* Read the file contents, knowing that st_size is an upper bound - on the number of bytes we can read. */ - length = safe_read (f, fp->buf, st_size); - fp->rlimit = fp->buf + length; - if (length < 0) goto nope; - } - else if (S_ISDIR (st.st_mode)) { - cpp_error (pfile, "directory `%s' specified in #include", fname); - close (f); - return 0; - } else { - /* Cannot count its file size before reading. - First read the entire file into heap and - copy them into buffer on stack. */ - - size_t bsize = 2000; - - st_size = 0; - fp->buf = (U_CHAR *) xmalloc (bsize + 2); - - for (;;) { - i = safe_read (f, fp->buf + st_size, bsize - st_size); - if (i < 0) - goto nope; /* error! */ - st_size += i; - if (st_size != bsize) - break; /* End of file */ - bsize *= 2; - fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2); - } - fp->cur = fp->buf; - length = st_size; - } + /* The ->dir field is only used when ignore_srcdir is not in effect; + see do_include */ + if (!CPP_OPTIONS (pfile)->ignore_srcdir) + { + char *last_slash; + fp->dir = savestring (fp->fname); + last_slash = rindex (fp->dir, '/'); + if (last_slash) + { + if (last_slash == fp->dir) + { + fp->dlen = 1; + last_slash[1] = '\0'; + } + else + { + fp->dlen = last_slash - fp->dir; + *last_slash = '\0'; + } + } + else + { + fp->dir[0] = '.'; + fp->dir[1] = '\0'; + fp->dlen = 1; + } + } + if (S_ISREG (st.st_mode)) + { + st_size = (size_t) st.st_size; + if (st_size != st.st_size || st_size + 2 < st_size) + { + cpp_error (pfile, "file `%s' too large", ihash->name); + goto fail; + } + fp->buf = (U_CHAR *) xmalloc (st_size + 2); + fp->alimit = fp->buf + st_size + 2; + fp->cur = fp->buf; + + /* Read the file contents, knowing that st_size is an upper bound + on the number of bytes we can read. */ + length = safe_read (fd, fp->buf, st_size); + fp->rlimit = fp->buf + length; + if (length < 0) + goto perror_fail; + } + else if (S_ISDIR (st.st_mode)) + { + cpp_pop_buffer (pfile); + cpp_error (pfile, "directory `%s' specified in #include", ihash->name); + goto fail; + } + else + { + /* Cannot count its file size before reading. + First read the entire file into heap and + copy them into buffer on stack. */ + + size_t bsize = 2000; + + st_size = 0; + fp->buf = (U_CHAR *) xmalloc (bsize + 2); + + for (;;) + { + i = safe_read (fd, fp->buf + st_size, bsize - st_size); + if (i < 0) + goto perror_fail; + st_size += i; + if (st_size != bsize) + break; /* End of file */ + bsize *= 2; + fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2); + } + fp->cur = fp->buf; + length = st_size; + } + + /* FIXME: Broken in presence of trigraphs (consider ??/) + and doesn't warn about a missing newline. */ if ((length > 0 && fp->buf[length - 1] != '\n') - /* Backslash-newline at end is not good enough. */ - || (length > 1 && fp->buf[length - 2] == '\\')) { + || (length > 1 && fp->buf[length - 2] == '\\')) fp->buf[length++] = '\n'; -#if 0 - missing_newline = 1; -#endif - } + fp->buf[length] = '\0'; fp->rlimit = fp->buf + length; - /* Close descriptor now, so nesting does not use lots of descriptors. */ - close (f); - - /* Must do this before calling trigraph_pcp, so that the correct file name - will be printed in warning messages. */ - + close (fd); pfile->input_stack_listing_current = 0; - -#if 0 - if (!no_trigraphs) - trigraph_pcp (fp); -#endif - -#if 0 - rescan (op, 0); - - if (missing_newline) - fp->lineno--; - - if (CPP_PEDANTIC (pfile) && missing_newline) - pedwarn ("file does not end in newline"); - - indepth--; - input_file_stack_tick++; - free (fp->buf); -#endif return 1; - nope: - - cpp_perror_with_name (pfile, fname); - close (f); - free (fp->buf); - return 1; + perror_fail: + cpp_pop_buffer (pfile); + cpp_error_from_errno (pfile, ihash->name); + fail: + close (fd); + return 0; } /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME, @@ -715,7 +800,7 @@ finclude (pfile, f, fname, system_header_p, dirptr) otherwise return the actual number of bytes read, which must be LEN unless end-of-file was reached. */ -static int +static long safe_read (desc, ptr, len) int desc; char *ptr; @@ -747,7 +832,194 @@ safe_read (desc, ptr, len) return len - left; } -#ifdef VMS +/* Add output to `deps_buffer' for the -M switch. + STRING points to the text to be output. + SPACER is ':' for targets, ' ' for dependencies, zero for text + to be inserted literally. */ + +void +deps_output (pfile, string, spacer) + cpp_reader *pfile; + char *string; + int spacer; +{ + int size; + int cr = 0; + + if (!*string) + return; + + size = strlen (string); + +#ifndef MAX_OUTPUT_COLUMNS +#define MAX_OUTPUT_COLUMNS 72 +#endif + if (pfile->deps_column > 0 + && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS) + { + size += 5; + cr = 1; + pfile->deps_column = 0; + } + + if (pfile->deps_size + size + 8 > pfile->deps_allocated_size) + { + pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2; + pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer, + pfile->deps_allocated_size); + } + + if (cr) + { + bcopy (" \\\n ", &pfile->deps_buffer[pfile->deps_size], 5); + pfile->deps_size += 5; + } + + if (spacer == ' ' && pfile->deps_column > 0) + pfile->deps_buffer[pfile->deps_size++] = ' '; + bcopy (string, &pfile->deps_buffer[pfile->deps_size], size); + pfile->deps_size += size; + pfile->deps_column += size; + if (spacer == ':') + pfile->deps_buffer[pfile->deps_size++] = ':'; + pfile->deps_buffer[pfile->deps_size] = 0; +} + +/* Simplify a path name in place, deleting redundant components. This + reduces OS overhead and guarantees that equivalent paths compare + the same (modulo symlinks). + + Transforms made: + foo/bar/../quux foo/quux + foo/./bar foo/bar + foo//bar foo/bar + /../quux /quux + //quux //quux (POSIX allows leading // as a namespace escape) + + Guarantees no trailing slashes. All transforms reduce the length + of the string. + */ +static void +simplify_pathname (char *path) +{ + char *from, *to; + char *base; + int absolute = 0; + +#if defined _WIN32 || defined __MSDOS__ + /* Convert all backslashes to slashes. */ + for (from = path; *from; from++) + if (*from == '\\') *from = '/'; + + /* Skip over leading drive letter if present. */ + if (ISALPHA (path[0]) && path[1] == ':') + from = to = &path[2]; + else + from = to = path; +#else + from = to = path; +#endif + + /* Remove redundant initial /s. */ + if (*from == '/') + { + absolute = 1; + to++; + from++; + if (*from == '/') + { + if (*++from == '/') + /* 3 or more initial /s are equivalent to 1 /. */ + while (*++from == '/'); + else + /* On some hosts // differs from /; Posix allows this. */ + to++; + } + } + base = to; + + for (;;) + { + while (*from == '/') + from++; + + if (from[0] == '.' && from[1] == '/') + from += 2; + else if (from[0] == '.' && from[1] == '\0') + goto done; + else if (from[0] == '.' && from[1] == '.' && from[2] == '/') + { + if (base == to) + { + if (absolute) + from += 3; + else + { + *to++ = *from++; + *to++ = *from++; + *to++ = *from++; + base = to; + } + } + else + { + to -= 2; + while (to > base && *to != '/') to--; + if (*to == '/') + to++; + from += 3; + } + } + else if (from[0] == '.' && from[1] == '.' && from[2] == '\0') + { + if (base == to) + { + if (!absolute) + { + *to++ = *from++; + *to++ = *from++; + } + } + else + { + to -= 2; + while (to > base && *to != '/') to--; + if (*to == '/') + to++; + } + goto done; + } + else + /* Copy this component and trailing /, if any. */ + while ((*to++ = *from++) != '/') + { + if (!to[-1]) + { + to--; + goto done; + } + } + + } + + done: + /* Trim trailing slash */ + if (to[0] == '/' && (!absolute || to > path+1)) + to--; + + /* Change the empty string to "." so that stat() on the result + will always work. */ + if (to == path) + *to++ = '.'; + + *to = '\0'; + + return; +} + +/* It is not clear when this should be used if at all, so I've + disabled it until someone who understands VMS can look at it. */ +#if 0 /* Under VMS we need to fix up the "include" specification filename. diff --git a/gcc/cpplib.c b/gcc/cpplib.c index 269ac6682ef..227441353a1 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -206,7 +206,6 @@ static int compare_defs PROTO ((cpp_reader *, DEFINITION *, DEFINITION *)); static int compare_token_lists PROTO ((struct arglist *, struct arglist *)); -static int is_system_include PROTO ((cpp_reader *, char *)); static HOST_WIDE_INT eval_if_expression PROTO ((cpp_reader *, U_CHAR *, int)); static int change_newlines PROTO ((U_CHAR *, int)); static struct arglist *read_token_list PROTO ((cpp_reader *, int *)); @@ -585,7 +584,6 @@ path_include (pfile, path) while (1) { char *q = p; char *name; - struct file_name_list *dirtmp; /* Find the end of this name. */ while (*q != 0 && *q != PATH_SEPARATOR) q++; @@ -601,14 +599,8 @@ path_include (pfile, path) name[q - p] = 0; } - dirtmp = (struct file_name_list *) - xmalloc (sizeof (struct file_name_list)); - dirtmp->next = 0; /* New one goes on the end */ - dirtmp->control_macro = 0; - dirtmp->c_system_include_path = 0; - dirtmp->fname = name; - dirtmp->got_name_map = 0; - append_include_chain (pfile, dirtmp, dirtmp); + append_include_chain (pfile, + &(CPP_OPTIONS (pfile)->bracket_include), name, 0); /* Advance past this name. */ p = q; @@ -2940,16 +2932,16 @@ do_include (pfile, keyword, unused1, unused2) int importing = (keyword->type == T_IMPORT); int skip_dirs = (keyword->type == T_INCLUDE_NEXT); int angle_brackets = 0; /* 0 for "...", 1 for <...> */ - char *fname; /* Dynamically allocated fname buffer */ - char *fbeg, *fend; /* Beginning and end of fname */ + int before; /* included before? */ long flen; + char *fbeg, *fend; + struct file_name_list *srcdir = 0; /* for "" includes */ enum cpp_token token; /* Chain of dirs to search */ - struct file_name_list *search_start = CPP_OPTIONS (pfile)->include; - struct file_name_list dsp; /* First in chain, if #include "..." */ - struct file_name_list *foundhere, *ptr; + struct include_hash *ihash; + struct file_name_list *search_start; long old_written = CPP_WRITTEN (pfile); @@ -2968,17 +2960,7 @@ do_include (pfile, keyword, unused1, unused2) && !CPP_BUFFER (pfile)->system_header_p && !pfile->import_warning) { pfile->import_warning = 1; - cpp_warning (pfile, "using `#import' is not recommended"); - fprintf (stderr, "The fact that a certain header file need not be processed more than once\n"); - fprintf (stderr, "should be indicated in the header file, not where it is used.\n"); - fprintf (stderr, "The best way to do this is with a conditional of this form:\n\n"); - fprintf (stderr, " #ifndef _FOO_H_INCLUDED\n"); - fprintf (stderr, " #define _FOO_H_INCLUDED\n"); - fprintf (stderr, " ... ...\n"); - fprintf (stderr, " #endif /* Not _FOO_H_INCLUDED */\n\n"); - fprintf (stderr, "Then users can use `#include' any number of times.\n"); - fprintf (stderr, "GNU C automatically avoids processing the file more than once\n"); - fprintf (stderr, "when it is equipped with such a conditional.\n"); + cpp_warning (pfile, "`#import' is obsolete, use an #ifdef wrapper in the header file"); } pfile->parsing_include_directive++; @@ -2991,71 +2973,17 @@ do_include (pfile, keyword, unused1, unused2) fend = CPP_PWRITTEN (pfile) - 1; *fend = '\0'; if (fbeg[-1] == '<') - { angle_brackets = 1; - /* If -I-, start with the first -I dir after the -I-. */ - if (CPP_OPTIONS (pfile)->first_bracket_include) - search_start = CPP_OPTIONS (pfile)->first_bracket_include; - } - /* If -I- was specified, don't search current dir, only spec'd ones. */ - else if (! CPP_OPTIONS (pfile)->ignore_srcdir) - { - cpp_buffer *fp = CPP_BUFFER (pfile); - /* We have "filename". Figure out directory this source - file is coming from and put it on the front of the list. */ - - for ( ; fp != CPP_NULL_BUFFER (pfile); fp = CPP_PREV_BUFFER (fp)) - { - int n; - char *ep,*nam; - - if ((nam = fp->nominal_fname) != NULL) - { - /* Found a named file. Figure out dir of the file, - and put it in front of the search list. */ - dsp.next = search_start; - search_start = &dsp; -#ifndef VMS - ep = rindex (nam, '/'); -#else /* VMS */ - ep = rindex (nam, ']'); - if (ep == NULL) ep = rindex (nam, '>'); - if (ep == NULL) ep = rindex (nam, ':'); - if (ep != NULL) ep++; -#endif /* VMS */ - if (ep != NULL) - { - n = ep - nam; - dsp.fname = (char *) alloca (n + 1); - strncpy (dsp.fname, nam, n); - dsp.fname[n] = '\0'; - if (n + INCLUDE_LEN_FUDGE > pfile->max_include_len) - pfile->max_include_len = n + INCLUDE_LEN_FUDGE; - } - else - { - dsp.fname = 0; /* Current directory */ - } - dsp.got_name_map = 0; - break; - } - } - } } #ifdef VMS else if (token == CPP_NAME) { - /* - * Support '#include xyz' like VAX-C to allow for easy use of all the - * decwindow include files. It defaults to '#include ' (so the - * code from case '<' is repeated here) and generates a warning. - */ + /* Support '#include xyz' like VAX-C to allow for easy use of + * all the decwindow include files. It defaults to '#include + * ' and generates a warning. */ cpp_warning (pfile, "VAX-C-style include specification found, use '#include ' !"); angle_brackets = 1; - /* If -I-, start with the first -I dir after the -I-. */ - if (CPP_OPTIONS (pfile)->first_bracket_include) - search_start = CPP_OPTIONS (pfile)->first_bracket_include; /* Append the missing `.h' to the name. */ CPP_PUTS (pfile, ".h", 3) @@ -3081,6 +3009,16 @@ do_include (pfile, keyword, unused1, unused2) skip_rest_of_line (pfile); } + CPP_SET_WRITTEN (pfile, old_written); + + flen = fend - fbeg; + + if (flen == 0) + { + cpp_error (pfile, "empty file name in `#%s'", keyword->name); + return 0; + } + /* For #include_next, skip in the search path past the dir in which the containing file was found. */ if (skip_dirs) @@ -3089,39 +3027,55 @@ do_include (pfile, keyword, unused1, unused2) for (; fp != CPP_NULL_BUFFER (pfile); fp = CPP_PREV_BUFFER (fp)) if (fp->fname != NULL) { - /* fp->dir is null if the containing file was specified with - an absolute file name. In that case, don't skip anything. */ - if (fp->dir == SELF_DIR_DUMMY) - search_start = CPP_OPTIONS (pfile)->include; - else if (fp->dir) - search_start = fp->dir->next; + /* Don't skip anything if the containing file was found + by an absolute path. */ + if (fp->ihash->foundhere == ABSOLUTE_PATH) + search_start = angle_brackets + ? CPP_OPTIONS (pfile)->bracket_include + : CPP_OPTIONS (pfile)->quote_include; + else + search_start = fp->ihash->foundhere->next; break; } } + else + search_start = angle_brackets + ? CPP_OPTIONS (pfile)->bracket_include + : CPP_OPTIONS (pfile)->quote_include; + + /* For "" includes when ignore_srcdir is off, tack the actual directory + of the current file onto the beginning of the search path. + The block must be permanently allocated since it may wind up + in the include hash. */ + if (!angle_brackets + && search_start == CPP_OPTIONS (pfile)->quote_include + && !CPP_OPTIONS (pfile)->ignore_srcdir) + { + srcdir = (struct file_name_list *) + xmalloc (sizeof (struct file_name_list)); + srcdir->next = CPP_OPTIONS (pfile)->quote_include; + srcdir->name = CPP_BUFFER (pfile)->dir; + srcdir->nlen = CPP_BUFFER (pfile)->dlen; + srcdir->sysp = 0; + srcdir->name_map = NULL; - CPP_SET_WRITTEN (pfile, old_written); - - flen = fend - fbeg; + search_start = srcdir; + } - if (flen == 0) + if (!search_start) { - cpp_error (pfile, "empty file name in `#%s'", keyword->name); + cpp_error (pfile, "No include path in which to find %s", fbeg); return 0; } - /* Allocate this permanently, because it gets stored in the definitions - of macros. */ - /* + 2 above for slash and terminating null. */ - fname = (char *) xmalloc (pfile->max_include_len + flen + 2); - - fd = find_include_file (pfile, fbeg, flen, fname, - importing, search_start, &foundhere); + fd = find_include_file (pfile, fbeg, search_start, &ihash, &before); + if (srcdir + && (ihash == (struct include_hash *)-1 || srcdir != ihash->foundhere)) + free (srcdir); + if (fd == -2) - { - free (fname); - return 0; - } + return 0; if (fd == -1) { @@ -3133,27 +3087,24 @@ do_include (pfile, keyword, unused1, unused2) deps_output (pfile, fbeg, ' '); 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_OPTIONS (pfile)->first_bracket_include) - ptr = CPP_OPTIONS (pfile)->first_bracket_include; + if (CPP_OPTIONS (pfile)->bracket_include) + ptr = CPP_OPTIONS (pfile)->bracket_include; else - ptr = CPP_OPTIONS (pfile)->include; - for (; ptr; ptr = ptr->next) - if (ptr->fname) - { - char *p; + ptr = CPP_OPTIONS (pfile)->quote_include; - if (ptr->fname[0] == 0) - continue; - p = (char *) alloca (strlen (ptr->fname) - + strlen (fname) + 2); - strcpy (p, ptr->fname); - strcat (p, "/"); - strcat (p, fname); - deps_output (pfile, p, ' '); - break; - } + p = (char *) alloca (strlen (ptr->name) + + strlen (fbeg) + 2); + if (*ptr->name != '\0') + { + strcpy (p, ptr->name); + strcat (p, "/"); + } + strcat (p, fbeg); + deps_output (pfile, p, ' '); } } /* If -M was specified, and this header file won't be added to @@ -3165,40 +3116,17 @@ do_include (pfile, keyword, unused1, unused2) 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 if (search_start) - cpp_error_from_errno (pfile, fname); + cpp_warning (pfile, "No include path in which to find %s", fbeg); else - cpp_error (pfile, "No include path in which to find %s", fname); + cpp_error_from_errno (pfile, fbeg); - free (fname); return 0; } - /* If we get here, we have a file to process. */ - - for (ptr = pfile->all_include_files; ptr; ptr = ptr->next) - if (!strcmp (ptr->fname, fname)) - break; /* This file was included before. */ - - if (ptr == 0) - { - /* This is the first time for this file. */ - /* Add it to list of files included. */ - - ptr = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); - ptr->control_macro = 0; - ptr->c_system_include_path = 0; - ptr->next = pfile->all_include_files; - pfile->all_include_files = ptr; - ptr->fname = savestring (fname); - ptr->got_name_map = 0; - - /* For -M, add this file to the dependencies. */ - if (CPP_PRINT_DEPS (pfile) - > (angle_brackets || (pfile->system_include_depth > 0))) - deps_output (pfile, fname, ' '); - } + /* 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_output (pfile, ihash->name, ' '); /* Handle -H option. */ if (CPP_OPTIONS(pfile)->print_include_names) @@ -3206,65 +3134,29 @@ do_include (pfile, keyword, unused1, unused2) cpp_buffer *buf = CPP_BUFFER (pfile); while ((buf = CPP_PREV_BUFFER (buf)) != CPP_NULL_BUFFER (pfile)) putc ('.', stderr); - fprintf (stderr, "%s\n", fname); + fprintf (stderr, " %s\n", ihash->name); } /* Actually process the file */ + + if (importing) + ihash->control_macro = ""; + if (cpp_push_buffer (pfile, NULL, 0) == NULL) { close (fd); - free (fname); return 0; } - + if (angle_brackets) - pfile->system_include_depth++; + pfile->system_include_depth++; /* Decremented in file_cleanup. */ - if (finclude (pfile, fd, fname, is_system_include (pfile, fname), - foundhere != &dsp ? foundhere : SELF_DIR_DUMMY)) + if (finclude (pfile, fd, ihash)) { output_line_command (pfile, 0, enter_file); pfile->only_seen_white = 2; } - - if (angle_brackets) - pfile->system_include_depth--; - - return 0; -} - -/* Return nonzero if the given FILENAME is an absolute pathname which - designates a file within one of the known "system" include file - directories. We assume here that if the given FILENAME looks like - it is the name of a file which resides either directly in a "system" - include file directory, or within any subdirectory thereof, then the - given file must be a "system" include file. This function tells us - if we should suppress pedantic errors/warnings for the given FILENAME. - - The value is 2 if the file is a C-language system header file - for which C++ should (on most systems) assume `extern "C"'. */ - -static int -is_system_include (pfile, filename) - cpp_reader *pfile; - register char *filename; -{ - struct file_name_list *searchptr; - for (searchptr = CPP_OPTIONS (pfile)->first_system_include; searchptr; - searchptr = searchptr->next) - if (searchptr->fname) { - register char *sys_dir = searchptr->fname; - register unsigned length = strlen (sys_dir); - - if (! strncmp (sys_dir, filename, length) && filename[length] == '/') - { - if (searchptr->c_system_include_path) - return 2; - else - return 1; - } - } return 0; } @@ -3665,7 +3557,6 @@ do_pragma (pfile, keyword, buf, limit) if (!strncmp (buf, "once", 4)) { cpp_buffer *ip = NULL; - struct file_name_list *new; /* Allow #pragma once in system headers, since that's not the user's fault. */ @@ -3679,39 +3570,36 @@ do_pragma (pfile, keyword, buf, limit) if (ip->fname != NULL) break; } - - new = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); - new->next = pfile->dont_repeat_files; - new->fname = savestring (ip->fname); - new->control_macro = 0; - new->got_name_map = 0; - new->c_system_include_path = 0; - pfile->dont_repeat_files = new; - } - if (!strncmp (buf, "implementation", 14)) { - /* Be quiet about `#pragma implementation' for a file only if it hasn't - been included yet. */ - struct file_name_list *ptr; - U_CHAR *p = buf + 14, *fname, *inc_fname; - int fname_len; - SKIP_WHITE_SPACE (p); - if (*p == '\n' || *p != '\"') - return 0; + if (CPP_PREV_BUFFER (ip) == CPP_NULL_BUFFER (pfile)) + cpp_warning (pfile, "`#pragma once' outside include file"); + else + ip->ihash->control_macro = ""; /* never repeat */ + } - fname = p + 1; - p = (U_CHAR *) index (fname, '\"'); - fname_len = p != NULL ? p - fname : strlen (fname); - - for (ptr = pfile->all_include_files; ptr; ptr = ptr->next) { - inc_fname = (U_CHAR *) rindex (ptr->fname, '/'); - inc_fname = inc_fname ? inc_fname + 1 : (U_CHAR *) ptr->fname; - if (inc_fname && !strncmp (inc_fname, fname, fname_len)) - cpp_warning (pfile, - "`#pragma implementation' for `%s' appears after file is included", - fname); + if (!strncmp (buf, "implementation", 14)) + { + /* Be quiet about `#pragma implementation' for a file only if it hasn't + been included yet. */ + struct include_hash *ptr; + U_CHAR *p = buf + 14, *fname, *fcopy; + SKIP_WHITE_SPACE (p); + if (*p == '\n' || *p != '\"') + return 0; + + fname = p + 1; + p = (U_CHAR *) index (fname, '\"'); + + fcopy = alloca (p - fname + 1); + bcopy (fname, fcopy, p - fname); + fcopy[p-fname] = '\0'; + + ptr = include_hash (pfile, fcopy, 0); + if (ptr) + cpp_warning (pfile, + "`#pragma implementation' for `%s' appears after file is included", + fcopy); } - } return 0; } @@ -4219,31 +4107,15 @@ do_endif (pfile, keyword, buf, limit) if (c == EOF) { - /* If we get here, this #endif ends a #ifndef + /* This #endif ends a #ifndef that contains all of the file (aside from whitespace). Arrange not to include the file again - if the macro that was tested is defined. - - Do not do this for the top-level file in a -include or any - file in a -imacros. */ -#if 0 -FIXME! - if (indepth != 0 - && ! (indepth == 1 && pfile->no_record_file) - && ! (pfile->no_record_file && no_output)) -#endif - { - struct file_name_list *ifile = pfile->all_include_files; - - for ( ; ifile != NULL; ifile = ifile->next) - { - if (!strcmp (ifile->fname, CPP_BUFFER (pfile)->fname)) - { - ifile->control_macro = temp->control_macro; - break; - } - } - } + if the macro that was tested is defined. */ + struct cpp_buffer *ip; + for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip)) + if (ip->fname != NULL) + break; + ip->ihash->control_macro = temp->control_macro; } } free (temp); @@ -4995,6 +4867,7 @@ cpp_start_read (pfile, fname) char *p; int f; cpp_buffer *fp; + struct include_hash *ih_fake; /* The code looks at the defaults through this pointer, rather than through the constant structure above. This pointer gets changed if an environment @@ -5193,9 +5066,6 @@ cpp_start_read (pfile, fname) } } - append_include_chain (pfile, opts->before_system, opts->last_before_system); - opts->first_system_include = opts->before_system; - /* Unless -fnostdinc, tack on the standard include file dirs to the specified list */ if (!opts->no_standard_includes) { @@ -5218,19 +5088,14 @@ cpp_start_read (pfile, fname) /* Does this dir start with the prefix? */ if (!strncmp (p->fname, default_prefix, default_len)) { /* Yes; change prefix and add to search list. */ - struct file_name_list *new - = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); - int this_len = strlen (specd_prefix) + strlen (p->fname) - default_len; + int this_len = strlen (specd_prefix) + + strlen (p->fname) - default_len; char *str = (char *) xmalloc (this_len + 1); strcpy (str, specd_prefix); strcat (str, p->fname + default_len); - new->fname = str; - new->control_macro = 0; - new->c_system_include_path = !p->cxx_aware; - new->got_name_map = 0; - append_include_chain (pfile, new, new); - if (opts->first_system_include == 0) - opts->first_system_include = new; + + append_include_chain (pfile, &opts->system_include, + str, !p->cxx_aware); } } } @@ -5239,32 +5104,23 @@ cpp_start_read (pfile, fname) /* Some standard dirs are only for C++. */ if (!p->cplusplus || (opts->cplusplus && !opts->no_standard_cplusplus_includes)) { - struct file_name_list *new - = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); - new->control_macro = 0; - new->c_system_include_path = !p->cxx_aware; - new->fname = update_path (p->fname, p->component); - new->got_name_map = 0; - append_include_chain (pfile, new, new); - if (opts->first_system_include == 0) - opts->first_system_include = new; + char *str = update_path (p->fname, p->component); + append_include_chain (pfile, &opts->system_include, + str, !p->cxx_aware); } } } - /* Tack the after_include chain at the end of the include chain. */ - append_include_chain (pfile, opts->after_include, opts->last_after_include); - if (opts->first_system_include == 0) - opts->first_system_include = opts->after_include; + merge_include_chains (opts); /* With -v, print the list of dirs to search. */ if (opts->verbose) { struct file_name_list *p; fprintf (stderr, "#include \"...\" search starts here:\n"); - for (p = opts->include; p; p = p->next) { - if (p == opts->first_bracket_include) + for (p = opts->quote_include; p; p = p->next) { + if (p == opts->bracket_include) fprintf (stderr, "#include <...> search starts here:\n"); - fprintf (stderr, " %s\n", p->fname); + fprintf (stderr, " %s\n", p->name); } fprintf (stderr, "End of search list.\n"); } @@ -5416,7 +5272,15 @@ cpp_start_read (pfile, fname) /* Must call finclude() on the main input before processing -include switches; otherwise the -included text winds up after the main input. */ - if (!finclude (pfile, f, fname, 0, NULL_PTR)) + ih_fake = (struct include_hash *) xmalloc (sizeof (struct include_hash)); + ih_fake->next = 0; + ih_fake->next_this_file = 0; + ih_fake->foundhere = ABSOLUTE_PATH; /* well sort of ... */ + ih_fake->name = fname; + ih_fake->control_macro = 0; + ih_fake->buf = (char *)-1; + ih_fake->limit = 0; + if (!finclude (pfile, f, ih_fake)) return 0; output_line_command (pfile, 0, same_file); pfile->only_seen_white = 2; @@ -5429,6 +5293,7 @@ cpp_start_read (pfile, fname) means the -imacros files have to be done separately and first. */ pfile->no_record_file++; + opts->no_output++; for (pend = opts->pending; pend; pend = pend->next) { if (pend->cmd != NULL) @@ -5443,13 +5308,23 @@ cpp_start_read (pfile, fname) } if (!cpp_push_buffer (pfile, NULL, 0)) return 0; - opts->no_output++; - if (finclude (pfile, fd, pend->arg, 0, NULL_PTR)) + + ih_fake = (struct include_hash *) + xmalloc (sizeof (struct include_hash)); + ih_fake->next = 0; + ih_fake->next_this_file = 0; + ih_fake->foundhere = ABSOLUTE_PATH; /* well sort of ... */ + ih_fake->name = pend->arg; + ih_fake->control_macro = 0; + ih_fake->buf = (char *)-1; + ih_fake->limit = 0; + if (!finclude (pfile, fd, ih_fake)) cpp_scan_buffer (pfile); - opts->no_output--; + free (ih_fake); } } } + opts->no_output--; opts->pending = nreverse_pending (opts->pending); for (pend = opts->pending; pend; pend = pend->next) { @@ -5465,7 +5340,17 @@ cpp_start_read (pfile, fname) } if (!cpp_push_buffer (pfile, NULL, 0)) return 0; - if (finclude (pfile, fd, pend->arg, 0, NULL_PTR)) + + ih_fake = (struct include_hash *) + xmalloc (sizeof (struct include_hash)); + ih_fake->next = 0; + ih_fake->next_this_file = 0; + ih_fake->foundhere = ABSOLUTE_PATH; /* well sort of ... */ + ih_fake->name = pend->arg; + ih_fake->control_macro = 0; + ih_fake->buf = (char *)-1; + ih_fake->limit = 0; + if (finclude (pfile, fd, ih_fake)) output_line_command (pfile, 0, enter_file); } } @@ -5495,10 +5380,6 @@ cpp_reader_init (pfile) pfile->token_buffer = (U_CHAR *) xmalloc (pfile->token_buffer_size); CPP_SET_WRITTEN (pfile, 0); - pfile->system_include_depth = 0; - pfile->dont_repeat_files = 0; - pfile->all_include_files = 0; - pfile->max_include_len = 0; pfile->timebuf = NULL; pfile->only_seen_white = 1; pfile->buffer = CPP_NULL_BUFFER(pfile); @@ -5644,131 +5525,121 @@ cpp_handle_option (pfile, argc, argv) user_label_prefix = ""; break; + case 'I': /* Add directory to path for includes. */ + if (!strcmp (argv[i] + 2, "-")) + { + if (! opts->ignore_srcdir) + { + opts->ignore_srcdir = 1; + /* Don't use any preceding -I directories for #include <...>. */ + opts->quote_include = opts->bracket_include; + opts->bracket_include = 0; + } + } + else + { + char *fname; + if (argv[i][2] != 0) + fname = argv[i] + 2; + else if (i + 1 == argc) + goto missing_dirname; + else + fname = argv[++i]; + append_include_chain (pfile, &opts->bracket_include, fname, 0); + } + break; + case 'i': - if (!strcmp (argv[i], "-include") - || !strcmp (argv[i], "-imacros")) { - if (i + 1 == argc) - goto missing_filename; - else - push_pending (pfile, argv[i], argv[i+1]), i++; - } - if (!strcmp (argv[i], "-iprefix")) { - if (i + 1 == argc) - goto missing_filename; - else - opts->include_prefix = argv[++i]; - } - if (!strcmp (argv[i], "-ifoutput")) { - opts->output_conditionals = 1; - } - if (!strcmp (argv[i], "-isystem")) { - struct file_name_list *dirtmp; - - if (i + 1 == argc) - goto missing_filename; - - dirtmp = (struct file_name_list *) - xmalloc (sizeof (struct file_name_list)); - dirtmp->next = 0; - dirtmp->control_macro = 0; - dirtmp->c_system_include_path = 1; - dirtmp->fname = (char *) xmalloc (strlen (argv[i+1]) + 1); - strcpy (dirtmp->fname, argv[++i]); - dirtmp->got_name_map = 0; - - if (opts->before_system == 0) - opts->before_system = dirtmp; - else - opts->last_before_system->next = dirtmp; - opts->last_before_system = dirtmp; /* Tail follows the last one */ - } + /* Add directory to beginning of system include path, as a system + include directory. */ + if (!strcmp (argv[i], "-isystem")) + { + if (i + 1 == argc) + goto missing_filename; + append_include_chain (pfile, &opts->system_include, argv[++i], 1); + } /* Add directory to end of path for includes, with the default prefix at the front of its name. */ - if (!strcmp (argv[i], "-iwithprefix")) { - struct file_name_list *dirtmp; - char *prefix; - - if (opts->include_prefix != 0) - prefix = opts->include_prefix; - else { - prefix = savestring (GCC_INCLUDE_DIR); - /* Remove the `include' from /usr/local/lib/gcc.../include. */ - if (!strcmp (prefix + strlen (prefix) - 8, "/include")) - prefix[strlen (prefix) - 7] = 0; - } - - dirtmp = (struct file_name_list *) - xmalloc (sizeof (struct file_name_list)); - dirtmp->next = 0; /* New one goes on the end */ - dirtmp->control_macro = 0; - dirtmp->c_system_include_path = 0; - if (i + 1 == argc) - goto missing_dirname; - - dirtmp->fname = (char *) xmalloc (strlen (argv[i+1]) - + strlen (prefix) + 1); - strcpy (dirtmp->fname, prefix); - strcat (dirtmp->fname, argv[++i]); - dirtmp->got_name_map = 0; - - if (opts->after_include == 0) - opts->after_include = dirtmp; - else - opts->last_after_include->next = dirtmp; - opts->last_after_include = dirtmp; /* Tail follows the last one */ + else if (!strcmp (argv[i], "-iwithprefix")) + { + char *fname; + if (i + 1 == argc) + goto missing_dirname; + ++i; + + if (opts->include_prefix != 0) + { + fname = xmalloc (strlen (opts->include_prefix) + + strlen (argv[i]) + 1); + strcpy (fname, opts->include_prefix); + strcat (fname, argv[i]); + } + else + { + fname = xmalloc (strlen (GCC_INCLUDE_DIR) + + strlen (argv[i]) + 1); + strcpy (fname, GCC_INCLUDE_DIR); + /* Remove the `include' from /usr/local/lib/gcc.../include. */ + if (!strcmp (fname + strlen (fname) - 8, "/include")) + fname[strlen (fname) - 7] = 0; + strcat (fname, argv[i]); + } + + append_include_chain (pfile, &opts->system_include, fname, 0); } /* Add directory to main path for includes, with the default prefix at the front of its name. */ - if (!strcmp (argv[i], "-iwithprefixbefore")) { - struct file_name_list *dirtmp; - char *prefix; - - if (opts->include_prefix != 0) - prefix = opts->include_prefix; - else { - prefix = savestring (GCC_INCLUDE_DIR); - /* Remove the `include' from /usr/local/lib/gcc.../include. */ - if (!strcmp (prefix + strlen (prefix) - 8, "/include")) - prefix[strlen (prefix) - 7] = 0; - } - - dirtmp = (struct file_name_list *) - xmalloc (sizeof (struct file_name_list)); - dirtmp->next = 0; /* New one goes on the end */ - dirtmp->control_macro = 0; - dirtmp->c_system_include_path = 0; - if (i + 1 == argc) - goto missing_dirname; - - dirtmp->fname = (char *) xmalloc (strlen (argv[i+1]) - + strlen (prefix) + 1); - strcpy (dirtmp->fname, prefix); - strcat (dirtmp->fname, argv[++i]); - dirtmp->got_name_map = 0; - - append_include_chain (pfile, dirtmp, dirtmp); - } + else if (!strcmp (argv[i], "-iwithprefix")) + { + char *fname; + if (i + 1 == argc) + goto missing_dirname; + ++i; + + if (opts->include_prefix != 0) + { + fname = xmalloc (strlen (opts->include_prefix) + + strlen (argv[i]) + 1); + strcpy (fname, opts->include_prefix); + strcat (fname, argv[i]); + } + else + { + fname = xmalloc (strlen (GCC_INCLUDE_DIR) + + strlen (argv[i]) + 1); + strcpy (fname, GCC_INCLUDE_DIR); + /* Remove the `include' from /usr/local/lib/gcc.../include. */ + if (!strcmp (fname + strlen (fname) - 8, "/include")) + fname[strlen (fname) - 7] = 0; + strcat (fname, argv[i]); + } + + append_include_chain (pfile, &opts->bracket_include, fname, 0); + } /* Add directory to end of path for includes. */ - if (!strcmp (argv[i], "-idirafter")) { - struct file_name_list *dirtmp; - - dirtmp = (struct file_name_list *) - xmalloc (sizeof (struct file_name_list)); - dirtmp->next = 0; /* New one goes on the end */ - dirtmp->control_macro = 0; - dirtmp->c_system_include_path = 0; - if (i + 1 == argc) - goto missing_dirname; - else - dirtmp->fname = argv[++i]; - dirtmp->got_name_map = 0; - - if (opts->after_include == 0) - opts->after_include = dirtmp; - else - opts->last_after_include->next = dirtmp; - opts->last_after_include = dirtmp; /* Tail follows the last one */ - } + else if (!strcmp (argv[i], "-idirafter")) + { + if (i + 1 == argc) + goto missing_dirname; + append_include_chain (pfile, &opts->after_include, argv[++i], 0); + } + else if (!strcmp (argv[i], "-include") || !strcmp (argv[i], "-imacros")) + { + if (i + 1 == argc) + goto missing_filename; + else + push_pending (pfile, argv[i], argv[i+1]), i++; + } + else if (!strcmp (argv[i], "-iprefix")) + { + if (i + 1 == argc) + goto missing_filename; + else + opts->include_prefix = argv[++i]; + } + else if (!strcmp (argv[i], "-ifoutput")) + opts->output_conditionals = 1; + break; case 'o': @@ -6051,34 +5922,6 @@ cpp_handle_option (pfile, argc, argv) opts->dollars_in_ident = 0; break; - case 'I': /* Add directory to path for includes. */ - { - struct file_name_list *dirtmp; - - if (! CPP_OPTIONS(pfile)->ignore_srcdir - && !strcmp (argv[i] + 2, "-")) { - CPP_OPTIONS (pfile)->ignore_srcdir = 1; - /* Don't use any preceding -I directories for #include <...>. */ - CPP_OPTIONS (pfile)->first_bracket_include = 0; - } - else { - dirtmp = (struct file_name_list *) - xmalloc (sizeof (struct file_name_list)); - dirtmp->next = 0; /* New one goes on the end */ - dirtmp->control_macro = 0; - dirtmp->c_system_include_path = 0; - if (argv[i][2] != 0) - dirtmp->fname = argv[i] + 2; - else if (i + 1 == argc) - goto missing_dirname; - else - dirtmp->fname = argv[++i]; - dirtmp->got_name_map = 0; - append_include_chain (pfile, dirtmp, dirtmp); - } - } - break; - case 'n': if (!strcmp (argv[i], "-nostdinc")) /* -nostdinc causes no default include directories. @@ -6171,6 +6014,28 @@ cpp_finish (pfile) } } } + +#if 0 + /* Debugging: dump statistics on the include hash table. */ + { + struct include_hash *x; + int i, j; + + for(i = 0; i < ALL_INCLUDE_HASHSIZE; i++) + { + x = pfile->all_include_files[i]; + j = 0; + while(x) + { + j++; + x = x->next; + } + fprintf(stderr, "%d/%d ", i, j); + } + fputc('\n', stderr); + } +#endif + } /* Free resources used by PFILE. @@ -6204,33 +6069,20 @@ cpp_cleanup (pfile) free (temp); } - while (pfile->dont_repeat_files) - { - struct file_name_list *temp = pfile->dont_repeat_files; - pfile->dont_repeat_files = temp->next; - free (temp->fname); - free (temp); - } - - while (pfile->all_include_files) + for (i = ALL_INCLUDE_HASHSIZE; --i >= 0; ) { - struct file_name_list *temp = pfile->all_include_files; - pfile->all_include_files = temp->next; - free (temp->fname); - free (temp); - } - - for (i = IMPORT_HASH_SIZE; --i >= 0; ) - { - register struct import_file *imp = pfile->import_hash_table[i]; + struct include_hash *imp = pfile->all_include_files[i]; while (imp) { - struct import_file *next = imp->next; + struct include_hash *next = imp->next; +#if 0 + /* This gets freed elsewhere - I think. */ free (imp->name); +#endif free (imp); imp = next; } - pfile->import_hash_table[i] = 0; + pfile->all_include_files[i] = 0; } for (i = ASSERTION_HASHSIZE; --i >= 0; ) diff --git a/gcc/cpplib.h b/gcc/cpplib.h index 99745c98f22..fe2810237dc 100644 --- a/gcc/cpplib.h +++ b/gcc/cpplib.h @@ -96,17 +96,6 @@ extern enum cpp_token cpp_get_non_space_token PARAMS ((cpp_reader *)); /* This frees resources used by PFILE. */ extern void cpp_cleanup PARAMS ((cpp_reader *PFILE)); -/* Maintain and search list of included files, for #import. */ - -#define IMPORT_HASH_SIZE 31 - -struct import_file { - char *name; - ino_t inode; - dev_t dev; - struct import_file *next; -}; - /* If we have a huge buffer, may need to cache more recent counts */ #define CPP_LINE_BASE(BUF) ((BUF)->buf + (BUF)->line_base) @@ -120,10 +109,14 @@ struct cpp_buffer { char *fname; /* Filename specified with #line command. */ char *nominal_fname; + /* Actual directory of this file, used only for "" includes */ + char *dir; + size_t dlen; - /* Record where in the search path this file was found. - For #include_next. */ - struct file_name_list *dir; + /* Pointer into the include hash table. Used for include_next and + to record control macros. + ->fname is an alias to ->ihash->fname. */ + struct include_hash *ihash; long line_base; long lineno; /* Line number at CPP_LINE_BASE. */ @@ -185,20 +178,13 @@ struct cpp_reader { /* Current depth in #include directives that use <...>. */ int system_include_depth; - /* List of included files that contained #pragma once. */ - struct file_name_list *dont_repeat_files; - - /* List of other included files. - If ->control_macro if nonzero, the file had a #ifndef - around the entire contents, and ->control_macro gives the macro name. */ - struct file_name_list *all_include_files; + /* Hash table of other included files. See cppfiles.c */ +#define ALL_INCLUDE_HASHSIZE 71 + struct include_hash *all_include_files[ALL_INCLUDE_HASHSIZE]; /* Current maximum length of directory names in the search path for include files. (Altered as we get more of them.) */ - int max_include_len; - - /* Hash table of files already included with #include or #import. */ - struct import_file *import_hash_table[IMPORT_HASH_SIZE]; + unsigned int max_include_len; struct if_stack *if_stack; @@ -441,23 +427,12 @@ struct cpp_options { char done_initializing; - struct file_name_list *include; /* First dir to search */ - /* First dir to search for */ - /* This is the first element to use for #include <...>. - If it is 0, use the entire chain for such includes. */ - struct file_name_list *first_bracket_include; - /* This is the first element in the chain that corresponds to - a directory of system header files. */ - struct file_name_list *first_system_include; - struct file_name_list *last_include; /* Last in chain */ - - /* Chain of include directories to put at the end of the other chain. */ - struct file_name_list *after_include; - struct file_name_list *last_after_include; /* Last in chain */ - - /* Chain to put at the start of the system include files. */ - struct file_name_list *before_system; - struct file_name_list *last_before_system; /* Last in chain */ + /* Search paths for include files. system_include, after_include are + only used during option parsing. */ + struct file_name_list *quote_include; /* First dir to search for "file" */ + struct file_name_list *bracket_include;/* First dir to search for */ + struct file_name_list *system_include; /* First dir with system headers */ + struct file_name_list *after_include; /* Headers to search after system */ /* Directory prefix that should replace `/usr' in the standard include file directories. */ @@ -506,22 +481,45 @@ struct cpp_options { #define CPP_PEDANTIC(PFILE) (CPP_OPTIONS (PFILE)->pedantic) #define CPP_PRINT_DEPS(PFILE) (CPP_OPTIONS (PFILE)->print_deps) +/* List of directories to look for include files in. */ struct file_name_list - { - struct file_name_list *next; - char *fname; - /* If the following is nonzero, it is a macro name. - Don't include the file again if that macro is defined. */ - U_CHAR *control_macro; - /* If the following is nonzero, it is a C-language system include - directory. */ - int c_system_include_path; - /* Mapping of file names for this directory. */ - struct file_name_map *name_map; - /* Non-zero if name_map is valid. */ - int got_name_map; - }; +{ + struct file_name_list *next; + char *name; + unsigned int nlen; + /* We use these to tell if the directory mentioned here is a duplicate + of an earlier directory on the search path. */ + ino_t ino; + dev_t dev; + /* If the following is nonzero, it is a C-language system include + directory. */ + int sysp; + /* Mapping of file names for this directory. + Only used on MS-DOS and related platforms. */ + struct file_name_map *name_map; +}; +#define ABSOLUTE_PATH ((struct file_name_list *)-1) +/* This structure is used for the table of all includes. It is + indexed by the `short name' (the name as it appeared in the + #include statement) which is stored in *nshort. */ +struct include_hash +{ + struct include_hash *next; + /* Next file with the same short name but a + different (partial) pathname). */ + struct include_hash *next_this_file; + + /* Location of the file in the include search path. + Used for include_next */ + struct file_name_list *foundhere; + char *name; /* (partial) pathname of file */ + char *nshort; /* name of file as referenced in #include */ + char *control_macro; /* macro, if any, preventing reinclusion - see + redundant_include_p */ + char *buf, *limit; /* for file content cache, not yet implemented */ +}; + /* If a buffer's dir field is SELF_DIR_DUMMY, it means the file was found via the same directory as the file that #included it. */ #define SELF_DIR_DUMMY ((struct file_name_list *) (~0)) @@ -706,15 +704,17 @@ extern void cpp_print_containing_files PROTO ((cpp_reader *)); /* In cppfiles.c */ extern void append_include_chain PROTO ((cpp_reader *, - struct file_name_list *, - struct file_name_list *)); -extern int finclude PROTO ((cpp_reader *, int, char *, - int, struct file_name_list *)); + struct file_name_list **, + char *, int)); +extern void merge_include_chains PROTO ((struct cpp_options *)); extern int find_include_file PROTO ((cpp_reader *, char *, - unsigned long, char *, int, struct file_name_list *, - struct file_name_list **)); + struct include_hash **, + int *)); +extern int finclude PROTO ((cpp_reader *, int, + struct include_hash *)); extern void deps_output PROTO ((cpp_reader *, char *, int)); +extern struct include_hash *include_hash PROTO ((cpp_reader *, char *, int)); /* Bleargh. */ extern char *savestring PROTO ((char *));