Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1 | /* Part of CPP library. (include file handling) |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 2 | Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998, |
| 3 | 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 4 | Written by Per Bothner, 1994. |
| 5 | Based on CCCP program by Paul Rubin, June 1986 |
| 6 | Adapted to ANSI C, Richard Stallman, Jan 1987 |
| 7 | Split out of cpplib.c, Zack Weinberg, Oct 1998 |
| 8 | |
| 9 | This program is free software; you can redistribute it and/or modify it |
| 10 | under the terms of the GNU General Public License as published by the |
| 11 | Free Software Foundation; either version 2, or (at your option) any |
| 12 | later version. |
| 13 | |
| 14 | This program is distributed in the hope that it will be useful, |
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 17 | GNU General Public License for more details. |
| 18 | |
| 19 | You should have received a copy of the GNU General Public License |
| 20 | along with this program; if not, write to the Free Software |
Richard Kenner | e38992e | 2000-04-18 20:42:00 +0000 | [diff] [blame] | 21 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 22 | |
| 23 | #include "config.h" |
| 24 | #include "system.h" |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 25 | #include <dirent.h> |
Zack Weinberg | 4977bab | 2002-12-16 18:23:00 +0000 | [diff] [blame] | 26 | #include "coretypes.h" |
| 27 | #include "tm.h" |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 28 | #include "cpplib.h" |
Zack Weinberg | 88ae23e | 2000-03-08 23:35:19 +0000 | [diff] [blame] | 29 | #include "cpphash.h" |
Zack Weinberg | c1212d2 | 2000-02-06 23:46:18 +0000 | [diff] [blame] | 30 | #include "intl.h" |
Zack Weinberg | 168d373 | 2000-03-14 06:34:11 +0000 | [diff] [blame] | 31 | #include "mkdeps.h" |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 32 | #include "splay-tree.h" |
Hans-Peter Nilsson | 414d23a | 2002-11-20 19:49:53 +0000 | [diff] [blame] | 33 | #ifdef ENABLE_VALGRIND_CHECKING |
| 34 | #include <valgrind.h> |
| 35 | #else |
| 36 | /* Avoid #ifdef:s when we can help it. */ |
| 37 | #define VALGRIND_DISCARD(x) |
| 38 | #endif |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 39 | |
Zack Weinberg | f8f769e | 2000-05-28 05:56:38 +0000 | [diff] [blame] | 40 | #ifdef HAVE_MMAP_FILE |
| 41 | # include <sys/mman.h> |
| 42 | # ifndef MMAP_THRESHOLD |
| 43 | # define MMAP_THRESHOLD 3 /* Minimum page count to mmap the file. */ |
| 44 | # endif |
Christopher Faylor | 969815c | 2002-01-14 19:45:11 +0000 | [diff] [blame] | 45 | # if MMAP_THRESHOLD |
| 46 | # define TEST_THRESHOLD(size, pagesize) \ |
| 47 | (size / pagesize >= MMAP_THRESHOLD && (size % pagesize) != 0) |
| 48 | /* Use mmap if the file is big enough to be worth it (controlled |
| 49 | by MMAP_THRESHOLD) and if we can safely count on there being |
| 50 | at least one readable NUL byte after the end of the file's |
| 51 | contents. This is true for all tested operating systems when |
| 52 | the file size is not an exact multiple of the page size. */ |
| 53 | # ifndef __CYGWIN__ |
| 54 | # define SHOULD_MMAP(size, pagesize) TEST_THRESHOLD (size, pagesize) |
| 55 | # else |
| 56 | # define WIN32_LEAN_AND_MEAN |
| 57 | # include <windows.h> |
| 58 | /* Cygwin can't correctly emulate mmap under Windows 9x style systems so |
| 59 | disallow use of mmap on those systems. Windows 9x does not zero fill |
| 60 | memory at EOF and beyond, as required. */ |
| 61 | # define SHOULD_MMAP(size, pagesize) ((GetVersion() & 0x80000000) \ |
| 62 | ? 0 : TEST_THRESHOLD (size, pagesize)) |
| 63 | # endif |
| 64 | # endif |
Zack Weinberg | f8f769e | 2000-05-28 05:56:38 +0000 | [diff] [blame] | 65 | |
| 66 | #else /* No MMAP_FILE */ |
| 67 | # undef MMAP_THRESHOLD |
| 68 | # define MMAP_THRESHOLD 0 |
| 69 | #endif |
| 70 | |
Zack Weinberg | d7a2e0f | 2000-06-01 20:06:57 +0000 | [diff] [blame] | 71 | #ifndef O_BINARY |
| 72 | # define O_BINARY 0 |
| 73 | #endif |
| 74 | |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 75 | /* If errno is inspected immediately after a system call fails, it will be |
| 76 | nonzero, and no error number will ever be zero. */ |
| 77 | #ifndef ENOENT |
| 78 | # define ENOENT 0 |
| 79 | #endif |
| 80 | #ifndef ENOTDIR |
| 81 | # define ENOTDIR 0 |
| 82 | #endif |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 83 | |
Zack Weinberg | f9a0e96 | 2000-07-13 02:32:41 +0000 | [diff] [blame] | 84 | /* Suppress warning about function macros used w/o arguments in traditional |
| 85 | C. It is unlikely that glibc's strcmp macro helps this file at all. */ |
| 86 | #undef strcmp |
| 87 | |
Neil Booth | 642ce43 | 2000-12-07 23:17:56 +0000 | [diff] [blame] | 88 | /* This structure is used for the table of all includes. */ |
Kazu Hirata | dc65cd6 | 2002-11-19 06:55:04 +0000 | [diff] [blame] | 89 | struct include_file { |
Neil Booth | 642ce43 | 2000-12-07 23:17:56 +0000 | [diff] [blame] | 90 | const char *name; /* actual path name of file */ |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 91 | const char *header_name; /* the original header found */ |
Neil Booth | 642ce43 | 2000-12-07 23:17:56 +0000 | [diff] [blame] | 92 | const cpp_hashnode *cmacro; /* macro, if any, preventing reinclusion. */ |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 93 | const struct cpp_path *foundhere; |
Neil Booth | 642ce43 | 2000-12-07 23:17:56 +0000 | [diff] [blame] | 94 | /* location in search path where file was |
| 95 | found, for #include_next and sysp. */ |
| 96 | const unsigned char *buffer; /* pointer to cached file contents */ |
| 97 | struct stat st; /* copy of stat(2) data for file */ |
| 98 | int fd; /* fd open on file (short term storage only) */ |
Neil Booth | f277b5e | 2001-05-05 11:12:19 +0000 | [diff] [blame] | 99 | int err_no; /* errno obtained if opening a file failed */ |
Neil Booth | 642ce43 | 2000-12-07 23:17:56 +0000 | [diff] [blame] | 100 | unsigned short include_count; /* number of times file has been read */ |
| 101 | unsigned short refcnt; /* number of stacked buffers using this file */ |
| 102 | unsigned char mapped; /* file buffer is mmapped */ |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 103 | unsigned char pch; /* 0: file not known to be a PCH. |
| 104 | 1: file is a PCH |
| 105 | (on return from find_include_file). |
| 106 | 2: file is not and never will be a valid |
| 107 | precompiled header. |
| 108 | 3: file is always a valid precompiled |
| 109 | header. */ |
Neil Booth | 642ce43 | 2000-12-07 23:17:56 +0000 | [diff] [blame] | 110 | }; |
| 111 | |
Douglas B Rupp | ae1139f | 2001-11-21 17:03:27 -0500 | [diff] [blame] | 112 | /* Variable length record files on VMS will have a stat size that includes |
Kazu Hirata | 3ef42a0 | 2002-01-18 13:40:36 +0000 | [diff] [blame] | 113 | record control characters that won't be included in the read size. */ |
Douglas B Rupp | ae1139f | 2001-11-21 17:03:27 -0500 | [diff] [blame] | 114 | #ifdef VMS |
| 115 | # define FAB_C_VAR 2 /* variable length records (see Starlet fabdef.h) */ |
| 116 | # define STAT_SIZE_TOO_BIG(ST) ((ST).st_fab_rfm == FAB_C_VAR) |
| 117 | #else |
| 118 | # define STAT_SIZE_TOO_BIG(ST) 0 |
| 119 | #endif |
| 120 | |
Neil Booth | 28e0f04 | 2000-12-09 12:06:37 +0000 | [diff] [blame] | 121 | /* The cmacro works like this: If it's NULL, the file is to be |
| 122 | included again. If it's NEVER_REREAD, the file is never to be |
| 123 | included again. Otherwise it is a macro hashnode, and the file is |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 124 | to be included again if the macro is defined. */ |
Kazu Hirata | dc65cd6 | 2002-11-19 06:55:04 +0000 | [diff] [blame] | 125 | #define NEVER_REREAD ((const cpp_hashnode *) -1) |
Neil Booth | 28e0f04 | 2000-12-09 12:06:37 +0000 | [diff] [blame] | 126 | #define DO_NOT_REREAD(inc) \ |
| 127 | ((inc)->cmacro && ((inc)->cmacro == NEVER_REREAD \ |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 128 | || (inc)->cmacro->type == NT_MACRO)) |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 129 | #define NO_INCLUDE_PATH ((struct include_file *) -1) |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 130 | #define INCLUDE_PCH_P(F) (((F)->pch & 1) != 0) |
Neil Booth | 28e0f04 | 2000-12-09 12:06:37 +0000 | [diff] [blame] | 131 | |
Zack Weinberg | a73ac7a | 2000-01-30 18:09:07 +0000 | [diff] [blame] | 132 | static struct file_name_map *read_name_map |
Zack Weinberg | 38b24ee | 2000-03-08 20:37:23 +0000 | [diff] [blame] | 133 | PARAMS ((cpp_reader *, const char *)); |
| 134 | static char *read_filename_string PARAMS ((int, FILE *)); |
| 135 | static char *remap_filename PARAMS ((cpp_reader *, char *, |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 136 | struct cpp_path *)); |
| 137 | static struct cpp_path *search_from PARAMS ((cpp_reader *, |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 138 | enum include_type)); |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 139 | static struct include_file * |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 140 | find_include_file PARAMS ((cpp_reader *, const cpp_token *, |
| 141 | enum include_type)); |
Neil Booth | 2047e26 | 2000-09-21 18:01:22 +0000 | [diff] [blame] | 142 | static struct include_file *open_file PARAMS ((cpp_reader *, const char *)); |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 143 | static struct include_file *validate_pch PARAMS ((cpp_reader *, |
| 144 | const char *, |
| 145 | const char *)); |
| 146 | static struct include_file *open_file_pch PARAMS ((cpp_reader *, |
| 147 | const char *)); |
Neil Booth | 7c09271 | 2001-04-06 05:21:36 +0000 | [diff] [blame] | 148 | static int read_include_file PARAMS ((cpp_reader *, struct include_file *)); |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 149 | static bool stack_include_file PARAMS ((cpp_reader *, struct include_file *)); |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 150 | static void purge_cache PARAMS ((struct include_file *)); |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 151 | static void destroy_node PARAMS ((splay_tree_value)); |
Zack Weinberg | c71f835 | 2000-07-05 05:33:57 +0000 | [diff] [blame] | 152 | static int report_missing_guard PARAMS ((splay_tree_node, void *)); |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 153 | static splay_tree_node find_or_create_entry PARAMS ((cpp_reader *, |
| 154 | const char *)); |
| 155 | static void handle_missing_header PARAMS ((cpp_reader *, const char *, int)); |
Neil Booth | 986b1f1 | 2003-03-02 17:44:18 +0000 | [diff] [blame^] | 156 | static int remove_component_p PARAMS ((const char *)); |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 157 | |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 158 | /* Set up the splay tree we use to store information about all the |
| 159 | file names seen in this compilation. We also have entries for each |
| 160 | file we tried to open but failed; this saves system calls since we |
| 161 | don't try to open it again in future. |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 162 | |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 163 | The key of each node is the file name, after processing by |
Neil Booth | 986b1f1 | 2003-03-02 17:44:18 +0000 | [diff] [blame^] | 164 | cpp_simplify_path. The path name may or may not be absolute. |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 165 | The path string has been malloced, as is automatically freed by |
| 166 | registering free () as the splay tree key deletion function. |
Neil Booth | d6d52dd | 2001-01-13 18:39:26 +0000 | [diff] [blame] | 167 | |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 168 | A node's value is a pointer to a struct include_file, and is never |
| 169 | NULL. */ |
Zack Weinberg | d35364d | 2000-03-12 23:46:05 +0000 | [diff] [blame] | 170 | void |
Zack Weinberg | c71f835 | 2000-07-05 05:33:57 +0000 | [diff] [blame] | 171 | _cpp_init_includes (pfile) |
Zack Weinberg | d35364d | 2000-03-12 23:46:05 +0000 | [diff] [blame] | 172 | cpp_reader *pfile; |
| 173 | { |
| 174 | pfile->all_include_files |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 175 | = splay_tree_new ((splay_tree_compare_fn) strcmp, |
| 176 | (splay_tree_delete_key_fn) free, |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 177 | destroy_node); |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 178 | } |
| 179 | |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 180 | /* Tear down the splay tree. */ |
Zack Weinberg | c71f835 | 2000-07-05 05:33:57 +0000 | [diff] [blame] | 181 | void |
| 182 | _cpp_cleanup_includes (pfile) |
| 183 | cpp_reader *pfile; |
| 184 | { |
| 185 | splay_tree_delete (pfile->all_include_files); |
| 186 | } |
| 187 | |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 188 | /* Free a node. The path string is automatically freed. */ |
| 189 | static void |
| 190 | destroy_node (v) |
| 191 | splay_tree_value v; |
| 192 | { |
Kazu Hirata | dc65cd6 | 2002-11-19 06:55:04 +0000 | [diff] [blame] | 193 | struct include_file *f = (struct include_file *) v; |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 194 | |
| 195 | if (f) |
| 196 | { |
| 197 | purge_cache (f); |
| 198 | free (f); |
| 199 | } |
| 200 | } |
| 201 | |
Neil Booth | 642ce43 | 2000-12-07 23:17:56 +0000 | [diff] [blame] | 202 | /* Mark a file to not be reread (e.g. #import, read failure). */ |
| 203 | void |
| 204 | _cpp_never_reread (file) |
| 205 | struct include_file *file; |
| 206 | { |
| 207 | file->cmacro = NEVER_REREAD; |
| 208 | } |
| 209 | |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 210 | /* Lookup a filename, which is simplified after making a copy, and |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 211 | create an entry if none exists. */ |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 212 | static splay_tree_node |
| 213 | find_or_create_entry (pfile, fname) |
| 214 | cpp_reader *pfile; |
| 215 | const char *fname; |
| 216 | { |
| 217 | splay_tree_node node; |
| 218 | struct include_file *file; |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 219 | char *name = xstrdup (fname); |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 220 | |
Neil Booth | 986b1f1 | 2003-03-02 17:44:18 +0000 | [diff] [blame^] | 221 | cpp_simplify_path (name); |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 222 | node = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name); |
| 223 | if (node) |
| 224 | free (name); |
| 225 | else |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 226 | { |
| 227 | file = xcnew (struct include_file); |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 228 | file->name = name; |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 229 | file->header_name = name; |
Neil Booth | 986b1f1 | 2003-03-02 17:44:18 +0000 | [diff] [blame^] | 230 | file->err_no = errno; |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 231 | node = splay_tree_insert (pfile->all_include_files, |
| 232 | (splay_tree_key) file->name, |
| 233 | (splay_tree_value) file); |
| 234 | } |
| 235 | |
| 236 | return node; |
| 237 | } |
| 238 | |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 239 | /* Enter a file name in the splay tree, for the sake of cpp_included. */ |
Neil Booth | d6d52dd | 2001-01-13 18:39:26 +0000 | [diff] [blame] | 240 | void |
| 241 | _cpp_fake_include (pfile, fname) |
| 242 | cpp_reader *pfile; |
| 243 | const char *fname; |
| 244 | { |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 245 | find_or_create_entry (pfile, fname); |
Neil Booth | d6d52dd | 2001-01-13 18:39:26 +0000 | [diff] [blame] | 246 | } |
| 247 | |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 248 | /* Given a file name, look it up in the cache; if there is no entry, |
Neil Booth | 2047e26 | 2000-09-21 18:01:22 +0000 | [diff] [blame] | 249 | create one with a non-NULL value (regardless of success in opening |
| 250 | the file). If the file doesn't exist or is inaccessible, this |
| 251 | entry is flagged so we don't attempt to open it again in the |
Neil Booth | 373e217 | 2001-02-21 07:29:56 +0000 | [diff] [blame] | 252 | future. If the file isn't open, open it. The empty string is |
| 253 | interpreted as stdin. |
Neil Booth | 2047e26 | 2000-09-21 18:01:22 +0000 | [diff] [blame] | 254 | |
| 255 | Returns an include_file structure with an open file descriptor on |
| 256 | success, or NULL on failure. */ |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 257 | static struct include_file * |
Neil Booth | 2047e26 | 2000-09-21 18:01:22 +0000 | [diff] [blame] | 258 | open_file (pfile, filename) |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 259 | cpp_reader *pfile; |
| 260 | const char *filename; |
Neil Booth | 2047e26 | 2000-09-21 18:01:22 +0000 | [diff] [blame] | 261 | { |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 262 | splay_tree_node nd = find_or_create_entry (pfile, filename); |
| 263 | struct include_file *file = (struct include_file *) nd->value; |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 264 | |
Neil Booth | f277b5e | 2001-05-05 11:12:19 +0000 | [diff] [blame] | 265 | if (file->err_no) |
| 266 | { |
| 267 | /* Ugh. handle_missing_header () needs errno to be set. */ |
| 268 | errno = file->err_no; |
| 269 | return 0; |
| 270 | } |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 271 | |
Kazu Hirata | ec5c56d | 2001-08-01 17:57:27 +0000 | [diff] [blame] | 272 | /* Don't reopen an idempotent file. */ |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 273 | if (DO_NOT_REREAD (file)) |
| 274 | return file; |
Kazu Hirata | df38348 | 2002-05-22 22:02:16 +0000 | [diff] [blame] | 275 | |
Kazu Hirata | ec5c56d | 2001-08-01 17:57:27 +0000 | [diff] [blame] | 276 | /* Don't reopen one which is already loaded. */ |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 277 | if (file->buffer != NULL) |
| 278 | return file; |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 279 | |
| 280 | /* We used to open files in nonblocking mode, but that caused more |
| 281 | problems than it solved. Do take care not to acquire a |
| 282 | controlling terminal by mistake (this can't happen on sane |
| 283 | systems, but paranoia is a virtue). |
| 284 | |
| 285 | Use the three-argument form of open even though we aren't |
| 286 | specifying O_CREAT, to defend against broken system headers. |
| 287 | |
| 288 | O_BINARY tells some runtime libraries (notably DJGPP) not to do |
| 289 | newline translation; we can handle DOS line breaks just fine |
| 290 | ourselves. |
| 291 | |
| 292 | Special case: the empty string is translated to stdin. */ |
Zack Weinberg | d450696 | 2000-06-28 19:03:08 +0000 | [diff] [blame] | 293 | |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 294 | if (filename[0] == '\0') |
Andris Pavenis | 85be8c2 | 2002-05-13 23:28:28 +0300 | [diff] [blame] | 295 | { |
| 296 | file->fd = 0; |
| 297 | #ifdef __DJGPP__ |
| 298 | /* For DJGPP redirected input is opened in text mode. Change it |
| 299 | to binary mode. */ |
| 300 | if (! isatty (file->fd)) |
Kazu Hirata | df38348 | 2002-05-22 22:02:16 +0000 | [diff] [blame] | 301 | setmode (file->fd, O_BINARY); |
Andris Pavenis | 85be8c2 | 2002-05-13 23:28:28 +0300 | [diff] [blame] | 302 | #endif |
| 303 | } |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 304 | else |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 305 | file->fd = open (file->name, O_RDONLY | O_NOCTTY | O_BINARY, 0666); |
Zack Weinberg | d450696 | 2000-06-28 19:03:08 +0000 | [diff] [blame] | 306 | |
Neil Booth | 2047e26 | 2000-09-21 18:01:22 +0000 | [diff] [blame] | 307 | if (file->fd != -1 && fstat (file->fd, &file->st) == 0) |
| 308 | { |
Neil Booth | c0bfe99 | 2001-10-08 17:54:15 +0000 | [diff] [blame] | 309 | if (!S_ISDIR (file->st.st_mode)) |
| 310 | return file; |
Zack Weinberg | 55485cd | 2001-12-06 16:41:18 +0000 | [diff] [blame] | 311 | |
Neil Booth | 7c09271 | 2001-04-06 05:21:36 +0000 | [diff] [blame] | 312 | /* If it's a directory, we return null and continue the search |
| 313 | as the file we're looking for may appear elsewhere in the |
| 314 | search path. */ |
Neil Booth | c0bfe99 | 2001-10-08 17:54:15 +0000 | [diff] [blame] | 315 | errno = ENOENT; |
Zack Weinberg | 55485cd | 2001-12-06 16:41:18 +0000 | [diff] [blame] | 316 | close (file->fd); |
| 317 | file->fd = -1; |
Neil Booth | 2047e26 | 2000-09-21 18:01:22 +0000 | [diff] [blame] | 318 | } |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 319 | |
Neil Booth | f277b5e | 2001-05-05 11:12:19 +0000 | [diff] [blame] | 320 | file->err_no = errno; |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 321 | return 0; |
| 322 | } |
| 323 | |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 324 | static struct include_file * |
| 325 | validate_pch (pfile, filename, pchname) |
| 326 | cpp_reader *pfile; |
| 327 | const char *filename; |
| 328 | const char *pchname; |
| 329 | { |
| 330 | struct include_file * file; |
| 331 | |
| 332 | file = open_file (pfile, pchname); |
| 333 | if (file == NULL) |
| 334 | return NULL; |
| 335 | if ((file->pch & 2) == 0) |
| 336 | file->pch = pfile->cb.valid_pch (pfile, pchname, file->fd); |
| 337 | if (INCLUDE_PCH_P (file)) |
| 338 | { |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 339 | char *f = xstrdup (filename); |
Neil Booth | 986b1f1 | 2003-03-02 17:44:18 +0000 | [diff] [blame^] | 340 | cpp_simplify_path (f); |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 341 | file->header_name = f; |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 342 | return file; |
| 343 | } |
| 344 | close (file->fd); |
| 345 | file->fd = -1; |
| 346 | return NULL; |
| 347 | } |
| 348 | |
| 349 | |
| 350 | /* Like open_file, but also look for a precompiled header if (a) one exists |
| 351 | and (b) it is valid. */ |
| 352 | static struct include_file * |
| 353 | open_file_pch (pfile, filename) |
| 354 | cpp_reader *pfile; |
| 355 | const char *filename; |
| 356 | { |
| 357 | if (filename[0] != '\0' |
| 358 | && pfile->cb.valid_pch != NULL) |
| 359 | { |
| 360 | size_t namelen = strlen (filename); |
| 361 | char *pchname = alloca (namelen + 5); |
| 362 | struct include_file * file; |
| 363 | splay_tree_node nd; |
| 364 | |
| 365 | memcpy (pchname, filename, namelen); |
Geoffrey Keating | d8fad4e | 2003-02-28 23:06:10 +0000 | [diff] [blame] | 366 | memcpy (pchname + namelen, ".gch", 5); |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 367 | |
| 368 | nd = find_or_create_entry (pfile, pchname); |
| 369 | file = (struct include_file *) nd->value; |
| 370 | |
| 371 | if (file != NULL) |
| 372 | { |
| 373 | if (stat (file->name, &file->st) == 0 && S_ISDIR (file->st.st_mode)) |
| 374 | { |
| 375 | DIR * thedir; |
| 376 | struct dirent *d; |
| 377 | size_t subname_len = namelen + 64; |
| 378 | char *subname = xmalloc (subname_len); |
| 379 | |
| 380 | thedir = opendir (pchname); |
| 381 | if (thedir == NULL) |
| 382 | return NULL; |
| 383 | memcpy (subname, pchname, namelen + 4); |
| 384 | subname[namelen+4] = '/'; |
| 385 | while ((d = readdir (thedir)) != NULL) |
| 386 | { |
| 387 | if (strlen (d->d_name) + namelen + 7 > subname_len) |
| 388 | { |
| 389 | subname_len = strlen (d->d_name) + namelen + 64; |
| 390 | subname = xrealloc (subname, subname_len); |
| 391 | } |
| 392 | strcpy (subname + namelen + 5, d->d_name); |
| 393 | file = validate_pch (pfile, filename, subname); |
| 394 | if (file) |
| 395 | break; |
| 396 | } |
| 397 | closedir (thedir); |
| 398 | free (subname); |
| 399 | } |
| 400 | else |
| 401 | file = validate_pch (pfile, filename, pchname); |
| 402 | if (file) |
| 403 | return file; |
| 404 | } |
| 405 | } |
| 406 | return open_file (pfile, filename); |
| 407 | } |
| 408 | |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 409 | /* Place the file referenced by INC into a new buffer on the buffer |
| 410 | stack, unless there are errors, or the file is not re-included |
| 411 | because of e.g. multiple-include guards. Returns true if a buffer |
| 412 | is stacked. */ |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 413 | static bool |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 414 | stack_include_file (pfile, inc) |
| 415 | cpp_reader *pfile; |
| 416 | struct include_file *inc; |
| 417 | { |
| 418 | cpp_buffer *fp; |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 419 | int sysp; |
Neil Booth | bb74c96 | 2001-08-17 22:23:49 +0000 | [diff] [blame] | 420 | const char *filename; |
Neil Booth | 51d0f32 | 2001-02-19 19:50:21 +0000 | [diff] [blame] | 421 | |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 422 | if (DO_NOT_REREAD (inc)) |
| 423 | return false; |
| 424 | |
Neil Booth | 47d89cf | 2001-08-11 07:33:39 +0000 | [diff] [blame] | 425 | sysp = MAX ((pfile->map ? pfile->map->sysp : 0), |
Alexandre Oliva | 11bca30 | 2001-03-16 05:19:46 +0000 | [diff] [blame] | 426 | (inc->foundhere ? inc->foundhere->sysp : 0)); |
Neil Booth | 51d0f32 | 2001-02-19 19:50:21 +0000 | [diff] [blame] | 427 | |
Neil Booth | 182d89a | 2002-08-14 22:34:50 +0000 | [diff] [blame] | 428 | /* Add the file to the dependencies on its first inclusion. */ |
Neil Booth | f4ff5a6 | 2002-08-12 22:44:30 +0000 | [diff] [blame] | 429 | if (CPP_OPTION (pfile, deps.style) > !!sysp && !inc->include_count) |
Neil Booth | 182d89a | 2002-08-14 22:34:50 +0000 | [diff] [blame] | 430 | { |
| 431 | if (pfile->buffer || CPP_OPTION (pfile, deps.ignore_main_file) == 0) |
| 432 | deps_add_dep (pfile->deps, inc->name); |
| 433 | } |
Neil Booth | 51d0f32 | 2001-02-19 19:50:21 +0000 | [diff] [blame] | 434 | |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 435 | /* PCH files get dealt with immediately. */ |
| 436 | if (INCLUDE_PCH_P (inc)) |
| 437 | { |
| 438 | pfile->cb.read_pch (pfile, inc->name, inc->fd, inc->header_name); |
| 439 | close (inc->fd); |
| 440 | inc->fd = -1; |
| 441 | return false; |
| 442 | } |
| 443 | |
Neil Booth | 7c09271 | 2001-04-06 05:21:36 +0000 | [diff] [blame] | 444 | /* Not in cache? */ |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 445 | if (! inc->buffer) |
Neil Booth | 7c09271 | 2001-04-06 05:21:36 +0000 | [diff] [blame] | 446 | { |
Neil Booth | 4d6baaf | 2001-11-26 23:44:54 +0000 | [diff] [blame] | 447 | if (read_include_file (pfile, inc)) |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 448 | { |
Neil Booth | c0bfe99 | 2001-10-08 17:54:15 +0000 | [diff] [blame] | 449 | /* If an error occurs, do not try to read this file again. */ |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 450 | _cpp_never_reread (inc); |
| 451 | return false; |
| 452 | } |
Neil Booth | 4d6baaf | 2001-11-26 23:44:54 +0000 | [diff] [blame] | 453 | /* Mark a regular, zero-length file never-reread. We read it, |
| 454 | NUL-terminate it, and stack it once, so preprocessing a main |
| 455 | file of zero length does not raise an error. */ |
| 456 | if (S_ISREG (inc->st.st_mode) && inc->st.st_size == 0) |
| 457 | _cpp_never_reread (inc); |
Neil Booth | 7c09271 | 2001-04-06 05:21:36 +0000 | [diff] [blame] | 458 | close (inc->fd); |
| 459 | inc->fd = -1; |
| 460 | } |
| 461 | |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 462 | if (pfile->buffer) |
Neil Booth | 5993019 | 2001-08-21 21:17:48 +0000 | [diff] [blame] | 463 | /* We don't want MI guard advice for the main file. */ |
| 464 | inc->include_count++; |
Neil Booth | eb1f4d9 | 2000-12-18 19:00:26 +0000 | [diff] [blame] | 465 | |
| 466 | /* Push a buffer. */ |
Neil Booth | 29401c3 | 2001-08-22 20:37:20 +0000 | [diff] [blame] | 467 | fp = cpp_push_buffer (pfile, inc->buffer, inc->st.st_size, |
| 468 | /* from_stage3 */ CPP_OPTION (pfile, preprocessed), 0); |
Neil Booth | eb1f4d9 | 2000-12-18 19:00:26 +0000 | [diff] [blame] | 469 | fp->inc = inc; |
Neil Booth | 3cf3593 | 2000-12-05 23:42:43 +0000 | [diff] [blame] | 470 | fp->inc->refcnt++; |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 471 | |
Kazu Hirata | 4912a07 | 2002-09-14 15:51:45 +0000 | [diff] [blame] | 472 | /* Initialize controlling macro state. */ |
Neil Booth | 6d18adb | 2001-07-29 17:27:57 +0000 | [diff] [blame] | 473 | pfile->mi_valid = true; |
Neil Booth | 3cf3593 | 2000-12-05 23:42:43 +0000 | [diff] [blame] | 474 | pfile->mi_cmacro = 0; |
Neil Booth | eb1f4d9 | 2000-12-18 19:00:26 +0000 | [diff] [blame] | 475 | |
| 476 | /* Generate the call back. */ |
Neil Booth | bb74c96 | 2001-08-17 22:23:49 +0000 | [diff] [blame] | 477 | filename = inc->name; |
| 478 | if (*filename == '\0') |
Philipp Thomas | 0b26406 | 2001-12-28 00:09:47 +0000 | [diff] [blame] | 479 | filename = "<stdin>"; |
Neil Booth | bb74c96 | 2001-08-17 22:23:49 +0000 | [diff] [blame] | 480 | _cpp_do_file_change (pfile, LC_ENTER, filename, 1, sysp); |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 481 | |
| 482 | return true; |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 483 | } |
| 484 | |
| 485 | /* Read the file referenced by INC into the file cache. |
| 486 | |
| 487 | If fd points to a plain file, we might be able to mmap it; we can |
| 488 | definitely allocate the buffer all at once. If fd is a pipe or |
| 489 | terminal, we can't do either. If fd is something weird, like a |
Neil Booth | 7c09271 | 2001-04-06 05:21:36 +0000 | [diff] [blame] | 490 | block device, we don't want to read it at all. |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 491 | |
| 492 | Unfortunately, different systems use different st.st_mode values |
| 493 | for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and |
| 494 | zero the entire struct stat except a couple fields. Hence we don't |
Neil Booth | 7c09271 | 2001-04-06 05:21:36 +0000 | [diff] [blame] | 495 | even try to figure out what something is, except for plain files |
| 496 | and block devices. |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 497 | |
| 498 | FIXME: Flush file cache and try again if we run out of memory. */ |
Neil Booth | 7c09271 | 2001-04-06 05:21:36 +0000 | [diff] [blame] | 499 | static int |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 500 | read_include_file (pfile, inc) |
| 501 | cpp_reader *pfile; |
| 502 | struct include_file *inc; |
| 503 | { |
| 504 | ssize_t size, offset, count; |
Neil Booth | 562a5c2 | 2002-04-21 18:46:42 +0000 | [diff] [blame] | 505 | uchar *buf; |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 506 | #if MMAP_THRESHOLD |
| 507 | static int pagesize = -1; |
| 508 | #endif |
| 509 | |
| 510 | if (S_ISREG (inc->st.st_mode)) |
| 511 | { |
| 512 | /* off_t might have a wider range than ssize_t - in other words, |
| 513 | the max size of a file might be bigger than the address |
| 514 | space. We can't handle a file that large. (Anyone with |
| 515 | a single source file bigger than 2GB needs to rethink |
| 516 | their coding style.) Some systems (e.g. AIX 4.1) define |
| 517 | SSIZE_MAX to be much smaller than the actual range of the |
| 518 | type. Use INTTYPE_MAXIMUM unconditionally to ensure this |
| 519 | does not bite us. */ |
| 520 | if (inc->st.st_size > INTTYPE_MAXIMUM (ssize_t)) |
| 521 | { |
Neil Booth | ebef4e8 | 2002-04-14 18:42:47 +0000 | [diff] [blame] | 522 | cpp_error (pfile, DL_ERROR, "%s is too large", inc->name); |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 523 | goto fail; |
| 524 | } |
| 525 | size = inc->st.st_size; |
| 526 | |
Laurynas Biveinis | ae0f4de | 2000-09-16 18:17:53 +0000 | [diff] [blame] | 527 | inc->mapped = 0; |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 528 | #if MMAP_THRESHOLD |
| 529 | if (pagesize == -1) |
| 530 | pagesize = getpagesize (); |
| 531 | |
Christopher Faylor | 969815c | 2002-01-14 19:45:11 +0000 | [diff] [blame] | 532 | if (SHOULD_MMAP (size, pagesize)) |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 533 | { |
Neil Booth | 562a5c2 | 2002-04-21 18:46:42 +0000 | [diff] [blame] | 534 | buf = (uchar *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0); |
Kazu Hirata | dc65cd6 | 2002-11-19 06:55:04 +0000 | [diff] [blame] | 535 | if (buf == (uchar *) -1) |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 536 | goto perror_fail; |
Hans-Peter Nilsson | 414d23a | 2002-11-20 19:49:53 +0000 | [diff] [blame] | 537 | |
| 538 | /* We must tell Valgrind that the byte at buf[size] is actually |
| 539 | readable. Discard the handle to avoid handle leak. */ |
| 540 | VALGRIND_DISCARD (VALGRIND_MAKE_READABLE (buf + size, 1)); |
| 541 | |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 542 | inc->mapped = 1; |
| 543 | } |
| 544 | else |
| 545 | #endif |
| 546 | { |
Neil Booth | 562a5c2 | 2002-04-21 18:46:42 +0000 | [diff] [blame] | 547 | buf = (uchar *) xmalloc (size + 1); |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 548 | offset = 0; |
| 549 | while (offset < size) |
| 550 | { |
| 551 | count = read (inc->fd, buf + offset, size - offset); |
| 552 | if (count < 0) |
| 553 | goto perror_fail; |
| 554 | if (count == 0) |
| 555 | { |
Douglas B Rupp | ae1139f | 2001-11-21 17:03:27 -0500 | [diff] [blame] | 556 | if (!STAT_SIZE_TOO_BIG (inc->st)) |
Neil Booth | ebef4e8 | 2002-04-14 18:42:47 +0000 | [diff] [blame] | 557 | cpp_error (pfile, DL_WARNING, |
| 558 | "%s is shorter than expected", inc->name); |
Douglas B Rupp | cdb2905 | 2001-12-12 07:42:03 -0500 | [diff] [blame] | 559 | size = offset; |
| 560 | buf = xrealloc (buf, size + 1); |
| 561 | inc->st.st_size = size; |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 562 | break; |
| 563 | } |
| 564 | offset += count; |
| 565 | } |
Neil Booth | 4d6baaf | 2001-11-26 23:44:54 +0000 | [diff] [blame] | 566 | /* The lexer requires that the buffer be NUL-terminated. */ |
| 567 | buf[size] = '\0'; |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 568 | } |
| 569 | } |
| 570 | else if (S_ISBLK (inc->st.st_mode)) |
| 571 | { |
Neil Booth | ebef4e8 | 2002-04-14 18:42:47 +0000 | [diff] [blame] | 572 | cpp_error (pfile, DL_ERROR, "%s is a block device", inc->name); |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 573 | goto fail; |
| 574 | } |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 575 | else |
| 576 | { |
| 577 | /* 8 kilobytes is a sensible starting size. It ought to be |
| 578 | bigger than the kernel pipe buffer, and it's definitely |
| 579 | bigger than the majority of C source files. */ |
| 580 | size = 8 * 1024; |
| 581 | |
Neil Booth | 562a5c2 | 2002-04-21 18:46:42 +0000 | [diff] [blame] | 582 | buf = (uchar *) xmalloc (size + 1); |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 583 | offset = 0; |
| 584 | while ((count = read (inc->fd, buf + offset, size - offset)) > 0) |
| 585 | { |
| 586 | offset += count; |
| 587 | if (offset == size) |
Neil Booth | 4d6baaf | 2001-11-26 23:44:54 +0000 | [diff] [blame] | 588 | { |
| 589 | size *= 2; |
| 590 | buf = xrealloc (buf, size + 1); |
| 591 | } |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 592 | } |
| 593 | if (count < 0) |
| 594 | goto perror_fail; |
| 595 | |
Neil Booth | 4d6baaf | 2001-11-26 23:44:54 +0000 | [diff] [blame] | 596 | if (offset + 1 < size) |
| 597 | buf = xrealloc (buf, offset + 1); |
| 598 | |
| 599 | /* The lexer requires that the buffer be NUL-terminated. */ |
| 600 | buf[offset] = '\0'; |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 601 | inc->st.st_size = offset; |
| 602 | } |
| 603 | |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 604 | inc->buffer = buf; |
Neil Booth | 7c09271 | 2001-04-06 05:21:36 +0000 | [diff] [blame] | 605 | return 0; |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 606 | |
| 607 | perror_fail: |
Neil Booth | ebef4e8 | 2002-04-14 18:42:47 +0000 | [diff] [blame] | 608 | cpp_errno (pfile, DL_ERROR, inc->name); |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 609 | fail: |
Neil Booth | 7c09271 | 2001-04-06 05:21:36 +0000 | [diff] [blame] | 610 | return 1; |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 611 | } |
| 612 | |
Neil Booth | 5d8ebbd | 2002-01-03 21:43:09 +0000 | [diff] [blame] | 613 | /* Drop INC's buffer from memory, if we are unlikely to need it again. */ |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 614 | static void |
| 615 | purge_cache (inc) |
| 616 | struct include_file *inc; |
| 617 | { |
| 618 | if (inc->buffer) |
| 619 | { |
Laurynas Biveinis | ae0f4de | 2000-09-16 18:17:53 +0000 | [diff] [blame] | 620 | #if MMAP_THRESHOLD |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 621 | if (inc->mapped) |
Hans-Peter Nilsson | 414d23a | 2002-11-20 19:49:53 +0000 | [diff] [blame] | 622 | { |
| 623 | /* Undo the previous annotation for the |
| 624 | known-zero-byte-after-mmap. Discard the handle to avoid |
| 625 | handle leak. */ |
| 626 | VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (inc->buffer |
| 627 | + inc->st.st_size, 1)); |
| 628 | munmap ((PTR) inc->buffer, inc->st.st_size); |
| 629 | } |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 630 | else |
Laurynas Biveinis | ae0f4de | 2000-09-16 18:17:53 +0000 | [diff] [blame] | 631 | #endif |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 632 | free ((PTR) inc->buffer); |
| 633 | inc->buffer = NULL; |
| 634 | } |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 635 | } |
| 636 | |
Zack Weinberg | b0699da | 2000-03-07 20:58:47 +0000 | [diff] [blame] | 637 | /* Return 1 if the file named by FNAME has been included before in |
| 638 | any context, 0 otherwise. */ |
| 639 | int |
| 640 | cpp_included (pfile, fname) |
| 641 | cpp_reader *pfile; |
| 642 | const char *fname; |
| 643 | { |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 644 | struct cpp_path *path; |
Neil Booth | e718266 | 2001-03-14 19:35:08 +0000 | [diff] [blame] | 645 | char *name, *n; |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 646 | splay_tree_node nd; |
Zack Weinberg | b0699da | 2000-03-07 20:58:47 +0000 | [diff] [blame] | 647 | |
Neil Booth | 05e8172 | 2001-01-11 21:30:16 +0000 | [diff] [blame] | 648 | if (IS_ABSOLUTE_PATHNAME (fname)) |
Zack Weinberg | f2d5f0c | 2000-04-14 23:29:45 +0000 | [diff] [blame] | 649 | { |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 650 | /* Just look it up. */ |
| 651 | nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) fname); |
| 652 | return (nd && nd->value); |
Zack Weinberg | f2d5f0c | 2000-04-14 23:29:45 +0000 | [diff] [blame] | 653 | } |
Kazu Hirata | df38348 | 2002-05-22 22:02:16 +0000 | [diff] [blame] | 654 | |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 655 | /* Search directory path for the file. */ |
Neil Booth | b6464a7 | 2001-03-11 14:54:56 +0000 | [diff] [blame] | 656 | name = (char *) alloca (strlen (fname) + pfile->max_include_len + 2); |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 657 | for (path = pfile->quote_include; path; path = path->next) |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 658 | { |
Neil Booth | 591e15a | 2001-03-02 07:35:12 +0000 | [diff] [blame] | 659 | memcpy (name, path->name, path->len); |
| 660 | name[path->len] = '/'; |
| 661 | strcpy (&name[path->len + 1], fname); |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 662 | if (CPP_OPTION (pfile, remap)) |
Neil Booth | e718266 | 2001-03-14 19:35:08 +0000 | [diff] [blame] | 663 | n = remap_filename (pfile, name, path); |
| 664 | else |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 665 | n = name; |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 666 | |
Neil Booth | e718266 | 2001-03-14 19:35:08 +0000 | [diff] [blame] | 667 | nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) n); |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 668 | if (nd && nd->value) |
| 669 | return 1; |
Zack Weinberg | f2d5f0c | 2000-04-14 23:29:45 +0000 | [diff] [blame] | 670 | } |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 671 | return 0; |
Zack Weinberg | e576beb | 2000-03-15 22:03:37 +0000 | [diff] [blame] | 672 | } |
| 673 | |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 674 | /* Search for HEADER. Return 0 if there is no such file (or it's |
| 675 | un-openable), in which case an error code will be in errno. If |
| 676 | there is no include path to use it returns NO_INCLUDE_PATH, |
| 677 | otherwise an include_file structure. If this request originates |
Neil Booth | 5d8ebbd | 2002-01-03 21:43:09 +0000 | [diff] [blame] | 678 | from a directive of TYPE #include_next, set INCLUDE_NEXT to true. */ |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 679 | static struct include_file * |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 680 | find_include_file (pfile, header, type) |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 681 | cpp_reader *pfile; |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 682 | const cpp_token *header; |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 683 | enum include_type type; |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 684 | { |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 685 | const char *fname = (const char *) header->val.str.text; |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 686 | struct cpp_path *path; |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 687 | struct include_file *file; |
Neil Booth | e718266 | 2001-03-14 19:35:08 +0000 | [diff] [blame] | 688 | char *name, *n; |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 689 | |
Neil Booth | 05e8172 | 2001-01-11 21:30:16 +0000 | [diff] [blame] | 690 | if (IS_ABSOLUTE_PATHNAME (fname)) |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 691 | return open_file_pch (pfile, fname); |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 692 | |
| 693 | /* For #include_next, skip in the search path past the dir in which |
Neil Booth | e718266 | 2001-03-14 19:35:08 +0000 | [diff] [blame] | 694 | the current file was found, but if it was found via an absolute |
| 695 | path use the normal search logic. */ |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 696 | if (type == IT_INCLUDE_NEXT && pfile->buffer->inc->foundhere) |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 697 | path = pfile->buffer->inc->foundhere->next; |
| 698 | else if (header->type == CPP_HEADER_NAME) |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 699 | path = pfile->bracket_include; |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 700 | else |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 701 | path = search_from (pfile, type); |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 702 | |
| 703 | if (path == NULL) |
| 704 | { |
Neil Booth | ebef4e8 | 2002-04-14 18:42:47 +0000 | [diff] [blame] | 705 | cpp_error (pfile, DL_ERROR, "no include path in which to find %s", |
| 706 | fname); |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 707 | return NO_INCLUDE_PATH; |
| 708 | } |
| 709 | |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 710 | /* Search directory path for the file. */ |
Neil Booth | b6464a7 | 2001-03-11 14:54:56 +0000 | [diff] [blame] | 711 | name = (char *) alloca (strlen (fname) + pfile->max_include_len + 2); |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 712 | for (; path; path = path->next) |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 713 | { |
Zack Weinberg | 55485cd | 2001-12-06 16:41:18 +0000 | [diff] [blame] | 714 | int len = path->len; |
| 715 | memcpy (name, path->name, len); |
| 716 | /* Don't turn / into // or // into ///; // may be a namespace |
| 717 | escape. */ |
| 718 | if (name[len-1] == '/') |
| 719 | len--; |
| 720 | name[len] = '/'; |
| 721 | strcpy (&name[len + 1], fname); |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 722 | if (CPP_OPTION (pfile, remap)) |
Neil Booth | e718266 | 2001-03-14 19:35:08 +0000 | [diff] [blame] | 723 | n = remap_filename (pfile, name, path); |
| 724 | else |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 725 | n = name; |
Zack Weinberg | d35364d | 2000-03-12 23:46:05 +0000 | [diff] [blame] | 726 | |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 727 | file = open_file_pch (pfile, n); |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 728 | if (file) |
Zack Weinberg | d35364d | 2000-03-12 23:46:05 +0000 | [diff] [blame] | 729 | { |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 730 | file->foundhere = path; |
| 731 | return file; |
Zack Weinberg | d35364d | 2000-03-12 23:46:05 +0000 | [diff] [blame] | 732 | } |
Zack Weinberg | d35364d | 2000-03-12 23:46:05 +0000 | [diff] [blame] | 733 | } |
Neil Booth | 591e15a | 2001-03-02 07:35:12 +0000 | [diff] [blame] | 734 | |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 735 | return 0; |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 736 | } |
| 737 | |
Zack Weinberg | e605b04 | 2000-06-21 23:08:17 +0000 | [diff] [blame] | 738 | /* Not everyone who wants to set system-header-ness on a buffer can |
Neil Booth | 642ce43 | 2000-12-07 23:17:56 +0000 | [diff] [blame] | 739 | see the details of a buffer. This is an exported interface because |
| 740 | fix-header needs it. */ |
Zack Weinberg | e605b04 | 2000-06-21 23:08:17 +0000 | [diff] [blame] | 741 | void |
Neil Booth | 614c7d3 | 2000-12-04 07:32:04 +0000 | [diff] [blame] | 742 | cpp_make_system_header (pfile, syshdr, externc) |
Zack Weinberg | e605b04 | 2000-06-21 23:08:17 +0000 | [diff] [blame] | 743 | cpp_reader *pfile; |
Neil Booth | 614c7d3 | 2000-12-04 07:32:04 +0000 | [diff] [blame] | 744 | int syshdr, externc; |
Zack Weinberg | e605b04 | 2000-06-21 23:08:17 +0000 | [diff] [blame] | 745 | { |
Neil Booth | 614c7d3 | 2000-12-04 07:32:04 +0000 | [diff] [blame] | 746 | int flags = 0; |
| 747 | |
| 748 | /* 1 = system header, 2 = system header to be treated as C. */ |
| 749 | if (syshdr) |
| 750 | flags = 1 + (externc != 0); |
Neil Booth | 47d89cf | 2001-08-11 07:33:39 +0000 | [diff] [blame] | 751 | _cpp_do_file_change (pfile, LC_RENAME, pfile->map->to_file, |
| 752 | SOURCE_LINE (pfile->map, pfile->line), flags); |
Zack Weinberg | e605b04 | 2000-06-21 23:08:17 +0000 | [diff] [blame] | 753 | } |
| 754 | |
Zack Weinberg | c71f835 | 2000-07-05 05:33:57 +0000 | [diff] [blame] | 755 | /* Report on all files that might benefit from a multiple include guard. |
| 756 | Triggered by -H. */ |
| 757 | void |
| 758 | _cpp_report_missing_guards (pfile) |
| 759 | cpp_reader *pfile; |
| 760 | { |
| 761 | int banner = 0; |
| 762 | splay_tree_foreach (pfile->all_include_files, report_missing_guard, |
| 763 | (PTR) &banner); |
| 764 | } |
| 765 | |
Neil Booth | 5d8ebbd | 2002-01-03 21:43:09 +0000 | [diff] [blame] | 766 | /* Callback function for splay_tree_foreach(). */ |
Zack Weinberg | c71f835 | 2000-07-05 05:33:57 +0000 | [diff] [blame] | 767 | static int |
| 768 | report_missing_guard (n, b) |
| 769 | splay_tree_node n; |
| 770 | void *b; |
| 771 | { |
| 772 | struct include_file *f = (struct include_file *) n->value; |
Kazu Hirata | dc65cd6 | 2002-11-19 06:55:04 +0000 | [diff] [blame] | 773 | int *bannerp = (int *) b; |
Zack Weinberg | c71f835 | 2000-07-05 05:33:57 +0000 | [diff] [blame] | 774 | |
| 775 | if (f && f->cmacro == 0 && f->include_count == 1) |
| 776 | { |
| 777 | if (*bannerp == 0) |
| 778 | { |
| 779 | fputs (_("Multiple include guards may be useful for:\n"), stderr); |
| 780 | *bannerp = 1; |
| 781 | } |
| 782 | fputs (f->name, stderr); |
| 783 | putc ('\n', stderr); |
| 784 | } |
| 785 | return 0; |
| 786 | } |
| 787 | |
Neil Booth | 5d8ebbd | 2002-01-03 21:43:09 +0000 | [diff] [blame] | 788 | /* Create a dependency for file FNAME, or issue an error message as |
Kazu Hirata | da7d830 | 2002-09-22 02:03:17 +0000 | [diff] [blame] | 789 | appropriate. ANGLE_BRACKETS is nonzero if the file was bracketed |
Neil Booth | 5d8ebbd | 2002-01-03 21:43:09 +0000 | [diff] [blame] | 790 | like <..>. */ |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 791 | static void |
| 792 | handle_missing_header (pfile, fname, angle_brackets) |
| 793 | cpp_reader *pfile; |
| 794 | const char *fname; |
| 795 | int angle_brackets; |
| 796 | { |
Neil Booth | f4ff5a6 | 2002-08-12 22:44:30 +0000 | [diff] [blame] | 797 | bool print_dep |
| 798 | = CPP_OPTION (pfile, deps.style) > (angle_brackets || pfile->map->sysp); |
Kazu Hirata | dc65cd6 | 2002-11-19 06:55:04 +0000 | [diff] [blame] | 799 | |
Neil Booth | f4ff5a6 | 2002-08-12 22:44:30 +0000 | [diff] [blame] | 800 | if (CPP_OPTION (pfile, deps.missing_files) && print_dep) |
Robert Spier | 3f8ffc7 | 2002-05-08 21:21:19 +0000 | [diff] [blame] | 801 | deps_add_dep (pfile->deps, fname); |
Neil Booth | e718266 | 2001-03-14 19:35:08 +0000 | [diff] [blame] | 802 | /* If -M was specified, then don't count this as an error, because |
| 803 | we can still produce correct output. Otherwise, we can't produce |
| 804 | correct output, because there may be dependencies we need inside |
| 805 | the missing file, and we don't know what directory this missing |
Neil Booth | ebef4e8 | 2002-04-14 18:42:47 +0000 | [diff] [blame] | 806 | file exists in. */ |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 807 | else |
Neil Booth | f4ff5a6 | 2002-08-12 22:44:30 +0000 | [diff] [blame] | 808 | cpp_errno (pfile, CPP_OPTION (pfile, deps.style) && ! print_dep |
Neil Booth | ebef4e8 | 2002-04-14 18:42:47 +0000 | [diff] [blame] | 809 | ? DL_WARNING: DL_ERROR, fname); |
Neil Booth | a36c54f | 2001-03-12 19:33:08 +0000 | [diff] [blame] | 810 | } |
| 811 | |
Neil Booth | 5d8ebbd | 2002-01-03 21:43:09 +0000 | [diff] [blame] | 812 | /* Handles #include-family directives (distinguished by TYPE), |
| 813 | including HEADER, and the command line -imacros and -include. |
| 814 | Returns true if a buffer was stacked. */ |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 815 | bool |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 816 | _cpp_execute_include (pfile, header, type) |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 817 | cpp_reader *pfile; |
Neil Booth | 93c80368 | 2000-10-28 17:59:06 +0000 | [diff] [blame] | 818 | const cpp_token *header; |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 819 | enum include_type type; |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 820 | { |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 821 | bool stacked = false; |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 822 | struct include_file *inc = find_include_file (pfile, header, type); |
Neil Booth | 642ce43 | 2000-12-07 23:17:56 +0000 | [diff] [blame] | 823 | |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 824 | if (inc == 0) |
| 825 | handle_missing_header (pfile, (const char *) header->val.str.text, |
| 826 | header->type == CPP_HEADER_NAME); |
| 827 | else if (inc != NO_INCLUDE_PATH) |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 828 | { |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 829 | stacked = stack_include_file (pfile, inc); |
Neil Booth | 51d0f32 | 2001-02-19 19:50:21 +0000 | [diff] [blame] | 830 | |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 831 | if (type == IT_IMPORT) |
Neil Booth | e718266 | 2001-03-14 19:35:08 +0000 | [diff] [blame] | 832 | _cpp_never_reread (inc); |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 833 | } |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 834 | |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 835 | return stacked; |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 836 | } |
| 837 | |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 838 | /* Locate HEADER, and determine whether it is newer than the current |
| 839 | file. If it cannot be located or dated, return -1, if it is newer |
| 840 | newer, return 1, otherwise 0. */ |
Nathan Sidwell | f3f751a | 2000-06-30 09:47:49 +0000 | [diff] [blame] | 841 | int |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 842 | _cpp_compare_file_date (pfile, header) |
Nathan Sidwell | f3f751a | 2000-06-30 09:47:49 +0000 | [diff] [blame] | 843 | cpp_reader *pfile; |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 844 | const cpp_token *header; |
Nathan Sidwell | f3f751a | 2000-06-30 09:47:49 +0000 | [diff] [blame] | 845 | { |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 846 | struct include_file *inc = find_include_file (pfile, header, 0); |
Kazu Hirata | df38348 | 2002-05-22 22:02:16 +0000 | [diff] [blame] | 847 | |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 848 | if (inc == NULL || inc == NO_INCLUDE_PATH) |
Nathan Sidwell | f3f751a | 2000-06-30 09:47:49 +0000 | [diff] [blame] | 849 | return -1; |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 850 | |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 851 | if (inc->fd > 0) |
Nathan Sidwell | f3f751a | 2000-06-30 09:47:49 +0000 | [diff] [blame] | 852 | { |
Nathan Sidwell | f3f751a | 2000-06-30 09:47:49 +0000 | [diff] [blame] | 853 | close (inc->fd); |
| 854 | inc->fd = -1; |
| 855 | } |
Kazu Hirata | df38348 | 2002-05-22 22:02:16 +0000 | [diff] [blame] | 856 | |
Neil Booth | 41947a5 | 2001-03-13 23:55:10 +0000 | [diff] [blame] | 857 | return inc->st.st_mtime > pfile->buffer->inc->st.st_mtime; |
Nathan Sidwell | f3f751a | 2000-06-30 09:47:49 +0000 | [diff] [blame] | 858 | } |
| 859 | |
| 860 | |
Neil Booth | e5eba70 | 2001-08-21 19:23:24 +0000 | [diff] [blame] | 861 | /* Push an input buffer and load it up with the contents of FNAME. If |
| 862 | FNAME is "", read standard input. Return true if a buffer was |
| 863 | stacked. */ |
| 864 | bool |
Neil Booth | 614c7d3 | 2000-12-04 07:32:04 +0000 | [diff] [blame] | 865 | _cpp_read_file (pfile, fname) |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 866 | cpp_reader *pfile; |
| 867 | const char *fname; |
| 868 | { |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 869 | /* This uses open_file, because we don't allow a PCH to be used as |
| 870 | the toplevel compilation (that would prevent re-compiling an |
| 871 | existing PCH without deleting it first). */ |
Neil Booth | 373e217 | 2001-02-21 07:29:56 +0000 | [diff] [blame] | 872 | struct include_file *f = open_file (pfile, fname); |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 873 | |
Zack Weinberg | 041c319 | 2000-07-04 01:58:21 +0000 | [diff] [blame] | 874 | if (f == NULL) |
Neil Booth | c0bfe99 | 2001-10-08 17:54:15 +0000 | [diff] [blame] | 875 | { |
Neil Booth | ebef4e8 | 2002-04-14 18:42:47 +0000 | [diff] [blame] | 876 | cpp_errno (pfile, DL_ERROR, fname); |
Neil Booth | c0bfe99 | 2001-10-08 17:54:15 +0000 | [diff] [blame] | 877 | return false; |
| 878 | } |
Zack Weinberg | 041c319 | 2000-07-04 01:58:21 +0000 | [diff] [blame] | 879 | |
Neil Booth | c0bfe99 | 2001-10-08 17:54:15 +0000 | [diff] [blame] | 880 | return stack_include_file (pfile, f); |
Zack Weinberg | c31a650 | 2000-06-21 18:33:51 +0000 | [diff] [blame] | 881 | } |
Zack Weinberg | f2d5f0c | 2000-04-14 23:29:45 +0000 | [diff] [blame] | 882 | |
Neil Booth | 5d8ebbd | 2002-01-03 21:43:09 +0000 | [diff] [blame] | 883 | /* Do appropriate cleanup when a file INC's buffer is popped off the |
Neil Booth | af0d16c | 2002-04-22 17:48:02 +0000 | [diff] [blame] | 884 | input stack. */ |
| 885 | void |
Neil Booth | 29401c3 | 2001-08-22 20:37:20 +0000 | [diff] [blame] | 886 | _cpp_pop_file_buffer (pfile, inc) |
Zack Weinberg | f9a0e96 | 2000-07-13 02:32:41 +0000 | [diff] [blame] | 887 | cpp_reader *pfile; |
Neil Booth | 29401c3 | 2001-08-22 20:37:20 +0000 | [diff] [blame] | 888 | struct include_file *inc; |
Zack Weinberg | f9a0e96 | 2000-07-13 02:32:41 +0000 | [diff] [blame] | 889 | { |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 890 | /* Record the inclusion-preventing macro, which could be NULL |
Neil Booth | 6d18adb | 2001-07-29 17:27:57 +0000 | [diff] [blame] | 891 | meaning no controlling macro. */ |
| 892 | if (pfile->mi_valid && inc->cmacro == NULL) |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 893 | inc->cmacro = pfile->mi_cmacro; |
Neil Booth | 93c80368 | 2000-10-28 17:59:06 +0000 | [diff] [blame] | 894 | |
| 895 | /* Invalidate control macros in the #including file. */ |
Neil Booth | 6d18adb | 2001-07-29 17:27:57 +0000 | [diff] [blame] | 896 | pfile->mi_valid = false; |
Neil Booth | 93c80368 | 2000-10-28 17:59:06 +0000 | [diff] [blame] | 897 | |
Zack Weinberg | a58d32c | 2000-09-12 03:42:30 +0000 | [diff] [blame] | 898 | inc->refcnt--; |
| 899 | if (inc->refcnt == 0 && DO_NOT_REREAD (inc)) |
| 900 | purge_cache (inc); |
Zack Weinberg | f9a0e96 | 2000-07-13 02:32:41 +0000 | [diff] [blame] | 901 | } |
| 902 | |
Neil Booth | 591e15a | 2001-03-02 07:35:12 +0000 | [diff] [blame] | 903 | /* Returns the first place in the include chain to start searching for |
| 904 | "" includes. This involves stripping away the basename of the |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 905 | current file, unless -I- was specified. |
| 906 | |
| 907 | If we're handling -include or -imacros, use the "" chain, but with |
| 908 | the preprocessor's cwd prepended. */ |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 909 | static struct cpp_path * |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 910 | search_from (pfile, type) |
Neil Booth | 591e15a | 2001-03-02 07:35:12 +0000 | [diff] [blame] | 911 | cpp_reader *pfile; |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 912 | enum include_type type; |
Neil Booth | 591e15a | 2001-03-02 07:35:12 +0000 | [diff] [blame] | 913 | { |
| 914 | cpp_buffer *buffer = pfile->buffer; |
| 915 | unsigned int dlen; |
| 916 | |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 917 | /* Command line uses the cwd, and does not cache the result. */ |
| 918 | if (type == IT_CMDLINE) |
| 919 | goto use_cwd; |
| 920 | |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 921 | /* Ignore the current file's directory? */ |
| 922 | if (pfile->quote_ignores_source_dir) |
| 923 | return pfile->quote_include; |
Neil Booth | 591e15a | 2001-03-02 07:35:12 +0000 | [diff] [blame] | 924 | |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 925 | if (! buffer->search_cached) |
Neil Booth | 591e15a | 2001-03-02 07:35:12 +0000 | [diff] [blame] | 926 | { |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 927 | buffer->search_cached = 1; |
Neil Booth | 591e15a | 2001-03-02 07:35:12 +0000 | [diff] [blame] | 928 | |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 929 | dlen = lbasename (buffer->inc->name) - buffer->inc->name; |
Neil Booth | 591e15a | 2001-03-02 07:35:12 +0000 | [diff] [blame] | 930 | |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 931 | if (dlen) |
| 932 | { |
| 933 | /* We don't guarantee NAME is null-terminated. This saves |
Neil Booth | 29401c3 | 2001-08-22 20:37:20 +0000 | [diff] [blame] | 934 | allocating and freeing memory. Drop a trailing '/'. */ |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 935 | buffer->dir.name = (char *) buffer->inc->name; |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 936 | if (dlen > 1) |
| 937 | dlen--; |
| 938 | } |
| 939 | else |
| 940 | { |
| 941 | use_cwd: |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 942 | buffer->dir.name = (char *) "."; |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 943 | dlen = 1; |
| 944 | } |
| 945 | |
| 946 | if (dlen > pfile->max_include_len) |
| 947 | pfile->max_include_len = dlen; |
| 948 | |
| 949 | buffer->dir.len = dlen; |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 950 | buffer->dir.next = pfile->quote_include; |
Neil Booth | 47d89cf | 2001-08-11 07:33:39 +0000 | [diff] [blame] | 951 | buffer->dir.sysp = pfile->map->sysp; |
Neil Booth | ba133c9 | 2001-03-15 07:57:13 +0000 | [diff] [blame] | 952 | } |
Neil Booth | 591e15a | 2001-03-02 07:35:12 +0000 | [diff] [blame] | 953 | |
| 954 | return &buffer->dir; |
| 955 | } |
| 956 | |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 957 | /* The file_name_map structure holds a mapping of file names for a |
| 958 | particular directory. This mapping is read from the file named |
| 959 | FILE_NAME_MAP_FILE in that directory. Such a file can be used to |
| 960 | map filenames on a file system with severe filename restrictions, |
| 961 | such as DOS. The format of the file name map file is just a series |
| 962 | of lines with two tokens on each line. The first token is the name |
| 963 | to map, and the second token is the actual name to use. */ |
Kazu Hirata | dc65cd6 | 2002-11-19 06:55:04 +0000 | [diff] [blame] | 964 | struct file_name_map { |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 965 | struct file_name_map *map_next; |
| 966 | char *map_from; |
| 967 | char *map_to; |
| 968 | }; |
| 969 | |
| 970 | #define FILE_NAME_MAP_FILE "header.gcc" |
| 971 | |
| 972 | /* Read a space delimited string of unlimited length from a stdio |
Neil Booth | 5d8ebbd | 2002-01-03 21:43:09 +0000 | [diff] [blame] | 973 | file F. */ |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 974 | static char * |
| 975 | read_filename_string (ch, f) |
| 976 | int ch; |
| 977 | FILE *f; |
| 978 | { |
| 979 | char *alloc, *set; |
| 980 | int len; |
| 981 | |
| 982 | len = 20; |
| 983 | set = alloc = xmalloc (len + 1); |
Kazu Hirata | dc65cd6 | 2002-11-19 06:55:04 +0000 | [diff] [blame] | 984 | if (! is_space (ch)) |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 985 | { |
| 986 | *set++ = ch; |
Kazu Hirata | dc65cd6 | 2002-11-19 06:55:04 +0000 | [diff] [blame] | 987 | while ((ch = getc (f)) != EOF && ! is_space (ch)) |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 988 | { |
| 989 | if (set - alloc == len) |
| 990 | { |
| 991 | len *= 2; |
| 992 | alloc = xrealloc (alloc, len + 1); |
| 993 | set = alloc + len / 2; |
| 994 | } |
| 995 | *set++ = ch; |
| 996 | } |
| 997 | } |
| 998 | *set = '\0'; |
| 999 | ungetc (ch, f); |
| 1000 | return alloc; |
| 1001 | } |
| 1002 | |
| 1003 | /* This structure holds a linked list of file name maps, one per directory. */ |
Kazu Hirata | dc65cd6 | 2002-11-19 06:55:04 +0000 | [diff] [blame] | 1004 | struct file_name_map_list { |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1005 | struct file_name_map_list *map_list_next; |
| 1006 | char *map_list_name; |
| 1007 | struct file_name_map *map_list_map; |
| 1008 | }; |
| 1009 | |
| 1010 | /* Read the file name map file for DIRNAME. */ |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1011 | static struct file_name_map * |
| 1012 | read_name_map (pfile, dirname) |
| 1013 | cpp_reader *pfile; |
Kaveh R. Ghazi | 460ee11 | 1999-01-05 19:11:22 +0000 | [diff] [blame] | 1014 | const char *dirname; |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1015 | { |
Stan Shebs | b369484 | 2001-10-11 03:16:15 +0000 | [diff] [blame] | 1016 | struct file_name_map_list *map_list_ptr; |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1017 | char *name; |
| 1018 | FILE *f; |
| 1019 | |
Neil Booth | 8767c89 | 2000-12-13 19:20:14 +0000 | [diff] [blame] | 1020 | /* Check the cache of directories, and mappings in their remap file. */ |
Zack Weinberg | ae79697 | 2000-03-31 23:16:11 +0000 | [diff] [blame] | 1021 | for (map_list_ptr = CPP_OPTION (pfile, map_list); map_list_ptr; |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1022 | map_list_ptr = map_list_ptr->map_list_next) |
| 1023 | if (! strcmp (map_list_ptr->map_list_name, dirname)) |
| 1024 | return map_list_ptr->map_list_map; |
| 1025 | |
| 1026 | map_list_ptr = ((struct file_name_map_list *) |
| 1027 | xmalloc (sizeof (struct file_name_map_list))); |
Zack Weinberg | c49445e | 1998-12-15 11:23:27 +0000 | [diff] [blame] | 1028 | map_list_ptr->map_list_name = xstrdup (dirname); |
Neil Booth | 8767c89 | 2000-12-13 19:20:14 +0000 | [diff] [blame] | 1029 | |
| 1030 | /* The end of the list ends in NULL. */ |
Laurynas Biveinis | 4b58824 | 2000-07-16 21:22:19 +0000 | [diff] [blame] | 1031 | map_list_ptr->map_list_map = NULL; |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1032 | |
| 1033 | name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2); |
| 1034 | strcpy (name, dirname); |
| 1035 | if (*dirname) |
| 1036 | strcat (name, "/"); |
| 1037 | strcat (name, FILE_NAME_MAP_FILE); |
| 1038 | f = fopen (name, "r"); |
Neil Booth | 8767c89 | 2000-12-13 19:20:14 +0000 | [diff] [blame] | 1039 | |
| 1040 | /* Silently return NULL if we cannot open. */ |
| 1041 | if (f) |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1042 | { |
| 1043 | int ch; |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1044 | |
| 1045 | while ((ch = getc (f)) != EOF) |
| 1046 | { |
| 1047 | char *from, *to; |
| 1048 | struct file_name_map *ptr; |
| 1049 | |
Kazu Hirata | dc65cd6 | 2002-11-19 06:55:04 +0000 | [diff] [blame] | 1050 | if (is_space (ch)) |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1051 | continue; |
| 1052 | from = read_filename_string (ch, f); |
Kazu Hirata | dc65cd6 | 2002-11-19 06:55:04 +0000 | [diff] [blame] | 1053 | while ((ch = getc (f)) != EOF && is_hspace (ch)) |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1054 | ; |
| 1055 | to = read_filename_string (ch, f); |
| 1056 | |
| 1057 | ptr = ((struct file_name_map *) |
| 1058 | xmalloc (sizeof (struct file_name_map))); |
| 1059 | ptr->map_from = from; |
| 1060 | |
| 1061 | /* Make the real filename absolute. */ |
Neil Booth | 05e8172 | 2001-01-11 21:30:16 +0000 | [diff] [blame] | 1062 | if (IS_ABSOLUTE_PATHNAME (to)) |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1063 | ptr->map_to = to; |
| 1064 | else |
| 1065 | { |
Kaveh R. Ghazi | 1dcd444 | 2002-07-30 02:24:17 +0000 | [diff] [blame] | 1066 | ptr->map_to = concat (dirname, "/", to, NULL); |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1067 | free (to); |
Kazu Hirata | df38348 | 2002-05-22 22:02:16 +0000 | [diff] [blame] | 1068 | } |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1069 | |
| 1070 | ptr->map_next = map_list_ptr->map_list_map; |
| 1071 | map_list_ptr->map_list_map = ptr; |
| 1072 | |
| 1073 | while ((ch = getc (f)) != '\n') |
| 1074 | if (ch == EOF) |
| 1075 | break; |
| 1076 | } |
| 1077 | fclose (f); |
| 1078 | } |
Kazu Hirata | df38348 | 2002-05-22 22:02:16 +0000 | [diff] [blame] | 1079 | |
Neil Booth | 8767c89 | 2000-12-13 19:20:14 +0000 | [diff] [blame] | 1080 | /* Add this information to the cache. */ |
Zack Weinberg | ae79697 | 2000-03-31 23:16:11 +0000 | [diff] [blame] | 1081 | map_list_ptr->map_list_next = CPP_OPTION (pfile, map_list); |
| 1082 | CPP_OPTION (pfile, map_list) = map_list_ptr; |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1083 | |
| 1084 | return map_list_ptr->map_list_map; |
Kazu Hirata | df38348 | 2002-05-22 22:02:16 +0000 | [diff] [blame] | 1085 | } |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1086 | |
Neil Booth | e718266 | 2001-03-14 19:35:08 +0000 | [diff] [blame] | 1087 | /* Remap an unsimplified path NAME based on the file_name_map (if any) |
| 1088 | for LOC. */ |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 1089 | static char * |
| 1090 | remap_filename (pfile, name, loc) |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1091 | cpp_reader *pfile; |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 1092 | char *name; |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 1093 | struct cpp_path *loc; |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1094 | { |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 1095 | struct file_name_map *map; |
Neil Booth | 8767c89 | 2000-12-13 19:20:14 +0000 | [diff] [blame] | 1096 | const char *from, *p; |
Neil Booth | e718266 | 2001-03-14 19:35:08 +0000 | [diff] [blame] | 1097 | char *dir; |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 1098 | |
| 1099 | if (! loc->name_map) |
Neil Booth | 8767c89 | 2000-12-13 19:20:14 +0000 | [diff] [blame] | 1100 | { |
Neil Booth | e718266 | 2001-03-14 19:35:08 +0000 | [diff] [blame] | 1101 | /* Get a null-terminated path. */ |
| 1102 | char *dname = alloca (loc->len + 1); |
| 1103 | memcpy (dname, loc->name, loc->len); |
| 1104 | dname[loc->len] = '\0'; |
| 1105 | |
Neil Booth | 591e15a | 2001-03-02 07:35:12 +0000 | [diff] [blame] | 1106 | loc->name_map = read_name_map (pfile, dname); |
Neil Booth | 8767c89 | 2000-12-13 19:20:14 +0000 | [diff] [blame] | 1107 | if (! loc->name_map) |
| 1108 | return name; |
| 1109 | } |
Kazu Hirata | df38348 | 2002-05-22 22:02:16 +0000 | [diff] [blame] | 1110 | |
Neil Booth | e718266 | 2001-03-14 19:35:08 +0000 | [diff] [blame] | 1111 | /* This works since NAME has not been simplified yet. */ |
Neil Booth | 591e15a | 2001-03-02 07:35:12 +0000 | [diff] [blame] | 1112 | from = name + loc->len + 1; |
Kazu Hirata | df38348 | 2002-05-22 22:02:16 +0000 | [diff] [blame] | 1113 | |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 1114 | for (map = loc->name_map; map; map = map->map_next) |
| 1115 | if (!strcmp (map->map_from, from)) |
| 1116 | return map->map_to; |
| 1117 | |
| 1118 | /* Try to find a mapping file for the particular directory we are |
| 1119 | looking in. Thus #include <sys/types.h> will look up sys/types.h |
| 1120 | in /usr/include/header.gcc and look up types.h in |
| 1121 | /usr/include/sys/header.gcc. */ |
Neil Booth | 7ceb359 | 2000-03-11 00:49:44 +0000 | [diff] [blame] | 1122 | p = strrchr (name, '/'); |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 1123 | if (!p) |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 1124 | return name; |
| 1125 | |
Neil Booth | 8767c89 | 2000-12-13 19:20:14 +0000 | [diff] [blame] | 1126 | /* We know p != name as absolute paths don't call remap_filename. */ |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 1127 | if (p == name) |
Neil Booth | ebef4e8 | 2002-04-14 18:42:47 +0000 | [diff] [blame] | 1128 | cpp_error (pfile, DL_ICE, "absolute file name in remap_filename"); |
Neil Booth | 8767c89 | 2000-12-13 19:20:14 +0000 | [diff] [blame] | 1129 | |
| 1130 | dir = (char *) alloca (p - name + 1); |
| 1131 | memcpy (dir, name, p - name); |
| 1132 | dir[p - name] = '\0'; |
| 1133 | from = p + 1; |
Kazu Hirata | df38348 | 2002-05-22 22:02:16 +0000 | [diff] [blame] | 1134 | |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 1135 | for (map = read_name_map (pfile, dir); map; map = map->map_next) |
Neil Booth | 8767c89 | 2000-12-13 19:20:14 +0000 | [diff] [blame] | 1136 | if (! strcmp (map->map_from, from)) |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 1137 | return map->map_to; |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1138 | |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 1139 | return name; |
Zack Weinberg | add7091 | 1998-10-29 11:54:13 +0000 | [diff] [blame] | 1140 | } |
| 1141 | |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 1142 | /* Set the include chain for "" to QUOTE, for <> to BRACKET. If |
| 1143 | QUOTE_IGNORES_SOURCE_DIR, then "" includes do not look in the |
| 1144 | directory of the including file. |
| 1145 | |
| 1146 | If BRACKET does not lie in the QUOTE chain, it is set to QUOTE. */ |
| 1147 | void |
| 1148 | cpp_set_include_chains (pfile, quote, bracket, quote_ignores_source_dir) |
| 1149 | cpp_reader *pfile; |
| 1150 | cpp_path *quote, *bracket; |
| 1151 | int quote_ignores_source_dir; |
Neil Booth | f9200da | 2001-04-06 07:22:01 +0000 | [diff] [blame] | 1152 | { |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 1153 | pfile->quote_include = quote; |
| 1154 | pfile->bracket_include = quote; |
| 1155 | pfile->quote_ignores_source_dir = quote_ignores_source_dir; |
| 1156 | pfile->max_include_len = 0; |
Neil Booth | f9200da | 2001-04-06 07:22:01 +0000 | [diff] [blame] | 1157 | |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 1158 | for (; quote; quote = quote->next) |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 1159 | { |
Neil Booth | 5793b27 | 2003-03-01 14:31:21 +0000 | [diff] [blame] | 1160 | quote->name_map = NULL; |
| 1161 | quote->len = strlen (quote->name); |
| 1162 | if (quote->len > pfile->max_include_len) |
| 1163 | pfile->max_include_len = quote->len; |
| 1164 | if (quote == bracket) |
| 1165 | pfile->bracket_include = bracket; |
Neil Booth | f9200da | 2001-04-06 07:22:01 +0000 | [diff] [blame] | 1166 | } |
Zack Weinberg | 0b3d776 | 1998-11-25 11:56:54 +0000 | [diff] [blame] | 1167 | } |
Neil Booth | 986b1f1 | 2003-03-02 17:44:18 +0000 | [diff] [blame^] | 1168 | |
| 1169 | /* Returns true if it is safe to remove the final component of path, |
| 1170 | when it is followed by a ".." component. We use lstat to avoid |
| 1171 | symlinks if we have it. If not, we can still catch errors with |
| 1172 | stat (). */ |
| 1173 | static int |
| 1174 | remove_component_p (path) |
| 1175 | const char *path; |
| 1176 | { |
| 1177 | struct stat s; |
| 1178 | int result; |
| 1179 | |
| 1180 | #ifdef HAVE_LSTAT |
| 1181 | result = lstat (path, &s); |
| 1182 | #else |
| 1183 | result = stat (path, &s); |
| 1184 | #endif |
| 1185 | |
| 1186 | /* There's no guarantee that errno will be unchanged, even on |
| 1187 | success. Cygwin's lstat(), for example, will often set errno to |
| 1188 | ENOSYS. In case of success, reset errno to zero. */ |
| 1189 | if (result == 0) |
| 1190 | errno = 0; |
| 1191 | |
| 1192 | return result == 0 && S_ISDIR (s.st_mode); |
| 1193 | } |
| 1194 | |
| 1195 | /* Simplify a path name in place, deleting redundant components. This |
| 1196 | reduces OS overhead and guarantees that equivalent paths compare |
| 1197 | the same (modulo symlinks). |
| 1198 | |
| 1199 | Transforms made: |
| 1200 | foo/bar/../quux foo/quux |
| 1201 | foo/./bar foo/bar |
| 1202 | foo//bar foo/bar |
| 1203 | /../quux /quux |
| 1204 | //quux //quux (POSIX allows leading // as a namespace escape) |
| 1205 | |
| 1206 | Guarantees no trailing slashes. All transforms reduce the length |
| 1207 | of the string. Returns PATH. errno is 0 if no error occurred; |
| 1208 | nonzero if an error occurred when using stat () or lstat (). */ |
| 1209 | void |
| 1210 | cpp_simplify_path (path) |
| 1211 | char *path ATTRIBUTE_UNUSED; |
| 1212 | { |
| 1213 | #ifndef VMS |
| 1214 | char *from, *to; |
| 1215 | char *base, *orig_base; |
| 1216 | int absolute = 0; |
| 1217 | |
| 1218 | errno = 0; |
| 1219 | /* Don't overflow the empty path by putting a '.' in it below. */ |
| 1220 | if (*path == '\0') |
| 1221 | return; |
| 1222 | |
| 1223 | #if defined (HAVE_DOS_BASED_FILE_SYSTEM) |
| 1224 | /* Convert all backslashes to slashes. */ |
| 1225 | for (from = path; *from; from++) |
| 1226 | if (*from == '\\') *from = '/'; |
| 1227 | |
| 1228 | /* Skip over leading drive letter if present. */ |
| 1229 | if (ISALPHA (path[0]) && path[1] == ':') |
| 1230 | from = to = &path[2]; |
| 1231 | else |
| 1232 | from = to = path; |
| 1233 | #else |
| 1234 | from = to = path; |
| 1235 | #endif |
| 1236 | |
| 1237 | /* Remove redundant leading /s. */ |
| 1238 | if (*from == '/') |
| 1239 | { |
| 1240 | absolute = 1; |
| 1241 | to++; |
| 1242 | from++; |
| 1243 | if (*from == '/') |
| 1244 | { |
| 1245 | if (*++from == '/') |
| 1246 | /* 3 or more initial /s are equivalent to 1 /. */ |
| 1247 | while (*++from == '/'); |
| 1248 | else |
| 1249 | /* On some hosts // differs from /; Posix allows this. */ |
| 1250 | to++; |
| 1251 | } |
| 1252 | } |
| 1253 | |
| 1254 | base = orig_base = to; |
| 1255 | for (;;) |
| 1256 | { |
| 1257 | int move_base = 0; |
| 1258 | |
| 1259 | while (*from == '/') |
| 1260 | from++; |
| 1261 | |
| 1262 | if (*from == '\0') |
| 1263 | break; |
| 1264 | |
| 1265 | if (*from == '.') |
| 1266 | { |
| 1267 | if (from[1] == '\0') |
| 1268 | break; |
| 1269 | if (from[1] == '/') |
| 1270 | { |
| 1271 | from += 2; |
| 1272 | continue; |
| 1273 | } |
| 1274 | else if (from[1] == '.' && (from[2] == '/' || from[2] == '\0')) |
| 1275 | { |
| 1276 | /* Don't simplify if there was no previous component. */ |
| 1277 | if (absolute && orig_base == to) |
| 1278 | { |
| 1279 | from += 2; |
| 1280 | continue; |
| 1281 | } |
| 1282 | /* Don't simplify if the previous component was "../", |
| 1283 | or if an error has already occurred with (l)stat. */ |
| 1284 | if (base != to && errno == 0) |
| 1285 | { |
| 1286 | /* We don't back up if it's a symlink. */ |
| 1287 | *to = '\0'; |
| 1288 | if (remove_component_p (path)) |
| 1289 | { |
| 1290 | while (to > base && *to != '/') |
| 1291 | to--; |
| 1292 | from += 2; |
| 1293 | continue; |
| 1294 | } |
| 1295 | } |
| 1296 | move_base = 1; |
| 1297 | } |
| 1298 | } |
| 1299 | |
| 1300 | /* Add the component separator. */ |
| 1301 | if (to > orig_base) |
| 1302 | *to++ = '/'; |
| 1303 | |
| 1304 | /* Copy this component until the trailing null or '/'. */ |
| 1305 | while (*from != '\0' && *from != '/') |
| 1306 | *to++ = *from++; |
| 1307 | |
| 1308 | if (move_base) |
| 1309 | base = to; |
| 1310 | } |
| 1311 | |
| 1312 | /* Change the empty string to "." so that it is not treated as stdin. |
| 1313 | Null terminate. */ |
| 1314 | if (to == path) |
| 1315 | *to++ = '.'; |
| 1316 | *to = '\0'; |
| 1317 | #else /* VMS */ |
| 1318 | errno = 0; |
| 1319 | #endif /* !VMS */ |
| 1320 | } |