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. */
31 static IHASH *redundant_include_p PARAMS ((cpp_reader *, IHASH *,
32 struct file_name_list *));
33 static IHASH *make_IHASH PARAMS ((const char *, const char *,
34 struct file_name_list *,
35 unsigned int, IHASH **));
36 static struct file_name_map *read_name_map
37 PARAMS ((cpp_reader *, const char *));
38 static char *read_filename_string PARAMS ((int, FILE *));
39 static char *remap_filename PARAMS ((cpp_reader *, char *,
40 struct file_name_list *));
41 static struct file_name_list *actual_directory
42 PARAMS ((cpp_reader *, const char *));
43 static unsigned int hash_IHASH PARAMS ((const void *));
44 static int eq_IHASH PARAMS ((const void *, const void *));
45 static int find_include_file PARAMS ((cpp_reader *, const char *,
46 struct file_name_list *,
48 static int read_include_file PARAMS ((cpp_reader *, int, IHASH *));
49 static inline int open_include_file PARAMS ((cpp_reader *, const char *));
52 static void hack_vms_include_specification PARAMS ((char *));
55 /* Initial size of include hash table. */
58 #ifndef INCLUDE_LEN_FUDGE
59 #define INCLUDE_LEN_FUDGE 0
62 /* Calculate hash of an IHASH entry. */
67 const IHASH *i = (const IHASH *)x;
71 /* Compare an existing IHASH structure with a potential one. */
77 const U_CHAR *a = ((const IHASH *)x)->nshort;
78 const U_CHAR *b = ((const IHASH *)y)->nshort;
79 return !strcmp (a, b);
82 /* Init the hash table. In here so it can see the hash and eq functions. */
84 _cpp_init_include_hash (pfile)
87 pfile->all_include_files
88 = htab_create (IHASHSIZE, hash_IHASH, eq_IHASH, free);
91 /* Return 0 if the file pointed to by IHASH has never been included before,
92 -1 if it has been included before and need not be again,
93 or a pointer to an IHASH entry which is the file to be reread.
94 "Never before" is with respect to the position in ILIST.
96 This will not detect redundancies involving odd uses of the
97 `current directory' rule for "" includes. They aren't quite
98 pathological, but I think they are rare enough not to worry about.
99 The simplest example is:
108 and the problem is that for `current directory' includes,
109 ihash->foundhere is not on any of the global include chains,
110 so the test below (i->foundhere == l) may be false even when
111 the directories are in fact the same. */
114 redundant_include_p (pfile, ihash, ilist)
117 struct file_name_list *ilist;
119 struct file_name_list *l;
122 if (! ihash->foundhere)
125 for (i = ihash; i; i = i->next_this_file)
126 for (l = ilist; l; l = l->next)
127 if (i->foundhere == l)
128 /* The control_macro works like this: If it's NULL, the file
129 is to be included again. If it's "", the file is never to
130 be included again. If it's a string, the file is not to be
131 included again if the string is the name of a defined macro. */
132 return (i->control_macro
133 && (i->control_macro[0] == '\0'
134 || cpp_defined (pfile, i->control_macro,
135 strlen (i->control_macro))))
141 /* Return 1 if the file named by FNAME has been included before in
142 any context, 0 otherwise. */
144 cpp_included (pfile, fname)
149 dummy.nshort = fname;
150 dummy.hash = _cpp_calc_hash (fname, strlen (fname));
151 ptr = htab_find_with_hash (pfile->all_include_files,
152 (const void *)&dummy, dummy.hash);
153 return (ptr != NULL);
156 /* Create an IHASH entry and insert it in SLOT. */
158 make_IHASH (name, fname, path, hash, slot)
159 const char *name, *fname;
160 struct file_name_list *path;
165 if (path == ABSOLUTE_PATH)
167 ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name));
168 ih->nshort = ih->name;
174 if ((s = strstr (name, fname)) != NULL)
176 ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name));
177 ih->nshort = ih->name + (s - name);
181 ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name)
182 + strlen (fname) + 1);
183 ih->nshort = ih->name + strlen (name) + 1;
184 strcpy ((char *)ih->nshort, fname);
187 strcpy ((char *)ih->name, name);
188 ih->foundhere = path;
189 ih->control_macro = NULL;
191 ih->next_this_file = *slot;
196 /* Centralize calls to open(2) here. This provides a hook for future
197 changes which might, e.g. look for and open a precompiled version
198 of the header. It also means all the magic currently associated
199 with calling open is in one place, and if we ever need more, it'll
202 We used to open files in nonblocking mode, but that caused more
203 problems than it solved. Do take care not to acquire a controlling
204 terminal by mistake (this can't happen on sane systems, but
205 paranoia is a virtue).
207 Use the three-argument form of open even though we aren't
208 specifying O_CREAT, to defend against broken system headers. */
211 open_include_file (pfile, filename)
212 cpp_reader *pfile ATTRIBUTE_UNUSED;
213 const char *filename;
215 return open (filename, O_RDONLY|O_NOCTTY, 0666);
218 /* Search for include file FNAME in the include chain starting at
219 SEARCH_START. Return -2 if this file doesn't need to be included
220 (because it was included already and it's marked idempotent),
221 -1 if an error occurred, or a file descriptor open on the file.
222 *IHASH is set to point to the include hash entry for this file, and
223 *BEFORE is set to 1 if the file was included before (but needs to be read
226 find_include_file (pfile, fname, search_start, ihash, before)
229 struct file_name_list *search_start;
233 struct file_name_list *path;
239 dummy.nshort = fname;
240 dummy.hash = _cpp_calc_hash (fname, strlen (fname));
241 path = (fname[0] == '/') ? ABSOLUTE_PATH : search_start;
242 slot = (IHASH **) htab_find_slot_with_hash (pfile->all_include_files,
243 (const void *) &dummy,
246 if (*slot && (ih = redundant_include_p (pfile, *slot, path)))
248 if (ih == (IHASH *)-1)
253 return open_include_file (pfile, ih->name);
256 if (path == ABSOLUTE_PATH)
258 name = (char *) fname;
259 f = open_include_file (pfile, name);
263 /* Search directory path, trying to open the file. */
264 name = (char *) alloca (strlen (fname) + pfile->max_include_len
265 + 2 + INCLUDE_LEN_FUDGE);
268 memcpy (name, path->name, path->nlen);
269 name[path->nlen] = '/';
270 strcpy (&name[path->nlen+1], fname);
271 _cpp_simplify_pathname (name);
272 if (CPP_OPTION (pfile, remap))
273 name = remap_filename (pfile, name, path);
275 f = open_include_file (pfile, name);
277 if (f == -1 && errno == EACCES)
280 "included file `%s' exists but is not readable",
294 ih = make_IHASH (name, fname, path, dummy.hash, slot);
300 /* Create a dummy IHASH entry for FNAME, and return its name pointer.
301 This is used by #line. */
303 _cpp_fake_ihash (pfile, fname)
310 dummy.nshort = fname;
311 dummy.hash = _cpp_calc_hash (fname, strlen (fname));
312 slot = (IHASH **) htab_find_slot_with_hash (pfile->all_include_files,
313 (const void *) &dummy,
316 return (*slot)->name;
317 ih = make_IHASH (fname, 0, ABSOLUTE_PATH, dummy.hash, slot);
322 /* The file_name_map structure holds a mapping of file names for a
323 particular directory. This mapping is read from the file named
324 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
325 map filenames on a file system with severe filename restrictions,
326 such as DOS. The format of the file name map file is just a series
327 of lines with two tokens on each line. The first token is the name
328 to map, and the second token is the actual name to use. */
332 struct file_name_map *map_next;
337 #define FILE_NAME_MAP_FILE "header.gcc"
339 /* Read a space delimited string of unlimited length from a stdio
343 read_filename_string (ch, f)
351 set = alloc = xmalloc (len + 1);
355 while ((ch = getc (f)) != EOF && ! is_space(ch))
357 if (set - alloc == len)
360 alloc = xrealloc (alloc, len + 1);
361 set = alloc + len / 2;
371 /* This structure holds a linked list of file name maps, one per directory. */
373 struct file_name_map_list
375 struct file_name_map_list *map_list_next;
377 struct file_name_map *map_list_map;
380 /* Read the file name map file for DIRNAME. */
382 static struct file_name_map *
383 read_name_map (pfile, dirname)
387 register struct file_name_map_list *map_list_ptr;
391 for (map_list_ptr = CPP_OPTION (pfile, map_list); map_list_ptr;
392 map_list_ptr = map_list_ptr->map_list_next)
393 if (! strcmp (map_list_ptr->map_list_name, dirname))
394 return map_list_ptr->map_list_map;
396 map_list_ptr = ((struct file_name_map_list *)
397 xmalloc (sizeof (struct file_name_map_list)));
398 map_list_ptr->map_list_name = xstrdup (dirname);
400 name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
401 strcpy (name, dirname);
404 strcat (name, FILE_NAME_MAP_FILE);
405 f = fopen (name, "r");
407 map_list_ptr->map_list_map = (struct file_name_map *)-1;
411 int dirlen = strlen (dirname);
413 while ((ch = getc (f)) != EOF)
416 struct file_name_map *ptr;
420 from = read_filename_string (ch, f);
421 while ((ch = getc (f)) != EOF && is_hspace(ch))
423 to = read_filename_string (ch, f);
425 ptr = ((struct file_name_map *)
426 xmalloc (sizeof (struct file_name_map)));
427 ptr->map_from = from;
429 /* Make the real filename absolute. */
434 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
435 strcpy (ptr->map_to, dirname);
436 ptr->map_to[dirlen] = '/';
437 strcpy (ptr->map_to + dirlen + 1, to);
441 ptr->map_next = map_list_ptr->map_list_map;
442 map_list_ptr->map_list_map = ptr;
444 while ((ch = getc (f)) != '\n')
451 map_list_ptr->map_list_next = CPP_OPTION (pfile, map_list);
452 CPP_OPTION (pfile, map_list) = map_list_ptr;
454 return map_list_ptr->map_list_map;
457 /* Remap NAME based on the file_name_map (if any) for LOC. */
460 remap_filename (pfile, name, loc)
463 struct file_name_list *loc;
465 struct file_name_map *map;
466 const char *from, *p, *dir;
469 loc->name_map = read_name_map (pfile,
473 if (loc->name_map == (struct file_name_map *)-1)
476 from = name + strlen (loc->name) + 1;
478 for (map = loc->name_map; map; map = map->map_next)
479 if (!strcmp (map->map_from, from))
482 /* Try to find a mapping file for the particular directory we are
483 looking in. Thus #include <sys/types.h> will look up sys/types.h
484 in /usr/include/header.gcc and look up types.h in
485 /usr/include/sys/header.gcc. */
486 p = strrchr (name, '/');
490 && strlen (loc->name) == (size_t) (p - name)
491 && !strncmp (loc->name, name, p - name))
492 /* FILENAME is in SEARCHPTR, which we've already checked. */
502 char * newdir = (char *) alloca (p - name + 1);
503 memcpy (newdir, name, p - name);
504 newdir[p - name] = '\0';
509 for (map = read_name_map (pfile, dir); map; map = map->map_next)
510 if (! strcmp (map->map_from, name))
518 _cpp_execute_include (pfile, fname, len, no_reinclude, search_start)
523 struct file_name_list *search_start;
527 int angle_brackets = fname[0] == '<';
533 search_start = CPP_OPTION (pfile, bracket_include);
534 else if (CPP_OPTION (pfile, ignore_srcdir))
535 search_start = CPP_OPTION (pfile, quote_include);
537 search_start = CPP_BUFFER (pfile)->actual_dir;
542 cpp_error (pfile, "No include path in which to find %s", fname);
546 /* Remove quote marks. */
551 fd = find_include_file (pfile, fname, search_start, &ihash, &before);
558 if (CPP_OPTION (pfile, print_deps_missing_files)
559 && CPP_PRINT_DEPS (pfile) > (angle_brackets ||
560 (pfile->system_include_depth > 0)))
563 deps_add_dep (pfile->deps, fname);
567 struct file_name_list *ptr;
568 /* If requested as a system header, assume it belongs in
569 the first system header directory. */
570 if (CPP_OPTION (pfile, bracket_include))
571 ptr = CPP_OPTION (pfile, bracket_include);
573 ptr = CPP_OPTION (pfile, quote_include);
575 p = (char *) alloca (strlen (ptr->name)
576 + strlen (fname) + 2);
577 if (*ptr->name != '\0')
579 strcpy (p, ptr->name);
583 deps_add_dep (pfile->deps, p);
586 /* If -M was specified, and this header file won't be added to
587 the dependency list, then don't count this as an error,
588 because we can still produce correct output. Otherwise, we
589 can't produce correct output, because there may be
590 dependencies we need inside the missing file, and we don't
591 know what directory this missing file exists in. */
592 else if (CPP_PRINT_DEPS (pfile)
593 && (CPP_PRINT_DEPS (pfile)
594 <= (angle_brackets || (pfile->system_include_depth > 0))))
595 cpp_warning (pfile, "No include path in which to find %s", fname);
597 cpp_error_from_errno (pfile, fname);
602 /* For -M, add the file to the dependencies on its first inclusion. */
603 if (!before && (CPP_PRINT_DEPS (pfile)
604 > (angle_brackets || (pfile->system_include_depth > 0))))
605 deps_add_dep (pfile->deps, ihash->name);
607 /* Handle -H option. */
608 if (CPP_OPTION (pfile, print_include_names))
610 cpp_buffer *fp = CPP_BUFFER (pfile);
611 while ((fp = CPP_PREV_BUFFER (fp)) != NULL)
613 fprintf (stderr, " %s\n", ihash->name);
616 /* Actually process the file. */
618 ihash->control_macro = (const U_CHAR *) "";
620 if (read_include_file (pfile, fd, ihash))
623 pfile->system_include_depth++;
628 /* Push an input buffer and load it up with the contents of FNAME.
629 If FNAME is "" or NULL, read standard input. */
631 cpp_read_file (pfile, fname)
642 dummy.nshort = fname;
643 /* _cpp_calc_hash doesn't like zero-length strings. */
647 dummy.hash = _cpp_calc_hash (fname, strlen (fname));
648 slot = (IHASH **) htab_find_slot_with_hash (pfile->all_include_files,
649 (const void *) &dummy,
651 if (*slot && (ih = redundant_include_p (pfile, *slot, ABSOLUTE_PATH)))
653 if (ih == (IHASH *) -1)
654 return 1; /* Already included. */
657 ih = make_IHASH (fname, 0, ABSOLUTE_PATH, dummy.hash, slot);
662 f = open_include_file (pfile, fname);
664 return read_include_file (pfile, f, ih);
667 /* Read the contents of FD into the buffer on the top of PFILE's stack.
668 IHASH points to the include hash entry for the file associated with
671 The caller is responsible for the cpp_push_buffer. */
674 read_include_file (pfile, fd, ihash)
684 fp = cpp_push_buffer (pfile, NULL, 0);
689 if (fstat (fd, &st) < 0)
692 /* If fd points to a plain file, we know how big it is, so we can
693 allocate the buffer all at once. If fd is a pipe or terminal, we
694 can't. Most C source files are 4k or less, so we guess that. If
695 fd is something weird, like a directory, we don't want to read it
698 Unfortunately, different systems use different st.st_mode values
699 for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and
700 zero the entire struct stat except a couple fields. Hence we don't
701 even try to figure out what something is, except for plain files,
702 directories, and block devices.
704 In all cases, read_and_prescan will resize the buffer if it
705 turns out there's more data than we thought. */
707 if (S_ISREG (st.st_mode))
709 /* off_t might have a wider range than size_t - in other words,
710 the max size of a file might be bigger than the address
711 space. We can't handle a file that large. (Anyone with
712 a single source file bigger than 4GB needs to rethink
713 their coding style.) */
714 st_size = (size_t) st.st_size;
715 if ((unsigned HOST_WIDEST_INT) st_size
716 != (unsigned HOST_WIDEST_INT) st.st_size)
718 cpp_error (pfile, "file `%s' is too large", ihash->name);
722 else if (S_ISBLK (st.st_mode))
724 cpp_error (pfile, "%s is a block device", ihash->name);
727 else if (S_ISDIR (st.st_mode))
729 cpp_error (pfile, "%s is a directory", ihash->name);
734 /* We don't know how big this is. 4k is a decent first guess. */
738 /* Read the file, converting end-of-line characters and trigraphs
741 fp->nominal_fname = ihash->name;
742 length = _cpp_read_and_prescan (pfile, fp, fd, st_size);
746 ihash->control_macro = (const U_CHAR *) ""; /* never re-include */
749 fp->rlimit = fp->buf + length;
751 if (ihash->foundhere != ABSOLUTE_PATH)
752 fp->system_header_p = ihash->foundhere->sysp;
754 fp->line_base = fp->buf;
756 /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
758 if (!CPP_OPTION (pfile, ignore_srcdir))
759 fp->actual_dir = actual_directory (pfile, ihash->name);
761 pfile->input_stack_listing_current = 0;
762 pfile->only_seen_white = 2;
766 cpp_error_from_errno (pfile, ihash->name);
768 cpp_pop_buffer (pfile);
774 /* Given a path FNAME, extract the directory component and place it
775 onto the actual_dirs list. Return a pointer to the allocated
776 file_name_list structure. These structures are used to implement
777 current-directory "" include searching. */
779 static struct file_name_list *
780 actual_directory (pfile, fname)
784 char *last_slash, *dir;
786 struct file_name_list *x;
788 dir = xstrdup (fname);
789 last_slash = strrchr (dir, '/');
792 if (last_slash == dir)
795 last_slash[1] = '\0';
799 dlen = last_slash - dir;
810 if (dlen > pfile->max_include_len)
811 pfile->max_include_len = dlen;
813 for (x = pfile->actual_dirs; x; x = x->alloc)
814 if (!strcmp (x->name, dir))
820 /* Not found, make a new one. */
821 x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
824 x->next = CPP_OPTION (pfile, quote_include);
825 x->alloc = pfile->actual_dirs;
826 x->sysp = CPP_BUFFER (pfile)->system_header_p;
829 pfile->actual_dirs = x;
833 /* Simplify a path name in place, deleting redundant components. This
834 reduces OS overhead and guarantees that equivalent paths compare
835 the same (modulo symlinks).
838 foo/bar/../quux foo/quux
842 //quux //quux (POSIX allows leading // as a namespace escape)
844 Guarantees no trailing slashes. All transforms reduce the length
848 _cpp_simplify_pathname (path)
855 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
856 /* Convert all backslashes to slashes. */
857 for (from = path; *from; from++)
858 if (*from == '\\') *from = '/';
860 /* Skip over leading drive letter if present. */
861 if (ISALPHA (path[0]) && path[1] == ':')
862 from = to = &path[2];
869 /* Remove redundant initial /s. */
878 /* 3 or more initial /s are equivalent to 1 /. */
879 while (*++from == '/');
881 /* On some hosts // differs from /; Posix allows this. */
892 if (from[0] == '.' && from[1] == '/')
894 else if (from[0] == '.' && from[1] == '\0')
896 else if (from[0] == '.' && from[1] == '.' && from[2] == '/')
913 while (to > base && *to != '/') to--;
919 else if (from[0] == '.' && from[1] == '.' && from[2] == '\0')
932 while (to > base && *to != '/') to--;
939 /* Copy this component and trailing /, if any. */
940 while ((*to++ = *from++) != '/')
952 /* Trim trailing slash */
953 if (to[0] == '/' && (!absolute || to > path+1))
956 /* Change the empty string to "." so that stat() on the result
966 /* It is not clear when this should be used if at all, so I've
967 disabled it until someone who understands VMS can look at it. */
970 /* Under VMS we need to fix up the "include" specification filename.
972 Rules for possible conversions
977 ./dir/name [.dir]name
979 /name [000000]name, name
980 dir/name dir:[000000]name, dir:name, dir/name
981 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
982 path:/name path:[000000]name, path:name
983 path:/dir/name path:[000000.dir]name, path:[dir]name
984 path:dir/name path:[dir]name
985 [path]:[dir]name [path.dir]name
986 path/[dir]name [path.dir]name
988 The path:/name input is constructed when expanding <> includes. */
992 hack_vms_include_specification (fullname)
995 register char *basename, *unixname, *local_ptr, *first_slash;
996 int f, check_filename_before_returning, must_revert;
999 check_filename_before_returning = 0;
1001 /* See if we can find a 1st slash. If not, there's no path information. */
1002 first_slash = strchr (fullname, '/');
1003 if (first_slash == 0)
1004 return 0; /* Nothing to do!!! */
1006 /* construct device spec if none given. */
1008 if (strchr (fullname, ':') == 0)
1011 /* If fullname has a slash, take it as device spec. */
1013 if (first_slash == fullname)
1015 first_slash = strchr (fullname + 1, '/'); /* 2nd slash ? */
1017 *first_slash = ':'; /* make device spec */
1018 for (basename = fullname; *basename != 0; basename++)
1019 *basename = *(basename+1); /* remove leading slash */
1021 else if ((first_slash[-1] != '.') /* keep ':/', './' */
1022 && (first_slash[-1] != ':')
1023 && (first_slash[-1] != ']')) /* or a vms path */
1027 else if ((first_slash[1] == '[') /* skip './' in './[dir' */
1028 && (first_slash[-1] == '.'))
1032 /* Get part after first ':' (basename[-1] == ':')
1033 or last '/' (basename[-1] == '/'). */
1035 basename = base_name (fullname);
1037 local_ptr = Local; /* initialize */
1039 /* We are trying to do a number of things here. First of all, we are
1040 trying to hammer the filenames into a standard format, such that later
1041 processing can handle them.
1043 If the file name contains something like [dir.], then it recognizes this
1044 as a root, and strips the ".]". Later processing will add whatever is
1045 needed to get things working properly.
1047 If no device is specified, then the first directory name is taken to be
1048 a device name (or a rooted logical). */
1050 /* Point to the UNIX filename part (which needs to be fixed!)
1051 but skip vms path information.
1052 [basename != fullname since first_slash != 0]. */
1054 if ((basename[-1] == ':') /* vms path spec. */
1055 || (basename[-1] == ']')
1056 || (basename[-1] == '>'))
1057 unixname = basename;
1059 unixname = fullname;
1061 if (*unixname == '/')
1064 /* If the directory spec is not rooted, we can just copy
1065 the UNIX filename part and we are done. */
1067 if (((basename - fullname) > 1)
1068 && ( (basename[-1] == ']')
1069 || (basename[-1] == '>')))
1071 if (basename[-2] != '.')
1074 /* The VMS part ends in a `]', and the preceding character is not a `.'.
1075 -> PATH]:/name (basename = '/name', unixname = 'name')
1076 We strip the `]', and then splice the two parts of the name in the
1077 usual way. Given the default locations for include files,
1078 we will only use this code if the user specifies alternate locations
1079 with the /include (-I) switch on the command line. */
1081 basename -= 1; /* Strip "]" */
1082 unixname--; /* backspace */
1087 /* The VMS part has a ".]" at the end, and this will not do. Later
1088 processing will add a second directory spec, and this would be a syntax
1089 error. Thus we strip the ".]", and thus merge the directory specs.
1090 We also backspace unixname, so that it points to a '/'. This inhibits the
1091 generation of the 000000 root directory spec (which does not belong here
1094 basename -= 2; /* Strip ".]" */
1095 unixname--; /* backspace */
1103 /* We drop in here if there is no VMS style directory specification yet.
1104 If there is no device specification either, we make the first dir a
1105 device and try that. If we do not do this, then we will be essentially
1106 searching the users default directory (as if they did a #include "asdf.h").
1108 Then all we need to do is to push a '[' into the output string. Later
1109 processing will fill this in, and close the bracket. */
1111 if ((unixname != fullname) /* vms path spec found. */
1112 && (basename[-1] != ':'))
1113 *local_ptr++ = ':'; /* dev not in spec. take first dir */
1115 *local_ptr++ = '['; /* Open the directory specification */
1118 if (unixname == fullname) /* no vms dir spec. */
1121 if ((first_slash != 0) /* unix dir spec. */
1122 && (*unixname != '/') /* not beginning with '/' */
1123 && (*unixname != '.')) /* or './' or '../' */
1124 *local_ptr++ = '.'; /* dir is local ! */
1127 /* at this point we assume that we have the device spec, and (at least
1128 the opening "[" for a directory specification. We may have directories
1131 If there are no other slashes then the filename will be
1132 in the "root" directory. Otherwise, we need to add
1133 directory specifications. */
1135 if (strchr (unixname, '/') == 0)
1137 /* if no directories specified yet and none are following. */
1138 if (local_ptr[-1] == '[')
1140 /* Just add "000000]" as the directory string */
1141 strcpy (local_ptr, "000000]");
1142 local_ptr += strlen (local_ptr);
1143 check_filename_before_returning = 1; /* we might need to fool with this later */
1149 /* As long as there are still subdirectories to add, do them. */
1150 while (strchr (unixname, '/') != 0)
1152 /* If this token is "." we can ignore it
1153 if it's not at the beginning of a path. */
1154 if ((unixname[0] == '.') && (unixname[1] == '/'))
1156 /* remove it at beginning of path. */
1157 if ( ((unixname == fullname) /* no device spec */
1158 && (fullname+2 != basename)) /* starts with ./ */
1160 || ((basename[-1] == ':') /* device spec */
1161 && (unixname-1 == basename))) /* and ./ afterwards */
1162 *local_ptr++ = '.'; /* make '[.' start of path. */
1167 /* Add a subdirectory spec. Do not duplicate "." */
1168 if ( local_ptr[-1] != '.'
1169 && local_ptr[-1] != '['
1170 && local_ptr[-1] != '<')
1173 /* If this is ".." then the spec becomes "-" */
1174 if ( (unixname[0] == '.')
1175 && (unixname[1] == '.')
1176 && (unixname[2] == '/'))
1178 /* Add "-" and skip the ".." */
1179 if ((local_ptr[-1] == '.')
1180 && (local_ptr[-2] == '['))
1181 local_ptr--; /* prevent [.- */
1187 /* Copy the subdirectory */
1188 while (*unixname != '/')
1189 *local_ptr++= *unixname++;
1191 unixname++; /* Skip the "/" */
1194 /* Close the directory specification */
1195 if (local_ptr[-1] == '.') /* no trailing periods */
1198 if (local_ptr[-1] == '[') /* no dir needed */
1204 /* Now add the filename. */
1207 *local_ptr++ = *unixname++;
1210 /* Now append it to the original VMS spec. */
1212 strcpy ((must_revert==1)?fullname:basename, Local);
1214 /* If we put a [000000] in the filename, try to open it first. If this fails,
1215 remove the [000000], and return that name. This provides flexibility
1216 to the user in that they can use both rooted and non-rooted logical names
1217 to point to the location of the file. */
1219 if (check_filename_before_returning)
1221 f = open (fullname, O_RDONLY|O_NONBLOCK);
1224 /* The file name is OK as it is, so return it as is. */
1229 /* The filename did not work. Try to remove the [000000] from the name,
1232 basename = strchr (fullname, '[');
1233 local_ptr = strchr (fullname, ']') + 1;
1234 strcpy (basename, local_ptr); /* this gets rid of it */