1 /* Part of CPP library. (include file handling)
2 Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998,
3 1999, 2000 Free Software Foundation, Inc.
4 Written by Per Bothner, 1994.
5 Based on CCCP program by Paul Rubin, June 1986
6 Adapted to ANSI C, Richard Stallman, Jan 1987
7 Split out of cpplib.c, Zack Weinberg, Oct 1998
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding! */
35 static IHASH *redundant_include_p PARAMS ((cpp_reader *, IHASH *,
36 struct file_name_list *));
37 static struct file_name_map *read_name_map
38 PARAMS ((cpp_reader *, const char *));
39 static char *read_filename_string PARAMS ((int, FILE *));
40 static char *remap_filename PARAMS ((cpp_reader *, char *,
41 struct file_name_list *));
42 static struct file_name_list *actual_directory
43 PARAMS ((cpp_reader *, const char *));
44 static unsigned int hash_IHASH PARAMS ((const void *));
45 static int eq_IHASH PARAMS ((const void *, const void *));
46 static int file_cleanup PARAMS ((cpp_buffer *, cpp_reader *));
47 static int find_include_file PARAMS ((cpp_reader *, const char *,
48 struct file_name_list *,
50 static int read_include_file PARAMS ((cpp_reader *, int, IHASH *));
54 static void hack_vms_include_specification PARAMS ((char *));
57 /* Initial size of include hash table. */
60 #ifndef INCLUDE_LEN_FUDGE
61 #define INCLUDE_LEN_FUDGE 0
64 /* Open files in nonblocking mode, so we don't get stuck if someone
65 clever has asked cpp to process /dev/rmt0. read_include_file
66 will check that we have a real file to work with. Also take care
67 not to acquire a controlling terminal by mistake (this can't happen
68 on sane systems, but paranoia is a virtue). */
69 #define OMODES O_RDONLY|O_NONBLOCK|O_NOCTTY
71 /* Calculate hash of an IHASH entry. */
76 IHASH *i = (IHASH *)x;
77 unsigned int r = 0, len = 0;
78 const U_CHAR *s = i->nshort;
80 if (i->hash != (unsigned long)-1)
84 len++, r = r * 67 + (*s++ - 113);
85 while (*s && *s != '.');
90 /* Compare an existing IHASH structure with a potential one. */
96 const U_CHAR *a = ((const IHASH *)x)->nshort;
97 const U_CHAR *b = ((const IHASH *)y)->nshort;
98 return !strcmp (a, b);
101 /* Init the hash table. In here so it can see the hash and eq functions. */
103 _cpp_init_include_hash (pfile)
106 pfile->all_include_files
107 = htab_create (IHASHSIZE, hash_IHASH, eq_IHASH, free);
110 /* Return 0 if the file pointed to by IHASH has never been included before,
111 -1 if it has been included before and need not be again,
112 or a pointer to an IHASH entry which is the file to be reread.
113 "Never before" is with respect to the position in ILIST.
115 This will not detect redundancies involving odd uses of the
116 `current directory' rule for "" includes. They aren't quite
117 pathological, but I think they are rare enough not to worry about.
118 The simplest example is:
127 and the problem is that for `current directory' includes,
128 ihash->foundhere is not on any of the global include chains,
129 so the test below (i->foundhere == l) may be false even when
130 the directories are in fact the same. */
133 redundant_include_p (pfile, ihash, ilist)
136 struct file_name_list *ilist;
138 struct file_name_list *l;
141 if (! ihash->foundhere)
144 for (i = ihash; i; i = i->next_this_file)
145 for (l = ilist; l; l = l->next)
146 if (i->foundhere == l)
147 /* The control_macro works like this: If it's NULL, the file
148 is to be included again. If it's "", the file is never to
149 be included again. If it's a string, the file is not to be
150 included again if the string is the name of a defined macro. */
151 return (i->control_macro
152 && (i->control_macro[0] == '\0'
153 || cpp_defined (pfile, i->control_macro, -1)))
159 /* Return 1 if the file named by FNAME has been included before in
160 any context, 0 otherwise. */
162 cpp_included (pfile, fname)
167 dummy.nshort = fname;
169 ptr = htab_find (pfile->all_include_files, (const void *)&dummy);
170 return (ptr != NULL);
174 file_cleanup (pbuf, pfile)
179 free ((PTR) pbuf->buf);
180 if (pfile->system_include_depth)
181 pfile->system_include_depth--;
185 /* Search for include file FNAME in the include chain starting at
186 SEARCH_START. Return -2 if this file doesn't need to be included
187 (because it was included already and it's marked idempotent),
188 -1 if an error occurred, or a file descriptor open on the file.
189 *IHASH is set to point to the include hash entry for this file, and
190 *BEFORE is set to 1 if the file was included before (but needs to be read
193 find_include_file (pfile, fname, search_start, ihash, before)
196 struct file_name_list *search_start;
200 struct file_name_list *path;
207 dummy.nshort = fname;
208 path = (fname[0] == '/') ? ABSOLUTE_PATH : search_start;
209 slot = (IHASH **) htab_find_slot (pfile->all_include_files,
210 (const void *)&dummy, 1);
212 if (*slot && (ih = redundant_include_p (pfile, *slot, path)))
214 if (ih == (IHASH *)-1)
219 return open (ih->name, OMODES);
222 if (path == ABSOLUTE_PATH)
224 name = (char *) fname;
225 f = open (name, OMODES);
229 /* Search directory path, trying to open the file. */
230 name = alloca (strlen (fname) + pfile->max_include_len
231 + 2 + INCLUDE_LEN_FUDGE);
234 memcpy (name, path->name, path->nlen);
235 name[path->nlen] = '/';
236 strcpy (&name[path->nlen+1], fname);
237 _cpp_simplify_pathname (name);
238 if (CPP_OPTIONS (pfile)->remap)
239 name = remap_filename (pfile, name, path);
241 f = open (name, OMODES);
243 if (f == -1 && errno == EACCES)
246 "included file `%s' exists but is not readable",
260 ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name));
261 strcpy ((char *)ih->name, name);
262 ih->foundhere = path;
263 if (path == ABSOLUTE_PATH)
264 ih->nshort = ih->name;
266 ih->nshort = strstr (ih->name, fname);
267 ih->control_macro = NULL;
268 ih->hash = dummy.hash;
270 ih->next_this_file = *slot;
278 /* The file_name_map structure holds a mapping of file names for a
279 particular directory. This mapping is read from the file named
280 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
281 map filenames on a file system with severe filename restrictions,
282 such as DOS. The format of the file name map file is just a series
283 of lines with two tokens on each line. The first token is the name
284 to map, and the second token is the actual name to use. */
288 struct file_name_map *map_next;
293 #define FILE_NAME_MAP_FILE "header.gcc"
295 /* Read a space delimited string of unlimited length from a stdio
299 read_filename_string (ch, f)
307 set = alloc = xmalloc (len + 1);
311 while ((ch = getc (f)) != EOF && ! is_space(ch))
313 if (set - alloc == len)
316 alloc = xrealloc (alloc, len + 1);
317 set = alloc + len / 2;
327 /* This structure holds a linked list of file name maps, one per directory. */
329 struct file_name_map_list
331 struct file_name_map_list *map_list_next;
333 struct file_name_map *map_list_map;
336 /* Read the file name map file for DIRNAME. */
338 static struct file_name_map *
339 read_name_map (pfile, dirname)
343 register struct file_name_map_list *map_list_ptr;
347 for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
348 map_list_ptr = map_list_ptr->map_list_next)
349 if (! strcmp (map_list_ptr->map_list_name, dirname))
350 return map_list_ptr->map_list_map;
352 map_list_ptr = ((struct file_name_map_list *)
353 xmalloc (sizeof (struct file_name_map_list)));
354 map_list_ptr->map_list_name = xstrdup (dirname);
356 name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
357 strcpy (name, dirname);
360 strcat (name, FILE_NAME_MAP_FILE);
361 f = fopen (name, "r");
363 map_list_ptr->map_list_map = (struct file_name_map *)-1;
367 int dirlen = strlen (dirname);
369 while ((ch = getc (f)) != EOF)
372 struct file_name_map *ptr;
376 from = read_filename_string (ch, f);
377 while ((ch = getc (f)) != EOF && is_hspace(ch))
379 to = read_filename_string (ch, f);
381 ptr = ((struct file_name_map *)
382 xmalloc (sizeof (struct file_name_map)));
383 ptr->map_from = from;
385 /* Make the real filename absolute. */
390 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
391 strcpy (ptr->map_to, dirname);
392 ptr->map_to[dirlen] = '/';
393 strcpy (ptr->map_to + dirlen + 1, to);
397 ptr->map_next = map_list_ptr->map_list_map;
398 map_list_ptr->map_list_map = ptr;
400 while ((ch = getc (f)) != '\n')
407 map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
408 CPP_OPTIONS (pfile)->map_list = map_list_ptr;
410 return map_list_ptr->map_list_map;
413 /* Remap NAME based on the file_name_map (if any) for LOC. */
416 remap_filename (pfile, name, loc)
419 struct file_name_list *loc;
421 struct file_name_map *map;
422 const char *from, *p, *dir;
425 loc->name_map = read_name_map (pfile,
429 if (loc->name_map == (struct file_name_map *)-1)
432 from = name + strlen (loc->name) + 1;
434 for (map = loc->name_map; map; map = map->map_next)
435 if (!strcmp (map->map_from, from))
438 /* Try to find a mapping file for the particular directory we are
439 looking in. Thus #include <sys/types.h> will look up sys/types.h
440 in /usr/include/header.gcc and look up types.h in
441 /usr/include/sys/header.gcc. */
442 p = strrchr (name, '/');
446 && strlen (loc->name) == (size_t) (p - name)
447 && !strncmp (loc->name, name, p - name))
448 /* FILENAME is in SEARCHPTR, which we've already checked. */
458 char * newdir = (char *) alloca (p - name + 1);
459 memcpy (newdir, name, p - name);
460 newdir[p - name] = '\0';
465 for (map = read_name_map (pfile, dir); map; map = map->map_next)
466 if (! strcmp (map->map_from, name))
474 _cpp_execute_include (pfile, fname, len, no_reinclude, search_start)
479 struct file_name_list *search_start;
483 int angle_brackets = fname[0] == '<';
489 search_start = CPP_OPTIONS (pfile)->bracket_include;
490 else if (CPP_OPTIONS (pfile)->ignore_srcdir)
491 search_start = CPP_OPTIONS (pfile)->quote_include;
493 search_start = CPP_BUFFER (pfile)->actual_dir;
498 cpp_error (pfile, "No include path in which to find %s", fname);
502 /* Remove quote marks. */
507 fd = find_include_file (pfile, fname, search_start, &ihash, &before);
514 if (CPP_OPTIONS (pfile)->print_deps_missing_files
515 && CPP_PRINT_DEPS (pfile) > (angle_brackets ||
516 (pfile->system_include_depth > 0)))
519 deps_add_dep (pfile->deps, fname);
523 struct file_name_list *ptr;
524 /* If requested as a system header, assume it belongs in
525 the first system header directory. */
526 if (CPP_OPTIONS (pfile)->bracket_include)
527 ptr = CPP_OPTIONS (pfile)->bracket_include;
529 ptr = CPP_OPTIONS (pfile)->quote_include;
531 p = (char *) alloca (strlen (ptr->name)
532 + strlen (fname) + 2);
533 if (*ptr->name != '\0')
535 strcpy (p, ptr->name);
539 deps_add_dep (pfile->deps, p);
542 /* If -M was specified, and this header file won't be added to
543 the dependency list, then don't count this as an error,
544 because we can still produce correct output. Otherwise, we
545 can't produce correct output, because there may be
546 dependencies we need inside the missing file, and we don't
547 know what directory this missing file exists in. */
548 else if (CPP_PRINT_DEPS (pfile)
549 && (CPP_PRINT_DEPS (pfile)
550 <= (angle_brackets || (pfile->system_include_depth > 0))))
551 cpp_warning (pfile, "No include path in which to find %s", fname);
553 cpp_error_from_errno (pfile, fname);
558 /* For -M, add the file to the dependencies on its first inclusion. */
559 if (!before && (CPP_PRINT_DEPS (pfile)
560 > (angle_brackets || (pfile->system_include_depth > 0))))
561 deps_add_dep (pfile->deps, ihash->name);
563 /* Handle -H option. */
564 if (CPP_OPTIONS(pfile)->print_include_names)
566 cpp_buffer *fp = CPP_BUFFER (pfile);
567 while ((fp = CPP_PREV_BUFFER (fp)) != NULL)
569 fprintf (stderr, " %s\n", ihash->name);
572 /* Actually process the file */
575 ihash->control_macro = (const U_CHAR *) "";
577 if (read_include_file (pfile, fd, ihash))
579 _cpp_output_line_command (pfile, enter_file);
581 pfile->system_include_depth++; /* Decremented in file_cleanup. */
586 /* Push an input buffer and load it up with the contents of FNAME.
587 If FNAME is "" or NULL, read standard input. */
589 cpp_read_file (pfile, fname)
601 dummy.nshort = fname;
602 slot = (IHASH **) htab_find_slot (pfile->all_include_files,
603 (const void *) &dummy, 1);
604 if (*slot && (ih = redundant_include_p (pfile, *slot, ABSOLUTE_PATH)))
606 if (ih == (IHASH *)-1)
607 return 1; /* Already included. */
611 ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (fname));
612 ih->control_macro = 0;
613 ih->foundhere = ABSOLUTE_PATH; /* well sort of ... */
614 ih->hash = dummy.hash;
615 strcpy ((char *)ih->name, fname);
616 ih->nshort = ih->name;
618 ih->next_this_file = *slot;
625 f = open (fname, OMODES);
627 return read_include_file (pfile, f, ih);
630 /* Read the contents of FD into the buffer on the top of PFILE's stack.
631 IHASH points to the include hash entry for the file associated with
634 The caller is responsible for the cpp_push_buffer. */
637 read_include_file (pfile, fd, ihash)
647 fp = cpp_push_buffer (pfile, NULL, 0);
652 if (fstat (fd, &st) < 0)
654 if (fcntl (fd, F_SETFL, 0) == -1) /* turn off nonblocking mode */
657 /* If fd points to a plain file, we know how big it is, so we can
658 allocate the buffer all at once. If fd is a pipe or terminal, we
659 can't. Most C source files are 4k or less, so we guess that. If
660 fd is something weird, like a block device or a directory, we
661 don't want to read it at all.
663 Unfortunately, different systems use different st.st_mode values
664 for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and
665 zero the entire struct stat except a couple fields. Hence the
668 In all cases, read_and_prescan will resize the buffer if it
669 turns out there's more data than we thought. */
671 if (S_ISREG (st.st_mode))
673 /* off_t might have a wider range than size_t - in other words,
674 the max size of a file might be bigger than the address
675 space. We can't handle a file that large. (Anyone with
676 a single source file bigger than 4GB needs to rethink
677 their coding style.) */
678 st_size = (size_t) st.st_size;
679 if ((unsigned HOST_WIDEST_INT) st_size
680 != (unsigned HOST_WIDEST_INT) st.st_size)
682 cpp_error (pfile, "file `%s' is too large", ihash->name);
686 else if (S_ISFIFO (st.st_mode) || S_ISSOCK (st.st_mode)
687 /* Permit any kind of character device: the sensible ones are
688 ttys and /dev/null, but weeding out the others is too hard. */
689 || S_ISCHR (st.st_mode)
690 /* Some 4.x (x<4) derivatives have a bug that makes fstat() of a
691 socket or pipe return a stat struct with most fields zeroed. */
692 || (st.st_mode == 0 && st.st_nlink == 0 && st.st_size == 0))
694 /* Cannot get its file size before reading. 4k is a decent
700 cpp_error (pfile, "`%s' is not a file, pipe, or tty", ihash->name);
704 /* Read the file, converting end-of-line characters and trigraphs
707 fp->nominal_fname = ihash->name;
708 length = _cpp_read_and_prescan (pfile, fp, fd, st_size);
712 ihash->control_macro = (const U_CHAR *) ""; /* never re-include */
715 fp->rlimit = fp->alimit = fp->buf + length;
717 if (ihash->foundhere != ABSOLUTE_PATH)
718 fp->system_header_p = ihash->foundhere->sysp;
721 fp->line_base = fp->buf;
722 fp->cleanup = file_cleanup;
724 /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
726 if (!CPP_OPTIONS (pfile)->ignore_srcdir)
727 fp->actual_dir = actual_directory (pfile, ihash->name);
729 pfile->input_stack_listing_current = 0;
730 pfile->only_seen_white = 2;
734 cpp_error_from_errno (pfile, ihash->name);
736 cpp_pop_buffer (pfile);
742 /* Given a path FNAME, extract the directory component and place it
743 onto the actual_dirs list. Return a pointer to the allocated
744 file_name_list structure. These structures are used to implement
745 current-directory "" include searching. */
747 static struct file_name_list *
748 actual_directory (pfile, fname)
752 char *last_slash, *dir;
754 struct file_name_list *x;
756 dir = xstrdup (fname);
757 last_slash = strrchr (dir, '/');
760 if (last_slash == dir)
763 last_slash[1] = '\0';
767 dlen = last_slash - dir;
778 if (dlen > pfile->max_include_len)
779 pfile->max_include_len = dlen;
781 for (x = pfile->actual_dirs; x; x = x->alloc)
782 if (!strcmp (x->name, dir))
788 /* Not found, make a new one. */
789 x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
792 x->next = CPP_OPTIONS (pfile)->quote_include;
793 x->alloc = pfile->actual_dirs;
794 x->sysp = CPP_BUFFER (pfile)->system_header_p;
797 pfile->actual_dirs = x;
801 /* Simplify a path name in place, deleting redundant components. This
802 reduces OS overhead and guarantees that equivalent paths compare
803 the same (modulo symlinks).
806 foo/bar/../quux foo/quux
810 //quux //quux (POSIX allows leading // as a namespace escape)
812 Guarantees no trailing slashes. All transforms reduce the length
816 _cpp_simplify_pathname (path)
823 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
824 /* Convert all backslashes to slashes. */
825 for (from = path; *from; from++)
826 if (*from == '\\') *from = '/';
828 /* Skip over leading drive letter if present. */
829 if (ISALPHA (path[0]) && path[1] == ':')
830 from = to = &path[2];
837 /* Remove redundant initial /s. */
846 /* 3 or more initial /s are equivalent to 1 /. */
847 while (*++from == '/');
849 /* On some hosts // differs from /; Posix allows this. */
860 if (from[0] == '.' && from[1] == '/')
862 else if (from[0] == '.' && from[1] == '\0')
864 else if (from[0] == '.' && from[1] == '.' && from[2] == '/')
881 while (to > base && *to != '/') to--;
887 else if (from[0] == '.' && from[1] == '.' && from[2] == '\0')
900 while (to > base && *to != '/') to--;
907 /* Copy this component and trailing /, if any. */
908 while ((*to++ = *from++) != '/')
920 /* Trim trailing slash */
921 if (to[0] == '/' && (!absolute || to > path+1))
924 /* Change the empty string to "." so that stat() on the result
934 /* It is not clear when this should be used if at all, so I've
935 disabled it until someone who understands VMS can look at it. */
938 /* Under VMS we need to fix up the "include" specification filename.
940 Rules for possible conversions
945 ./dir/name [.dir]name
947 /name [000000]name, name
948 dir/name dir:[000000]name, dir:name, dir/name
949 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
950 path:/name path:[000000]name, path:name
951 path:/dir/name path:[000000.dir]name, path:[dir]name
952 path:dir/name path:[dir]name
953 [path]:[dir]name [path.dir]name
954 path/[dir]name [path.dir]name
956 The path:/name input is constructed when expanding <> includes. */
960 hack_vms_include_specification (fullname)
963 register char *basename, *unixname, *local_ptr, *first_slash;
964 int f, check_filename_before_returning, must_revert;
967 check_filename_before_returning = 0;
969 /* See if we can find a 1st slash. If not, there's no path information. */
970 first_slash = strchr (fullname, '/');
971 if (first_slash == 0)
972 return 0; /* Nothing to do!!! */
974 /* construct device spec if none given. */
976 if (strchr (fullname, ':') == 0)
979 /* If fullname has a slash, take it as device spec. */
981 if (first_slash == fullname)
983 first_slash = strchr (fullname + 1, '/'); /* 2nd slash ? */
985 *first_slash = ':'; /* make device spec */
986 for (basename = fullname; *basename != 0; basename++)
987 *basename = *(basename+1); /* remove leading slash */
989 else if ((first_slash[-1] != '.') /* keep ':/', './' */
990 && (first_slash[-1] != ':')
991 && (first_slash[-1] != ']')) /* or a vms path */
995 else if ((first_slash[1] == '[') /* skip './' in './[dir' */
996 && (first_slash[-1] == '.'))
1000 /* Get part after first ':' (basename[-1] == ':')
1001 or last '/' (basename[-1] == '/'). */
1003 basename = base_name (fullname);
1005 local_ptr = Local; /* initialize */
1007 /* We are trying to do a number of things here. First of all, we are
1008 trying to hammer the filenames into a standard format, such that later
1009 processing can handle them.
1011 If the file name contains something like [dir.], then it recognizes this
1012 as a root, and strips the ".]". Later processing will add whatever is
1013 needed to get things working properly.
1015 If no device is specified, then the first directory name is taken to be
1016 a device name (or a rooted logical). */
1018 /* Point to the UNIX filename part (which needs to be fixed!)
1019 but skip vms path information.
1020 [basename != fullname since first_slash != 0]. */
1022 if ((basename[-1] == ':') /* vms path spec. */
1023 || (basename[-1] == ']')
1024 || (basename[-1] == '>'))
1025 unixname = basename;
1027 unixname = fullname;
1029 if (*unixname == '/')
1032 /* If the directory spec is not rooted, we can just copy
1033 the UNIX filename part and we are done. */
1035 if (((basename - fullname) > 1)
1036 && ( (basename[-1] == ']')
1037 || (basename[-1] == '>')))
1039 if (basename[-2] != '.')
1042 /* The VMS part ends in a `]', and the preceding character is not a `.'.
1043 -> PATH]:/name (basename = '/name', unixname = 'name')
1044 We strip the `]', and then splice the two parts of the name in the
1045 usual way. Given the default locations for include files in cccp.c,
1046 we will only use this code if the user specifies alternate locations
1047 with the /include (-I) switch on the command line. */
1049 basename -= 1; /* Strip "]" */
1050 unixname--; /* backspace */
1055 /* The VMS part has a ".]" at the end, and this will not do. Later
1056 processing will add a second directory spec, and this would be a syntax
1057 error. Thus we strip the ".]", and thus merge the directory specs.
1058 We also backspace unixname, so that it points to a '/'. This inhibits the
1059 generation of the 000000 root directory spec (which does not belong here
1062 basename -= 2; /* Strip ".]" */
1063 unixname--; /* backspace */
1071 /* We drop in here if there is no VMS style directory specification yet.
1072 If there is no device specification either, we make the first dir a
1073 device and try that. If we do not do this, then we will be essentially
1074 searching the users default directory (as if they did a #include "asdf.h").
1076 Then all we need to do is to push a '[' into the output string. Later
1077 processing will fill this in, and close the bracket. */
1079 if ((unixname != fullname) /* vms path spec found. */
1080 && (basename[-1] != ':'))
1081 *local_ptr++ = ':'; /* dev not in spec. take first dir */
1083 *local_ptr++ = '['; /* Open the directory specification */
1086 if (unixname == fullname) /* no vms dir spec. */
1089 if ((first_slash != 0) /* unix dir spec. */
1090 && (*unixname != '/') /* not beginning with '/' */
1091 && (*unixname != '.')) /* or './' or '../' */
1092 *local_ptr++ = '.'; /* dir is local ! */
1095 /* at this point we assume that we have the device spec, and (at least
1096 the opening "[" for a directory specification. We may have directories
1099 If there are no other slashes then the filename will be
1100 in the "root" directory. Otherwise, we need to add
1101 directory specifications. */
1103 if (strchr (unixname, '/') == 0)
1105 /* if no directories specified yet and none are following. */
1106 if (local_ptr[-1] == '[')
1108 /* Just add "000000]" as the directory string */
1109 strcpy (local_ptr, "000000]");
1110 local_ptr += strlen (local_ptr);
1111 check_filename_before_returning = 1; /* we might need to fool with this later */
1117 /* As long as there are still subdirectories to add, do them. */
1118 while (strchr (unixname, '/') != 0)
1120 /* If this token is "." we can ignore it
1121 if it's not at the beginning of a path. */
1122 if ((unixname[0] == '.') && (unixname[1] == '/'))
1124 /* remove it at beginning of path. */
1125 if ( ((unixname == fullname) /* no device spec */
1126 && (fullname+2 != basename)) /* starts with ./ */
1128 || ((basename[-1] == ':') /* device spec */
1129 && (unixname-1 == basename))) /* and ./ afterwards */
1130 *local_ptr++ = '.'; /* make '[.' start of path. */
1135 /* Add a subdirectory spec. Do not duplicate "." */
1136 if ( local_ptr[-1] != '.'
1137 && local_ptr[-1] != '['
1138 && local_ptr[-1] != '<')
1141 /* If this is ".." then the spec becomes "-" */
1142 if ( (unixname[0] == '.')
1143 && (unixname[1] == '.')
1144 && (unixname[2] == '/'))
1146 /* Add "-" and skip the ".." */
1147 if ((local_ptr[-1] == '.')
1148 && (local_ptr[-2] == '['))
1149 local_ptr--; /* prevent [.- */
1155 /* Copy the subdirectory */
1156 while (*unixname != '/')
1157 *local_ptr++= *unixname++;
1159 unixname++; /* Skip the "/" */
1162 /* Close the directory specification */
1163 if (local_ptr[-1] == '.') /* no trailing periods */
1166 if (local_ptr[-1] == '[') /* no dir needed */
1172 /* Now add the filename. */
1175 *local_ptr++ = *unixname++;
1178 /* Now append it to the original VMS spec. */
1180 strcpy ((must_revert==1)?fullname:basename, Local);
1182 /* If we put a [000000] in the filename, try to open it first. If this fails,
1183 remove the [000000], and return that name. This provides flexibility
1184 to the user in that they can use both rooted and non-rooted logical names
1185 to point to the location of the file. */
1187 if (check_filename_before_returning)
1189 f = open (fullname, OMODES);
1192 /* The file name is OK as it is, so return it as is. */
1197 /* The filename did not work. Try to remove the [000000] from the name,
1200 basename = strchr (fullname, '[');
1201 local_ptr = strchr (fullname, ']') + 1;
1202 strcpy (basename, local_ptr); /* this gets rid of it */