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
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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! */
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. */
35 static struct include_hash *redundant_include_p
37 struct include_hash *,
38 struct file_name_list *));
39 static struct file_name_map *read_name_map PROTO ((cpp_reader *,
41 static char *read_filename_string PROTO ((int, FILE *));
42 static char *remap_filename PROTO ((cpp_reader *, char *,
43 struct file_name_list *));
44 static long read_and_prescan PROTO ((cpp_reader *, cpp_buffer *,
46 static void simplify_pathname PROTO ((char *));
47 static struct file_name_list *actual_directory PROTO ((cpp_reader *, char *));
50 static void hack_vms_include_specification PROTO ((char *));
53 /* Windows does not natively support inodes, and neither does MSDOS.
54 VMS has non-numeric inodes. */
56 #define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a)))
57 #elif (defined _WIN32 && !defined CYGWIN) || defined __MSDOS__
58 #define INO_T_EQ(a, b) 0
60 #define INO_T_EQ(a, b) ((a) == (b))
63 /* Append an entry for dir DIR to list LIST, simplifying it if
64 possible. SYS says whether this is a system include directory.
65 *** DIR is modified in place. It must be writable and permanently
66 allocated. LIST is a pointer to the head pointer, because we actually
67 *prepend* the dir, and reverse the list later (in merge_include_chains). */
69 append_include_chain (pfile, list, dir, sysp)
71 struct file_name_list **list;
75 struct file_name_list *new;
78 char * newdir = xstrdup (dir);
80 simplify_pathname (newdir);
81 if (stat (newdir, &st))
83 /* Dirs that don't exist are silently ignored. */
85 cpp_perror_with_name (pfile, newdir);
89 if (!S_ISDIR (st.st_mode))
91 cpp_message (pfile, 1, "%s: %s: Not a directory", progname, newdir);
96 if (len > pfile->max_include_len)
97 pfile->max_include_len = len;
99 new = (struct file_name_list *)xmalloc (sizeof (struct file_name_list));
103 new->ino = st.st_ino;
104 new->dev = st.st_dev;
106 new->name_map = NULL;
111 /* Merge the four include chains together in the order quote, bracket,
112 system, after. Remove duplicate dirs (as determined by
113 INO_T_EQ()). The system_include and after_include chains are never
114 referred to again after this function; all access is through the
115 bracket_include path.
117 For the future: Check if the directory is empty (but
118 how?) and possibly preload the include hash. */
121 merge_include_chains (opts)
122 struct cpp_options *opts;
124 struct file_name_list *prev, *next, *cur, *other;
125 struct file_name_list *quote, *brack, *systm, *after;
126 struct file_name_list *qtail, *btail, *stail, *atail;
128 qtail = opts->quote_include;
129 btail = opts->bracket_include;
130 stail = opts->system_include;
131 atail = opts->after_include;
133 /* Nreverse the four lists. */
135 for (cur = qtail; cur; cur = next)
144 for (cur = btail; cur; cur = next)
153 for (cur = stail; cur; cur = next)
162 for (cur = atail; cur; cur = next)
170 /* Paste together bracket, system, and after include chains. */
180 /* This is a bit tricky.
181 First we drop dupes from the quote-include list.
182 Then we drop dupes from the bracket-include list.
183 Finally, if qtail and brack are the same directory,
186 We can't just merge the lists and then uniquify them because
187 then we may lose directories from the <> search path that should
188 be there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however
189 safe to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written
190 -Ibar -I- -Ifoo -Iquux. */
192 for (cur = quote; cur; cur = cur->next)
194 for (other = quote; other != cur; other = other->next)
195 if (INO_T_EQ (cur->ino, other->ino)
196 && cur->dev == other->dev)
198 prev->next = cur->next;
208 for (cur = brack; cur; cur = cur->next)
210 for (other = brack; other != cur; other = other->next)
211 if (INO_T_EQ (cur->ino, other->ino)
212 && cur->dev == other->dev)
214 prev->next = cur->next;
225 if (INO_T_EQ (qtail->ino, brack->ino) && qtail->dev == brack->dev)
236 while (cur->next != qtail)
249 opts->quote_include = quote;
250 opts->bracket_include = brack;
251 opts->system_include = NULL;
252 opts->after_include = NULL;
255 /* Look up or add an entry to the table of all includes. This table
256 is indexed by the name as it appears in the #include line. The
257 ->next_this_file chain stores all different files with the same
258 #include name (there are at least three ways this can happen). The
259 hash function could probably be improved a bit. */
261 struct include_hash *
262 include_hash (pfile, fname, add)
267 unsigned int hash = 0;
268 struct include_hash *l, *m;
274 l = pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE];
276 for (; l; m = l, l = l->next)
277 if (!strcmp (l->nshort, fname))
283 l = (struct include_hash *) xmalloc (sizeof (struct include_hash));
285 l->next_this_file = NULL;
292 pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE] = l;
297 /* Return 0 if the file pointed to by IHASH has never been included before,
298 -1 if it has been included before and need not be again,
299 or a pointer to an IHASH entry which is the file to be reread.
300 "Never before" is with respect to the position in ILIST.
302 This will not detect redundancies involving odd uses of the
303 `current directory' rule for "" includes. They aren't quite
304 pathological, but I think they are rare enough not to worry about.
305 The simplest example is:
314 and the problem is that for `current directory' includes,
315 ihash->foundhere is not on any of the global include chains,
316 so the test below (i->foundhere == l) may be false even when
317 the directories are in fact the same. */
319 static struct include_hash *
320 redundant_include_p (pfile, ihash, ilist)
322 struct include_hash *ihash;
323 struct file_name_list *ilist;
325 struct file_name_list *l;
326 struct include_hash *i;
328 if (! ihash->foundhere)
331 for (i = ihash; i; i = i->next_this_file)
332 for (l = ilist; l; l = l->next)
333 if (i->foundhere == l)
334 /* The control_macro works like this: If it's NULL, the file
335 is to be included again. If it's "", the file is never to
336 be included again. If it's a string, the file is not to be
337 included again if the string is the name of a defined macro. */
338 return (i->control_macro
339 && (i->control_macro[0] == '\0'
340 || cpp_lookup (pfile, i->control_macro, -1, -1)))
341 ? (struct include_hash *)-1 : i;
347 file_cleanup (pbuf, pfile)
356 if (pfile->system_include_depth)
357 pfile->system_include_depth--;
361 /* Search for include file FNAME in the include chain starting at
362 SEARCH_START. Return -2 if this file doesn't need to be included
363 (because it was included already and it's marked idempotent),
364 -1 if an error occurred, or a file descriptor open on the file.
365 *IHASH is set to point to the include hash entry for this file, and
366 *BEFORE is 1 if the file was included before (but needs to be read
369 find_include_file (pfile, fname, search_start, ihash, before)
372 struct file_name_list *search_start;
373 struct include_hash **ihash;
376 struct file_name_list *l;
377 struct include_hash *ih, *jh;
381 ih = include_hash (pfile, fname, 1);
382 jh = redundant_include_p (pfile, ih,
383 fname[0] == '/' ? ABSOLUTE_PATH : search_start);
390 if (jh == (struct include_hash *)-1)
393 return open (jh->name, O_RDONLY, 0666);
397 /* A file is already known by this name, but it's not the same file.
398 Allocate another include_hash block and add it to the next_this_file
401 jh = (struct include_hash *)xmalloc (sizeof (struct include_hash));
402 while (ih->next_this_file) ih = ih->next_this_file;
404 ih->next_this_file = jh;
406 ih = ih->next_this_file;
409 ih->next_this_file = NULL;
415 ih->nshort = xstrdup (fname);
416 ih->control_macro = NULL;
418 /* If the pathname is absolute, just open it. */
421 ih->foundhere = ABSOLUTE_PATH;
422 ih->name = ih->nshort;
423 return open (ih->name, O_RDONLY, 0666);
426 /* Search directory path, trying to open the file. */
428 len = strlen (fname);
429 name = xmalloc (len + pfile->max_include_len + 2 + INCLUDE_LEN_FUDGE);
431 for (l = search_start; l; l = l->next)
433 bcopy (l->name, name, l->nlen);
435 strcpy (&name[l->nlen+1], fname);
436 simplify_pathname (name);
437 if (CPP_OPTIONS (pfile)->remap)
438 name = remap_filename (pfile, name, l);
440 f = open (name, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666);
442 if (f == -1 && errno == EACCES)
444 cpp_error(pfile, "included file `%s' exists but is not readable",
453 ih->name = xrealloc (name, strlen (name)+1);
460 jh->next_this_file = NULL;
464 *ihash = (struct include_hash *)-1;
468 /* The file_name_map structure holds a mapping of file names for a
469 particular directory. This mapping is read from the file named
470 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
471 map filenames on a file system with severe filename restrictions,
472 such as DOS. The format of the file name map file is just a series
473 of lines with two tokens on each line. The first token is the name
474 to map, and the second token is the actual name to use. */
478 struct file_name_map *map_next;
483 #define FILE_NAME_MAP_FILE "header.gcc"
485 /* Read a space delimited string of unlimited length from a stdio
489 read_filename_string (ch, f)
497 set = alloc = xmalloc (len + 1);
501 while ((ch = getc (f)) != EOF && ! is_space[ch])
503 if (set - alloc == len)
506 alloc = xrealloc (alloc, len + 1);
507 set = alloc + len / 2;
517 /* This structure holds a linked list of file name maps, one per directory. */
519 struct file_name_map_list
521 struct file_name_map_list *map_list_next;
523 struct file_name_map *map_list_map;
526 /* Read the file name map file for DIRNAME. */
528 static struct file_name_map *
529 read_name_map (pfile, dirname)
533 register struct file_name_map_list *map_list_ptr;
537 for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
538 map_list_ptr = map_list_ptr->map_list_next)
539 if (! strcmp (map_list_ptr->map_list_name, dirname))
540 return map_list_ptr->map_list_map;
542 map_list_ptr = ((struct file_name_map_list *)
543 xmalloc (sizeof (struct file_name_map_list)));
544 map_list_ptr->map_list_name = xstrdup (dirname);
546 name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
547 strcpy (name, dirname);
550 strcat (name, FILE_NAME_MAP_FILE);
551 f = fopen (name, "r");
553 map_list_ptr->map_list_map = (struct file_name_map *)-1;
557 int dirlen = strlen (dirname);
559 while ((ch = getc (f)) != EOF)
562 struct file_name_map *ptr;
566 from = read_filename_string (ch, f);
567 while ((ch = getc (f)) != EOF && is_hor_space[ch])
569 to = read_filename_string (ch, f);
571 ptr = ((struct file_name_map *)
572 xmalloc (sizeof (struct file_name_map)));
573 ptr->map_from = from;
575 /* Make the real filename absolute. */
580 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
581 strcpy (ptr->map_to, dirname);
582 ptr->map_to[dirlen] = '/';
583 strcpy (ptr->map_to + dirlen + 1, to);
587 ptr->map_next = map_list_ptr->map_list_map;
588 map_list_ptr->map_list_map = ptr;
590 while ((ch = getc (f)) != '\n')
597 map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
598 CPP_OPTIONS (pfile)->map_list = map_list_ptr;
600 return map_list_ptr->map_list_map;
603 /* Remap NAME based on the file_name_map (if any) for LOC. */
606 remap_filename (pfile, name, loc)
609 struct file_name_list *loc;
611 struct file_name_map *map;
612 const char *from, *p, *dir;
615 loc->name_map = read_name_map (pfile,
619 if (loc->name_map == (struct file_name_map *)-1)
622 from = name + strlen (loc->name) + 1;
624 for (map = loc->name_map; map; map = map->map_next)
625 if (!strcmp (map->map_from, from))
628 /* Try to find a mapping file for the particular directory we are
629 looking in. Thus #include <sys/types.h> will look up sys/types.h
630 in /usr/include/header.gcc and look up types.h in
631 /usr/include/sys/header.gcc. */
632 p = rindex (name, '/');
636 && strlen (loc->name) == (size_t) (p - name)
637 && !strncmp (loc->name, name, p - name))
638 /* FILENAME is in SEARCHPTR, which we've already checked. */
648 char * newdir = (char *) alloca (p - name + 1);
649 bcopy (name, newdir, p - name);
650 newdir[p - name] = '\0';
655 for (map = read_name_map (pfile, dir); map; map = map->map_next)
656 if (! strcmp (map->map_from, name))
662 /* Read the contents of FD into the buffer on the top of PFILE's stack.
663 IHASH points to the include hash entry for the file associated with
666 The caller is responsible for the cpp_push_buffer. */
669 finclude (pfile, fd, ihash)
672 struct include_hash *ihash;
679 if (fstat (fd, &st) < 0)
681 if (fcntl (fd, F_SETFL, 0) == -1) /* turn off nonblocking mode */
684 fp = CPP_BUFFER (pfile);
686 if (S_ISREG (st.st_mode))
688 /* off_t might have a wider range than size_t - in other words,
689 the max size of a file might be bigger than the address
690 space, and we need to detect that now. */
691 st_size = (size_t) st.st_size;
692 if ((unsigned HOST_WIDE_INT) st_size
693 != (unsigned HOST_WIDE_INT) st.st_size)
695 cpp_error (pfile, "file `%s' is too large", ihash->name);
699 else if (S_ISFIFO (st.st_mode) || (S_ISCHR (st.st_mode) && isatty (fd)))
701 /* Cannot get its file size before reading. 4k is a decent
707 cpp_error (pfile, "`%s' is not a file, pipe, or tty", ihash->name);
711 /* Read the file, converting end-of-line characters and trigraphs
714 fp->nominal_fname = fp->fname = ihash->name;
715 length = read_and_prescan (pfile, fp, fd, st_size);
719 ihash->control_macro = ""; /* never re-include */
722 fp->rlimit = fp->alimit = fp->buf + length;
724 fp->system_header_p = (ihash->foundhere != ABSOLUTE_PATH
725 && ihash->foundhere->sysp);
728 fp->cleanup = file_cleanup;
730 /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
732 if (!CPP_OPTIONS (pfile)->ignore_srcdir)
733 fp->actual_dir = actual_directory (pfile, fp->fname);
735 pfile->input_stack_listing_current = 0;
739 cpp_error_from_errno (pfile, ihash->name);
741 cpp_pop_buffer (pfile);
746 static struct file_name_list *
747 actual_directory (pfile, fname)
751 char *last_slash, *dir;
753 struct file_name_list *x;
755 dir = xstrdup (fname);
756 last_slash = rindex (dir, '/');
759 if (last_slash == dir)
762 last_slash[1] = '\0';
766 dlen = last_slash - dir;
777 if (dlen > pfile->max_include_len)
778 pfile->max_include_len = dlen;
780 for (x = pfile->actual_dirs; x; x = x->alloc)
781 if (!strcmp (x->name, dir))
787 /* Not found, make a new one. */
788 x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
791 x->next = CPP_OPTIONS (pfile)->quote_include;
792 x->alloc = pfile->actual_dirs;
796 pfile->actual_dirs = x;
800 /* Read the entire contents of file DESC into buffer BUF, convert end-of-line
801 markers to canonical form, and convert trigraphs if enabled. Also, make
802 sure there is a newline at the end of the file. LEN is how much room we
803 have to start with (this can be expanded if necessary).
804 Returns -1 on failure, or the actual length of the data to be scanned.
806 N.B. This function has been rearranged to out-of-line the uncommon cases
807 as much as possible; this is important to prevent it from being a
808 performance bottleneck. */
811 read_and_prescan (pfile, fp, desc, len)
818 U_CHAR *buf = (U_CHAR *) xmalloc (len);
819 U_CHAR *ip, *op, *line_base;
824 /* 4096 bytes of buffer proper, 2 to detect running off the end without
825 address arithmetic all the time, and 2 for pushback in the case there's
826 a potential trigraph or end-of-line digraph at the end of a block. */
827 #define INTERMED_BUFFER_SIZE 4096
828 U_CHAR intermed[INTERMED_BUFFER_SIZE + 2 + 2];
834 ibase = intermed + 2;
840 count = read (desc, intermed + 2, INTERMED_BUFFER_SIZE);
845 count += 2 - (ibase - intermed);
850 ip[count] = ip[count+1] = '\0';
851 ibase = intermed + 2;
856 size_t delta_op = op - buf;
857 size_t delta_line_base = line_base - buf;
861 This could happen if the file is larger than half the
862 maximum address space of the machine. */
864 buf = xrealloc (buf, len);
866 line_base = buf + delta_line_base;
875 /* The default case is at the top so gcc will realize
876 it's the common case, and leave c in a register.
877 Also, cache utilization is a little better this way. */
888 if (*ip == '\n') ip++;
889 else if (*ip == '\0' && !seen_eof)
900 if (*ip == '\r') ip++;
901 else if (*ip == '\0' && !seen_eof)
912 if (CPP_OPTIONS (pfile)->trigraphs
913 || CPP_OPTIONS (pfile)->warn_trigraphs)
915 /* If we're at the end of the intermediate buffer,
916 we have to shift the ?'s down to the start and
917 come back next pass. */
919 if (c == '\0' && !seen_eof)
930 if (c == '\0' && !seen_eof)
936 if (!trigraph_table[c])
942 if (CPP_OPTIONS (pfile)->warn_trigraphs)
943 cpp_warning_with_line (pfile, line, op-line_base,
944 "trigraph ??%c encountered", c);
945 if (CPP_OPTIONS (pfile)->trigraphs)
947 *op++ = trigraph_table[c];
969 if (op[-1] != '\n' || op[-2] == '\\')
971 cpp_pedwarn_with_line (pfile, line, op - line_base,
972 "no newline at end of file");
973 if (offset + 2 > len)
976 if (offset + 2 > len)
978 buf = xrealloc (buf, len);
986 buf = xrealloc (buf, op - buf);
991 cpp_error (pfile, "file is too large");
996 cpp_error_from_errno (pfile, fp->fname);
1001 /* Add output to `deps_buffer' for the -M switch.
1002 STRING points to the text to be output.
1003 SPACER is ':' for targets, ' ' for dependencies, zero for text
1004 to be inserted literally. */
1007 deps_output (pfile, string, spacer)
1018 size = strlen (string);
1020 #ifndef MAX_OUTPUT_COLUMNS
1021 #define MAX_OUTPUT_COLUMNS 72
1023 if (pfile->deps_column > 0
1024 && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS)
1028 pfile->deps_column = 0;
1031 if (pfile->deps_size + size + 8 > pfile->deps_allocated_size)
1033 pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2;
1034 pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer,
1035 pfile->deps_allocated_size);
1040 bcopy (" \\\n ", &pfile->deps_buffer[pfile->deps_size], 5);
1041 pfile->deps_size += 5;
1044 if (spacer == ' ' && pfile->deps_column > 0)
1045 pfile->deps_buffer[pfile->deps_size++] = ' ';
1046 bcopy (string, &pfile->deps_buffer[pfile->deps_size], size);
1047 pfile->deps_size += size;
1048 pfile->deps_column += size;
1050 pfile->deps_buffer[pfile->deps_size++] = ':';
1051 pfile->deps_buffer[pfile->deps_size] = 0;
1054 /* Simplify a path name in place, deleting redundant components. This
1055 reduces OS overhead and guarantees that equivalent paths compare
1056 the same (modulo symlinks).
1059 foo/bar/../quux foo/quux
1063 //quux //quux (POSIX allows leading // as a namespace escape)
1065 Guarantees no trailing slashes. All transforms reduce the length
1069 simplify_pathname (path)
1076 #if defined _WIN32 || defined __MSDOS__
1077 /* Convert all backslashes to slashes. */
1078 for (from = path; *from; from++)
1079 if (*from == '\\') *from = '/';
1081 /* Skip over leading drive letter if present. */
1082 if (ISALPHA (path[0]) && path[1] == ':')
1083 from = to = &path[2];
1090 /* Remove redundant initial /s. */
1099 /* 3 or more initial /s are equivalent to 1 /. */
1100 while (*++from == '/');
1102 /* On some hosts // differs from /; Posix allows this. */
1110 while (*from == '/')
1113 if (from[0] == '.' && from[1] == '/')
1115 else if (from[0] == '.' && from[1] == '\0')
1117 else if (from[0] == '.' && from[1] == '.' && from[2] == '/')
1134 while (to > base && *to != '/') to--;
1140 else if (from[0] == '.' && from[1] == '.' && from[2] == '\0')
1153 while (to > base && *to != '/') to--;
1160 /* Copy this component and trailing /, if any. */
1161 while ((*to++ = *from++) != '/')
1173 /* Trim trailing slash */
1174 if (to[0] == '/' && (!absolute || to > path+1))
1177 /* Change the empty string to "." so that stat() on the result
1178 will always work. */
1187 /* It is not clear when this should be used if at all, so I've
1188 disabled it until someone who understands VMS can look at it. */
1191 /* Under VMS we need to fix up the "include" specification filename.
1193 Rules for possible conversions
1195 fullname tried paths
1198 ./dir/name [.dir]name
1200 /name [000000]name, name
1201 dir/name dir:[000000]name, dir:name, dir/name
1202 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
1203 path:/name path:[000000]name, path:name
1204 path:/dir/name path:[000000.dir]name, path:[dir]name
1205 path:dir/name path:[dir]name
1206 [path]:[dir]name [path.dir]name
1207 path/[dir]name [path.dir]name
1209 The path:/name input is constructed when expanding <> includes. */
1213 hack_vms_include_specification (fullname)
1216 register char *basename, *unixname, *local_ptr, *first_slash;
1217 int f, check_filename_before_returning, must_revert;
1220 check_filename_before_returning = 0;
1222 /* See if we can find a 1st slash. If not, there's no path information. */
1223 first_slash = index (fullname, '/');
1224 if (first_slash == 0)
1225 return 0; /* Nothing to do!!! */
1227 /* construct device spec if none given. */
1229 if (index (fullname, ':') == 0)
1232 /* If fullname has a slash, take it as device spec. */
1234 if (first_slash == fullname)
1236 first_slash = index (fullname+1, '/'); /* 2nd slash ? */
1238 *first_slash = ':'; /* make device spec */
1239 for (basename = fullname; *basename != 0; basename++)
1240 *basename = *(basename+1); /* remove leading slash */
1242 else if ((first_slash[-1] != '.') /* keep ':/', './' */
1243 && (first_slash[-1] != ':')
1244 && (first_slash[-1] != ']')) /* or a vms path */
1248 else if ((first_slash[1] == '[') /* skip './' in './[dir' */
1249 && (first_slash[-1] == '.'))
1253 /* Get part after first ':' (basename[-1] == ':')
1254 or last '/' (basename[-1] == '/'). */
1256 basename = base_name (fullname);
1258 local_ptr = Local; /* initialize */
1260 /* We are trying to do a number of things here. First of all, we are
1261 trying to hammer the filenames into a standard format, such that later
1262 processing can handle them.
1264 If the file name contains something like [dir.], then it recognizes this
1265 as a root, and strips the ".]". Later processing will add whatever is
1266 needed to get things working properly.
1268 If no device is specified, then the first directory name is taken to be
1269 a device name (or a rooted logical). */
1271 /* Point to the UNIX filename part (which needs to be fixed!)
1272 but skip vms path information.
1273 [basename != fullname since first_slash != 0]. */
1275 if ((basename[-1] == ':') /* vms path spec. */
1276 || (basename[-1] == ']')
1277 || (basename[-1] == '>'))
1278 unixname = basename;
1280 unixname = fullname;
1282 if (*unixname == '/')
1285 /* If the directory spec is not rooted, we can just copy
1286 the UNIX filename part and we are done. */
1288 if (((basename - fullname) > 1)
1289 && ( (basename[-1] == ']')
1290 || (basename[-1] == '>')))
1292 if (basename[-2] != '.')
1295 /* The VMS part ends in a `]', and the preceding character is not a `.'.
1296 -> PATH]:/name (basename = '/name', unixname = 'name')
1297 We strip the `]', and then splice the two parts of the name in the
1298 usual way. Given the default locations for include files in cccp.c,
1299 we will only use this code if the user specifies alternate locations
1300 with the /include (-I) switch on the command line. */
1302 basename -= 1; /* Strip "]" */
1303 unixname--; /* backspace */
1308 /* The VMS part has a ".]" at the end, and this will not do. Later
1309 processing will add a second directory spec, and this would be a syntax
1310 error. Thus we strip the ".]", and thus merge the directory specs.
1311 We also backspace unixname, so that it points to a '/'. This inhibits the
1312 generation of the 000000 root directory spec (which does not belong here
1315 basename -= 2; /* Strip ".]" */
1316 unixname--; /* backspace */
1324 /* We drop in here if there is no VMS style directory specification yet.
1325 If there is no device specification either, we make the first dir a
1326 device and try that. If we do not do this, then we will be essentially
1327 searching the users default directory (as if they did a #include "asdf.h").
1329 Then all we need to do is to push a '[' into the output string. Later
1330 processing will fill this in, and close the bracket. */
1332 if ((unixname != fullname) /* vms path spec found. */
1333 && (basename[-1] != ':'))
1334 *local_ptr++ = ':'; /* dev not in spec. take first dir */
1336 *local_ptr++ = '['; /* Open the directory specification */
1339 if (unixname == fullname) /* no vms dir spec. */
1342 if ((first_slash != 0) /* unix dir spec. */
1343 && (*unixname != '/') /* not beginning with '/' */
1344 && (*unixname != '.')) /* or './' or '../' */
1345 *local_ptr++ = '.'; /* dir is local ! */
1348 /* at this point we assume that we have the device spec, and (at least
1349 the opening "[" for a directory specification. We may have directories
1352 If there are no other slashes then the filename will be
1353 in the "root" directory. Otherwise, we need to add
1354 directory specifications. */
1356 if (index (unixname, '/') == 0)
1358 /* if no directories specified yet and none are following. */
1359 if (local_ptr[-1] == '[')
1361 /* Just add "000000]" as the directory string */
1362 strcpy (local_ptr, "000000]");
1363 local_ptr += strlen (local_ptr);
1364 check_filename_before_returning = 1; /* we might need to fool with this later */
1370 /* As long as there are still subdirectories to add, do them. */
1371 while (index (unixname, '/') != 0)
1373 /* If this token is "." we can ignore it
1374 if it's not at the beginning of a path. */
1375 if ((unixname[0] == '.') && (unixname[1] == '/'))
1377 /* remove it at beginning of path. */
1378 if ( ((unixname == fullname) /* no device spec */
1379 && (fullname+2 != basename)) /* starts with ./ */
1381 || ((basename[-1] == ':') /* device spec */
1382 && (unixname-1 == basename))) /* and ./ afterwards */
1383 *local_ptr++ = '.'; /* make '[.' start of path. */
1388 /* Add a subdirectory spec. Do not duplicate "." */
1389 if ( local_ptr[-1] != '.'
1390 && local_ptr[-1] != '['
1391 && local_ptr[-1] != '<')
1394 /* If this is ".." then the spec becomes "-" */
1395 if ( (unixname[0] == '.')
1396 && (unixname[1] == '.')
1397 && (unixname[2] == '/'))
1399 /* Add "-" and skip the ".." */
1400 if ((local_ptr[-1] == '.')
1401 && (local_ptr[-2] == '['))
1402 local_ptr--; /* prevent [.- */
1408 /* Copy the subdirectory */
1409 while (*unixname != '/')
1410 *local_ptr++= *unixname++;
1412 unixname++; /* Skip the "/" */
1415 /* Close the directory specification */
1416 if (local_ptr[-1] == '.') /* no trailing periods */
1419 if (local_ptr[-1] == '[') /* no dir needed */
1425 /* Now add the filename. */
1428 *local_ptr++ = *unixname++;
1431 /* Now append it to the original VMS spec. */
1433 strcpy ((must_revert==1)?fullname:basename, Local);
1435 /* If we put a [000000] in the filename, try to open it first. If this fails,
1436 remove the [000000], and return that name. This provides flexibility
1437 to the user in that they can use both rooted and non-rooted logical names
1438 to point to the location of the file. */
1440 if (check_filename_before_returning)
1442 f = open (fullname, O_RDONLY, 0666);
1445 /* The file name is OK as it is, so return it as is. */
1450 /* The filename did not work. Try to remove the [000000] from the name,
1453 basename = index (fullname, '[');
1454 local_ptr = index (fullname, ']') + 1;
1455 strcpy (basename, local_ptr); /* this gets rid of it */