00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "cpplib.h"
00026 #include "cpphash.h"
00027 #include "intl.h"
00028 #include "mkdeps.h"
00029 #include "splay-tree.h"
00030 #ifdef ENABLE_VALGRIND_CHECKING
00031 #include <valgrind.h>
00032 #else
00033
00034 #define VALGRIND_DISCARD(x)
00035 #endif
00036
00037 #ifdef HAVE_MMAP_FILE
00038 # include <sys/mman.h>
00039 # ifndef MMAP_THRESHOLD
00040 # define MMAP_THRESHOLD 3
00041 # endif
00042 # if MMAP_THRESHOLD
00043 # define TEST_THRESHOLD(size, pagesize) \
00044 (size / pagesize >= MMAP_THRESHOLD && (size % pagesize) != 0)
00045
00046
00047
00048
00049
00050 # ifndef __CYGWIN__
00051 # define SHOULD_MMAP(size, pagesize) TEST_THRESHOLD (size, pagesize)
00052 # else
00053 # define WIN32_LEAN_AND_MEAN
00054 # include <windows.h>
00055
00056
00057
00058 # define SHOULD_MMAP(size, pagesize) ((GetVersion() & 0x80000000) \
00059 ? 0 : TEST_THRESHOLD (size, pagesize))
00060 # endif
00061 # endif
00062
00063 #else
00064 # undef MMAP_THRESHOLD
00065 # define MMAP_THRESHOLD 0
00066 #endif
00067
00068 #ifndef O_BINARY
00069 # define O_BINARY 0
00070 #endif
00071
00072
00073
00074 #ifndef ENOENT
00075 # define ENOENT 0
00076 #endif
00077 #ifndef ENOTDIR
00078 # define ENOTDIR 0
00079 #endif
00080
00081
00082
00083 #undef strcmp
00084
00085
00086 struct include_file {
00087 const char *name;
00088 const cpp_hashnode *cmacro;
00089 const struct search_path *foundhere;
00090
00091
00092 const unsigned char *buffer;
00093 struct stat st;
00094 int fd;
00095 int err_no;
00096 unsigned short include_count;
00097 unsigned short refcnt;
00098 unsigned char mapped;
00099 };
00100
00101
00102
00103 #ifdef VMS
00104 # define FAB_C_VAR 2
00105 # define STAT_SIZE_TOO_BIG(ST) ((ST).st_fab_rfm == FAB_C_VAR)
00106 #else
00107 # define STAT_SIZE_TOO_BIG(ST) 0
00108 #endif
00109
00110
00111
00112
00113
00114 #define NEVER_REREAD ((const cpp_hashnode *) -1)
00115 #define DO_NOT_REREAD(inc) \
00116 ((inc)->cmacro && ((inc)->cmacro == NEVER_REREAD \
00117 || (inc)->cmacro->type == NT_MACRO))
00118 #define NO_INCLUDE_PATH ((struct include_file *) -1)
00119
00120 static struct file_name_map *read_name_map
00121 PARAMS ((cpp_reader *, const char *));
00122 static char *read_filename_string PARAMS ((int, FILE *));
00123 static char *remap_filename PARAMS ((cpp_reader *, char *,
00124 struct search_path *));
00125 static struct search_path *search_from PARAMS ((cpp_reader *,
00126 enum include_type));
00127 static struct include_file *
00128 find_include_file PARAMS ((cpp_reader *, const cpp_token *,
00129 enum include_type));
00130 static struct include_file *open_file PARAMS ((cpp_reader *, const char *));
00131 static int read_include_file PARAMS ((cpp_reader *, struct include_file *));
00132 static bool stack_include_file PARAMS ((cpp_reader *, struct include_file *));
00133 static void purge_cache PARAMS ((struct include_file *));
00134 static void destroy_node PARAMS ((splay_tree_value));
00135 static int report_missing_guard PARAMS ((splay_tree_node, void *));
00136 static splay_tree_node find_or_create_entry PARAMS ((cpp_reader *,
00137 const char *));
00138 static void handle_missing_header PARAMS ((cpp_reader *, const char *, int));
00139 static int remove_component_p PARAMS ((const char *));
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 void
00154 _cpp_init_includes (pfile)
00155 cpp_reader *pfile;
00156 {
00157 pfile->all_include_files
00158 = splay_tree_new ((splay_tree_compare_fn) strcmp,
00159 (splay_tree_delete_key_fn) free,
00160 destroy_node);
00161 }
00162
00163
00164 void
00165 _cpp_cleanup_includes (pfile)
00166 cpp_reader *pfile;
00167 {
00168 splay_tree_delete (pfile->all_include_files);
00169 }
00170
00171
00172 static void
00173 destroy_node (v)
00174 splay_tree_value v;
00175 {
00176 struct include_file *f = (struct include_file *) v;
00177
00178 if (f)
00179 {
00180 purge_cache (f);
00181 free (f);
00182 }
00183 }
00184
00185
00186 void
00187 _cpp_never_reread (file)
00188 struct include_file *file;
00189 {
00190 file->cmacro = NEVER_REREAD;
00191 }
00192
00193
00194
00195
00196 static splay_tree_node
00197 find_or_create_entry (pfile, fname)
00198 cpp_reader *pfile;
00199 const char *fname;
00200 {
00201 splay_tree_node node;
00202 struct include_file *file;
00203 char *name = xstrdup (fname);
00204
00205 _cpp_simplify_pathname (name);
00206 node = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name);
00207 if (node)
00208 free (name);
00209 else
00210 {
00211 file = xcnew (struct include_file);
00212 file->name = name;
00213 file->err_no = errno;
00214 node = splay_tree_insert (pfile->all_include_files,
00215 (splay_tree_key) file->name,
00216 (splay_tree_value) file);
00217 }
00218
00219 return node;
00220 }
00221
00222
00223 void
00224 _cpp_fake_include (pfile, fname)
00225 cpp_reader *pfile;
00226 const char *fname;
00227 {
00228 find_or_create_entry (pfile, fname);
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 static struct include_file *
00241 open_file (pfile, filename)
00242 cpp_reader *pfile;
00243 const char *filename;
00244 {
00245 splay_tree_node nd = find_or_create_entry (pfile, filename);
00246 struct include_file *file = (struct include_file *) nd->value;
00247
00248 if (file->err_no)
00249 {
00250
00251 errno = file->err_no;
00252 return 0;
00253 }
00254
00255
00256 if (DO_NOT_REREAD (file))
00257 return file;
00258
00259
00260 if (file->buffer != NULL)
00261 return file;
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 if (filename[0] == '\0')
00278 {
00279 file->fd = 0;
00280 #ifdef __DJGPP__
00281
00282
00283 if (! isatty (file->fd))
00284 setmode (file->fd, O_BINARY);
00285 #endif
00286 }
00287 else
00288 file->fd = open (file->name, O_RDONLY | O_NOCTTY | O_BINARY, 0666);
00289
00290 if (file->fd != -1 && fstat (file->fd, &file->st) == 0)
00291 {
00292 if (!S_ISDIR (file->st.st_mode))
00293 return file;
00294
00295
00296
00297
00298 errno = ENOENT;
00299 close (file->fd);
00300 file->fd = -1;
00301 }
00302
00303 file->err_no = errno;
00304 return 0;
00305 }
00306
00307
00308
00309
00310
00311 static bool
00312 stack_include_file (pfile, inc)
00313 cpp_reader *pfile;
00314 struct include_file *inc;
00315 {
00316 cpp_buffer *fp;
00317 int sysp;
00318 const char *filename;
00319
00320 if (DO_NOT_REREAD (inc))
00321 return false;
00322
00323 sysp = MAX ((pfile->map ? pfile->map->sysp : 0),
00324 (inc->foundhere ? inc->foundhere->sysp : 0));
00325
00326
00327 if (CPP_OPTION (pfile, deps.style) > !!sysp && !inc->include_count)
00328 {
00329 if (pfile->buffer || CPP_OPTION (pfile, deps.ignore_main_file) == 0)
00330 deps_add_dep (pfile->deps, inc->name);
00331 }
00332
00333
00334 if (! inc->buffer)
00335 {
00336 if (read_include_file (pfile, inc))
00337 {
00338
00339 _cpp_never_reread (inc);
00340 return false;
00341 }
00342
00343
00344
00345 if (S_ISREG (inc->st.st_mode) && inc->st.st_size == 0)
00346 _cpp_never_reread (inc);
00347 close (inc->fd);
00348 inc->fd = -1;
00349 }
00350
00351 if (pfile->buffer)
00352
00353 inc->include_count++;
00354
00355
00356 fp = cpp_push_buffer (pfile, inc->buffer, inc->st.st_size,
00357 CPP_OPTION (pfile, preprocessed), 0);
00358 fp->inc = inc;
00359 fp->inc->refcnt++;
00360
00361
00362 pfile->mi_valid = true;
00363 pfile->mi_cmacro = 0;
00364
00365
00366 filename = inc->name;
00367 if (*filename == '\0')
00368 filename = "<stdin>";
00369 _cpp_do_file_change (pfile, LC_ENTER, filename, 1, sysp);
00370
00371 return true;
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 static int
00389 read_include_file (pfile, inc)
00390 cpp_reader *pfile;
00391 struct include_file *inc;
00392 {
00393 ssize_t size, offset, count;
00394 uchar *buf;
00395 #if MMAP_THRESHOLD
00396 static int pagesize = -1;
00397 #endif
00398
00399 if (S_ISREG (inc->st.st_mode))
00400 {
00401
00402
00403
00404
00405
00406
00407
00408
00409 if (inc->st.st_size > INTTYPE_MAXIMUM (ssize_t))
00410 {
00411 cpp_error (pfile, DL_ERROR, "%s is too large", inc->name);
00412 goto fail;
00413 }
00414 size = inc->st.st_size;
00415
00416 inc->mapped = 0;
00417 #if MMAP_THRESHOLD
00418 if (pagesize == -1)
00419 pagesize = getpagesize ();
00420
00421 if (SHOULD_MMAP (size, pagesize))
00422 {
00423 buf = (uchar *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0);
00424 if (buf == (uchar *) -1)
00425 goto perror_fail;
00426
00427
00428
00429 VALGRIND_DISCARD (VALGRIND_MAKE_READABLE (buf + size, 1));
00430
00431 inc->mapped = 1;
00432 }
00433 else
00434 #endif
00435 {
00436 buf = (uchar *) xmalloc (size + 1);
00437 offset = 0;
00438 while (offset < size)
00439 {
00440 count = read (inc->fd, buf + offset, size - offset);
00441 if (count < 0)
00442 goto perror_fail;
00443 if (count == 0)
00444 {
00445 if (!STAT_SIZE_TOO_BIG (inc->st))
00446 cpp_error (pfile, DL_WARNING,
00447 "%s is shorter than expected", inc->name);
00448 size = offset;
00449 buf = xrealloc (buf, size + 1);
00450 inc->st.st_size = size;
00451 break;
00452 }
00453 offset += count;
00454 }
00455
00456 buf[size] = '\0';
00457 }
00458 }
00459 else if (S_ISBLK (inc->st.st_mode))
00460 {
00461 cpp_error (pfile, DL_ERROR, "%s is a block device", inc->name);
00462 goto fail;
00463 }
00464 else
00465 {
00466
00467
00468
00469 size = 8 * 1024;
00470
00471 buf = (uchar *) xmalloc (size + 1);
00472 offset = 0;
00473 while ((count = read (inc->fd, buf + offset, size - offset)) > 0)
00474 {
00475 offset += count;
00476 if (offset == size)
00477 {
00478 size *= 2;
00479 buf = xrealloc (buf, size + 1);
00480 }
00481 }
00482 if (count < 0)
00483 goto perror_fail;
00484
00485 if (offset + 1 < size)
00486 buf = xrealloc (buf, offset + 1);
00487
00488
00489 buf[offset] = '\0';
00490 inc->st.st_size = offset;
00491 }
00492
00493 inc->buffer = buf;
00494 return 0;
00495
00496 perror_fail:
00497 cpp_errno (pfile, DL_ERROR, inc->name);
00498 fail:
00499 return 1;
00500 }
00501
00502
00503 static void
00504 purge_cache (inc)
00505 struct include_file *inc;
00506 {
00507 if (inc->buffer)
00508 {
00509 #if MMAP_THRESHOLD
00510 if (inc->mapped)
00511 {
00512
00513
00514
00515 VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (inc->buffer
00516 + inc->st.st_size, 1));
00517 munmap ((PTR) inc->buffer, inc->st.st_size);
00518 }
00519 else
00520 #endif
00521 free ((PTR) inc->buffer);
00522 inc->buffer = NULL;
00523 }
00524 }
00525
00526
00527
00528 int
00529 cpp_included (pfile, fname)
00530 cpp_reader *pfile;
00531 const char *fname;
00532 {
00533 struct search_path *path;
00534 char *name, *n;
00535 splay_tree_node nd;
00536
00537 if (IS_ABSOLUTE_PATHNAME (fname))
00538 {
00539
00540 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) fname);
00541 return (nd && nd->value);
00542 }
00543
00544
00545 name = (char *) alloca (strlen (fname) + pfile->max_include_len + 2);
00546 for (path = CPP_OPTION (pfile, quote_include); path; path = path->next)
00547 {
00548 memcpy (name, path->name, path->len);
00549 name[path->len] = '/';
00550 strcpy (&name[path->len + 1], fname);
00551 if (CPP_OPTION (pfile, remap))
00552 n = remap_filename (pfile, name, path);
00553 else
00554 n = name;
00555
00556 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) n);
00557 if (nd && nd->value)
00558 return 1;
00559 }
00560 return 0;
00561 }
00562
00563
00564
00565
00566
00567
00568 static struct include_file *
00569 find_include_file (pfile, header, type)
00570 cpp_reader *pfile;
00571 const cpp_token *header;
00572 enum include_type type;
00573 {
00574 const char *fname = (const char *) header->val.str.text;
00575 struct search_path *path;
00576 struct include_file *file;
00577 char *name, *n;
00578
00579 if (IS_ABSOLUTE_PATHNAME (fname))
00580 return open_file (pfile, fname);
00581
00582
00583
00584
00585 if (type == IT_INCLUDE_NEXT && pfile->buffer->inc->foundhere)
00586 path = pfile->buffer->inc->foundhere->next;
00587 else if (header->type == CPP_HEADER_NAME)
00588 path = CPP_OPTION (pfile, bracket_include);
00589 else
00590 path = search_from (pfile, type);
00591
00592 if (path == NULL)
00593 {
00594 cpp_error (pfile, DL_ERROR, "no include path in which to find %s",
00595 fname);
00596 return NO_INCLUDE_PATH;
00597 }
00598
00599
00600 name = (char *) alloca (strlen (fname) + pfile->max_include_len + 2);
00601 for (; path; path = path->next)
00602 {
00603 int len = path->len;
00604 memcpy (name, path->name, len);
00605
00606
00607 if (name[len-1] == '/')
00608 len--;
00609 name[len] = '/';
00610 strcpy (&name[len + 1], fname);
00611 if (CPP_OPTION (pfile, remap))
00612 n = remap_filename (pfile, name, path);
00613 else
00614 n = name;
00615
00616 file = open_file (pfile, n);
00617 if (file)
00618 {
00619 file->foundhere = path;
00620 return file;
00621 }
00622 }
00623
00624 return 0;
00625 }
00626
00627
00628
00629
00630 void
00631 cpp_make_system_header (pfile, syshdr, externc)
00632 cpp_reader *pfile;
00633 int syshdr, externc;
00634 {
00635 int flags = 0;
00636
00637
00638 if (syshdr)
00639 flags = 1 + (externc != 0);
00640 _cpp_do_file_change (pfile, LC_RENAME, pfile->map->to_file,
00641 SOURCE_LINE (pfile->map, pfile->line), flags);
00642 }
00643
00644
00645
00646 void
00647 _cpp_report_missing_guards (pfile)
00648 cpp_reader *pfile;
00649 {
00650 int banner = 0;
00651 splay_tree_foreach (pfile->all_include_files, report_missing_guard,
00652 (PTR) &banner);
00653 }
00654
00655
00656 static int
00657 report_missing_guard (n, b)
00658 splay_tree_node n;
00659 void *b;
00660 {
00661 struct include_file *f = (struct include_file *) n->value;
00662 int *bannerp = (int *) b;
00663
00664 if (f && f->cmacro == 0 && f->include_count == 1)
00665 {
00666 if (*bannerp == 0)
00667 {
00668 fputs (_("Multiple include guards may be useful for:\n"), stderr);
00669 *bannerp = 1;
00670 }
00671 fputs (f->name, stderr);
00672 putc ('\n', stderr);
00673 }
00674 return 0;
00675 }
00676
00677
00678
00679
00680 static void
00681 handle_missing_header (pfile, fname, angle_brackets)
00682 cpp_reader *pfile;
00683 const char *fname;
00684 int angle_brackets;
00685 {
00686 bool print_dep
00687 = CPP_OPTION (pfile, deps.style) > (angle_brackets || pfile->map->sysp);
00688
00689 if (CPP_OPTION (pfile, deps.missing_files) && print_dep)
00690 deps_add_dep (pfile->deps, fname);
00691
00692
00693
00694
00695
00696 else
00697 cpp_errno (pfile, CPP_OPTION (pfile, deps.style) && ! print_dep
00698 ? DL_WARNING: DL_ERROR, fname);
00699 }
00700
00701
00702
00703
00704 bool
00705 _cpp_execute_include (pfile, header, type)
00706 cpp_reader *pfile;
00707 const cpp_token *header;
00708 enum include_type type;
00709 {
00710 bool stacked = false;
00711 struct include_file *inc = find_include_file (pfile, header, type);
00712
00713 if (inc == 0)
00714 handle_missing_header (pfile, (const char *) header->val.str.text,
00715 header->type == CPP_HEADER_NAME);
00716 else if (inc != NO_INCLUDE_PATH)
00717 {
00718 stacked = stack_include_file (pfile, inc);
00719
00720 if (type == IT_IMPORT)
00721 _cpp_never_reread (inc);
00722 }
00723
00724 return stacked;
00725 }
00726
00727
00728
00729
00730 int
00731 _cpp_compare_file_date (pfile, header)
00732 cpp_reader *pfile;
00733 const cpp_token *header;
00734 {
00735 struct include_file *inc = find_include_file (pfile, header, 0);
00736
00737 if (inc == NULL || inc == NO_INCLUDE_PATH)
00738 return -1;
00739
00740 if (inc->fd > 0)
00741 {
00742 close (inc->fd);
00743 inc->fd = -1;
00744 }
00745
00746 return inc->st.st_mtime > pfile->buffer->inc->st.st_mtime;
00747 }
00748
00749
00750
00751
00752
00753 bool
00754 _cpp_read_file (pfile, fname)
00755 cpp_reader *pfile;
00756 const char *fname;
00757 {
00758 struct include_file *f = open_file (pfile, fname);
00759
00760 if (f == NULL)
00761 {
00762 cpp_errno (pfile, DL_ERROR, fname);
00763 return false;
00764 }
00765
00766 return stack_include_file (pfile, f);
00767 }
00768
00769
00770
00771 void
00772 _cpp_pop_file_buffer (pfile, inc)
00773 cpp_reader *pfile;
00774 struct include_file *inc;
00775 {
00776
00777
00778 if (pfile->mi_valid && inc->cmacro == NULL)
00779 inc->cmacro = pfile->mi_cmacro;
00780
00781
00782 pfile->mi_valid = false;
00783
00784 inc->refcnt--;
00785 if (inc->refcnt == 0 && DO_NOT_REREAD (inc))
00786 purge_cache (inc);
00787 }
00788
00789
00790
00791
00792
00793
00794
00795 static struct search_path *
00796 search_from (pfile, type)
00797 cpp_reader *pfile;
00798 enum include_type type;
00799 {
00800 cpp_buffer *buffer = pfile->buffer;
00801 unsigned int dlen;
00802
00803
00804 if (type == IT_CMDLINE)
00805 goto use_cwd;
00806
00807
00808 if (CPP_OPTION (pfile, ignore_srcdir))
00809 return CPP_OPTION (pfile, quote_include);
00810
00811 if (! buffer->search_cached)
00812 {
00813 buffer->search_cached = 1;
00814
00815 dlen = lbasename (buffer->inc->name) - buffer->inc->name;
00816
00817 if (dlen)
00818 {
00819
00820
00821 buffer->dir.name = buffer->inc->name;
00822 if (dlen > 1)
00823 dlen--;
00824 }
00825 else
00826 {
00827 use_cwd:
00828 buffer->dir.name = ".";
00829 dlen = 1;
00830 }
00831
00832 if (dlen > pfile->max_include_len)
00833 pfile->max_include_len = dlen;
00834
00835 buffer->dir.len = dlen;
00836 buffer->dir.next = CPP_OPTION (pfile, quote_include);
00837 buffer->dir.sysp = pfile->map->sysp;
00838 }
00839
00840 return &buffer->dir;
00841 }
00842
00843
00844
00845
00846
00847
00848
00849
00850 struct file_name_map {
00851 struct file_name_map *map_next;
00852 char *map_from;
00853 char *map_to;
00854 };
00855
00856 #define FILE_NAME_MAP_FILE "header.gcc"
00857
00858
00859
00860 static char *
00861 read_filename_string (ch, f)
00862 int ch;
00863 FILE *f;
00864 {
00865 char *alloc, *set;
00866 int len;
00867
00868 len = 20;
00869 set = alloc = xmalloc (len + 1);
00870 if (! is_space (ch))
00871 {
00872 *set++ = ch;
00873 while ((ch = getc (f)) != EOF && ! is_space (ch))
00874 {
00875 if (set - alloc == len)
00876 {
00877 len *= 2;
00878 alloc = xrealloc (alloc, len + 1);
00879 set = alloc + len / 2;
00880 }
00881 *set++ = ch;
00882 }
00883 }
00884 *set = '\0';
00885 ungetc (ch, f);
00886 return alloc;
00887 }
00888
00889
00890 struct file_name_map_list {
00891 struct file_name_map_list *map_list_next;
00892 char *map_list_name;
00893 struct file_name_map *map_list_map;
00894 };
00895
00896
00897 static struct file_name_map *
00898 read_name_map (pfile, dirname)
00899 cpp_reader *pfile;
00900 const char *dirname;
00901 {
00902 struct file_name_map_list *map_list_ptr;
00903 char *name;
00904 FILE *f;
00905
00906
00907 for (map_list_ptr = CPP_OPTION (pfile, map_list); map_list_ptr;
00908 map_list_ptr = map_list_ptr->map_list_next)
00909 if (! strcmp (map_list_ptr->map_list_name, dirname))
00910 return map_list_ptr->map_list_map;
00911
00912 map_list_ptr = ((struct file_name_map_list *)
00913 xmalloc (sizeof (struct file_name_map_list)));
00914 map_list_ptr->map_list_name = xstrdup (dirname);
00915
00916
00917 map_list_ptr->map_list_map = NULL;
00918
00919 name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
00920 strcpy (name, dirname);
00921 if (*dirname)
00922 strcat (name, "/");
00923 strcat (name, FILE_NAME_MAP_FILE);
00924 f = fopen (name, "r");
00925
00926
00927 if (f)
00928 {
00929 int ch;
00930
00931 while ((ch = getc (f)) != EOF)
00932 {
00933 char *from, *to;
00934 struct file_name_map *ptr;
00935
00936 if (is_space (ch))
00937 continue;
00938 from = read_filename_string (ch, f);
00939 while ((ch = getc (f)) != EOF && is_hspace (ch))
00940 ;
00941 to = read_filename_string (ch, f);
00942
00943 ptr = ((struct file_name_map *)
00944 xmalloc (sizeof (struct file_name_map)));
00945 ptr->map_from = from;
00946
00947
00948 if (IS_ABSOLUTE_PATHNAME (to))
00949 ptr->map_to = to;
00950 else
00951 {
00952 ptr->map_to = concat (dirname, "/", to, NULL);
00953 free (to);
00954 }
00955
00956 ptr->map_next = map_list_ptr->map_list_map;
00957 map_list_ptr->map_list_map = ptr;
00958
00959 while ((ch = getc (f)) != '\n')
00960 if (ch == EOF)
00961 break;
00962 }
00963 fclose (f);
00964 }
00965
00966
00967 map_list_ptr->map_list_next = CPP_OPTION (pfile, map_list);
00968 CPP_OPTION (pfile, map_list) = map_list_ptr;
00969
00970 return map_list_ptr->map_list_map;
00971 }
00972
00973
00974
00975 static char *
00976 remap_filename (pfile, name, loc)
00977 cpp_reader *pfile;
00978 char *name;
00979 struct search_path *loc;
00980 {
00981 struct file_name_map *map;
00982 const char *from, *p;
00983 char *dir;
00984
00985 if (! loc->name_map)
00986 {
00987
00988 char *dname = alloca (loc->len + 1);
00989 memcpy (dname, loc->name, loc->len);
00990 dname[loc->len] = '\0';
00991
00992 loc->name_map = read_name_map (pfile, dname);
00993 if (! loc->name_map)
00994 return name;
00995 }
00996
00997
00998 from = name + loc->len + 1;
00999
01000 for (map = loc->name_map; map; map = map->map_next)
01001 if (!strcmp (map->map_from, from))
01002 return map->map_to;
01003
01004
01005
01006
01007
01008 p = strrchr (name, '/');
01009 if (!p)
01010 return name;
01011
01012
01013 if (p == name)
01014 cpp_error (pfile, DL_ICE, "absolute file name in remap_filename");
01015
01016 dir = (char *) alloca (p - name + 1);
01017 memcpy (dir, name, p - name);
01018 dir[p - name] = '\0';
01019 from = p + 1;
01020
01021 for (map = read_name_map (pfile, dir); map; map = map->map_next)
01022 if (! strcmp (map->map_from, from))
01023 return map->map_to;
01024
01025 return name;
01026 }
01027
01028
01029
01030
01031
01032 static int
01033 remove_component_p (path)
01034 const char *path;
01035 {
01036 struct stat s;
01037 int result;
01038
01039 #ifdef HAVE_LSTAT
01040 result = lstat (path, &s);
01041 #else
01042 result = stat (path, &s);
01043 #endif
01044
01045
01046
01047
01048 if (result == 0)
01049 errno = 0;
01050
01051 return result == 0 && S_ISDIR (s.st_mode);
01052 }
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068 char *
01069 _cpp_simplify_pathname (path)
01070 char *path;
01071 {
01072 #ifndef VMS
01073 char *from, *to;
01074 char *base, *orig_base;
01075 int absolute = 0;
01076
01077 errno = 0;
01078
01079 if (*path == '\0')
01080 return path;
01081
01082 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
01083
01084 for (from = path; *from; from++)
01085 if (*from == '\\') *from = '/';
01086
01087
01088 if (ISALPHA (path[0]) && path[1] == ':')
01089 from = to = &path[2];
01090 else
01091 from = to = path;
01092 #else
01093 from = to = path;
01094 #endif
01095
01096
01097 if (*from == '/')
01098 {
01099 absolute = 1;
01100 to++;
01101 from++;
01102 if (*from == '/')
01103 {
01104 if (*++from == '/')
01105
01106 while (*++from == '/');
01107 else
01108
01109 to++;
01110 }
01111 }
01112
01113 base = orig_base = to;
01114 for (;;)
01115 {
01116 int move_base = 0;
01117
01118 while (*from == '/')
01119 from++;
01120
01121 if (*from == '\0')
01122 break;
01123
01124 if (*from == '.')
01125 {
01126 if (from[1] == '\0')
01127 break;
01128 if (from[1] == '/')
01129 {
01130 from += 2;
01131 continue;
01132 }
01133 else if (from[1] == '.' && (from[2] == '/' || from[2] == '\0'))
01134 {
01135
01136 if (absolute && orig_base == to)
01137 {
01138 from += 2;
01139 continue;
01140 }
01141
01142
01143 if (base != to && errno == 0)
01144 {
01145
01146 *to = '\0';
01147 if (remove_component_p (path))
01148 {
01149 while (to > base && *to != '/')
01150 to--;
01151 from += 2;
01152 continue;
01153 }
01154 }
01155 move_base = 1;
01156 }
01157 }
01158
01159
01160 if (to > orig_base)
01161 *to++ = '/';
01162
01163
01164 while (*from != '\0' && *from != '/')
01165 *to++ = *from++;
01166
01167 if (move_base)
01168 base = to;
01169 }
01170
01171
01172
01173 if (to == path)
01174 *to++ = '.';
01175 *to = '\0';
01176
01177 return path;
01178 #else
01179 errno = 0;
01180 return path;
01181 #endif
01182 }