]>
Commit | Line | Data |
---|---|---|
add7091b | 1 | /* Part of CPP library. (include file handling) |
5e7b4e25 JL |
2 | Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998, |
3 | 1999, 2000 Free Software Foundation, Inc. | |
add7091b ZW |
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 | |
e38992e8 | 21 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
add7091b ZW |
22 | |
23 | #include "config.h" | |
24 | #include "system.h" | |
add7091b | 25 | #include "cpplib.h" |
88ae23e7 | 26 | #include "cpphash.h" |
c1212d2f | 27 | #include "intl.h" |
168d3732 | 28 | #include "mkdeps.h" |
c31a6508 | 29 | #include "splay-tree.h" |
add7091b | 30 | |
f8f769ea ZW |
31 | #ifdef HAVE_MMAP_FILE |
32 | # include <sys/mman.h> | |
33 | # ifndef MMAP_THRESHOLD | |
34 | # define MMAP_THRESHOLD 3 /* Minimum page count to mmap the file. */ | |
35 | # endif | |
36 | ||
37 | #else /* No MMAP_FILE */ | |
38 | # undef MMAP_THRESHOLD | |
39 | # define MMAP_THRESHOLD 0 | |
40 | #endif | |
41 | ||
d7a2e0f7 ZW |
42 | #ifndef O_BINARY |
43 | # define O_BINARY 0 | |
44 | #endif | |
45 | ||
a58d32c2 ZW |
46 | #ifndef INCLUDE_LEN_FUDGE |
47 | # define INCLUDE_LEN_FUDGE 0 | |
48 | #endif | |
49 | ||
50 | /* If errno is inspected immediately after a system call fails, it will be | |
51 | nonzero, and no error number will ever be zero. */ | |
52 | #ifndef ENOENT | |
53 | # define ENOENT 0 | |
54 | #endif | |
55 | #ifndef ENOTDIR | |
56 | # define ENOTDIR 0 | |
57 | #endif | |
58 | #ifndef ENOMEM | |
59 | # define ENOMEM 0 | |
60 | #endif | |
61 | ||
f9a0e96c ZW |
62 | /* Suppress warning about function macros used w/o arguments in traditional |
63 | C. It is unlikely that glibc's strcmp macro helps this file at all. */ | |
64 | #undef strcmp | |
65 | ||
642ce434 NB |
66 | /* This structure is used for the table of all includes. */ |
67 | struct include_file | |
68 | { | |
69 | const char *name; /* actual path name of file */ | |
70 | const cpp_hashnode *cmacro; /* macro, if any, preventing reinclusion. */ | |
71 | const struct file_name_list *foundhere; | |
72 | /* location in search path where file was | |
73 | found, for #include_next and sysp. */ | |
74 | const unsigned char *buffer; /* pointer to cached file contents */ | |
75 | struct stat st; /* copy of stat(2) data for file */ | |
76 | int fd; /* fd open on file (short term storage only) */ | |
77 | unsigned short include_count; /* number of times file has been read */ | |
78 | unsigned short refcnt; /* number of stacked buffers using this file */ | |
79 | unsigned char mapped; /* file buffer is mmapped */ | |
80 | unsigned char defined; /* cmacro prevents inclusion in this state */ | |
81 | }; | |
82 | ||
28e0f040 NB |
83 | /* The cmacro works like this: If it's NULL, the file is to be |
84 | included again. If it's NEVER_REREAD, the file is never to be | |
85 | included again. Otherwise it is a macro hashnode, and the file is | |
86 | to be included again if the macro is defined or not as specified by | |
87 | DEFINED. */ | |
88 | #define NEVER_REREAD ((const cpp_hashnode *)-1) | |
89 | #define DO_NOT_REREAD(inc) \ | |
90 | ((inc)->cmacro && ((inc)->cmacro == NEVER_REREAD \ | |
91 | || ((inc)->cmacro->type == NT_MACRO) == (inc)->defined)) | |
92 | ||
a73ac7a5 | 93 | static struct file_name_map *read_name_map |
38b24ee2 ZW |
94 | PARAMS ((cpp_reader *, const char *)); |
95 | static char *read_filename_string PARAMS ((int, FILE *)); | |
96 | static char *remap_filename PARAMS ((cpp_reader *, char *, | |
97 | struct file_name_list *)); | |
a73ac7a5 | 98 | static struct file_name_list *actual_directory |
38b24ee2 | 99 | PARAMS ((cpp_reader *, const char *)); |
c31a6508 ZW |
100 | static struct include_file *find_include_file |
101 | PARAMS ((cpp_reader *, const char *, | |
102 | struct file_name_list *)); | |
2047e26f | 103 | static struct include_file *open_file PARAMS ((cpp_reader *, const char *)); |
3cf3593f NB |
104 | static void read_include_file PARAMS ((cpp_reader *, struct include_file *)); |
105 | static void stack_include_file PARAMS ((cpp_reader *, struct include_file *)); | |
a58d32c2 | 106 | static void purge_cache PARAMS ((struct include_file *)); |
c31a6508 | 107 | static void destroy_include_file_node PARAMS ((splay_tree_value)); |
c71f835b | 108 | static int report_missing_guard PARAMS ((splay_tree_node, void *)); |
c31a6508 | 109 | |
c31a6508 ZW |
110 | /* We use a splay tree to store information about all the include |
111 | files seen in this compilation. The key of each tree node is the | |
112 | physical path to the file. The value is 0 if the file does not | |
113 | exist, or a struct include_file pointer. */ | |
add7091b | 114 | |
c31a6508 ZW |
115 | static void |
116 | destroy_include_file_node (v) | |
117 | splay_tree_value v; | |
d35364d1 | 118 | { |
c31a6508 ZW |
119 | struct include_file *f = (struct include_file *)v; |
120 | if (f) | |
121 | { | |
a58d32c2 | 122 | purge_cache (f); |
2047e26f | 123 | free (f); /* The tree is registered with free to free f->name. */ |
c31a6508 | 124 | } |
d35364d1 | 125 | } |
add7091b | 126 | |
d35364d1 | 127 | void |
c71f835b | 128 | _cpp_init_includes (pfile) |
d35364d1 ZW |
129 | cpp_reader *pfile; |
130 | { | |
131 | pfile->all_include_files | |
c31a6508 ZW |
132 | = splay_tree_new ((splay_tree_compare_fn) strcmp, |
133 | (splay_tree_delete_key_fn) free, | |
134 | destroy_include_file_node); | |
0b3d776a | 135 | } |
add7091b | 136 | |
c71f835b ZW |
137 | void |
138 | _cpp_cleanup_includes (pfile) | |
139 | cpp_reader *pfile; | |
140 | { | |
141 | splay_tree_delete (pfile->all_include_files); | |
142 | } | |
143 | ||
642ce434 NB |
144 | /* Mark a file to not be reread (e.g. #import, read failure). */ |
145 | void | |
146 | _cpp_never_reread (file) | |
147 | struct include_file *file; | |
148 | { | |
149 | file->cmacro = NEVER_REREAD; | |
150 | } | |
151 | ||
a58d32c2 | 152 | /* Given a file name, look it up in the cache; if there is no entry, |
2047e26f NB |
153 | create one with a non-NULL value (regardless of success in opening |
154 | the file). If the file doesn't exist or is inaccessible, this | |
155 | entry is flagged so we don't attempt to open it again in the | |
156 | future. If the file isn't open, open it. | |
157 | ||
158 | Returns an include_file structure with an open file descriptor on | |
159 | success, or NULL on failure. */ | |
add7091b | 160 | |
c31a6508 | 161 | static struct include_file * |
2047e26f | 162 | open_file (pfile, filename) |
c31a6508 ZW |
163 | cpp_reader *pfile; |
164 | const char *filename; | |
2047e26f | 165 | { |
c31a6508 | 166 | splay_tree_node nd; |
2047e26f | 167 | struct include_file *file; |
add7091b | 168 | |
a58d32c2 | 169 | nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) filename); |
add7091b | 170 | |
c31a6508 | 171 | if (nd) |
2047e26f NB |
172 | { |
173 | file = (struct include_file *) nd->value; | |
174 | ||
175 | /* Don't retry opening if we failed previously. */ | |
176 | if (file->fd == -2) | |
177 | return 0; | |
178 | ||
def3263a NS |
179 | /* Don't reopen an idempotent file. */ |
180 | if (DO_NOT_REREAD (file)) | |
181 | return file; | |
182 | ||
183 | /* Don't reopen one which is already loaded. */ | |
184 | if (file->buffer != NULL) | |
185 | return file; | |
2047e26f NB |
186 | } |
187 | else | |
188 | { | |
642ce434 | 189 | /* In particular, this clears foundhere. */ |
2047e26f NB |
190 | file = xcnew (struct include_file); |
191 | file->name = xstrdup (filename); | |
192 | splay_tree_insert (pfile->all_include_files, | |
193 | (splay_tree_key) file->name, | |
194 | (splay_tree_value) file); | |
195 | } | |
add7091b | 196 | |
c31a6508 ZW |
197 | /* We used to open files in nonblocking mode, but that caused more |
198 | problems than it solved. Do take care not to acquire a | |
199 | controlling terminal by mistake (this can't happen on sane | |
200 | systems, but paranoia is a virtue). | |
add7091b | 201 | |
c31a6508 ZW |
202 | Use the three-argument form of open even though we aren't |
203 | specifying O_CREAT, to defend against broken system headers. | |
add7091b | 204 | |
c31a6508 ZW |
205 | O_BINARY tells some runtime libraries (notably DJGPP) not to do |
206 | newline translation; we can handle DOS line breaks just fine | |
207 | ourselves. | |
b0699dad | 208 | |
c31a6508 | 209 | Special case: the empty string is translated to stdin. */ |
d4506961 | 210 | |
c31a6508 | 211 | if (filename[0] == '\0') |
2047e26f | 212 | file->fd = 0; |
f2d5f0cc | 213 | else |
2047e26f | 214 | file->fd = open (filename, O_RDONLY | O_NOCTTY | O_BINARY, 0666); |
a58d32c2 | 215 | |
2047e26f NB |
216 | if (file->fd != -1 && fstat (file->fd, &file->st) == 0) |
217 | { | |
218 | /* Mark a regular, zero-length file never-reread now. */ | |
219 | if (S_ISREG (file->st.st_mode) && file->st.st_size == 0) | |
def3263a | 220 | { |
642ce434 | 221 | _cpp_never_reread (file); |
def3263a NS |
222 | close (file->fd); |
223 | file->fd = -1; | |
224 | } | |
a58d32c2 | 225 | |
2047e26f NB |
226 | return file; |
227 | } | |
a58d32c2 ZW |
228 | |
229 | /* Don't issue an error message if the file doesn't exist. */ | |
230 | if (errno != ENOENT && errno != ENOTDIR) | |
231 | cpp_error_from_errno (pfile, filename); | |
232 | ||
2047e26f NB |
233 | /* Create a negative node for this path, and return null. */ |
234 | file->fd = -2; | |
235 | ||
a58d32c2 ZW |
236 | return 0; |
237 | } | |
238 | ||
3cf3593f NB |
239 | /* Place the file referenced by INC into a new buffer on PFILE's |
240 | stack. If there are errors, or the file should not be re-included, | |
241 | a null buffer is pushed. */ | |
a58d32c2 | 242 | |
3cf3593f | 243 | static void |
a58d32c2 ZW |
244 | stack_include_file (pfile, inc) |
245 | cpp_reader *pfile; | |
246 | struct include_file *inc; | |
247 | { | |
eb1f4d9d | 248 | size_t len = 0; |
a58d32c2 ZW |
249 | cpp_buffer *fp; |
250 | ||
3cf3593f NB |
251 | /* Not in cache? */ |
252 | if (! inc->buffer) | |
253 | read_include_file (pfile, inc); | |
a58d32c2 | 254 | |
3cf3593f | 255 | if (! DO_NOT_REREAD (inc)) |
eb1f4d9d NB |
256 | len = inc->st.st_size; |
257 | ||
258 | /* Push a buffer. */ | |
259 | fp = cpp_push_buffer (pfile, inc->buffer, len, BUF_FILE, inc->name); | |
260 | fp->inc = inc; | |
3cf3593f | 261 | fp->inc->refcnt++; |
642ce434 NB |
262 | if (inc->foundhere) |
263 | fp->sysp = inc->foundhere->sysp; | |
a58d32c2 ZW |
264 | |
265 | /* The ->actual_dir field is only used when ignore_srcdir is not in effect; | |
266 | see do_include */ | |
267 | if (!CPP_OPTION (pfile, ignore_srcdir)) | |
268 | fp->actual_dir = actual_directory (pfile, inc->name); | |
269 | ||
3cf3593f NB |
270 | /* Initialise controlling macro state. */ |
271 | pfile->mi_state = MI_OUTSIDE; | |
272 | pfile->mi_cmacro = 0; | |
a58d32c2 | 273 | pfile->include_depth++; |
eb1f4d9d NB |
274 | |
275 | /* Generate the call back. */ | |
276 | fp->lineno = 0; | |
277 | _cpp_do_file_change (pfile, FC_ENTER, 0, 0); | |
278 | fp->lineno = 1; | |
a58d32c2 ZW |
279 | } |
280 | ||
281 | /* Read the file referenced by INC into the file cache. | |
282 | ||
283 | If fd points to a plain file, we might be able to mmap it; we can | |
284 | definitely allocate the buffer all at once. If fd is a pipe or | |
285 | terminal, we can't do either. If fd is something weird, like a | |
286 | block device or a directory, we don't want to read it at all. | |
287 | ||
288 | Unfortunately, different systems use different st.st_mode values | |
289 | for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and | |
290 | zero the entire struct stat except a couple fields. Hence we don't | |
291 | even try to figure out what something is, except for plain files, | |
292 | directories, and block devices. | |
293 | ||
294 | FIXME: Flush file cache and try again if we run out of memory. */ | |
295 | ||
3cf3593f | 296 | static void |
a58d32c2 ZW |
297 | read_include_file (pfile, inc) |
298 | cpp_reader *pfile; | |
299 | struct include_file *inc; | |
300 | { | |
301 | ssize_t size, offset, count; | |
302 | U_CHAR *buf; | |
303 | #if MMAP_THRESHOLD | |
304 | static int pagesize = -1; | |
305 | #endif | |
306 | ||
3cf3593f NB |
307 | if (DO_NOT_REREAD (inc)) |
308 | return; | |
309 | ||
a58d32c2 | 310 | if (S_ISREG (inc->st.st_mode)) |
f2d5f0cc | 311 | { |
a58d32c2 ZW |
312 | /* off_t might have a wider range than ssize_t - in other words, |
313 | the max size of a file might be bigger than the address | |
314 | space. We can't handle a file that large. (Anyone with | |
315 | a single source file bigger than 2GB needs to rethink | |
316 | their coding style.) Some systems (e.g. AIX 4.1) define | |
317 | SSIZE_MAX to be much smaller than the actual range of the | |
318 | type. Use INTTYPE_MAXIMUM unconditionally to ensure this | |
319 | does not bite us. */ | |
320 | if (inc->st.st_size > INTTYPE_MAXIMUM (ssize_t)) | |
f2d5f0cc | 321 | { |
a58d32c2 ZW |
322 | cpp_error (pfile, "%s is too large", inc->name); |
323 | goto fail; | |
f2d5f0cc | 324 | } |
a58d32c2 ZW |
325 | size = inc->st.st_size; |
326 | ||
ae0f4dee | 327 | inc->mapped = 0; |
a58d32c2 ZW |
328 | #if MMAP_THRESHOLD |
329 | if (pagesize == -1) | |
330 | pagesize = getpagesize (); | |
331 | ||
332 | if (size / pagesize >= MMAP_THRESHOLD) | |
333 | { | |
334 | buf = (U_CHAR *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0); | |
335 | if (buf == (U_CHAR *)-1) | |
336 | goto perror_fail; | |
337 | inc->mapped = 1; | |
338 | } | |
339 | else | |
c31a6508 | 340 | #endif |
d4506961 | 341 | { |
a58d32c2 ZW |
342 | buf = (U_CHAR *) xmalloc (size); |
343 | offset = 0; | |
344 | while (offset < size) | |
345 | { | |
346 | count = read (inc->fd, buf + offset, size - offset); | |
347 | if (count < 0) | |
348 | goto perror_fail; | |
349 | if (count == 0) | |
350 | { | |
351 | cpp_warning (pfile, "%s is shorter than expected", inc->name); | |
352 | break; | |
353 | } | |
354 | offset += count; | |
355 | } | |
d4506961 | 356 | } |
a58d32c2 ZW |
357 | } |
358 | else if (S_ISBLK (inc->st.st_mode)) | |
359 | { | |
360 | cpp_error (pfile, "%s is a block device", inc->name); | |
361 | goto fail; | |
362 | } | |
363 | else if (S_ISDIR (inc->st.st_mode)) | |
364 | { | |
365 | cpp_error (pfile, "%s is a directory", inc->name); | |
366 | goto fail; | |
367 | } | |
368 | else | |
369 | { | |
370 | /* 8 kilobytes is a sensible starting size. It ought to be | |
371 | bigger than the kernel pipe buffer, and it's definitely | |
372 | bigger than the majority of C source files. */ | |
373 | size = 8 * 1024; | |
d4506961 | 374 | |
a58d32c2 ZW |
375 | buf = (U_CHAR *) xmalloc (size); |
376 | offset = 0; | |
377 | while ((count = read (inc->fd, buf + offset, size - offset)) > 0) | |
f2d5f0cc | 378 | { |
a58d32c2 ZW |
379 | offset += count; |
380 | if (offset == size) | |
381 | buf = xrealloc (buf, (size *= 2)); | |
f2d5f0cc | 382 | } |
a58d32c2 ZW |
383 | if (count < 0) |
384 | goto perror_fail; | |
385 | ||
a58d32c2 ZW |
386 | if (offset < size) |
387 | buf = xrealloc (buf, offset); | |
388 | inc->st.st_size = offset; | |
f2d5f0cc | 389 | } |
d7a2e0f7 | 390 | |
a58d32c2 ZW |
391 | close (inc->fd); |
392 | inc->buffer = buf; | |
393 | inc->fd = -1; | |
3cf3593f | 394 | return; |
a58d32c2 ZW |
395 | |
396 | perror_fail: | |
397 | cpp_error_from_errno (pfile, inc->name); | |
398 | fail: | |
399 | /* Do not try to read this file again. */ | |
400 | close (inc->fd); | |
401 | inc->fd = -1; | |
642ce434 | 402 | _cpp_never_reread (inc); |
3cf3593f | 403 | return; |
a58d32c2 ZW |
404 | } |
405 | ||
406 | static void | |
407 | purge_cache (inc) | |
408 | struct include_file *inc; | |
409 | { | |
410 | if (inc->buffer) | |
c31a6508 | 411 | { |
ae0f4dee | 412 | #if MMAP_THRESHOLD |
a58d32c2 | 413 | if (inc->mapped) |
6f84c9bd | 414 | munmap ((PTR) inc->buffer, inc->st.st_size); |
a58d32c2 | 415 | else |
ae0f4dee | 416 | #endif |
a58d32c2 ZW |
417 | free ((PTR) inc->buffer); |
418 | inc->buffer = NULL; | |
c31a6508 | 419 | } |
e576beb0 ZW |
420 | } |
421 | ||
c31a6508 ZW |
422 | /* Return 1 if the file named by FNAME has been included before in |
423 | any context, 0 otherwise. */ | |
424 | int | |
425 | cpp_included (pfile, fname) | |
add7091b | 426 | cpp_reader *pfile; |
bcc5cac9 | 427 | const char *fname; |
add7091b | 428 | { |
d35364d1 | 429 | struct file_name_list *path; |
0b3d776a | 430 | char *name; |
c31a6508 | 431 | splay_tree_node nd; |
0b3d776a | 432 | |
c31a6508 | 433 | if (fname[0] == '/') |
0b3d776a | 434 | { |
c31a6508 ZW |
435 | /* Just look it up. */ |
436 | nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) fname); | |
437 | return (nd && nd->value); | |
0b3d776a | 438 | } |
c31a6508 ZW |
439 | |
440 | /* Search directory path for the file. */ | |
441 | name = (char *) alloca (strlen (fname) + pfile->max_include_len | |
442 | + 2 + INCLUDE_LEN_FUDGE); | |
443 | for (path = CPP_OPTION (pfile, quote_include); path; path = path->next) | |
0b3d776a | 444 | { |
c31a6508 ZW |
445 | memcpy (name, path->name, path->nlen); |
446 | name[path->nlen] = '/'; | |
447 | strcpy (&name[path->nlen+1], fname); | |
448 | _cpp_simplify_pathname (name); | |
449 | if (CPP_OPTION (pfile, remap)) | |
450 | name = remap_filename (pfile, name, path); | |
451 | ||
452 | nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name); | |
453 | if (nd && nd->value) | |
454 | return 1; | |
0b3d776a | 455 | } |
c31a6508 | 456 | return 0; |
add7091b ZW |
457 | } |
458 | ||
c31a6508 ZW |
459 | /* Search for include file FNAME in the include chain starting at |
460 | SEARCH_START. Return 0 if there is no such file (or it's un-openable), | |
a58d32c2 | 461 | otherwise an include_file structure. */ |
c31a6508 ZW |
462 | |
463 | static struct include_file * | |
464 | find_include_file (pfile, fname, search_start) | |
f2d5f0cc ZW |
465 | cpp_reader *pfile; |
466 | const char *fname; | |
c31a6508 | 467 | struct file_name_list *search_start; |
f2d5f0cc | 468 | { |
c31a6508 ZW |
469 | struct file_name_list *path; |
470 | char *name; | |
471 | struct include_file *file; | |
add7091b | 472 | |
c31a6508 | 473 | if (fname[0] == '/') |
2047e26f | 474 | return open_file (pfile, fname); |
c31a6508 ZW |
475 | |
476 | /* Search directory path for the file. */ | |
477 | name = (char *) alloca (strlen (fname) + pfile->max_include_len | |
478 | + 2 + INCLUDE_LEN_FUDGE); | |
479 | for (path = search_start; path; path = path->next) | |
add7091b | 480 | { |
c31a6508 ZW |
481 | memcpy (name, path->name, path->nlen); |
482 | name[path->nlen] = '/'; | |
483 | strcpy (&name[path->nlen+1], fname); | |
484 | _cpp_simplify_pathname (name); | |
485 | if (CPP_OPTION (pfile, remap)) | |
486 | name = remap_filename (pfile, name, path); | |
487 | ||
2047e26f | 488 | file = open_file (pfile, name); |
c31a6508 | 489 | if (file) |
add7091b | 490 | { |
c31a6508 ZW |
491 | file->foundhere = path; |
492 | return file; | |
add7091b ZW |
493 | } |
494 | } | |
c31a6508 | 495 | return 0; |
add7091b ZW |
496 | } |
497 | ||
e605b040 | 498 | /* Not everyone who wants to set system-header-ness on a buffer can |
642ce434 NB |
499 | see the details of a buffer. This is an exported interface because |
500 | fix-header needs it. */ | |
e605b040 | 501 | void |
614c7d37 | 502 | cpp_make_system_header (pfile, syshdr, externc) |
e605b040 | 503 | cpp_reader *pfile; |
614c7d37 | 504 | int syshdr, externc; |
e605b040 | 505 | { |
614c7d37 NB |
506 | int flags = 0; |
507 | ||
508 | /* 1 = system header, 2 = system header to be treated as C. */ | |
509 | if (syshdr) | |
510 | flags = 1 + (externc != 0); | |
642ce434 | 511 | pfile->buffer->sysp = flags; |
e605b040 ZW |
512 | } |
513 | ||
c71f835b ZW |
514 | /* Report on all files that might benefit from a multiple include guard. |
515 | Triggered by -H. */ | |
516 | void | |
517 | _cpp_report_missing_guards (pfile) | |
518 | cpp_reader *pfile; | |
519 | { | |
520 | int banner = 0; | |
521 | splay_tree_foreach (pfile->all_include_files, report_missing_guard, | |
522 | (PTR) &banner); | |
523 | } | |
524 | ||
525 | static int | |
526 | report_missing_guard (n, b) | |
527 | splay_tree_node n; | |
528 | void *b; | |
529 | { | |
530 | struct include_file *f = (struct include_file *) n->value; | |
531 | int *bannerp = (int *)b; | |
532 | ||
533 | if (f && f->cmacro == 0 && f->include_count == 1) | |
534 | { | |
535 | if (*bannerp == 0) | |
536 | { | |
537 | fputs (_("Multiple include guards may be useful for:\n"), stderr); | |
538 | *bannerp = 1; | |
539 | } | |
540 | fputs (f->name, stderr); | |
541 | putc ('\n', stderr); | |
542 | } | |
543 | return 0; | |
544 | } | |
545 | ||
c31a6508 | 546 | #define PRINT_THIS_DEP(p, b) (CPP_PRINT_DEPS(p) > (b||p->system_include_depth)) |
168d3732 | 547 | void |
642ce434 | 548 | _cpp_execute_include (pfile, header, no_reinclude, include_next) |
168d3732 | 549 | cpp_reader *pfile; |
93c80368 | 550 | const cpp_token *header; |
168d3732 | 551 | int no_reinclude; |
642ce434 | 552 | int include_next; |
168d3732 | 553 | { |
642ce434 | 554 | struct file_name_list *search_start = 0; |
93c80368 NB |
555 | unsigned int len = header->val.str.len; |
556 | unsigned int angle_brackets = header->type == CPP_HEADER_NAME; | |
c31a6508 | 557 | struct include_file *inc; |
041c3194 | 558 | char *fname; |
168d3732 | 559 | |
3cf3593f NB |
560 | /* Help protect #include or similar from recursion. */ |
561 | if (pfile->buffer_stack_depth >= CPP_STACK_MAX) | |
562 | { | |
563 | cpp_fatal (pfile, "#include nested too deeply"); | |
564 | return; | |
565 | } | |
566 | ||
567 | /* Check we've tidied up #include before entering the buffer. */ | |
568 | if (pfile->context->prev) | |
569 | { | |
570 | cpp_ice (pfile, "attempt to push file buffer with contexts stacked"); | |
571 | return; | |
572 | } | |
573 | ||
642ce434 NB |
574 | /* For #include_next, skip in the search path past the dir in which |
575 | the current file was found. If this is the last directory in the | |
576 | search path, don't include anything. If the current file was | |
577 | specified with an absolute path, use the normal search logic. If | |
578 | this is the primary source file, use the normal search logic and | |
579 | generate a warning. */ | |
580 | if (include_next) | |
581 | { | |
582 | if (! pfile->buffer->prev) | |
583 | cpp_warning (pfile, "#include_next in primary source file"); | |
584 | else | |
585 | { | |
586 | if (pfile->buffer->inc->foundhere) | |
587 | { | |
588 | search_start = pfile->buffer->inc->foundhere->next; | |
589 | if (! search_start) | |
590 | return; | |
591 | } | |
592 | } | |
593 | } | |
594 | ||
93c80368 NB |
595 | fname = alloca (len + 1); |
596 | memcpy (fname, header->val.str.text, len); | |
597 | fname[len] = '\0'; | |
598 | ||
168d3732 ZW |
599 | if (!search_start) |
600 | { | |
601 | if (angle_brackets) | |
ae79697b ZW |
602 | search_start = CPP_OPTION (pfile, bracket_include); |
603 | else if (CPP_OPTION (pfile, ignore_srcdir)) | |
604 | search_start = CPP_OPTION (pfile, quote_include); | |
168d3732 ZW |
605 | else |
606 | search_start = CPP_BUFFER (pfile)->actual_dir; | |
168d3732 | 607 | |
93c80368 NB |
608 | if (!search_start) |
609 | { | |
610 | cpp_error (pfile, "No include path in which to find %s", fname); | |
611 | return; | |
612 | } | |
168d3732 ZW |
613 | } |
614 | ||
c31a6508 | 615 | inc = find_include_file (pfile, fname, search_start); |
168d3732 | 616 | |
c31a6508 | 617 | if (inc) |
168d3732 | 618 | { |
c31a6508 | 619 | /* For -M, add the file to the dependencies on its first inclusion. */ |
d4506961 | 620 | if (!inc->include_count && PRINT_THIS_DEP (pfile, angle_brackets)) |
c31a6508 | 621 | deps_add_dep (pfile->deps, inc->name); |
d4506961 | 622 | inc->include_count++; |
c31a6508 | 623 | |
c31a6508 | 624 | /* Actually process the file. */ |
3cf3593f NB |
625 | stack_include_file (pfile, inc); |
626 | ||
627 | if (angle_brackets) | |
628 | pfile->system_include_depth++; | |
a58d32c2 | 629 | |
3cf3593f NB |
630 | if (! DO_NOT_REREAD (inc)) |
631 | { | |
a58d32c2 | 632 | if (no_reinclude) |
642ce434 | 633 | _cpp_never_reread (inc); |
a58d32c2 ZW |
634 | |
635 | /* Handle -H option. */ | |
636 | if (CPP_OPTION (pfile, print_include_names)) | |
637 | { | |
638 | cpp_buffer *fp = CPP_BUFFER (pfile); | |
639 | while ((fp = CPP_PREV_BUFFER (fp)) != NULL) | |
640 | putc ('.', stderr); | |
641 | fprintf (stderr, " %s\n", inc->name); | |
642 | } | |
c31a6508 | 643 | } |
3cf3593f | 644 | |
168d3732 ZW |
645 | return; |
646 | } | |
c31a6508 ZW |
647 | |
648 | if (CPP_OPTION (pfile, print_deps_missing_files) | |
649 | && PRINT_THIS_DEP (pfile, angle_brackets)) | |
168d3732 | 650 | { |
c31a6508 ZW |
651 | if (!angle_brackets) |
652 | deps_add_dep (pfile->deps, fname); | |
653 | else | |
654 | { | |
655 | char *p; | |
656 | struct file_name_list *ptr; | |
657 | /* If requested as a system header, assume it belongs in | |
658 | the first system header directory. */ | |
659 | if (CPP_OPTION (pfile, bracket_include)) | |
660 | ptr = CPP_OPTION (pfile, bracket_include); | |
661 | else | |
662 | ptr = CPP_OPTION (pfile, quote_include); | |
168d3732 | 663 | |
c31a6508 ZW |
664 | p = (char *) alloca (strlen (ptr->name) |
665 | + strlen (fname) + 2); | |
666 | if (*ptr->name != '\0') | |
667 | { | |
668 | strcpy (p, ptr->name); | |
669 | strcat (p, "/"); | |
670 | } | |
671 | strcat (p, fname); | |
672 | _cpp_simplify_pathname (p); | |
673 | deps_add_dep (pfile->deps, p); | |
674 | } | |
168d3732 | 675 | } |
c31a6508 ZW |
676 | /* If -M was specified, and this header file won't be added to |
677 | the dependency list, then don't count this as an error, | |
678 | because we can still produce correct output. Otherwise, we | |
679 | can't produce correct output, because there may be | |
680 | dependencies we need inside the missing file, and we don't | |
681 | know what directory this missing file exists in. */ | |
682 | else if (CPP_PRINT_DEPS (pfile) | |
683 | && ! PRINT_THIS_DEP (pfile, angle_brackets)) | |
684 | cpp_warning (pfile, "No include path in which to find %s", fname); | |
685 | else | |
686 | cpp_error_from_errno (pfile, fname); | |
168d3732 ZW |
687 | } |
688 | ||
f3f751ad NS |
689 | /* Locate file F, and determine whether it is newer than PFILE. Return -1, |
690 | if F cannot be located or dated, 1, if it is newer and 0 if older. */ | |
f3f751ad | 691 | int |
93c80368 | 692 | _cpp_compare_file_date (pfile, f) |
f3f751ad | 693 | cpp_reader *pfile; |
93c80368 | 694 | const cpp_token *f; |
f3f751ad | 695 | { |
93c80368 | 696 | unsigned int len = f->val.str.len; |
041c3194 ZW |
697 | char *fname; |
698 | struct file_name_list *search_start; | |
f3f751ad | 699 | struct include_file *inc; |
f3f751ad | 700 | |
93c80368 | 701 | if (f->type == CPP_HEADER_NAME) |
041c3194 ZW |
702 | search_start = CPP_OPTION (pfile, bracket_include); |
703 | else if (CPP_OPTION (pfile, ignore_srcdir)) | |
704 | search_start = CPP_OPTION (pfile, quote_include); | |
705 | else | |
706 | search_start = CPP_BUFFER (pfile)->actual_dir; | |
f3f751ad | 707 | |
041c3194 | 708 | fname = alloca (len + 1); |
93c80368 | 709 | memcpy (fname, f->val.str.text, len); |
f3f751ad | 710 | fname[len] = '\0'; |
f3f751ad NS |
711 | inc = find_include_file (pfile, fname, search_start); |
712 | ||
713 | if (!inc) | |
714 | return -1; | |
a58d32c2 | 715 | if (inc->fd > 0) |
f3f751ad | 716 | { |
f3f751ad NS |
717 | close (inc->fd); |
718 | inc->fd = -1; | |
719 | } | |
a58d32c2 | 720 | |
93c80368 | 721 | return inc->st.st_mtime > CPP_BUFFER (pfile)->inc->st.st_mtime; |
f3f751ad NS |
722 | } |
723 | ||
724 | ||
c45da1ca ZW |
725 | /* Push an input buffer and load it up with the contents of FNAME. |
726 | If FNAME is "" or NULL, read standard input. */ | |
727 | int | |
614c7d37 | 728 | _cpp_read_file (pfile, fname) |
c45da1ca ZW |
729 | cpp_reader *pfile; |
730 | const char *fname; | |
731 | { | |
c31a6508 | 732 | struct include_file *f; |
c45da1ca | 733 | |
d35364d1 ZW |
734 | if (fname == NULL) |
735 | fname = ""; | |
736 | ||
2047e26f | 737 | f = open_file (pfile, fname); |
c45da1ca | 738 | |
041c3194 ZW |
739 | if (f == NULL) |
740 | { | |
741 | cpp_error_from_errno (pfile, fname); | |
742 | return 0; | |
743 | } | |
744 | ||
3cf3593f NB |
745 | stack_include_file (pfile, f); |
746 | return 1; | |
f8f769ea ZW |
747 | } |
748 | ||
f9a0e96c ZW |
749 | /* Do appropriate cleanup when a file buffer is popped off the input |
750 | stack. */ | |
751 | void | |
752 | _cpp_pop_file_buffer (pfile, buf) | |
753 | cpp_reader *pfile; | |
754 | cpp_buffer *buf; | |
755 | { | |
756 | struct include_file *inc = buf->inc; | |
757 | ||
758 | if (pfile->system_include_depth) | |
759 | pfile->system_include_depth--; | |
760 | if (pfile->include_depth) | |
761 | pfile->include_depth--; | |
93c80368 NB |
762 | |
763 | /* Record the inclusion-preventing macro and its definedness. */ | |
764 | if (pfile->mi_state == MI_OUTSIDE && inc->cmacro != NEVER_REREAD) | |
f9a0e96c | 765 | { |
93c80368 NB |
766 | /* This could be NULL meaning no controlling macro. */ |
767 | inc->cmacro = pfile->mi_cmacro; | |
768 | inc->defined = 1; | |
f9a0e96c | 769 | } |
93c80368 NB |
770 | |
771 | /* Invalidate control macros in the #including file. */ | |
772 | pfile->mi_state = MI_FAILED; | |
f9a0e96c | 773 | |
a58d32c2 ZW |
774 | inc->refcnt--; |
775 | if (inc->refcnt == 0 && DO_NOT_REREAD (inc)) | |
776 | purge_cache (inc); | |
f9a0e96c ZW |
777 | } |
778 | ||
c31a6508 ZW |
779 | /* The file_name_map structure holds a mapping of file names for a |
780 | particular directory. This mapping is read from the file named | |
781 | FILE_NAME_MAP_FILE in that directory. Such a file can be used to | |
782 | map filenames on a file system with severe filename restrictions, | |
783 | such as DOS. The format of the file name map file is just a series | |
784 | of lines with two tokens on each line. The first token is the name | |
785 | to map, and the second token is the actual name to use. */ | |
786 | ||
787 | struct file_name_map | |
788 | { | |
789 | struct file_name_map *map_next; | |
790 | char *map_from; | |
791 | char *map_to; | |
792 | }; | |
793 | ||
794 | #define FILE_NAME_MAP_FILE "header.gcc" | |
795 | ||
796 | /* Read a space delimited string of unlimited length from a stdio | |
797 | file. */ | |
798 | ||
799 | static char * | |
800 | read_filename_string (ch, f) | |
801 | int ch; | |
802 | FILE *f; | |
803 | { | |
804 | char *alloc, *set; | |
805 | int len; | |
806 | ||
807 | len = 20; | |
808 | set = alloc = xmalloc (len + 1); | |
809 | if (! is_space(ch)) | |
810 | { | |
811 | *set++ = ch; | |
812 | while ((ch = getc (f)) != EOF && ! is_space(ch)) | |
813 | { | |
814 | if (set - alloc == len) | |
815 | { | |
816 | len *= 2; | |
817 | alloc = xrealloc (alloc, len + 1); | |
818 | set = alloc + len / 2; | |
819 | } | |
820 | *set++ = ch; | |
821 | } | |
822 | } | |
823 | *set = '\0'; | |
824 | ungetc (ch, f); | |
825 | return alloc; | |
826 | } | |
827 | ||
828 | /* This structure holds a linked list of file name maps, one per directory. */ | |
829 | ||
830 | struct file_name_map_list | |
831 | { | |
832 | struct file_name_map_list *map_list_next; | |
833 | char *map_list_name; | |
834 | struct file_name_map *map_list_map; | |
835 | }; | |
836 | ||
837 | /* Read the file name map file for DIRNAME. */ | |
838 | ||
839 | static struct file_name_map * | |
840 | read_name_map (pfile, dirname) | |
841 | cpp_reader *pfile; | |
842 | const char *dirname; | |
843 | { | |
844 | register struct file_name_map_list *map_list_ptr; | |
845 | char *name; | |
846 | FILE *f; | |
847 | ||
8767c894 | 848 | /* Check the cache of directories, and mappings in their remap file. */ |
c31a6508 ZW |
849 | for (map_list_ptr = CPP_OPTION (pfile, map_list); map_list_ptr; |
850 | map_list_ptr = map_list_ptr->map_list_next) | |
851 | if (! strcmp (map_list_ptr->map_list_name, dirname)) | |
852 | return map_list_ptr->map_list_map; | |
853 | ||
854 | map_list_ptr = ((struct file_name_map_list *) | |
855 | xmalloc (sizeof (struct file_name_map_list))); | |
856 | map_list_ptr->map_list_name = xstrdup (dirname); | |
8767c894 NB |
857 | |
858 | /* The end of the list ends in NULL. */ | |
4b588241 | 859 | map_list_ptr->map_list_map = NULL; |
c31a6508 ZW |
860 | |
861 | name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2); | |
862 | strcpy (name, dirname); | |
863 | if (*dirname) | |
864 | strcat (name, "/"); | |
865 | strcat (name, FILE_NAME_MAP_FILE); | |
866 | f = fopen (name, "r"); | |
8767c894 NB |
867 | |
868 | /* Silently return NULL if we cannot open. */ | |
869 | if (f) | |
c31a6508 ZW |
870 | { |
871 | int ch; | |
872 | int dirlen = strlen (dirname); | |
873 | ||
874 | while ((ch = getc (f)) != EOF) | |
875 | { | |
876 | char *from, *to; | |
877 | struct file_name_map *ptr; | |
878 | ||
879 | if (is_space(ch)) | |
880 | continue; | |
881 | from = read_filename_string (ch, f); | |
882 | while ((ch = getc (f)) != EOF && is_hspace(ch)) | |
883 | ; | |
884 | to = read_filename_string (ch, f); | |
885 | ||
886 | ptr = ((struct file_name_map *) | |
887 | xmalloc (sizeof (struct file_name_map))); | |
888 | ptr->map_from = from; | |
889 | ||
890 | /* Make the real filename absolute. */ | |
891 | if (*to == '/') | |
892 | ptr->map_to = to; | |
893 | else | |
894 | { | |
895 | ptr->map_to = xmalloc (dirlen + strlen (to) + 2); | |
896 | strcpy (ptr->map_to, dirname); | |
897 | ptr->map_to[dirlen] = '/'; | |
898 | strcpy (ptr->map_to + dirlen + 1, to); | |
899 | free (to); | |
900 | } | |
901 | ||
902 | ptr->map_next = map_list_ptr->map_list_map; | |
903 | map_list_ptr->map_list_map = ptr; | |
904 | ||
905 | while ((ch = getc (f)) != '\n') | |
906 | if (ch == EOF) | |
907 | break; | |
908 | } | |
909 | fclose (f); | |
910 | } | |
911 | ||
8767c894 | 912 | /* Add this information to the cache. */ |
c31a6508 ZW |
913 | map_list_ptr->map_list_next = CPP_OPTION (pfile, map_list); |
914 | CPP_OPTION (pfile, map_list) = map_list_ptr; | |
915 | ||
916 | return map_list_ptr->map_list_map; | |
917 | } | |
918 | ||
919 | /* Remap NAME based on the file_name_map (if any) for LOC. */ | |
920 | ||
921 | static char * | |
922 | remap_filename (pfile, name, loc) | |
923 | cpp_reader *pfile; | |
924 | char *name; | |
925 | struct file_name_list *loc; | |
926 | { | |
927 | struct file_name_map *map; | |
8767c894 NB |
928 | const char *from, *p; |
929 | char *dir; | |
c31a6508 ZW |
930 | |
931 | if (! loc->name_map) | |
8767c894 NB |
932 | { |
933 | loc->name_map = read_name_map (pfile, loc->name ? loc->name : "."); | |
934 | if (! loc->name_map) | |
935 | return name; | |
936 | } | |
c31a6508 ZW |
937 | |
938 | from = name + strlen (loc->name) + 1; | |
939 | ||
940 | for (map = loc->name_map; map; map = map->map_next) | |
941 | if (!strcmp (map->map_from, from)) | |
942 | return map->map_to; | |
943 | ||
944 | /* Try to find a mapping file for the particular directory we are | |
945 | looking in. Thus #include <sys/types.h> will look up sys/types.h | |
946 | in /usr/include/header.gcc and look up types.h in | |
947 | /usr/include/sys/header.gcc. */ | |
948 | p = strrchr (name, '/'); | |
949 | if (!p) | |
c31a6508 ZW |
950 | return name; |
951 | ||
8767c894 | 952 | /* We know p != name as absolute paths don't call remap_filename. */ |
c31a6508 | 953 | if (p == name) |
8767c894 NB |
954 | cpp_ice (pfile, "absolute file name in remap_filename"); |
955 | ||
956 | dir = (char *) alloca (p - name + 1); | |
957 | memcpy (dir, name, p - name); | |
958 | dir[p - name] = '\0'; | |
959 | from = p + 1; | |
c31a6508 ZW |
960 | |
961 | for (map = read_name_map (pfile, dir); map; map = map->map_next) | |
8767c894 | 962 | if (! strcmp (map->map_from, from)) |
c31a6508 ZW |
963 | return map->map_to; |
964 | ||
965 | return name; | |
966 | } | |
967 | ||
6458033d ZW |
968 | /* Given a path FNAME, extract the directory component and place it |
969 | onto the actual_dirs list. Return a pointer to the allocated | |
970 | file_name_list structure. These structures are used to implement | |
971 | current-directory "" include searching. */ | |
972 | ||
f1a86df6 ZW |
973 | static struct file_name_list * |
974 | actual_directory (pfile, fname) | |
975 | cpp_reader *pfile; | |
bcc5cac9 | 976 | const char *fname; |
f1a86df6 ZW |
977 | { |
978 | char *last_slash, *dir; | |
979 | size_t dlen; | |
980 | struct file_name_list *x; | |
981 | ||
c49445e0 | 982 | dir = xstrdup (fname); |
7ceb3598 | 983 | last_slash = strrchr (dir, '/'); |
f1a86df6 ZW |
984 | if (last_slash) |
985 | { | |
986 | if (last_slash == dir) | |
987 | { | |
988 | dlen = 1; | |
989 | last_slash[1] = '\0'; | |
990 | } | |
991 | else | |
992 | { | |
993 | dlen = last_slash - dir; | |
994 | *last_slash = '\0'; | |
995 | } | |
996 | } | |
997 | else | |
998 | { | |
87ae0c74 GM |
999 | free (dir); |
1000 | dir = xstrdup ("."); | |
f1a86df6 ZW |
1001 | dlen = 1; |
1002 | } | |
1003 | ||
1004 | if (dlen > pfile->max_include_len) | |
1005 | pfile->max_include_len = dlen; | |
1006 | ||
1007 | for (x = pfile->actual_dirs; x; x = x->alloc) | |
1008 | if (!strcmp (x->name, dir)) | |
1009 | { | |
1010 | free (dir); | |
1011 | return x; | |
1012 | } | |
1013 | ||
1014 | /* Not found, make a new one. */ | |
1015 | x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); | |
1016 | x->name = dir; | |
1017 | x->nlen = dlen; | |
ae79697b | 1018 | x->next = CPP_OPTION (pfile, quote_include); |
f1a86df6 | 1019 | x->alloc = pfile->actual_dirs; |
642ce434 | 1020 | x->sysp = pfile->buffer->sysp; |
f1a86df6 ZW |
1021 | x->name_map = NULL; |
1022 | ||
1023 | pfile->actual_dirs = x; | |
1024 | return x; | |
1025 | } | |
1026 | ||
0b3d776a ZW |
1027 | /* Simplify a path name in place, deleting redundant components. This |
1028 | reduces OS overhead and guarantees that equivalent paths compare | |
1029 | the same (modulo symlinks). | |
1030 | ||
1031 | Transforms made: | |
1032 | foo/bar/../quux foo/quux | |
1033 | foo/./bar foo/bar | |
1034 | foo//bar foo/bar | |
1035 | /../quux /quux | |
1036 | //quux //quux (POSIX allows leading // as a namespace escape) | |
1037 | ||
1038 | Guarantees no trailing slashes. All transforms reduce the length | |
1039 | of the string. | |
1040 | */ | |
0b22d65c | 1041 | void |
b0699dad | 1042 | _cpp_simplify_pathname (path) |
21380ab0 | 1043 | char *path; |
0b3d776a ZW |
1044 | { |
1045 | char *from, *to; | |
1046 | char *base; | |
1047 | int absolute = 0; | |
1048 | ||
509781a4 | 1049 | #if defined (HAVE_DOS_BASED_FILE_SYSTEM) |
0b3d776a ZW |
1050 | /* Convert all backslashes to slashes. */ |
1051 | for (from = path; *from; from++) | |
1052 | if (*from == '\\') *from = '/'; | |
1053 | ||
1054 | /* Skip over leading drive letter if present. */ | |
1055 | if (ISALPHA (path[0]) && path[1] == ':') | |
1056 | from = to = &path[2]; | |
1057 | else | |
1058 | from = to = path; | |
1059 | #else | |
1060 | from = to = path; | |
1061 | #endif | |
1062 | ||
1063 | /* Remove redundant initial /s. */ | |
1064 | if (*from == '/') | |
1065 | { | |
1066 | absolute = 1; | |
1067 | to++; | |
1068 | from++; | |
1069 | if (*from == '/') | |
1070 | { | |
1071 | if (*++from == '/') | |
1072 | /* 3 or more initial /s are equivalent to 1 /. */ | |
1073 | while (*++from == '/'); | |
1074 | else | |
1075 | /* On some hosts // differs from /; Posix allows this. */ | |
1076 | to++; | |
1077 | } | |
1078 | } | |
1079 | base = to; | |
1080 | ||
1081 | for (;;) | |
1082 | { | |
1083 | while (*from == '/') | |
1084 | from++; | |
1085 | ||
1086 | if (from[0] == '.' && from[1] == '/') | |
1087 | from += 2; | |
1088 | else if (from[0] == '.' && from[1] == '\0') | |
1089 | goto done; | |
1090 | else if (from[0] == '.' && from[1] == '.' && from[2] == '/') | |
1091 | { | |
1092 | if (base == to) | |
1093 | { | |
1094 | if (absolute) | |
1095 | from += 3; | |
1096 | else | |
1097 | { | |
1098 | *to++ = *from++; | |
1099 | *to++ = *from++; | |
1100 | *to++ = *from++; | |
1101 | base = to; | |
1102 | } | |
1103 | } | |
1104 | else | |
1105 | { | |
1106 | to -= 2; | |
1107 | while (to > base && *to != '/') to--; | |
1108 | if (*to == '/') | |
1109 | to++; | |
1110 | from += 3; | |
1111 | } | |
1112 | } | |
1113 | else if (from[0] == '.' && from[1] == '.' && from[2] == '\0') | |
1114 | { | |
1115 | if (base == to) | |
1116 | { | |
1117 | if (!absolute) | |
1118 | { | |
1119 | *to++ = *from++; | |
1120 | *to++ = *from++; | |
1121 | } | |
1122 | } | |
1123 | else | |
1124 | { | |
1125 | to -= 2; | |
1126 | while (to > base && *to != '/') to--; | |
1127 | if (*to == '/') | |
1128 | to++; | |
1129 | } | |
1130 | goto done; | |
1131 | } | |
1132 | else | |
1133 | /* Copy this component and trailing /, if any. */ | |
1134 | while ((*to++ = *from++) != '/') | |
1135 | { | |
1136 | if (!to[-1]) | |
1137 | { | |
1138 | to--; | |
1139 | goto done; | |
1140 | } | |
1141 | } | |
1142 | ||
1143 | } | |
1144 | ||
1145 | done: | |
1146 | /* Trim trailing slash */ | |
1147 | if (to[0] == '/' && (!absolute || to > path+1)) | |
1148 | to--; | |
1149 | ||
1150 | /* Change the empty string to "." so that stat() on the result | |
1151 | will always work. */ | |
1152 | if (to == path) | |
1153 | *to++ = '.'; | |
1154 | ||
1155 | *to = '\0'; | |
1156 | ||
1157 | return; | |
1158 | } |