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 safe_read PROTO ((int, char *, int));
45 static void simplify_pathname PROTO ((char *));
46 static struct file_name_list *actual_directory PROTO ((cpp_reader *, char *));
49 static void hack_vms_include_specification PROTO ((char *));
52 /* Windows does not natively support inodes, and neither does MSDOS.
53 VMS has non-numeric inodes. */
55 #define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a)))
56 #elif (defined _WIN32 && !defined CYGWIN) || defined __MSDOS__
57 #define INO_T_EQ(a, b) 0
59 #define INO_T_EQ(a, b) ((a) == (b))
62 /* Append an entry for dir DIR to list LIST, simplifying it if
63 possible. SYS says whether this is a system include directory.
64 *** DIR is modified in place. It must be writable and permanently
65 allocated. LIST is a pointer to the head pointer, because we actually
66 *prepend* the dir, and reverse the list later (in merge_include_chains). */
68 append_include_chain (pfile, list, dir, sysp)
70 struct file_name_list **list;
74 struct file_name_list *new;
77 char * newdir = xstrdup (dir);
79 simplify_pathname (newdir);
80 if (stat (newdir, &st))
82 /* Dirs that don't exist are silently ignored. */
84 cpp_perror_with_name (pfile, newdir);
88 if (!S_ISDIR (st.st_mode))
90 cpp_message (pfile, 1, "%s: %s: Not a directory", progname, newdir);
95 if (len > pfile->max_include_len)
96 pfile->max_include_len = len;
98 new = (struct file_name_list *)xmalloc (sizeof (struct file_name_list));
102 new->ino = st.st_ino;
103 new->dev = st.st_dev;
105 new->name_map = NULL;
110 /* Merge the four include chains together in the order quote, bracket,
111 system, after. Remove duplicate dirs (as determined by
112 INO_T_EQ()). The system_include and after_include chains are never
113 referred to again after this function; all access is through the
114 bracket_include path.
116 For the future: Check if the directory is empty (but
117 how?) and possibly preload the include hash. */
120 merge_include_chains (opts)
121 struct cpp_options *opts;
123 struct file_name_list *prev, *next, *cur, *other;
124 struct file_name_list *quote, *brack, *systm, *after;
125 struct file_name_list *qtail, *btail, *stail, *atail;
127 qtail = opts->quote_include;
128 btail = opts->bracket_include;
129 stail = opts->system_include;
130 atail = opts->after_include;
132 /* Nreverse the four lists. */
134 for (cur = qtail; cur; cur = next)
143 for (cur = btail; cur; cur = next)
152 for (cur = stail; cur; cur = next)
161 for (cur = atail; cur; cur = next)
169 /* Paste together bracket, system, and after include chains. */
179 /* This is a bit tricky.
180 First we drop dupes from the quote-include list.
181 Then we drop dupes from the bracket-include list.
182 Finally, if qtail and brack are the same directory,
185 We can't just merge the lists and then uniquify them because
186 then we may lose directories from the <> search path that should
187 be there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however
188 safe to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written
189 -Ibar -I- -Ifoo -Iquux. */
191 for (cur = quote; cur; cur = cur->next)
193 for (other = quote; other != cur; other = other->next)
194 if (INO_T_EQ (cur->ino, other->ino)
195 && cur->dev == other->dev)
197 prev->next = cur->next;
207 for (cur = brack; cur; cur = cur->next)
209 for (other = brack; other != cur; other = other->next)
210 if (INO_T_EQ (cur->ino, other->ino)
211 && cur->dev == other->dev)
213 prev->next = cur->next;
224 if (INO_T_EQ (qtail->ino, brack->ino) && qtail->dev == brack->dev)
235 while (cur->next != qtail)
248 opts->quote_include = quote;
249 opts->bracket_include = brack;
250 opts->system_include = NULL;
251 opts->after_include = NULL;
254 /* Look up or add an entry to the table of all includes. This table
255 is indexed by the name as it appears in the #include line. The
256 ->next_this_file chain stores all different files with the same
257 #include name (there are at least three ways this can happen). The
258 hash function could probably be improved a bit. */
260 struct include_hash *
261 include_hash (pfile, fname, add)
266 unsigned int hash = 0;
267 struct include_hash *l, *m;
273 l = pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE];
275 for (; l; m = l, l = l->next)
276 if (!strcmp (l->nshort, fname))
282 l = (struct include_hash *) xmalloc (sizeof (struct include_hash));
284 l->next_this_file = NULL;
291 pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE] = l;
296 /* Return 0 if the file pointed to by IHASH has never been included before,
297 -1 if it has been included before and need not be again,
298 or a pointer to an IHASH entry which is the file to be reread.
299 "Never before" is with respect to the position in ILIST.
301 This will not detect redundancies involving odd uses of the
302 `current directory' rule for "" includes. They aren't quite
303 pathological, but I think they are rare enough not to worry about.
304 The simplest example is:
313 and the problem is that for `current directory' includes,
314 ihash->foundhere is not on any of the global include chains,
315 so the test below (i->foundhere == l) may be false even when
316 the directories are in fact the same. */
318 static struct include_hash *
319 redundant_include_p (pfile, ihash, ilist)
321 struct include_hash *ihash;
322 struct file_name_list *ilist;
324 struct file_name_list *l;
325 struct include_hash *i;
327 if (! ihash->foundhere)
330 for (i = ihash; i; i = i->next_this_file)
331 for (l = ilist; l; l = l->next)
332 if (i->foundhere == l)
333 /* The control_macro works like this: If it's NULL, the file
334 is to be included again. If it's "", the file is never to
335 be included again. If it's a string, the file is not to be
336 included again if the string is the name of a defined macro. */
337 return (i->control_macro
338 && (i->control_macro[0] == '\0'
339 || cpp_lookup (pfile, i->control_macro, -1, -1)))
340 ? (struct include_hash *)-1 : i;
346 file_cleanup (pbuf, pfile)
355 if (pfile->system_include_depth)
356 pfile->system_include_depth--;
360 /* Search for include file FNAME in the include chain starting at
361 SEARCH_START. Return -2 if this file doesn't need to be included
362 (because it was included already and it's marked idempotent),
363 -1 if an error occurred, or a file descriptor open on the file.
364 *IHASH is set to point to the include hash entry for this file, and
365 *BEFORE is 1 if the file was included before (but needs to be read
368 find_include_file (pfile, fname, search_start, ihash, before)
371 struct file_name_list *search_start;
372 struct include_hash **ihash;
375 struct file_name_list *l;
376 struct include_hash *ih, *jh;
380 ih = include_hash (pfile, fname, 1);
381 jh = redundant_include_p (pfile, ih,
382 fname[0] == '/' ? ABSOLUTE_PATH : search_start);
389 if (jh == (struct include_hash *)-1)
392 return open (jh->name, O_RDONLY, 0666);
396 /* A file is already known by this name, but it's not the same file.
397 Allocate another include_hash block and add it to the next_this_file
400 jh = (struct include_hash *)xmalloc (sizeof (struct include_hash));
401 while (ih->next_this_file) ih = ih->next_this_file;
403 ih->next_this_file = jh;
405 ih = ih->next_this_file;
408 ih->next_this_file = NULL;
414 ih->nshort = xstrdup (fname);
415 ih->control_macro = NULL;
417 /* If the pathname is absolute, just open it. */
420 ih->foundhere = ABSOLUTE_PATH;
421 ih->name = ih->nshort;
422 return open (ih->name, O_RDONLY, 0666);
425 /* Search directory path, trying to open the file. */
427 len = strlen (fname);
428 name = xmalloc (len + pfile->max_include_len + 2 + INCLUDE_LEN_FUDGE);
430 for (l = search_start; l; l = l->next)
432 bcopy (l->name, name, l->nlen);
434 strcpy (&name[l->nlen+1], fname);
435 simplify_pathname (name);
436 if (CPP_OPTIONS (pfile)->remap)
437 name = remap_filename (pfile, name, l);
439 f = open (name, O_RDONLY, 0666);
441 if (f == -1 && errno == EACCES)
443 cpp_error(pfile, "included file `%s' exists but is not readable",
452 ih->name = xrealloc (name, strlen (name)+1);
459 jh->next_this_file = NULL;
463 *ihash = (struct include_hash *)-1;
467 /* The file_name_map structure holds a mapping of file names for a
468 particular directory. This mapping is read from the file named
469 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
470 map filenames on a file system with severe filename restrictions,
471 such as DOS. The format of the file name map file is just a series
472 of lines with two tokens on each line. The first token is the name
473 to map, and the second token is the actual name to use. */
477 struct file_name_map *map_next;
482 #define FILE_NAME_MAP_FILE "header.gcc"
484 /* Read a space delimited string of unlimited length from a stdio
488 read_filename_string (ch, f)
496 set = alloc = xmalloc (len + 1);
500 while ((ch = getc (f)) != EOF && ! is_space[ch])
502 if (set - alloc == len)
505 alloc = xrealloc (alloc, len + 1);
506 set = alloc + len / 2;
516 /* This structure holds a linked list of file name maps, one per directory. */
518 struct file_name_map_list
520 struct file_name_map_list *map_list_next;
522 struct file_name_map *map_list_map;
525 /* Read the file name map file for DIRNAME. */
527 static struct file_name_map *
528 read_name_map (pfile, dirname)
532 register struct file_name_map_list *map_list_ptr;
536 for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
537 map_list_ptr = map_list_ptr->map_list_next)
538 if (! strcmp (map_list_ptr->map_list_name, dirname))
539 return map_list_ptr->map_list_map;
541 map_list_ptr = ((struct file_name_map_list *)
542 xmalloc (sizeof (struct file_name_map_list)));
543 map_list_ptr->map_list_name = xstrdup (dirname);
545 name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
546 strcpy (name, dirname);
549 strcat (name, FILE_NAME_MAP_FILE);
550 f = fopen (name, "r");
552 map_list_ptr->map_list_map = (struct file_name_map *)-1;
556 int dirlen = strlen (dirname);
558 while ((ch = getc (f)) != EOF)
561 struct file_name_map *ptr;
565 from = read_filename_string (ch, f);
566 while ((ch = getc (f)) != EOF && is_hor_space[ch])
568 to = read_filename_string (ch, f);
570 ptr = ((struct file_name_map *)
571 xmalloc (sizeof (struct file_name_map)));
572 ptr->map_from = from;
574 /* Make the real filename absolute. */
579 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
580 strcpy (ptr->map_to, dirname);
581 ptr->map_to[dirlen] = '/';
582 strcpy (ptr->map_to + dirlen + 1, to);
586 ptr->map_next = map_list_ptr->map_list_map;
587 map_list_ptr->map_list_map = ptr;
589 while ((ch = getc (f)) != '\n')
596 map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
597 CPP_OPTIONS (pfile)->map_list = map_list_ptr;
599 return map_list_ptr->map_list_map;
602 /* Remap NAME based on the file_name_map (if any) for LOC. */
605 remap_filename (pfile, name, loc)
608 struct file_name_list *loc;
610 struct file_name_map *map;
611 const char *from, *p, *dir;
614 loc->name_map = read_name_map (pfile,
618 if (loc->name_map == (struct file_name_map *)-1)
621 from = name + strlen (loc->name) + 1;
623 for (map = loc->name_map; map; map = map->map_next)
624 if (!strcmp (map->map_from, from))
627 /* Try to find a mapping file for the particular directory we are
628 looking in. Thus #include <sys/types.h> will look up sys/types.h
629 in /usr/include/header.gcc and look up types.h in
630 /usr/include/sys/header.gcc. */
631 p = rindex (name, '/');
635 && strlen (loc->name) == (size_t) (p - name)
636 && !strncmp (loc->name, name, p - name))
637 /* FILENAME is in SEARCHPTR, which we've already checked. */
647 char * newdir = (char *) alloca (p - name + 1);
648 bcopy (name, newdir, p - name);
649 newdir[p - name] = '\0';
654 for (map = read_name_map (pfile, dir); map; map = map->map_next)
655 if (! strcmp (map->map_from, name))
661 /* Read the contents of FD into the buffer on the top of PFILE's stack.
662 IHASH points to the include hash entry for the file associated with
665 The caller is responsible for the cpp_push_buffer. */
668 finclude (pfile, fd, ihash)
671 struct include_hash *ihash;
678 if (fstat (fd, &st) < 0)
681 fp = CPP_BUFFER (pfile);
682 fp->nominal_fname = fp->fname = ihash->name;
684 fp->system_header_p = (ihash->foundhere != ABSOLUTE_PATH
685 && ihash->foundhere->sysp);
688 fp->cleanup = file_cleanup;
690 /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
692 if (!CPP_OPTIONS (pfile)->ignore_srcdir)
693 fp->actual_dir = actual_directory (pfile, fp->fname);
695 if (S_ISREG (st.st_mode))
697 st_size = (size_t) st.st_size;
698 if (st_size != st.st_size || st_size + 2 < st_size)
700 cpp_error (pfile, "file `%s' too large", ihash->name);
703 fp->buf = (U_CHAR *) xmalloc (st_size + 2);
704 fp->alimit = fp->buf + st_size + 2;
707 /* Read the file contents, knowing that st_size is an upper bound
708 on the number of bytes we can read. */
709 length = safe_read (fd, fp->buf, st_size);
710 fp->rlimit = fp->buf + length;
714 else if (S_ISDIR (st.st_mode))
716 cpp_pop_buffer (pfile);
717 cpp_error (pfile, "directory `%s' specified in #include", ihash->name);
722 /* Cannot count its file size before reading.
723 First read the entire file into heap and
724 copy them into buffer on stack. */
729 fp->buf = (U_CHAR *) xmalloc (bsize + 2);
733 i = safe_read (fd, fp->buf + st_size, bsize - st_size);
737 if (st_size != bsize)
738 break; /* End of file */
740 fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
746 /* FIXME: Broken in presence of trigraphs (consider ??/<EOF>)
747 and doesn't warn about a missing newline. */
748 if ((length > 0 && fp->buf[length - 1] != '\n')
749 || (length > 1 && fp->buf[length - 2] == '\\'))
750 fp->buf[length++] = '\n';
752 fp->buf[length] = '\0';
753 fp->rlimit = fp->buf + length;
756 pfile->input_stack_listing_current = 0;
760 cpp_pop_buffer (pfile);
761 cpp_error_from_errno (pfile, ihash->name);
767 static struct file_name_list *
768 actual_directory (pfile, fname)
772 char *last_slash, *dir;
774 struct file_name_list *x;
776 dir = xstrdup (fname);
777 last_slash = rindex (dir, '/');
780 if (last_slash == dir)
783 last_slash[1] = '\0';
787 dlen = last_slash - dir;
798 if (dlen > pfile->max_include_len)
799 pfile->max_include_len = dlen;
801 for (x = pfile->actual_dirs; x; x = x->alloc)
802 if (!strcmp (x->name, dir))
808 /* Not found, make a new one. */
809 x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
812 x->next = CPP_OPTIONS (pfile)->quote_include;
813 x->alloc = pfile->actual_dirs;
817 pfile->actual_dirs = x;
821 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
822 retrying if necessary. If MAX_READ_LEN is defined, read at most
823 that bytes at a time. Return a negative value if an error occurs,
824 otherwise return the actual number of bytes read,
825 which must be LEN unless end-of-file was reached. */
828 safe_read (desc, ptr, len)
833 int left, rcount, nchars;
839 if (rcount > MAX_READ_LEN)
840 rcount = MAX_READ_LEN;
842 nchars = read (desc, ptr, rcount);
859 /* Add output to `deps_buffer' for the -M switch.
860 STRING points to the text to be output.
861 SPACER is ':' for targets, ' ' for dependencies, zero for text
862 to be inserted literally. */
865 deps_output (pfile, string, spacer)
876 size = strlen (string);
878 #ifndef MAX_OUTPUT_COLUMNS
879 #define MAX_OUTPUT_COLUMNS 72
881 if (pfile->deps_column > 0
882 && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS)
886 pfile->deps_column = 0;
889 if (pfile->deps_size + size + 8 > pfile->deps_allocated_size)
891 pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2;
892 pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer,
893 pfile->deps_allocated_size);
898 bcopy (" \\\n ", &pfile->deps_buffer[pfile->deps_size], 5);
899 pfile->deps_size += 5;
902 if (spacer == ' ' && pfile->deps_column > 0)
903 pfile->deps_buffer[pfile->deps_size++] = ' ';
904 bcopy (string, &pfile->deps_buffer[pfile->deps_size], size);
905 pfile->deps_size += size;
906 pfile->deps_column += size;
908 pfile->deps_buffer[pfile->deps_size++] = ':';
909 pfile->deps_buffer[pfile->deps_size] = 0;
912 /* Simplify a path name in place, deleting redundant components. This
913 reduces OS overhead and guarantees that equivalent paths compare
914 the same (modulo symlinks).
917 foo/bar/../quux foo/quux
921 //quux //quux (POSIX allows leading // as a namespace escape)
923 Guarantees no trailing slashes. All transforms reduce the length
927 simplify_pathname (path)
934 #if defined _WIN32 || defined __MSDOS__
935 /* Convert all backslashes to slashes. */
936 for (from = path; *from; from++)
937 if (*from == '\\') *from = '/';
939 /* Skip over leading drive letter if present. */
940 if (ISALPHA (path[0]) && path[1] == ':')
941 from = to = &path[2];
948 /* Remove redundant initial /s. */
957 /* 3 or more initial /s are equivalent to 1 /. */
958 while (*++from == '/');
960 /* On some hosts // differs from /; Posix allows this. */
971 if (from[0] == '.' && from[1] == '/')
973 else if (from[0] == '.' && from[1] == '\0')
975 else if (from[0] == '.' && from[1] == '.' && from[2] == '/')
992 while (to > base && *to != '/') to--;
998 else if (from[0] == '.' && from[1] == '.' && from[2] == '\0')
1011 while (to > base && *to != '/') to--;
1018 /* Copy this component and trailing /, if any. */
1019 while ((*to++ = *from++) != '/')
1031 /* Trim trailing slash */
1032 if (to[0] == '/' && (!absolute || to > path+1))
1035 /* Change the empty string to "." so that stat() on the result
1036 will always work. */
1045 /* It is not clear when this should be used if at all, so I've
1046 disabled it until someone who understands VMS can look at it. */
1049 /* Under VMS we need to fix up the "include" specification filename.
1051 Rules for possible conversions
1053 fullname tried paths
1056 ./dir/name [.dir]name
1058 /name [000000]name, name
1059 dir/name dir:[000000]name, dir:name, dir/name
1060 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
1061 path:/name path:[000000]name, path:name
1062 path:/dir/name path:[000000.dir]name, path:[dir]name
1063 path:dir/name path:[dir]name
1064 [path]:[dir]name [path.dir]name
1065 path/[dir]name [path.dir]name
1067 The path:/name input is constructed when expanding <> includes. */
1071 hack_vms_include_specification (fullname)
1074 register char *basename, *unixname, *local_ptr, *first_slash;
1075 int f, check_filename_before_returning, must_revert;
1078 check_filename_before_returning = 0;
1080 /* See if we can find a 1st slash. If not, there's no path information. */
1081 first_slash = index (fullname, '/');
1082 if (first_slash == 0)
1083 return 0; /* Nothing to do!!! */
1085 /* construct device spec if none given. */
1087 if (index (fullname, ':') == 0)
1090 /* If fullname has a slash, take it as device spec. */
1092 if (first_slash == fullname)
1094 first_slash = index (fullname+1, '/'); /* 2nd slash ? */
1096 *first_slash = ':'; /* make device spec */
1097 for (basename = fullname; *basename != 0; basename++)
1098 *basename = *(basename+1); /* remove leading slash */
1100 else if ((first_slash[-1] != '.') /* keep ':/', './' */
1101 && (first_slash[-1] != ':')
1102 && (first_slash[-1] != ']')) /* or a vms path */
1106 else if ((first_slash[1] == '[') /* skip './' in './[dir' */
1107 && (first_slash[-1] == '.'))
1111 /* Get part after first ':' (basename[-1] == ':')
1112 or last '/' (basename[-1] == '/'). */
1114 basename = base_name (fullname);
1116 local_ptr = Local; /* initialize */
1118 /* We are trying to do a number of things here. First of all, we are
1119 trying to hammer the filenames into a standard format, such that later
1120 processing can handle them.
1122 If the file name contains something like [dir.], then it recognizes this
1123 as a root, and strips the ".]". Later processing will add whatever is
1124 needed to get things working properly.
1126 If no device is specified, then the first directory name is taken to be
1127 a device name (or a rooted logical). */
1129 /* Point to the UNIX filename part (which needs to be fixed!)
1130 but skip vms path information.
1131 [basename != fullname since first_slash != 0]. */
1133 if ((basename[-1] == ':') /* vms path spec. */
1134 || (basename[-1] == ']')
1135 || (basename[-1] == '>'))
1136 unixname = basename;
1138 unixname = fullname;
1140 if (*unixname == '/')
1143 /* If the directory spec is not rooted, we can just copy
1144 the UNIX filename part and we are done. */
1146 if (((basename - fullname) > 1)
1147 && ( (basename[-1] == ']')
1148 || (basename[-1] == '>')))
1150 if (basename[-2] != '.')
1153 /* The VMS part ends in a `]', and the preceding character is not a `.'.
1154 -> PATH]:/name (basename = '/name', unixname = 'name')
1155 We strip the `]', and then splice the two parts of the name in the
1156 usual way. Given the default locations for include files in cccp.c,
1157 we will only use this code if the user specifies alternate locations
1158 with the /include (-I) switch on the command line. */
1160 basename -= 1; /* Strip "]" */
1161 unixname--; /* backspace */
1166 /* The VMS part has a ".]" at the end, and this will not do. Later
1167 processing will add a second directory spec, and this would be a syntax
1168 error. Thus we strip the ".]", and thus merge the directory specs.
1169 We also backspace unixname, so that it points to a '/'. This inhibits the
1170 generation of the 000000 root directory spec (which does not belong here
1173 basename -= 2; /* Strip ".]" */
1174 unixname--; /* backspace */
1182 /* We drop in here if there is no VMS style directory specification yet.
1183 If there is no device specification either, we make the first dir a
1184 device and try that. If we do not do this, then we will be essentially
1185 searching the users default directory (as if they did a #include "asdf.h").
1187 Then all we need to do is to push a '[' into the output string. Later
1188 processing will fill this in, and close the bracket. */
1190 if ((unixname != fullname) /* vms path spec found. */
1191 && (basename[-1] != ':'))
1192 *local_ptr++ = ':'; /* dev not in spec. take first dir */
1194 *local_ptr++ = '['; /* Open the directory specification */
1197 if (unixname == fullname) /* no vms dir spec. */
1200 if ((first_slash != 0) /* unix dir spec. */
1201 && (*unixname != '/') /* not beginning with '/' */
1202 && (*unixname != '.')) /* or './' or '../' */
1203 *local_ptr++ = '.'; /* dir is local ! */
1206 /* at this point we assume that we have the device spec, and (at least
1207 the opening "[" for a directory specification. We may have directories
1210 If there are no other slashes then the filename will be
1211 in the "root" directory. Otherwise, we need to add
1212 directory specifications. */
1214 if (index (unixname, '/') == 0)
1216 /* if no directories specified yet and none are following. */
1217 if (local_ptr[-1] == '[')
1219 /* Just add "000000]" as the directory string */
1220 strcpy (local_ptr, "000000]");
1221 local_ptr += strlen (local_ptr);
1222 check_filename_before_returning = 1; /* we might need to fool with this later */
1228 /* As long as there are still subdirectories to add, do them. */
1229 while (index (unixname, '/') != 0)
1231 /* If this token is "." we can ignore it
1232 if it's not at the beginning of a path. */
1233 if ((unixname[0] == '.') && (unixname[1] == '/'))
1235 /* remove it at beginning of path. */
1236 if ( ((unixname == fullname) /* no device spec */
1237 && (fullname+2 != basename)) /* starts with ./ */
1239 || ((basename[-1] == ':') /* device spec */
1240 && (unixname-1 == basename))) /* and ./ afterwards */
1241 *local_ptr++ = '.'; /* make '[.' start of path. */
1246 /* Add a subdirectory spec. Do not duplicate "." */
1247 if ( local_ptr[-1] != '.'
1248 && local_ptr[-1] != '['
1249 && local_ptr[-1] != '<')
1252 /* If this is ".." then the spec becomes "-" */
1253 if ( (unixname[0] == '.')
1254 && (unixname[1] == '.')
1255 && (unixname[2] == '/'))
1257 /* Add "-" and skip the ".." */
1258 if ((local_ptr[-1] == '.')
1259 && (local_ptr[-2] == '['))
1260 local_ptr--; /* prevent [.- */
1266 /* Copy the subdirectory */
1267 while (*unixname != '/')
1268 *local_ptr++= *unixname++;
1270 unixname++; /* Skip the "/" */
1273 /* Close the directory specification */
1274 if (local_ptr[-1] == '.') /* no trailing periods */
1277 if (local_ptr[-1] == '[') /* no dir needed */
1283 /* Now add the filename. */
1286 *local_ptr++ = *unixname++;
1289 /* Now append it to the original VMS spec. */
1291 strcpy ((must_revert==1)?fullname:basename, Local);
1293 /* If we put a [000000] in the filename, try to open it first. If this fails,
1294 remove the [000000], and return that name. This provides flexibility
1295 to the user in that they can use both rooted and non-rooted logical names
1296 to point to the location of the file. */
1298 if (check_filename_before_returning)
1300 f = open (fullname, O_RDONLY, 0666);
1303 /* The file name is OK as it is, so return it as is. */
1308 /* The filename did not work. Try to remove the [000000] from the name,
1311 basename = index (fullname, '[');
1312 local_ptr = index (fullname, ']') + 1;
1313 strcpy (basename, local_ptr); /* this gets rid of it */