1 /* Part of CPP library. (include file handling)
2 Copyright (C) 1986, 87, 89, 92 - 95, 1998 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 *, char *));
40 static char *read_filename_string PROTO ((int, FILE *));
41 static char *remap_filename PROTO ((cpp_reader *, char *,
42 struct file_name_list *));
43 static long safe_read PROTO ((int, char *, int));
44 static void simplify_pathname PROTO ((char *));
47 static void hack_vms_include_specification PROTO ((char *));
50 /* Not safe to prototype these. */
51 extern char *xmalloc();
52 extern char *xrealloc();
54 /* Windows does not natively support inodes, and neither does MSDOS.
55 VMS has non-numeric inodes. */
57 #define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a)))
58 #elif (defined _WIN32 && !defined CYGWIN) || defined __MSDOS__
59 #define INO_T_EQ(a, b) 0
61 #define INO_T_EQ(a, b) ((a) == (b))
64 /* Append an entry for dir DIR to list LIST, simplifying it if
65 possible. SYS says whether this is a system include directory.
66 *** DIR is modified in place. It must be writable and permanently
67 allocated. LIST is a pointer to the head pointer, because we actually
68 *prepend* the dir, and reverse the list later (in merge_include_chains). */
70 append_include_chain (pfile, list, dir, sysp)
72 struct file_name_list **list;
76 struct file_name_list *new;
80 dir = savestring (dir);
81 simplify_pathname (dir);
84 /* Dirs that don't exist are silently ignored. */
86 cpp_perror_with_name (pfile, dir);
90 if (!S_ISDIR (st.st_mode))
92 cpp_message (pfile, 1, "%s: %s: Not a directory", progname, dir);
97 if (len > pfile->max_include_len)
98 pfile->max_include_len = len;
100 new = (struct file_name_list *)xmalloc (sizeof (struct file_name_list));
104 new->ino = st.st_ino;
105 new->dev = st.st_dev;
107 new->name_map = NULL;
112 /* Merge the four include chains together in the order quote, bracket,
113 system, after. Remove duplicate dirs (as determined by
114 INO_T_EQ()). The system_include and after_include chains are never
115 referred to again after this function; all access is through the
116 bracket_include path.
118 For the future: Check if the directory is empty (but
119 how?) and possibly preload the include hash. */
122 merge_include_chains (opts)
123 struct cpp_options *opts;
125 struct file_name_list *prev, *next, *cur, *other;
126 struct file_name_list *quote, *brack, *systm, *after;
127 struct file_name_list *qtail, *btail, *stail, *atail;
129 qtail = opts->quote_include;
130 btail = opts->bracket_include;
131 stail = opts->system_include;
132 atail = opts->after_include;
134 /* Nreverse the four lists. */
136 for (cur = qtail; cur; cur = next)
145 for (cur = btail; cur; cur = next)
154 for (cur = stail; cur; cur = next)
163 for (cur = atail; cur; cur = next)
171 /* Paste together bracket, system, and after include chains. */
181 /* This is a bit tricky.
182 First we drop dupes from the quote-include list.
183 Then we drop dupes from the bracket-include list.
184 Finally, if qtail and brack are the same directory,
187 We can't just merge the lists and then uniquify them because
188 then we may lose directories from the <> search path that should
189 be there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however
190 safe to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written
191 -Ibar -I- -Ifoo -Iquux. */
193 for (cur = quote; cur; cur = cur->next)
195 for (other = quote; other != cur; other = other->next)
196 if (INO_T_EQ (cur->ino, other->ino)
197 && cur->dev == other->dev)
199 prev->next = cur->next;
209 for (cur = brack; cur; cur = cur->next)
211 for (other = brack; other != cur; other = other->next)
212 if (INO_T_EQ (cur->ino, other->ino)
213 && cur->dev == other->dev)
215 prev->next = cur->next;
226 if (INO_T_EQ (qtail->ino, brack->ino) && qtail->dev == brack->dev)
237 while (cur->next != qtail)
250 opts->quote_include = quote;
251 opts->bracket_include = brack;
252 opts->system_include = NULL;
253 opts->after_include = NULL;
256 /* Look up or add an entry to the table of all includes. This table
257 is indexed by the name as it appears in the #include line. The
258 ->next_this_file chain stores all different files with the same
259 #include name (there are at least three ways this can happen). The
260 hash function could probably be improved a bit. */
262 struct include_hash *
263 include_hash (pfile, fname, add)
268 unsigned int hash = 0;
269 struct include_hash *l, *m;
275 l = pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE];
277 for (; l; m = l, l = l->next)
278 if (!strcmp (l->nshort, fname))
284 l = (struct include_hash *) xmalloc (sizeof (struct include_hash));
286 l->next_this_file = NULL;
293 pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE] = l;
298 /* Return 0 if the file pointed to by IHASH has never been included before,
299 -1 if it has been included before and need not be again,
300 or a pointer to an IHASH entry which is the file to be reread.
301 "Never before" is with respect to the position in ILIST.
303 This will not detect redundancies involving odd uses of the
304 `current directory' rule for "" includes. They aren't quite
305 pathological, but I think they are rare enough not to worry about.
306 The simplest example is:
315 and the problem is that for `current directory' includes,
316 ihash->foundhere is not on any of the global include chains,
317 so the test below (i->foundhere == l) may be false even when
318 the directories are in fact the same. */
320 static struct include_hash *
321 redundant_include_p (pfile, ihash, ilist)
323 struct include_hash *ihash;
324 struct file_name_list *ilist;
326 struct file_name_list *l;
327 struct include_hash *i;
329 if (! ihash->foundhere)
332 for (i = ihash; i; i = i->next_this_file)
333 for (l = ilist; l; l = l->next)
334 if (i->foundhere == l)
335 /* The control_macro works like this: If it's NULL, the file
336 is to be included again. If it's "", the file is never to
337 be included again. If it's a string, the file is not to be
338 included again if the string is the name of a defined macro. */
339 return (i->control_macro
340 && (i->control_macro[0] == '\0'
341 || cpp_lookup (pfile, i->control_macro, -1, -1)))
342 ? (struct include_hash *)-1 : i;
348 file_cleanup (pbuf, pfile)
357 if (pfile->system_include_depth)
358 pfile->system_include_depth--;
362 /* Search for include file FNAME in the include chain starting at
363 SEARCH_START. Return -2 if this file doesn't need to be included
364 (because it was included already and it's marked idempotent),
365 -1 if an error occurred, or a file descriptor open on the file.
366 *IHASH is set to point to the include hash entry for this file, and
367 *BEFORE is 1 if the file was included before (but needs to be read
370 find_include_file (pfile, fname, search_start, ihash, before)
373 struct file_name_list *search_start;
374 struct include_hash **ihash;
377 struct file_name_list *l;
378 struct include_hash *ih, *jh;
382 ih = include_hash (pfile, fname, 1);
383 jh = redundant_include_p (pfile, ih,
384 fname[0] == '/' ? ABSOLUTE_PATH : search_start);
391 if (jh == (struct include_hash *)-1)
394 return open (jh->name, O_RDONLY, 0666);
398 /* A file is already known by this name, but it's not the same file.
399 Allocate another include_hash block and add it to the next_this_file
402 jh = (struct include_hash *)xmalloc (sizeof (struct include_hash));
403 while (ih->next_this_file) ih = ih->next_this_file;
405 ih->next_this_file = jh;
407 ih = ih->next_this_file;
410 ih->next_this_file = NULL;
416 ih->nshort = savestring (fname);
417 ih->control_macro = NULL;
419 /* If the pathname is absolute, just open it. */
422 ih->foundhere = ABSOLUTE_PATH;
423 ih->name = ih->nshort;
424 return open (ih->name, O_RDONLY, 0666);
427 /* Search directory path, trying to open the file. */
429 /* The first entry in the search list may be a buffer-specific entry,
430 and its directory name may be longer than max_include_len. Adjust
432 if (pfile->max_include_len < search_start->nlen)
433 pfile->max_include_len = search_start->nlen;
434 len = strlen (fname);
435 name = xmalloc (len + pfile->max_include_len + 2 + INCLUDE_LEN_FUDGE);
437 for (l = search_start; l; l = l->next)
439 bcopy (l->name, name, l->nlen);
441 strcpy (&name[l->nlen+1], fname);
442 simplify_pathname (name);
443 if (CPP_OPTIONS (pfile)->remap)
444 name = remap_filename (pfile, name, l);
446 f = open (name, O_RDONLY, 0666);
448 if (f == -1 && errno == EACCES)
450 cpp_error(pfile, "included file `%s' exists but is not readable",
459 ih->name = xrealloc (name, strlen (name)+1);
466 jh->next_this_file = NULL;
470 *ihash = (struct include_hash *)-1;
474 /* The file_name_map structure holds a mapping of file names for a
475 particular directory. This mapping is read from the file named
476 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
477 map filenames on a file system with severe filename restrictions,
478 such as DOS. The format of the file name map file is just a series
479 of lines with two tokens on each line. The first token is the name
480 to map, and the second token is the actual name to use. */
484 struct file_name_map *map_next;
489 #define FILE_NAME_MAP_FILE "header.gcc"
491 /* Read a space delimited string of unlimited length from a stdio
495 read_filename_string (ch, f)
503 set = alloc = xmalloc (len + 1);
507 while ((ch = getc (f)) != EOF && ! is_space[ch])
509 if (set - alloc == len)
512 alloc = xrealloc (alloc, len + 1);
513 set = alloc + len / 2;
523 /* This structure holds a linked list of file name maps, one per directory. */
525 struct file_name_map_list
527 struct file_name_map_list *map_list_next;
529 struct file_name_map *map_list_map;
532 /* Read the file name map file for DIRNAME. */
534 static struct file_name_map *
535 read_name_map (pfile, dirname)
539 register struct file_name_map_list *map_list_ptr;
543 for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
544 map_list_ptr = map_list_ptr->map_list_next)
545 if (! strcmp (map_list_ptr->map_list_name, dirname))
546 return map_list_ptr->map_list_map;
548 map_list_ptr = ((struct file_name_map_list *)
549 xmalloc (sizeof (struct file_name_map_list)));
550 map_list_ptr->map_list_name = savestring (dirname);
552 name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
553 strcpy (name, dirname);
556 strcat (name, FILE_NAME_MAP_FILE);
557 f = fopen (name, "r");
559 map_list_ptr->map_list_map = (struct file_name_map *)-1;
563 int dirlen = strlen (dirname);
565 while ((ch = getc (f)) != EOF)
568 struct file_name_map *ptr;
572 from = read_filename_string (ch, f);
573 while ((ch = getc (f)) != EOF && is_hor_space[ch])
575 to = read_filename_string (ch, f);
577 ptr = ((struct file_name_map *)
578 xmalloc (sizeof (struct file_name_map)));
579 ptr->map_from = from;
581 /* Make the real filename absolute. */
586 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
587 strcpy (ptr->map_to, dirname);
588 ptr->map_to[dirlen] = '/';
589 strcpy (ptr->map_to + dirlen + 1, to);
593 ptr->map_next = map_list_ptr->map_list_map;
594 map_list_ptr->map_list_map = ptr;
596 while ((ch = getc (f)) != '\n')
603 map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
604 CPP_OPTIONS (pfile)->map_list = map_list_ptr;
606 return map_list_ptr->map_list_map;
609 /* Remap NAME based on the file_name_map (if any) for LOC. */
612 remap_filename (pfile, name, loc)
615 struct file_name_list *loc;
617 struct file_name_map *map;
622 loc->name_map = read_name_map (pfile,
626 if (loc->name_map == (struct file_name_map *)-1)
629 from = name + strlen (loc->name) + 1;
631 for (map = loc->name_map; map; map = map->map_next)
632 if (!strcmp (map->map_from, from))
635 /* Try to find a mapping file for the particular directory we are
636 looking in. Thus #include <sys/types.h> will look up sys/types.h
637 in /usr/include/header.gcc and look up types.h in
638 /usr/include/sys/header.gcc. */
639 p = rindex (name, '/');
643 && strlen (loc->name) == (size_t) (p - name)
644 && !strncmp (loc->name, name, p - name))
645 /* FILENAME is in SEARCHPTR, which we've already checked. */
655 dir = (char *) alloca (p - name + 1);
656 bcopy (name, dir, p - name);
657 dir[p - name] = '\0';
661 for (map = read_name_map (pfile, dir); map; map = map->map_next)
662 if (! strcmp (map->map_from, name))
668 /* Read the contents of FD into the buffer on the top of PFILE's stack.
669 IHASH points to the include hash entry for the file associated with
672 The caller is responsible for the cpp_push_buffer. */
675 finclude (pfile, fd, ihash)
678 struct include_hash *ihash;
685 if (fstat (fd, &st) < 0)
688 fp = CPP_BUFFER (pfile);
689 fp->nominal_fname = fp->fname = ihash->name;
691 fp->system_header_p = (ihash->foundhere != ABSOLUTE_PATH
692 && ihash->foundhere->sysp);
695 fp->cleanup = file_cleanup;
697 /* The ->dir field is only used when ignore_srcdir is not in effect;
699 if (!CPP_OPTIONS (pfile)->ignore_srcdir)
702 fp->dir = savestring (fp->fname);
703 last_slash = rindex (fp->dir, '/');
706 if (last_slash == fp->dir)
709 last_slash[1] = '\0';
713 fp->dlen = last_slash - fp->dir;
725 if (S_ISREG (st.st_mode))
727 st_size = (size_t) st.st_size;
728 if (st_size != st.st_size || st_size + 2 < st_size)
730 cpp_error (pfile, "file `%s' too large", ihash->name);
733 fp->buf = (U_CHAR *) xmalloc (st_size + 2);
734 fp->alimit = fp->buf + st_size + 2;
737 /* Read the file contents, knowing that st_size is an upper bound
738 on the number of bytes we can read. */
739 length = safe_read (fd, fp->buf, st_size);
740 fp->rlimit = fp->buf + length;
744 else if (S_ISDIR (st.st_mode))
746 cpp_pop_buffer (pfile);
747 cpp_error (pfile, "directory `%s' specified in #include", ihash->name);
752 /* Cannot count its file size before reading.
753 First read the entire file into heap and
754 copy them into buffer on stack. */
759 fp->buf = (U_CHAR *) xmalloc (bsize + 2);
763 i = safe_read (fd, fp->buf + st_size, bsize - st_size);
767 if (st_size != bsize)
768 break; /* End of file */
770 fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
776 /* FIXME: Broken in presence of trigraphs (consider ??/<EOF>)
777 and doesn't warn about a missing newline. */
778 if ((length > 0 && fp->buf[length - 1] != '\n')
779 || (length > 1 && fp->buf[length - 2] == '\\'))
780 fp->buf[length++] = '\n';
782 fp->buf[length] = '\0';
783 fp->rlimit = fp->buf + length;
786 pfile->input_stack_listing_current = 0;
790 cpp_pop_buffer (pfile);
791 cpp_error_from_errno (pfile, ihash->name);
797 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
798 retrying if necessary. If MAX_READ_LEN is defined, read at most
799 that bytes at a time. Return a negative value if an error occurs,
800 otherwise return the actual number of bytes read,
801 which must be LEN unless end-of-file was reached. */
804 safe_read (desc, ptr, len)
809 int left, rcount, nchars;
815 if (rcount > MAX_READ_LEN)
816 rcount = MAX_READ_LEN;
818 nchars = read (desc, ptr, rcount);
835 /* Add output to `deps_buffer' for the -M switch.
836 STRING points to the text to be output.
837 SPACER is ':' for targets, ' ' for dependencies, zero for text
838 to be inserted literally. */
841 deps_output (pfile, string, spacer)
852 size = strlen (string);
854 #ifndef MAX_OUTPUT_COLUMNS
855 #define MAX_OUTPUT_COLUMNS 72
857 if (pfile->deps_column > 0
858 && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS)
862 pfile->deps_column = 0;
865 if (pfile->deps_size + size + 8 > pfile->deps_allocated_size)
867 pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2;
868 pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer,
869 pfile->deps_allocated_size);
874 bcopy (" \\\n ", &pfile->deps_buffer[pfile->deps_size], 5);
875 pfile->deps_size += 5;
878 if (spacer == ' ' && pfile->deps_column > 0)
879 pfile->deps_buffer[pfile->deps_size++] = ' ';
880 bcopy (string, &pfile->deps_buffer[pfile->deps_size], size);
881 pfile->deps_size += size;
882 pfile->deps_column += size;
884 pfile->deps_buffer[pfile->deps_size++] = ':';
885 pfile->deps_buffer[pfile->deps_size] = 0;
888 /* Simplify a path name in place, deleting redundant components. This
889 reduces OS overhead and guarantees that equivalent paths compare
890 the same (modulo symlinks).
893 foo/bar/../quux foo/quux
897 //quux //quux (POSIX allows leading // as a namespace escape)
899 Guarantees no trailing slashes. All transforms reduce the length
903 simplify_pathname (char *path)
909 #if defined _WIN32 || defined __MSDOS__
910 /* Convert all backslashes to slashes. */
911 for (from = path; *from; from++)
912 if (*from == '\\') *from = '/';
914 /* Skip over leading drive letter if present. */
915 if (ISALPHA (path[0]) && path[1] == ':')
916 from = to = &path[2];
923 /* Remove redundant initial /s. */
932 /* 3 or more initial /s are equivalent to 1 /. */
933 while (*++from == '/');
935 /* On some hosts // differs from /; Posix allows this. */
946 if (from[0] == '.' && from[1] == '/')
948 else if (from[0] == '.' && from[1] == '\0')
950 else if (from[0] == '.' && from[1] == '.' && from[2] == '/')
967 while (to > base && *to != '/') to--;
973 else if (from[0] == '.' && from[1] == '.' && from[2] == '\0')
986 while (to > base && *to != '/') to--;
993 /* Copy this component and trailing /, if any. */
994 while ((*to++ = *from++) != '/')
1006 /* Trim trailing slash */
1007 if (to[0] == '/' && (!absolute || to > path+1))
1010 /* Change the empty string to "." so that stat() on the result
1011 will always work. */
1020 /* It is not clear when this should be used if at all, so I've
1021 disabled it until someone who understands VMS can look at it. */
1024 /* Under VMS we need to fix up the "include" specification filename.
1026 Rules for possible conversions
1028 fullname tried paths
1031 ./dir/name [.dir]name
1033 /name [000000]name, name
1034 dir/name dir:[000000]name, dir:name, dir/name
1035 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
1036 path:/name path:[000000]name, path:name
1037 path:/dir/name path:[000000.dir]name, path:[dir]name
1038 path:dir/name path:[dir]name
1039 [path]:[dir]name [path.dir]name
1040 path/[dir]name [path.dir]name
1042 The path:/name input is constructed when expanding <> includes. */
1046 hack_vms_include_specification (fullname)
1049 register char *basename, *unixname, *local_ptr, *first_slash;
1050 int f, check_filename_before_returning, must_revert;
1053 check_filename_before_returning = 0;
1055 /* See if we can find a 1st slash. If not, there's no path information. */
1056 first_slash = index (fullname, '/');
1057 if (first_slash == 0)
1058 return 0; /* Nothing to do!!! */
1060 /* construct device spec if none given. */
1062 if (index (fullname, ':') == 0)
1065 /* If fullname has a slash, take it as device spec. */
1067 if (first_slash == fullname)
1069 first_slash = index (fullname+1, '/'); /* 2nd slash ? */
1071 *first_slash = ':'; /* make device spec */
1072 for (basename = fullname; *basename != 0; basename++)
1073 *basename = *(basename+1); /* remove leading slash */
1075 else if ((first_slash[-1] != '.') /* keep ':/', './' */
1076 && (first_slash[-1] != ':')
1077 && (first_slash[-1] != ']')) /* or a vms path */
1081 else if ((first_slash[1] == '[') /* skip './' in './[dir' */
1082 && (first_slash[-1] == '.'))
1086 /* Get part after first ':' (basename[-1] == ':')
1087 or last '/' (basename[-1] == '/'). */
1089 basename = base_name (fullname);
1091 local_ptr = Local; /* initialize */
1093 /* We are trying to do a number of things here. First of all, we are
1094 trying to hammer the filenames into a standard format, such that later
1095 processing can handle them.
1097 If the file name contains something like [dir.], then it recognizes this
1098 as a root, and strips the ".]". Later processing will add whatever is
1099 needed to get things working properly.
1101 If no device is specified, then the first directory name is taken to be
1102 a device name (or a rooted logical). */
1104 /* Point to the UNIX filename part (which needs to be fixed!)
1105 but skip vms path information.
1106 [basename != fullname since first_slash != 0]. */
1108 if ((basename[-1] == ':') /* vms path spec. */
1109 || (basename[-1] == ']')
1110 || (basename[-1] == '>'))
1111 unixname = basename;
1113 unixname = fullname;
1115 if (*unixname == '/')
1118 /* If the directory spec is not rooted, we can just copy
1119 the UNIX filename part and we are done. */
1121 if (((basename - fullname) > 1)
1122 && ( (basename[-1] == ']')
1123 || (basename[-1] == '>')))
1125 if (basename[-2] != '.')
1128 /* The VMS part ends in a `]', and the preceding character is not a `.'.
1129 -> PATH]:/name (basename = '/name', unixname = 'name')
1130 We strip the `]', and then splice the two parts of the name in the
1131 usual way. Given the default locations for include files in cccp.c,
1132 we will only use this code if the user specifies alternate locations
1133 with the /include (-I) switch on the command line. */
1135 basename -= 1; /* Strip "]" */
1136 unixname--; /* backspace */
1141 /* The VMS part has a ".]" at the end, and this will not do. Later
1142 processing will add a second directory spec, and this would be a syntax
1143 error. Thus we strip the ".]", and thus merge the directory specs.
1144 We also backspace unixname, so that it points to a '/'. This inhibits the
1145 generation of the 000000 root directory spec (which does not belong here
1148 basename -= 2; /* Strip ".]" */
1149 unixname--; /* backspace */
1157 /* We drop in here if there is no VMS style directory specification yet.
1158 If there is no device specification either, we make the first dir a
1159 device and try that. If we do not do this, then we will be essentially
1160 searching the users default directory (as if they did a #include "asdf.h").
1162 Then all we need to do is to push a '[' into the output string. Later
1163 processing will fill this in, and close the bracket. */
1165 if ((unixname != fullname) /* vms path spec found. */
1166 && (basename[-1] != ':'))
1167 *local_ptr++ = ':'; /* dev not in spec. take first dir */
1169 *local_ptr++ = '['; /* Open the directory specification */
1172 if (unixname == fullname) /* no vms dir spec. */
1175 if ((first_slash != 0) /* unix dir spec. */
1176 && (*unixname != '/') /* not beginning with '/' */
1177 && (*unixname != '.')) /* or './' or '../' */
1178 *local_ptr++ = '.'; /* dir is local ! */
1181 /* at this point we assume that we have the device spec, and (at least
1182 the opening "[" for a directory specification. We may have directories
1185 If there are no other slashes then the filename will be
1186 in the "root" directory. Otherwise, we need to add
1187 directory specifications. */
1189 if (index (unixname, '/') == 0)
1191 /* if no directories specified yet and none are following. */
1192 if (local_ptr[-1] == '[')
1194 /* Just add "000000]" as the directory string */
1195 strcpy (local_ptr, "000000]");
1196 local_ptr += strlen (local_ptr);
1197 check_filename_before_returning = 1; /* we might need to fool with this later */
1203 /* As long as there are still subdirectories to add, do them. */
1204 while (index (unixname, '/') != 0)
1206 /* If this token is "." we can ignore it
1207 if it's not at the beginning of a path. */
1208 if ((unixname[0] == '.') && (unixname[1] == '/'))
1210 /* remove it at beginning of path. */
1211 if ( ((unixname == fullname) /* no device spec */
1212 && (fullname+2 != basename)) /* starts with ./ */
1214 || ((basename[-1] == ':') /* device spec */
1215 && (unixname-1 == basename))) /* and ./ afterwards */
1216 *local_ptr++ = '.'; /* make '[.' start of path. */
1221 /* Add a subdirectory spec. Do not duplicate "." */
1222 if ( local_ptr[-1] != '.'
1223 && local_ptr[-1] != '['
1224 && local_ptr[-1] != '<')
1227 /* If this is ".." then the spec becomes "-" */
1228 if ( (unixname[0] == '.')
1229 && (unixname[1] == '.')
1230 && (unixname[2] == '/'))
1232 /* Add "-" and skip the ".." */
1233 if ((local_ptr[-1] == '.')
1234 && (local_ptr[-2] == '['))
1235 local_ptr--; /* prevent [.- */
1241 /* Copy the subdirectory */
1242 while (*unixname != '/')
1243 *local_ptr++= *unixname++;
1245 unixname++; /* Skip the "/" */
1248 /* Close the directory specification */
1249 if (local_ptr[-1] == '.') /* no trailing periods */
1252 if (local_ptr[-1] == '[') /* no dir needed */
1258 /* Now add the filename. */
1261 *local_ptr++ = *unixname++;
1264 /* Now append it to the original VMS spec. */
1266 strcpy ((must_revert==1)?fullname:basename, Local);
1268 /* If we put a [000000] in the filename, try to open it first. If this fails,
1269 remove the [000000], and return that name. This provides flexibility
1270 to the user in that they can use both rooted and non-rooted logical names
1271 to point to the location of the file. */
1273 if (check_filename_before_returning)
1275 f = open (fullname, O_RDONLY, 0666);
1278 /* The file name is OK as it is, so return it as is. */
1283 /* The filename did not work. Try to remove the [000000] from the name,
1286 basename = index (fullname, '[');
1287 local_ptr = index (fullname, ']') + 1;
1288 strcpy (basename, local_ptr); /* this gets rid of it */