1/* Part of CPP library. (include file handling) 2 Copyright (C) 1986, 87, 89, 92 - 95, 98, 1999 Free Software Foundation, Inc. 3 Written by Per Bothner, 1994. 4 Based on CCCP program by Paul Rubin, June 1986 5 Adapted to ANSI C, Richard Stallman, Jan 1987 6 Split out of cpplib.c, Zack Weinberg, Oct 1998 7 8This program is free software; you can redistribute it and/or modify it 9under the terms of the GNU General Public License as published by the 10Free Software Foundation; either version 2, or (at your option) any 11later version. 12 13This program is distributed in the hope that it will be useful, 14but WITHOUT ANY WARRANTY; without even the implied warranty of 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16GNU General Public License for more details. 17 18You should have received a copy of the GNU General Public License 19along with this program; if not, write to the Free Software 20Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 22 In other words, you are welcome to use, share and improve this program. 23 You are forbidden to forbid anyone else to use, share and improve 24 what you give them. Help stamp out software-hoarding! */ 25 26#include "config.h" 27#include "system.h" 28#include "cpplib.h" 29 30/* The entry points to this file are: find_include_file, finclude, 31 include_hash, append_include_chain, deps_output, and file_cleanup. 32 file_cleanup is only called through CPP_BUFFER(pfile)->cleanup, 33 so it's static anyway. */ 34 35static struct include_hash *redundant_include_p 36 PROTO ((cpp_reader *, 37 struct include_hash *, 38 struct file_name_list *)); 39static struct file_name_map *read_name_map PROTO ((cpp_reader *, 40 const char *)); 41static char *read_filename_string PROTO ((int, FILE *)); 42static char *remap_filename PROTO ((cpp_reader *, char *, 43 struct file_name_list *)); 44static long read_and_prescan PROTO ((cpp_reader *, cpp_buffer *, 45 int, size_t)); 46static struct file_name_list *actual_directory PROTO ((cpp_reader *, char *)); 47 48static void initialize_input_buffer PROTO ((cpp_reader *, int, 49 struct stat *)); 50 51#if 0 52static void hack_vms_include_specification PROTO ((char *)); 53#endif 54 55/* Windows does not natively support inodes, and neither does MSDOS. 56 VMS has non-numeric inodes. */ 57#ifdef VMS 58#define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a))) 59#elif (defined _WIN32 && !defined CYGWIN && ! defined (_UWIN)) \ 60 || defined __MSDOS__ 61#define INO_T_EQ(a, b) 0 62#else 63#define INO_T_EQ(a, b) ((a) == (b)) 64#endif 65 66/* Merge the four include chains together in the order quote, bracket, 67 system, after. Remove duplicate dirs (as determined by 68 INO_T_EQ()). The system_include and after_include chains are never 69 referred to again after this function; all access is through the 70 bracket_include path. 71 72 For the future: Check if the directory is empty (but 73 how?) and possibly preload the include hash. */ 74 75void 76merge_include_chains (opts) 77 struct cpp_options *opts; 78{ 79 struct file_name_list *prev, *cur, *other; 80 struct file_name_list *quote, *brack, *systm, *after; 81 struct file_name_list *qtail, *btail, *stail, *atail; 82 83 qtail = opts->pending->quote_tail; 84 btail = opts->pending->brack_tail; 85 stail = opts->pending->systm_tail; 86 atail = opts->pending->after_tail; 87 88 quote = opts->pending->quote_head; 89 brack = opts->pending->brack_head; 90 systm = opts->pending->systm_head; 91 after = opts->pending->after_head; 92 93 /* Paste together bracket, system, and after include chains. */ 94 if (stail) 95 stail->next = after; 96 else 97 systm = after; 98 if (btail) 99 btail->next = systm; 100 else 101 brack = systm; 102 103 /* This is a bit tricky. 104 First we drop dupes from the quote-include list. 105 Then we drop dupes from the bracket-include list. 106 Finally, if qtail and brack are the same directory, 107 we cut out qtail. 108 109 We can't just merge the lists and then uniquify them because 110 then we may lose directories from the <> search path that should 111 be there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however 112 safe to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written 113 -Ibar -I- -Ifoo -Iquux. 114 115 Note that this algorithm is quadratic in the number of -I switches, 116 which is acceptable since there aren't usually that many of them. */ 117 118 for (cur = quote, prev = NULL; cur; cur = cur->next) 119 { 120 for (other = quote; other != cur; other = other->next) 121 if (INO_T_EQ (cur->ino, other->ino) 122 && cur->dev == other->dev) 123 { 124 if (opts->verbose) 125 cpp_notice ("ignoring duplicate directory `%s'\n", cur->name); 126 127 prev->next = cur->next; 128 free (cur->name); 129 free (cur); 130 cur = prev; 131 break; 132 } 133 prev = cur; 134 } 135 qtail = prev; 136 137 for (cur = brack; cur; cur = cur->next) 138 { 139 for (other = brack; other != cur; other = other->next) 140 if (INO_T_EQ (cur->ino, other->ino) 141 && cur->dev == other->dev) 142 { 143 if (opts->verbose) 144 cpp_notice ("ignoring duplicate directory `%s'\n", cur->name); 145 146 prev->next = cur->next; 147 free (cur->name); 148 free (cur); 149 cur = prev; 150 break; 151 } 152 prev = cur; 153 } 154 155 if (quote) 156 { 157 if (INO_T_EQ (qtail->ino, brack->ino) && qtail->dev == brack->dev) 158 { 159 if (quote == qtail) 160 { 161 if (opts->verbose) 162 cpp_notice ("ignoring duplicate directory `%s'\n", 163 quote->name); 164 165 free (quote->name); 166 free (quote); 167 quote = brack; 168 } 169 else 170 { 171 cur = quote; 172 while (cur->next != qtail) 173 cur = cur->next; 174 cur->next = brack; 175 if (opts->verbose) 176 cpp_notice ("ignoring duplicate directory `%s'\n", 177 qtail->name); 178 179 free (qtail->name); 180 free (qtail); 181 } 182 } 183 else 184 qtail->next = brack; 185 } 186 else 187 quote = brack; 188 189 opts->quote_include = quote; 190 opts->bracket_include = brack; 191} 192 193/* Look up or add an entry to the table of all includes. This table 194 is indexed by the name as it appears in the #include line. The 195 ->next_this_file chain stores all different files with the same 196 #include name (there are at least three ways this can happen). The 197 hash function could probably be improved a bit. */ 198 199struct include_hash * 200include_hash (pfile, fname, add) 201 cpp_reader *pfile; 202 char *fname; 203 int add; 204{ 205 unsigned int hash = 0; 206 struct include_hash *l, *m; 207 char *f = fname; 208 209 while (*f) 210 hash += *f++; 211 212 l = pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE]; 213 m = 0; 214 for (; l; m = l, l = l->next) 215 if (!strcmp (l->nshort, fname)) 216 return l; 217 218 if (!add) 219 return 0; 220 221 l = (struct include_hash *) xmalloc (sizeof (struct include_hash)); 222 l->next = NULL; 223 l->next_this_file = NULL; 224 l->foundhere = NULL; 225 l->buf = NULL; 226 l->limit = NULL; 227 if (m) 228 m->next = l; 229 else 230 pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE] = l; 231 232 return l; 233} 234 235/* Return 0 if the file pointed to by IHASH has never been included before, 236 -1 if it has been included before and need not be again, 237 or a pointer to an IHASH entry which is the file to be reread. 238 "Never before" is with respect to the position in ILIST. 239 240 This will not detect redundancies involving odd uses of the 241 `current directory' rule for "" includes. They aren't quite 242 pathological, but I think they are rare enough not to worry about. 243 The simplest example is: 244 245 top.c: 246 #include "a/a.h" 247 #include "b/b.h" 248 249 a/a.h: 250 #include "../b/b.h" 251 252 and the problem is that for `current directory' includes, 253 ihash->foundhere is not on any of the global include chains, 254 so the test below (i->foundhere == l) may be false even when 255 the directories are in fact the same. */ 256 257static struct include_hash * 258redundant_include_p (pfile, ihash, ilist) 259 cpp_reader *pfile; 260 struct include_hash *ihash; 261 struct file_name_list *ilist; 262{ 263 struct file_name_list *l; 264 struct include_hash *i; 265 266 if (! ihash->foundhere) 267 return 0; 268 269 for (i = ihash; i; i = i->next_this_file) 270 for (l = ilist; l; l = l->next) 271 if (i->foundhere == l) 272 /* The control_macro works like this: If it's NULL, the file 273 is to be included again. If it's "", the file is never to 274 be included again. If it's a string, the file is not to be 275 included again if the string is the name of a defined macro. */ 276 return (i->control_macro 277 && (i->control_macro[0] == '\0' 278 || cpp_lookup (pfile, i->control_macro, -1, -1))) 279 ? (struct include_hash *)-1 : i; 280 281 return 0; 282} 283 284static int 285file_cleanup (pbuf, pfile) 286 cpp_buffer *pbuf; 287 cpp_reader *pfile; 288{ 289 if (pbuf->buf) 290 { 291 free (pbuf->buf); 292 pbuf->buf = 0; 293 } 294 if (pfile->system_include_depth) 295 pfile->system_include_depth--; 296 return 0; 297} 298 299/* Search for include file FNAME in the include chain starting at 300 SEARCH_START. Return -2 if this file doesn't need to be included 301 (because it was included already and it's marked idempotent), 302 -1 if an error occurred, or a file descriptor open on the file. 303 *IHASH is set to point to the include hash entry for this file, and 304 *BEFORE is 1 if the file was included before (but needs to be read 305 again). */ 306int 307find_include_file (pfile, fname, search_start, ihash, before) 308 cpp_reader *pfile; 309 char *fname; 310 struct file_name_list *search_start; 311 struct include_hash **ihash; 312 int *before; 313{ 314 struct file_name_list *l; 315 struct include_hash *ih, *jh; 316 int f, len; 317 char *name; 318 319 ih = include_hash (pfile, fname, 1); 320 jh = redundant_include_p (pfile, ih, 321 fname[0] == '/' ? ABSOLUTE_PATH : search_start); 322 323 if (jh != 0) 324 { 325 *before = 1; 326 *ihash = jh; 327 328 if (jh == (struct include_hash *)-1) 329 return -2; 330 else 331 return open (jh->name, O_RDONLY, 0666); 332 } 333 334 if (ih->foundhere) 335 /* A file is already known by this name, but it's not the same file. 336 Allocate another include_hash block and add it to the next_this_file 337 chain. */ 338 { 339 jh = (struct include_hash *)xmalloc (sizeof (struct include_hash)); 340 while (ih->next_this_file) ih = ih->next_this_file; 341 342 ih->next_this_file = jh; 343 jh = ih; 344 ih = ih->next_this_file; 345 346 ih->next = NULL; 347 ih->next_this_file = NULL; 348 ih->buf = NULL; 349 ih->limit = NULL; 350 } 351 *before = 0; 352 *ihash = ih; 353 ih->nshort = xstrdup (fname); 354 ih->control_macro = NULL; 355 356 /* If the pathname is absolute, just open it. */ 357 if (fname[0] == '/') 358 { 359 ih->foundhere = ABSOLUTE_PATH; 360 ih->name = ih->nshort; 361 return open (ih->name, O_RDONLY, 0666); 362 } 363 364 /* Search directory path, trying to open the file. */ 365 366 len = strlen (fname); 367 name = xmalloc (len + pfile->max_include_len + 2 + INCLUDE_LEN_FUDGE); 368 369 for (l = search_start; l; l = l->next) 370 { 371 bcopy (l->name, name, l->nlen); 372 name[l->nlen] = '/'; 373 strcpy (&name[l->nlen+1], fname); 374 simplify_pathname (name); 375 if (CPP_OPTIONS (pfile)->remap) 376 name = remap_filename (pfile, name, l); 377 378 f = open (name, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666); 379#ifdef EACCES 380 if (f == -1 && errno == EACCES) 381 { 382 cpp_error(pfile, "included file `%s' exists but is not readable", 383 name); 384 return -1; 385 } 386#endif 387 388 if (f >= 0) 389 { 390 ih->foundhere = l; 391 ih->name = xrealloc (name, strlen (name)+1); 392 return f; 393 } 394 } 395 396 if (jh) 397 { 398 jh->next_this_file = NULL; 399 free (ih); 400 } 401 free (name); 402 *ihash = (struct include_hash *)-1; 403 return -1; 404} 405 406/* The file_name_map structure holds a mapping of file names for a 407 particular directory. This mapping is read from the file named 408 FILE_NAME_MAP_FILE in that directory. Such a file can be used to 409 map filenames on a file system with severe filename restrictions, 410 such as DOS. The format of the file name map file is just a series 411 of lines with two tokens on each line. The first token is the name 412 to map, and the second token is the actual name to use. */ 413 414struct file_name_map 415{ 416 struct file_name_map *map_next; 417 char *map_from; 418 char *map_to; 419}; 420 421#define FILE_NAME_MAP_FILE "header.gcc" 422 423/* Read a space delimited string of unlimited length from a stdio 424 file. */ 425 426static char * 427read_filename_string (ch, f) 428 int ch; 429 FILE *f; 430{ 431 char *alloc, *set; 432 int len; 433 434 len = 20; 435 set = alloc = xmalloc (len + 1); 436 if (! is_space[ch]) 437 { 438 *set++ = ch; 439 while ((ch = getc (f)) != EOF && ! is_space[ch]) 440 { 441 if (set - alloc == len) 442 { 443 len *= 2; 444 alloc = xrealloc (alloc, len + 1); 445 set = alloc + len / 2; 446 } 447 *set++ = ch; 448 } 449 } 450 *set = '\0'; 451 ungetc (ch, f); 452 return alloc; 453} 454 455/* This structure holds a linked list of file name maps, one per directory. */ 456 457struct file_name_map_list 458{ 459 struct file_name_map_list *map_list_next; 460 char *map_list_name; 461 struct file_name_map *map_list_map; 462}; 463 464/* Read the file name map file for DIRNAME. */ 465 466static struct file_name_map * 467read_name_map (pfile, dirname) 468 cpp_reader *pfile; 469 const char *dirname; 470{ 471 register struct file_name_map_list *map_list_ptr; 472 char *name; 473 FILE *f; 474 475 for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr; 476 map_list_ptr = map_list_ptr->map_list_next) 477 if (! strcmp (map_list_ptr->map_list_name, dirname)) 478 return map_list_ptr->map_list_map; 479 480 map_list_ptr = ((struct file_name_map_list *) 481 xmalloc (sizeof (struct file_name_map_list))); 482 map_list_ptr->map_list_name = xstrdup (dirname); 483 484 name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2); 485 strcpy (name, dirname); 486 if (*dirname) 487 strcat (name, "/"); 488 strcat (name, FILE_NAME_MAP_FILE); 489 f = fopen (name, "r"); 490 if (!f) 491 map_list_ptr->map_list_map = (struct file_name_map *)-1; 492 else 493 { 494 int ch; 495 int dirlen = strlen (dirname); 496 497 while ((ch = getc (f)) != EOF) 498 { 499 char *from, *to; 500 struct file_name_map *ptr; 501 502 if (is_space[ch]) 503 continue; 504 from = read_filename_string (ch, f); 505 while ((ch = getc (f)) != EOF && is_hor_space[ch]) 506 ; 507 to = read_filename_string (ch, f); 508 509 ptr = ((struct file_name_map *) 510 xmalloc (sizeof (struct file_name_map))); 511 ptr->map_from = from; 512 513 /* Make the real filename absolute. */ 514 if (*to == '/') 515 ptr->map_to = to; 516 else 517 { 518 ptr->map_to = xmalloc (dirlen + strlen (to) + 2); 519 strcpy (ptr->map_to, dirname); 520 ptr->map_to[dirlen] = '/'; 521 strcpy (ptr->map_to + dirlen + 1, to); 522 free (to); 523 } 524 525 ptr->map_next = map_list_ptr->map_list_map; 526 map_list_ptr->map_list_map = ptr; 527 528 while ((ch = getc (f)) != '\n') 529 if (ch == EOF) 530 break; 531 } 532 fclose (f); 533 } 534 535 map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list; 536 CPP_OPTIONS (pfile)->map_list = map_list_ptr; 537 538 return map_list_ptr->map_list_map; 539} 540 541/* Remap NAME based on the file_name_map (if any) for LOC. */ 542 543static char * 544remap_filename (pfile, name, loc) 545 cpp_reader *pfile; 546 char *name; 547 struct file_name_list *loc; 548{ 549 struct file_name_map *map; 550 const char *from, *p, *dir; 551 552 if (! loc->name_map) 553 loc->name_map = read_name_map (pfile, 554 loc->name 555 ? loc->name : "."); 556 557 if (loc->name_map == (struct file_name_map *)-1) 558 return name; 559 560 from = name + strlen (loc->name) + 1; 561 562 for (map = loc->name_map; map; map = map->map_next) 563 if (!strcmp (map->map_from, from)) 564 return map->map_to; 565 566 /* Try to find a mapping file for the particular directory we are 567 looking in. Thus #include <sys/types.h> will look up sys/types.h 568 in /usr/include/header.gcc and look up types.h in 569 /usr/include/sys/header.gcc. */ 570 p = rindex (name, '/'); 571 if (!p) 572 p = name; 573 if (loc && loc->name 574 && strlen (loc->name) == (size_t) (p - name) 575 && !strncmp (loc->name, name, p - name)) 576 /* FILENAME is in SEARCHPTR, which we've already checked. */ 577 return name; 578 579 if (p == name) 580 { 581 dir = "."; 582 from = name; 583 } 584 else 585 { 586 char * newdir = (char *) alloca (p - name + 1); 587 bcopy (name, newdir, p - name); 588 newdir[p - name] = '\0'; 589 dir = newdir; 590 from = p + 1; 591 } 592 593 for (map = read_name_map (pfile, dir); map; map = map->map_next) 594 if (! strcmp (map->map_from, name)) 595 return map->map_to; 596 597 return name; 598} 599 600/* Read the contents of FD into the buffer on the top of PFILE's stack. 601 IHASH points to the include hash entry for the file associated with 602 FD. 603 604 The caller is responsible for the cpp_push_buffer. */ 605 606int 607finclude (pfile, fd, ihash) 608 cpp_reader *pfile; 609 int fd; 610 struct include_hash *ihash; 611{ 612 struct stat st; 613 size_t st_size; 614 long length; 615 cpp_buffer *fp; 616 617 if (fstat (fd, &st) < 0) 618 goto perror_fail; 619 if (fcntl (fd, F_SETFL, 0) == -1) /* turn off nonblocking mode */ 620 goto perror_fail; 621 622 fp = CPP_BUFFER (pfile); 623 624 /* If fd points to a plain file, we know how big it is, so we can 625 allocate the buffer all at once. If fd is a pipe or terminal, we 626 can't. Most C source files are 4k or less, so we guess that. If 627 fd is something weird, like a block device or a directory, we 628 don't want to read it at all. 629 630 Unfortunately, different systems use different st.st_mode values 631 for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and 632 zero the entire struct stat except a couple fields. Hence the 633 mess below. 634 635 In all cases, read_and_prescan will resize the buffer if it 636 turns out there's more data than we thought. */ 637 638 if (S_ISREG (st.st_mode)) 639 { 640 /* off_t might have a wider range than size_t - in other words, 641 the max size of a file might be bigger than the address 642 space. We can't handle a file that large. (Anyone with 643 a single source file bigger than 4GB needs to rethink 644 their coding style.) */ 645 st_size = (size_t) st.st_size; 646 if ((unsigned HOST_WIDEST_INT) st_size 647 != (unsigned HOST_WIDEST_INT) st.st_size) 648 { 649 cpp_error (pfile, "file `%s' is too large", ihash->name); 650 goto fail; 651 } 652 } 653 else if (S_ISFIFO (st.st_mode) || S_ISSOCK (st.st_mode) 654 /* Permit any kind of character device: the sensible ones are 655 ttys and /dev/null, but weeding out the others is too hard. */ 656 || S_ISCHR (st.st_mode) 657 /* Some 4.x (x<4) derivatives have a bug that makes fstat() of a 658 socket or pipe return a stat struct with most fields zeroed. */ 659 || (st.st_mode == 0 && st.st_nlink == 0 && st.st_size == 0)) 660 { 661 /* Cannot get its file size before reading. 4k is a decent 662 first guess. */ 663 st_size = 4096; 664 } 665 else 666 { 667 cpp_error (pfile, "`%s' is not a file, pipe, or tty", ihash->name); 668 goto fail; 669 } 670 671 if (pfile->input_buffer == NULL) 672 initialize_input_buffer (pfile, fd, &st); 673 674 /* Read the file, converting end-of-line characters and trigraphs 675 (if enabled). */ 676 fp->ihash = ihash; 677 fp->nominal_fname = fp->fname = ihash->name; 678 length = read_and_prescan (pfile, fp, fd, st_size); 679 if (length < 0) 680 goto fail; 681 if (length == 0) 682 ihash->control_macro = ""; /* never re-include */ 683 684 close (fd); 685 fp->rlimit = fp->alimit = fp->buf + length; 686 fp->cur = fp->buf; 687 if (ihash->foundhere != ABSOLUTE_PATH) 688 fp->system_header_p = ihash->foundhere->sysp; 689 fp->lineno = 1; 690 fp->colno = 1; 691 fp->line_base = fp->buf; 692 fp->cleanup = file_cleanup; 693 694 /* The ->actual_dir field is only used when ignore_srcdir is not in effect; 695 see do_include */ 696 if (!CPP_OPTIONS (pfile)->ignore_srcdir) 697 fp->actual_dir = actual_directory (pfile, fp->fname); 698 699 pfile->input_stack_listing_current = 0; 700 return 1; 701 702 perror_fail: 703 cpp_error_from_errno (pfile, ihash->name); 704 fail: 705 cpp_pop_buffer (pfile); 706 close (fd); 707 return 0; 708} 709 710/* Given a path FNAME, extract the directory component and place it 711 onto the actual_dirs list. Return a pointer to the allocated 712 file_name_list structure. These structures are used to implement 713 current-directory "" include searching. */ 714 715static struct file_name_list * 716actual_directory (pfile, fname) 717 cpp_reader *pfile; 718 char *fname; 719{ 720 char *last_slash, *dir; 721 size_t dlen; 722 struct file_name_list *x; 723 724 dir = xstrdup (fname); 725 last_slash = rindex (dir, '/'); 726 if (last_slash) 727 { 728 if (last_slash == dir) 729 { 730 dlen = 1; 731 last_slash[1] = '\0'; 732 } 733 else 734 { 735 dlen = last_slash - dir; 736 *last_slash = '\0'; 737 } 738 } 739 else 740 { 741 dir[0] = '.'; 742 dir[1] = '\0'; 743 dlen = 1; 744 } 745 746 if (dlen > pfile->max_include_len) 747 pfile->max_include_len = dlen; 748 749 for (x = pfile->actual_dirs; x; x = x->alloc) 750 if (!strcmp (x->name, dir)) 751 { 752 free (dir); 753 return x; 754 } 755 756 /* Not found, make a new one. */ 757 x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); 758 x->name = dir; 759 x->nlen = dlen; 760 x->next = CPP_OPTIONS (pfile)->quote_include; 761 x->alloc = pfile->actual_dirs; 762 x->sysp = CPP_BUFFER (pfile)->system_header_p; 763 x->name_map = NULL; 764 765 pfile->actual_dirs = x; 766 return x; 767} 768 769/* Determine the current line and column. Used only by read_and_prescan. */ 770static void 771find_position (start, limit, linep, colp) 772 U_CHAR *start; 773 U_CHAR *limit; 774 unsigned long *linep; 775 unsigned long *colp; 776{ 777 unsigned long line = *linep, col = 0; 778 while (start < limit) 779 { 780 U_CHAR ch = *start++; 781 if (ch == '\n' || ch == '\r') 782 line++, col = 1; 783 else 784 col++; 785 } 786 *linep = line, *colp = col; 787} 788 789/* Read the entire contents of file DESC into buffer BUF. LEN is how 790 much memory to allocate initially; more will be allocated if 791 necessary. Convert end-of-line markers (\n, \r, \r\n, \n\r) to 792 canonical form (\n). If enabled, convert and/or warn about 793 trigraphs. Convert backslash-newline to a one-character escape 794 (\r) and remove it from "embarrassing" places (i.e. the middle of a 795 token). If there is no newline at the end of the file, add one and 796 warn. Returns -1 on failure, or the actual length of the data to 797 be scanned. 798 799 This function does a lot of work, and can be a serious performance 800 bottleneck. It has been tuned heavily; make sure you understand it 801 before hacking. The common case - no trigraphs, Unix style line 802 breaks, backslash-newline set off by whitespace, newline at EOF - 803 has been optimized at the expense of the others. The performance 804 penalty for DOS style line breaks (\r\n) is about 15%. 805 806 Warnings lose particularly heavily since we have to determine the 807 line number, which involves scanning from the beginning of the file 808 or from the last warning. The penalty for the absence of a newline 809 at the end of reload1.c is about 60%. (reload1.c is 329k.) 810 811 If your file has more than one kind of end-of-line marker, you 812 will get messed-up line numbering. */ 813 814/* Table of characters that can't be handled in the inner loop. 815 Keep these contiguous to optimize the performance of the code generated 816 for the switch that uses them. */ 817#define SPECCASE_EMPTY 0 818#define SPECCASE_NUL 1 819#define SPECCASE_CR 2 820#define SPECCASE_BACKSLASH 3 821#define SPECCASE_QUESTION 4 822 823static long 824read_and_prescan (pfile, fp, desc, len) 825 cpp_reader *pfile; 826 cpp_buffer *fp; 827 int desc; 828 size_t len; 829{ 830 U_CHAR *buf = (U_CHAR *) xmalloc (len); 831 U_CHAR *ip, *op, *line_base; 832 U_CHAR *ibase; 833 U_CHAR *speccase = pfile->input_speccase; 834 unsigned long line; 835 unsigned int deferred_newlines; 836 int count; 837 size_t offset; 838 839 offset = 0; 840 op = buf; 841 line_base = buf; 842 line = 1; 843 ibase = pfile->input_buffer + 2; 844 deferred_newlines = 0; 845 846 for (;;) 847 { 848 read_next: 849 850 count = read (desc, pfile->input_buffer + 2, pfile->input_buffer_len); 851 if (count < 0) 852 goto error; 853 else if (count == 0) 854 break; 855 856 offset += count; 857 ip = ibase; 858 ibase = pfile->input_buffer + 2; 859 ibase[count] = ibase[count+1] = '\0'; 860 861 if (offset > len) 862 { 863 size_t delta_op; 864 size_t delta_line_base; 865 len *= 2; 866 if (offset > len) 867 /* len overflowed. 868 This could happen if the file is larger than half the 869 maximum address space of the machine. */ 870 goto too_big; 871 872 delta_op = op - buf; 873 delta_line_base = line_base - buf; 874 buf = (U_CHAR *) xrealloc (buf, len); 875 op = buf + delta_op; 876 line_base = buf + delta_line_base; 877 } 878 879 for (;;) 880 { 881 unsigned int span = 0; 882 883 /* Deal with \-newline in the middle of a token. */ 884 if (deferred_newlines) 885 { 886 while (speccase[ip[span]] == SPECCASE_EMPTY 887 && ip[span] != '\n' 888 && ip[span] != '\t' 889 && ip[span] != ' ') 890 span++; 891 memcpy (op, ip, span); 892 op += span; 893 ip += span; 894 if (*ip == '\n' || *ip == '\t' 895 || *ip == ' ' || *ip == ' ') 896 while (deferred_newlines) 897 deferred_newlines--, *op++ = '\r'; 898 span = 0; 899 } 900 901 /* Copy as much as we can without special treatment. */ 902 while (speccase[ip[span]] == SPECCASE_EMPTY) span++; 903 memcpy (op, ip, span); 904 op += span; 905 ip += span; 906 907 switch (speccase[*ip++]) 908 { 909 case SPECCASE_NUL: /* \0 */ 910 ibase[-1] = op[-1]; 911 goto read_next; 912 913 case SPECCASE_CR: /* \r */ 914 if (*ip == '\n') 915 ip++; 916 else if (*ip == '\0') 917 { 918 *--ibase = '\r'; 919 goto read_next; 920 } 921 else if (ip[-2] == '\n') 922 continue; 923 *op++ = '\n'; 924 break; 925 926 case SPECCASE_BACKSLASH: /* \ */ 927 backslash: 928 { 929 /* If we're at the end of the intermediate buffer, 930 we have to shift the backslash down to the start 931 and come back next pass. */ 932 if (*ip == '\0') 933 { 934 *--ibase = '\\'; 935 goto read_next; 936 } 937 else if (*ip == '\n') 938 { 939 ip++; 940 if (*ip == '\r') ip++; 941 if (*ip == '\n' || *ip == '\t' || *ip == ' ') 942 *op++ = '\r'; 943 else if (op[-1] == '\t' || op[-1] == ' ' 944 || op[-1] == '\r' || op[-1] == '\n') 945 *op++ = '\r'; 946 else 947 deferred_newlines++; 948 line++; 949 line_base = op; 950 } 951 else if (*ip == '\r') 952 { 953 ip++; 954 if (*ip == '\n') ip++; 955 else if (*ip == '\0') 956 { 957 *--ibase = '\r'; 958 *--ibase = '\\'; 959 goto read_next; 960 } 961 else if (*ip == '\r' || *ip == '\t' || *ip == ' ') 962 *op++ = '\r'; 963 else 964 deferred_newlines++; 965 line++; 966 line_base = op; 967 } 968 else 969 *op++ = '\\'; 970 } 971 break; 972 973 case SPECCASE_QUESTION: /* ? */ 974 { 975 unsigned int d; 976 /* If we're at the end of the intermediate buffer, 977 we have to shift the ?'s down to the start and 978 come back next pass. */ 979 d = ip[0]; 980 if (d == '\0') 981 { 982 *--ibase = '?'; 983 goto read_next; 984 } 985 if (d != '?') 986 { 987 *op++ = '?'; 988 break; 989 } 990 d = ip[1]; 991 if (d == '\0') 992 { 993 *--ibase = '?'; 994 *--ibase = '?'; 995 goto read_next; 996 } 997 if (!trigraph_table[d]) 998 { 999 *op++ = '?'; 1000 break; 1001 } 1002 1003 if (CPP_OPTIONS (pfile)->warn_trigraphs) 1004 { 1005 unsigned long col; 1006 find_position (line_base, op, &line, &col); 1007 line_base = op - col; 1008 cpp_warning_with_line (pfile, line, col, 1009 "trigraph ??%c encountered", d); 1010 } 1011 if (CPP_OPTIONS (pfile)->trigraphs) 1012 { 1013 if (trigraph_table[d] == '\\') 1014 goto backslash; 1015 else 1016 *op++ = trigraph_table[d]; 1017 } 1018 else 1019 { 1020 *op++ = '?'; 1021 *op++ = '?'; 1022 *op++ = d; 1023 } 1024 ip += 2; 1025 } 1026 } 1027 } 1028 } 1029 1030 if (offset == 0) 1031 return 0; 1032 1033 /* Deal with pushed-back chars at true EOF. 1034 This may be any of: ?? ? \ \r \n \\r \\n. 1035 \r must become \n, \\r or \\n must become \r. 1036 We know we have space already. */ 1037 if (ibase == pfile->input_buffer) 1038 { 1039 if (*ibase == '?') 1040 { 1041 *op++ = '?'; 1042 *op++ = '?'; 1043 } 1044 else 1045 *op++ = '\r'; 1046 } 1047 else if (ibase == pfile->input_buffer + 1) 1048 { 1049 if (*ibase == '\r') 1050 *op++ = '\n'; 1051 else 1052 *op++ = *ibase; 1053 } 1054 1055 if (op[-1] != '\n') 1056 { 1057 unsigned long col; 1058 find_position (line_base, op, &line, &col); 1059 cpp_warning_with_line (pfile, line, col, "no newline at end of file\n"); 1060 if (offset + 1 > len) 1061 { 1062 len += 1; 1063 if (offset + 1 > len) 1064 goto too_big; 1065 buf = (U_CHAR *) xrealloc (buf, len); 1066 op = buf + offset; 1067 } 1068 *op++ = '\n'; 1069 } 1070 1071 fp->buf = ((len - offset < 20) ? buf : (U_CHAR *)xrealloc (buf, op - buf)); 1072 return op - buf; 1073 1074 too_big: 1075 cpp_error (pfile, "file is too large (>%lu bytes)\n", (unsigned long)offset); 1076 free (buf); 1077 return -1; 1078 1079 error: 1080 cpp_error_from_errno (pfile, fp->fname); 1081 free (buf); 1082 return -1; 1083} 1084 1085/* Initialize the `input_buffer' and `input_speccase' tables. 1086 These are only used by read_and_prescan, but they're large and 1087 somewhat expensive to set up, so we want them allocated once for 1088 the duration of the cpp run. */ 1089 1090static void 1091initialize_input_buffer (pfile, fd, st) 1092 cpp_reader *pfile; 1093 int fd; 1094 struct stat *st; 1095{ 1096 long pipe_buf; 1097 U_CHAR *tmp; 1098 1099 /* Table of characters that cannot be handled by the 1100 read_and_prescan inner loop. The number of non-EMPTY entries 1101 should be as small as humanly possible. */ 1102 1103 tmp = xmalloc (1 << CHAR_BIT); 1104 memset (tmp, SPECCASE_EMPTY, 1 << CHAR_BIT); 1105 tmp['\0'] = SPECCASE_NUL; 1106 tmp['\r'] = SPECCASE_CR; 1107 tmp['\\'] = SPECCASE_BACKSLASH; 1108 if (CPP_OPTIONS (pfile)->trigraphs || CPP_OPTIONS (pfile)->warn_trigraphs) 1109 tmp['?'] = SPECCASE_QUESTION; 1110 1111 pfile->input_speccase = tmp; 1112 1113 /* Determine the appropriate size for the input buffer. Normal C 1114 source files are smaller than eight K. If we are reading a pipe, 1115 we want to make sure the input buffer is bigger than the kernel's 1116 pipe buffer. */ 1117 pipe_buf = -1; 1118 1119 if (! S_ISREG (st->st_mode)) 1120 { 1121#ifdef _PC_PIPE_BUF 1122 pipe_buf = fpathconf (fd, _PC_PIPE_BUF); 1123#endif 1124 if (pipe_buf == -1) 1125 { 1126#ifdef PIPE_BUF 1127 pipe_buf = PIPE_BUF; 1128#else 1129 pipe_buf = 8192; 1130#endif 1131 } 1132 } 1133 1134 if (pipe_buf < 8192) 1135 pipe_buf = 8192; 1136 /* PIPE_BUF bytes of buffer proper, 2 to detect running off the end 1137 without address arithmetic all the time, and 2 for pushback in 1138 the case there's a potential trigraph or end-of-line digraph at 1139 the end of a block. */ 1140 1141 tmp = xmalloc (pipe_buf + 2 + 2); 1142 pfile->input_buffer = tmp; 1143 pfile->input_buffer_len = pipe_buf; 1144} 1145 1146/* Add output to `deps_buffer' for the -M switch. 1147 STRING points to the text to be output. 1148 SPACER is ':' for targets, ' ' for dependencies, zero for text 1149 to be inserted literally. */ 1150 1151void 1152deps_output (pfile, string, spacer) 1153 cpp_reader *pfile; 1154 char *string; 1155 int spacer; 1156{ 1157 int size; 1158 int cr = 0; 1159 1160 if (!*string) 1161 return; 1162 1163 size = strlen (string); 1164 1165#ifndef MAX_OUTPUT_COLUMNS 1166#define MAX_OUTPUT_COLUMNS 72 1167#endif 1168 if (pfile->deps_column > 0 1169 && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS) 1170 { 1171 cr = 5; 1172 pfile->deps_column = 0; 1173 } 1174 1175 if (pfile->deps_size + size + cr + 8 > pfile->deps_allocated_size) 1176 { 1177 pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2; 1178 pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer, 1179 pfile->deps_allocated_size); 1180 } 1181 1182 if (cr) 1183 { 1184 bcopy (" \\\n ", &pfile->deps_buffer[pfile->deps_size], 5); 1185 pfile->deps_size += 5; 1186 } 1187 1188 if (spacer == ' ' && pfile->deps_column > 0) 1189 pfile->deps_buffer[pfile->deps_size++] = ' '; 1190 bcopy (string, &pfile->deps_buffer[pfile->deps_size], size); 1191 pfile->deps_size += size; 1192 pfile->deps_column += size; 1193 if (spacer == ':') 1194 pfile->deps_buffer[pfile->deps_size++] = ':'; 1195 pfile->deps_buffer[pfile->deps_size] = 0; 1196} 1197 1198/* Simplify a path name in place, deleting redundant components. This 1199 reduces OS overhead and guarantees that equivalent paths compare 1200 the same (modulo symlinks). 1201 1202 Transforms made: 1203 foo/bar/../quux foo/quux 1204 foo/./bar foo/bar 1205 foo//bar foo/bar 1206 /../quux /quux 1207 //quux //quux (POSIX allows leading // as a namespace escape) 1208 1209 Guarantees no trailing slashes. All transforms reduce the length 1210 of the string. 1211 */ 1212void 1213simplify_pathname (path) 1214 char *path; 1215{ 1216 char *from, *to; 1217 char *base; 1218 int absolute = 0; 1219 1220#if defined (HAVE_DOS_BASED_FILE_SYSTEM) 1221 /* Convert all backslashes to slashes. */ 1222 for (from = path; *from; from++) 1223 if (*from == '\\') *from = '/'; 1224 1225 /* Skip over leading drive letter if present. */ 1226 if (ISALPHA (path[0]) && path[1] == ':') 1227 from = to = &path[2]; 1228 else 1229 from = to = path; 1230#else 1231 from = to = path; 1232#endif 1233 1234 /* Remove redundant initial /s. */ 1235 if (*from == '/') 1236 { 1237 absolute = 1; 1238 to++; 1239 from++; 1240 if (*from == '/') 1241 { 1242 if (*++from == '/') 1243 /* 3 or more initial /s are equivalent to 1 /. */ 1244 while (*++from == '/'); 1245 else 1246 /* On some hosts // differs from /; Posix allows this. */ 1247 to++; 1248 } 1249 } 1250 base = to; 1251 1252 for (;;) 1253 { 1254 while (*from == '/') 1255 from++; 1256 1257 if (from[0] == '.' && from[1] == '/') 1258 from += 2; 1259 else if (from[0] == '.' && from[1] == '\0') 1260 goto done; 1261 else if (from[0] == '.' && from[1] == '.' && from[2] == '/') 1262 { 1263 if (base == to) 1264 { 1265 if (absolute) 1266 from += 3; 1267 else 1268 { 1269 *to++ = *from++; 1270 *to++ = *from++; 1271 *to++ = *from++; 1272 base = to; 1273 } 1274 } 1275 else 1276 { 1277 to -= 2; 1278 while (to > base && *to != '/') to--; 1279 if (*to == '/') 1280 to++; 1281 from += 3; 1282 } 1283 } 1284 else if (from[0] == '.' && from[1] == '.' && from[2] == '\0') 1285 { 1286 if (base == to) 1287 { 1288 if (!absolute) 1289 { 1290 *to++ = *from++; 1291 *to++ = *from++; 1292 } 1293 } 1294 else 1295 { 1296 to -= 2; 1297 while (to > base && *to != '/') to--; 1298 if (*to == '/') 1299 to++; 1300 } 1301 goto done; 1302 } 1303 else 1304 /* Copy this component and trailing /, if any. */ 1305 while ((*to++ = *from++) != '/') 1306 { 1307 if (!to[-1]) 1308 { 1309 to--; 1310 goto done; 1311 } 1312 } 1313 1314 } 1315 1316 done: 1317 /* Trim trailing slash */ 1318 if (to[0] == '/' && (!absolute || to > path+1)) 1319 to--; 1320 1321 /* Change the empty string to "." so that stat() on the result 1322 will always work. */ 1323 if (to == path) 1324 *to++ = '.'; 1325 1326 *to = '\0'; 1327 1328 return; 1329} 1330 1331/* It is not clear when this should be used if at all, so I've 1332 disabled it until someone who understands VMS can look at it. */ 1333#if 0 1334 1335/* Under VMS we need to fix up the "include" specification filename. 1336 1337 Rules for possible conversions 1338 1339 fullname tried paths 1340 1341 name name 1342 ./dir/name [.dir]name 1343 /dir/name dir:name 1344 /name [000000]name, name 1345 dir/name dir:[000000]name, dir:name, dir/name 1346 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name 1347 path:/name path:[000000]name, path:name 1348 path:/dir/name path:[000000.dir]name, path:[dir]name 1349 path:dir/name path:[dir]name 1350 [path]:[dir]name [path.dir]name 1351 path/[dir]name [path.dir]name 1352 1353 The path:/name input is constructed when expanding <> includes. */ 1354 1355 1356static void 1357hack_vms_include_specification (fullname) 1358 char *fullname; 1359{ 1360 register char *basename, *unixname, *local_ptr, *first_slash; 1361 int f, check_filename_before_returning, must_revert; 1362 char Local[512]; 1363 1364 check_filename_before_returning = 0; 1365 must_revert = 0; 1366 /* See if we can find a 1st slash. If not, there's no path information. */ 1367 first_slash = index (fullname, '/'); 1368 if (first_slash == 0) 1369 return 0; /* Nothing to do!!! */ 1370 1371 /* construct device spec if none given. */ 1372 1373 if (index (fullname, ':') == 0) 1374 { 1375 1376 /* If fullname has a slash, take it as device spec. */ 1377 1378 if (first_slash == fullname) 1379 { 1380 first_slash = index (fullname+1, '/'); /* 2nd slash ? */ 1381 if (first_slash) 1382 *first_slash = ':'; /* make device spec */ 1383 for (basename = fullname; *basename != 0; basename++) 1384 *basename = *(basename+1); /* remove leading slash */ 1385 } 1386 else if ((first_slash[-1] != '.') /* keep ':/', './' */ 1387 && (first_slash[-1] != ':') 1388 && (first_slash[-1] != ']')) /* or a vms path */ 1389 { 1390 *first_slash = ':'; 1391 } 1392 else if ((first_slash[1] == '[') /* skip './' in './[dir' */ 1393 && (first_slash[-1] == '.')) 1394 fullname += 2; 1395 } 1396 1397 /* Get part after first ':' (basename[-1] == ':') 1398 or last '/' (basename[-1] == '/'). */ 1399 1400 basename = base_name (fullname); 1401 1402 local_ptr = Local; /* initialize */ 1403 1404 /* We are trying to do a number of things here. First of all, we are 1405 trying to hammer the filenames into a standard format, such that later 1406 processing can handle them. 1407 1408 If the file name contains something like [dir.], then it recognizes this 1409 as a root, and strips the ".]". Later processing will add whatever is 1410 needed to get things working properly. 1411 1412 If no device is specified, then the first directory name is taken to be 1413 a device name (or a rooted logical). */ 1414 1415 /* Point to the UNIX filename part (which needs to be fixed!) 1416 but skip vms path information. 1417 [basename != fullname since first_slash != 0]. */ 1418 1419 if ((basename[-1] == ':') /* vms path spec. */ 1420 || (basename[-1] == ']') 1421 || (basename[-1] == '>')) 1422 unixname = basename; 1423 else 1424 unixname = fullname; 1425 1426 if (*unixname == '/') 1427 unixname++; 1428 1429 /* If the directory spec is not rooted, we can just copy 1430 the UNIX filename part and we are done. */ 1431 1432 if (((basename - fullname) > 1) 1433 && ( (basename[-1] == ']') 1434 || (basename[-1] == '>'))) 1435 { 1436 if (basename[-2] != '.') 1437 { 1438 1439 /* The VMS part ends in a `]', and the preceding character is not a `.'. 1440 -> PATH]:/name (basename = '/name', unixname = 'name') 1441 We strip the `]', and then splice the two parts of the name in the 1442 usual way. Given the default locations for include files in cccp.c, 1443 we will only use this code if the user specifies alternate locations 1444 with the /include (-I) switch on the command line. */ 1445 1446 basename -= 1; /* Strip "]" */ 1447 unixname--; /* backspace */ 1448 } 1449 else 1450 { 1451 1452 /* The VMS part has a ".]" at the end, and this will not do. Later 1453 processing will add a second directory spec, and this would be a syntax 1454 error. Thus we strip the ".]", and thus merge the directory specs. 1455 We also backspace unixname, so that it points to a '/'. This inhibits the 1456 generation of the 000000 root directory spec (which does not belong here 1457 in this case). */ 1458 1459 basename -= 2; /* Strip ".]" */ 1460 unixname--; /* backspace */ 1461 } 1462 } 1463 1464 else 1465 1466 { 1467 1468 /* We drop in here if there is no VMS style directory specification yet. 1469 If there is no device specification either, we make the first dir a 1470 device and try that. If we do not do this, then we will be essentially 1471 searching the users default directory (as if they did a #include "asdf.h"). 1472 1473 Then all we need to do is to push a '[' into the output string. Later 1474 processing will fill this in, and close the bracket. */ 1475 1476 if ((unixname != fullname) /* vms path spec found. */ 1477 && (basename[-1] != ':')) 1478 *local_ptr++ = ':'; /* dev not in spec. take first dir */ 1479 1480 *local_ptr++ = '['; /* Open the directory specification */ 1481 } 1482 1483 if (unixname == fullname) /* no vms dir spec. */ 1484 { 1485 must_revert = 1; 1486 if ((first_slash != 0) /* unix dir spec. */ 1487 && (*unixname != '/') /* not beginning with '/' */ 1488 && (*unixname != '.')) /* or './' or '../' */ 1489 *local_ptr++ = '.'; /* dir is local ! */ 1490 } 1491 1492 /* at this point we assume that we have the device spec, and (at least 1493 the opening "[" for a directory specification. We may have directories 1494 specified already. 1495 1496 If there are no other slashes then the filename will be 1497 in the "root" directory. Otherwise, we need to add 1498 directory specifications. */ 1499 1500 if (index (unixname, '/') == 0) 1501 { 1502 /* if no directories specified yet and none are following. */ 1503 if (local_ptr[-1] == '[') 1504 { 1505 /* Just add "000000]" as the directory string */ 1506 strcpy (local_ptr, "000000]"); 1507 local_ptr += strlen (local_ptr); 1508 check_filename_before_returning = 1; /* we might need to fool with this later */ 1509 } 1510 } 1511 else 1512 { 1513 1514 /* As long as there are still subdirectories to add, do them. */ 1515 while (index (unixname, '/') != 0) 1516 { 1517 /* If this token is "." we can ignore it 1518 if it's not at the beginning of a path. */ 1519 if ((unixname[0] == '.') && (unixname[1] == '/')) 1520 { 1521 /* remove it at beginning of path. */ 1522 if ( ((unixname == fullname) /* no device spec */ 1523 && (fullname+2 != basename)) /* starts with ./ */ 1524 /* or */ 1525 || ((basename[-1] == ':') /* device spec */ 1526 && (unixname-1 == basename))) /* and ./ afterwards */ 1527 *local_ptr++ = '.'; /* make '[.' start of path. */ 1528 unixname += 2; 1529 continue; 1530 } 1531 1532 /* Add a subdirectory spec. Do not duplicate "." */ 1533 if ( local_ptr[-1] != '.' 1534 && local_ptr[-1] != '[' 1535 && local_ptr[-1] != '<') 1536 *local_ptr++ = '.'; 1537 1538 /* If this is ".." then the spec becomes "-" */ 1539 if ( (unixname[0] == '.') 1540 && (unixname[1] == '.') 1541 && (unixname[2] == '/')) 1542 { 1543 /* Add "-" and skip the ".." */ 1544 if ((local_ptr[-1] == '.') 1545 && (local_ptr[-2] == '[')) 1546 local_ptr--; /* prevent [.- */ 1547 *local_ptr++ = '-'; 1548 unixname += 3; 1549 continue; 1550 } 1551 1552 /* Copy the subdirectory */ 1553 while (*unixname != '/') 1554 *local_ptr++= *unixname++; 1555 1556 unixname++; /* Skip the "/" */ 1557 } 1558 1559 /* Close the directory specification */ 1560 if (local_ptr[-1] == '.') /* no trailing periods */ 1561 local_ptr--; 1562 1563 if (local_ptr[-1] == '[') /* no dir needed */ 1564 local_ptr--; 1565 else 1566 *local_ptr++ = ']'; 1567 } 1568 1569 /* Now add the filename. */ 1570 1571 while (*unixname) 1572 *local_ptr++ = *unixname++; 1573 *local_ptr = 0; 1574 1575 /* Now append it to the original VMS spec. */ 1576 1577 strcpy ((must_revert==1)?fullname:basename, Local); 1578 1579 /* If we put a [000000] in the filename, try to open it first. If this fails, 1580 remove the [000000], and return that name. This provides flexibility 1581 to the user in that they can use both rooted and non-rooted logical names 1582 to point to the location of the file. */ 1583 1584 if (check_filename_before_returning) 1585 { 1586 f = open (fullname, O_RDONLY, 0666); 1587 if (f >= 0) 1588 { 1589 /* The file name is OK as it is, so return it as is. */ 1590 close (f); 1591 return 1; 1592 } 1593 1594 /* The filename did not work. Try to remove the [000000] from the name, 1595 and return it. */ 1596 1597 basename = index (fullname, '['); 1598 local_ptr = index (fullname, ']') + 1; 1599 strcpy (basename, local_ptr); /* this gets rid of it */ 1600 1601 } 1602 1603 return 1; 1604} 1605#endif /* VMS */ 1606