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. */
29 #include "splay-tree.h"
32 # include <sys/mman.h>
33 # ifndef MMAP_THRESHOLD
34 # define MMAP_THRESHOLD 3 /* Minimum page count to mmap the file. */
37 #else /* No MMAP_FILE */
38 # undef MMAP_THRESHOLD
39 # define MMAP_THRESHOLD 0
46 static struct file_name_map *read_name_map
47 PARAMS ((cpp_reader *, const char *));
48 static char *read_filename_string PARAMS ((int, FILE *));
49 static char *remap_filename PARAMS ((cpp_reader *, char *,
50 struct file_name_list *));
51 static struct file_name_list *actual_directory
52 PARAMS ((cpp_reader *, const char *));
53 static struct include_file *find_include_file
54 PARAMS ((cpp_reader *, const char *,
55 struct file_name_list *));
56 static struct include_file *open_include_file
57 PARAMS ((cpp_reader *, const char *));
58 static int read_include_file PARAMS ((cpp_reader *, struct include_file *));
59 static ssize_t read_with_read PARAMS ((cpp_buffer *, int, ssize_t));
60 static ssize_t read_file PARAMS ((cpp_buffer *, int, ssize_t));
62 static void destroy_include_file_node PARAMS ((splay_tree_value));
63 static int close_cached_fd PARAMS ((splay_tree_node, void *));
66 static void hack_vms_include_specification PARAMS ((char *));
69 #ifndef INCLUDE_LEN_FUDGE
70 #define INCLUDE_LEN_FUDGE 0
73 /* We use a splay tree to store information about all the include
74 files seen in this compilation. The key of each tree node is the
75 physical path to the file. The value is 0 if the file does not
76 exist, or a struct include_file pointer. */
79 destroy_include_file_node (v)
82 struct include_file *f = (struct include_file *)v;
92 close_cached_fd (n, dummy)
94 void *dummy ATTRIBUTE_UNUSED;
96 struct include_file *f = (struct include_file *)n->value;
106 _cpp_init_include_table (pfile)
109 pfile->all_include_files
110 = splay_tree_new ((splay_tree_compare_fn) strcmp,
111 (splay_tree_delete_key_fn) free,
112 destroy_include_file_node);
115 /* Given a filename, look it up and possibly open it. If the file
116 does not exist, return NULL. If the file does exist but doesn't
117 need to be reread, return an include_file entry with fd == -1.
118 If it needs to be (re)read, return an include_file entry with
119 fd a file descriptor open on the file. */
121 static struct include_file *
122 open_include_file (pfile, filename)
124 const char *filename;
127 struct include_file *file = 0;
130 nd = splay_tree_lookup (pfile->all_include_files,
131 (splay_tree_key) filename);
138 file = (struct include_file *)nd->value;
140 if (DO_NOT_REREAD (file))
150 /* File descriptors are cached for files that might be reread. */
153 lseek (file->fd, 0, SEEK_SET);
158 /* We used to open files in nonblocking mode, but that caused more
159 problems than it solved. Do take care not to acquire a
160 controlling terminal by mistake (this can't happen on sane
161 systems, but paranoia is a virtue).
163 Use the three-argument form of open even though we aren't
164 specifying O_CREAT, to defend against broken system headers.
166 O_BINARY tells some runtime libraries (notably DJGPP) not to do
167 newline translation; we can handle DOS line breaks just fine
170 Special case: the empty string is translated to stdin. */
173 if (filename[0] == '\0')
176 fd = open (filename, O_RDONLY|O_NOCTTY|O_BINARY, 0666);
183 cpp_error (pfile, "included file `%s' exists but is not readable",
196 /* Too many files open. Close all cached file descriptors and
198 splay_tree_foreach (pfile->all_include_files, close_cached_fd, 0);
202 /* Nonexistent or inaccessible file. Create a negative node for it. */
206 "node for '%s' exists, open failed, error '%s', value %lx\n",
207 filename, strerror (errno), nd->value);
208 destroy_include_file_node (nd->value);
210 splay_tree_insert (pfile->all_include_files,
211 (splay_tree_key) xstrdup (filename), 0);
215 /* If we haven't seen this file before, create a positive node for it. */
218 file = xnew (struct include_file);
220 file->include_count = 0;
223 file->name = xstrdup (filename);
224 splay_tree_insert (pfile->all_include_files,
225 (splay_tree_key) file->name,
226 (splay_tree_value) file);
230 file->date = (time_t) -1;
234 /* Return 1 if the file named by FNAME has been included before in
235 any context, 0 otherwise. */
237 cpp_included (pfile, fname)
241 struct file_name_list *path;
247 /* Just look it up. */
248 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) fname);
249 return (nd && nd->value);
252 /* Search directory path for the file. */
253 name = (char *) alloca (strlen (fname) + pfile->max_include_len
254 + 2 + INCLUDE_LEN_FUDGE);
255 for (path = CPP_OPTION (pfile, quote_include); path; path = path->next)
257 memcpy (name, path->name, path->nlen);
258 name[path->nlen] = '/';
259 strcpy (&name[path->nlen+1], fname);
260 _cpp_simplify_pathname (name);
261 if (CPP_OPTION (pfile, remap))
262 name = remap_filename (pfile, name, path);
264 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name);
271 /* Search for include file FNAME in the include chain starting at
272 SEARCH_START. Return 0 if there is no such file (or it's un-openable),
273 otherwise an include_file structure, possibly with a file descriptor
276 static struct include_file *
277 find_include_file (pfile, fname, search_start)
280 struct file_name_list *search_start;
282 struct file_name_list *path;
284 struct include_file *file;
287 return open_include_file (pfile, fname);
289 /* Search directory path for the file. */
290 name = (char *) alloca (strlen (fname) + pfile->max_include_len
291 + 2 + INCLUDE_LEN_FUDGE);
292 for (path = search_start; path; path = path->next)
294 memcpy (name, path->name, path->nlen);
295 name[path->nlen] = '/';
296 strcpy (&name[path->nlen+1], fname);
297 _cpp_simplify_pathname (name);
298 if (CPP_OPTION (pfile, remap))
299 name = remap_filename (pfile, name, path);
301 file = open_include_file (pfile, name);
304 file->sysp = path->sysp;
305 file->foundhere = path;
312 /* #line uses this to save artificial file names. We have to try
313 opening the file because an all_include_files entry is always
314 either + or -, there's no 'I don't know' value. */
316 _cpp_fake_include (pfile, fname)
321 struct include_file *file;
324 file = find_include_file (pfile, fname, CPP_OPTION (pfile, quote_include));
328 name = xstrdup (fname);
329 _cpp_simplify_pathname (name);
331 /* We cannot just blindly insert a node, because there's still the
332 chance that the node already exists but isn't on the search path. */
333 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name);
337 return (const char *) nd->key;
340 splay_tree_insert (pfile->all_include_files, (splay_tree_key) name, 0);
341 return (const char *)name;
344 /* Not everyone who wants to set system-header-ness on a buffer can
345 see the details of struct include_file. This is an exported interface
346 because fix-header needs it. */
348 cpp_make_system_header (pfile, pbuf, flag)
353 if (flag < 0 || flag > 2)
354 cpp_ice (pfile, "cpp_make_system_header: bad flag %d\n", flag);
356 cpp_ice (pfile, "cpp_make_system_header called on non-file buffer");
358 pbuf->inc->sysp = flag;
361 #define PRINT_THIS_DEP(p, b) (CPP_PRINT_DEPS(p) > (b||p->system_include_depth))
363 _cpp_execute_include (pfile, f, len, no_reinclude, search_start)
368 struct file_name_list *search_start;
370 struct include_file *inc;
371 char *fname = (char *)f;
372 int angle_brackets = fname[0] == '<';
377 search_start = CPP_OPTION (pfile, bracket_include);
378 else if (CPP_OPTION (pfile, ignore_srcdir))
379 search_start = CPP_OPTION (pfile, quote_include);
381 search_start = CPP_BUFFER (pfile)->actual_dir;
386 cpp_error (pfile, "No include path in which to find %s", fname);
390 /* Remove quote marks. */
395 inc = find_include_file (pfile, fname, search_start);
402 /* For -M, add the file to the dependencies on its first inclusion. */
403 if (!inc->include_count && PRINT_THIS_DEP (pfile, angle_brackets))
404 deps_add_dep (pfile->deps, inc->name);
405 inc->include_count++;
407 /* Handle -H option. */
408 if (CPP_OPTION (pfile, print_include_names))
410 cpp_buffer *fp = CPP_BUFFER (pfile);
411 while ((fp = CPP_PREV_BUFFER (fp)) != NULL)
413 fprintf (stderr, " %s\n", inc->name);
416 /* Actually process the file. */
418 inc->cmacro = NEVER_REREAD;
420 if (read_include_file (pfile, inc))
423 pfile->system_include_depth++;
428 if (CPP_OPTION (pfile, print_deps_missing_files)
429 && PRINT_THIS_DEP (pfile, angle_brackets))
432 deps_add_dep (pfile->deps, fname);
436 struct file_name_list *ptr;
437 /* If requested as a system header, assume it belongs in
438 the first system header directory. */
439 if (CPP_OPTION (pfile, bracket_include))
440 ptr = CPP_OPTION (pfile, bracket_include);
442 ptr = CPP_OPTION (pfile, quote_include);
444 p = (char *) alloca (strlen (ptr->name)
445 + strlen (fname) + 2);
446 if (*ptr->name != '\0')
448 strcpy (p, ptr->name);
452 _cpp_simplify_pathname (p);
453 deps_add_dep (pfile->deps, p);
456 /* If -M was specified, and this header file won't be added to
457 the dependency list, then don't count this as an error,
458 because we can still produce correct output. Otherwise, we
459 can't produce correct output, because there may be
460 dependencies we need inside the missing file, and we don't
461 know what directory this missing file exists in. */
462 else if (CPP_PRINT_DEPS (pfile)
463 && ! PRINT_THIS_DEP (pfile, angle_brackets))
464 cpp_warning (pfile, "No include path in which to find %s", fname);
466 cpp_error_from_errno (pfile, fname);
469 /* Locate file F, and determine whether it is newer than PFILE. Return -1,
470 if F cannot be located or dated, 1, if it is newer and 0 if older. */
473 _cpp_compare_file_date (pfile, f, len, search_start)
477 struct file_name_list *search_start;
479 char *fname = (char *)f;
480 int angle_brackets = fname[0] == '<';
481 struct include_file *inc;
482 struct include_file *current_include = cpp_file_buffer (pfile)->inc;
487 search_start = CPP_OPTION (pfile, bracket_include);
488 else if (CPP_OPTION (pfile, ignore_srcdir))
489 search_start = CPP_OPTION (pfile, quote_include);
491 search_start = CPP_BUFFER (pfile)->actual_dir;
494 /* Remove quote marks. */
499 inc = find_include_file (pfile, fname, search_start);
507 if (fstat (inc->fd, &source) < 0)
513 inc->date = source.st_mtime;
517 if (inc->date == (time_t)-1 || current_include->date == (time_t)-1)
519 return inc->date > current_include->date;
523 /* Push an input buffer and load it up with the contents of FNAME.
524 If FNAME is "" or NULL, read standard input. */
526 cpp_read_file (pfile, fname)
530 struct include_file *f;
535 f = open_include_file (pfile, fname);
537 return read_include_file (pfile, f);
540 /* Read the file referenced by INC into a new buffer on PFILE's stack.
541 Return 1 if successful, 0 if not. */
544 read_include_file (pfile, inc)
546 struct include_file *inc;
553 fp = cpp_push_buffer (pfile, NULL, 0);
558 if (fstat (fd, &st) < 0)
561 inc->date = st.st_mtime;
563 /* If fd points to a plain file, we might be able to mmap it; we can
564 definitely allocate the buffer all at once. If fd is a pipe or
565 terminal, we can't do either. If fd is something weird, like a
566 block device or a directory, we don't want to read it at all.
568 Unfortunately, different systems use different st.st_mode values
569 for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and
570 zero the entire struct stat except a couple fields. Hence we don't
571 even try to figure out what something is, except for plain files,
572 directories, and block devices. */
574 if (S_ISREG (st.st_mode))
578 /* off_t might have a wider range than ssize_t - in other words,
579 the max size of a file might be bigger than the address
580 space. We can't handle a file that large. (Anyone with
581 a single source file bigger than 2GB needs to rethink
582 their coding style.) Some systems (e.g. AIX 4.1) define
583 SSIZE_MAX to be much smaller than the actual range of the
584 type. Use INTTYPE_MAXIMUM unconditionally to ensure this
586 if (st.st_size > INTTYPE_MAXIMUM (ssize_t))
588 cpp_error (pfile, "%s is too large", inc->name);
591 st_size = st.st_size;
592 length = read_file (fp, fd, st_size);
595 if (length < st_size)
596 cpp_warning (pfile, "%s is shorter than expected\n", inc->name);
598 else if (S_ISBLK (st.st_mode))
600 cpp_error (pfile, "%s is a block device", inc->name);
603 else if (S_ISDIR (st.st_mode))
605 cpp_error (pfile, "%s is a directory", inc->name);
610 /* 8 kilobytes is a sensible starting size. It ought to be
611 bigger than the kernel pipe buffer, and it's definitely
612 bigger than the majority of C source files. */
613 length = read_with_read (fp, fd, 8 * 1024);
618 /* These must be set before prescan. */
620 fp->nominal_fname = inc->name;
621 pfile->include_depth++;
624 inc->cmacro = NEVER_REREAD;
626 /* Temporary - I hope. */
627 length = _cpp_prescan (pfile, fp, length);
629 fp->rlimit = fp->buf + length;
632 fp->line_base = fp->buf;
634 /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
636 if (!CPP_OPTION (pfile, ignore_srcdir))
637 fp->actual_dir = actual_directory (pfile, inc->name);
639 pfile->input_stack_listing_current = 0;
640 pfile->only_seen_white = 2;
644 cpp_error_from_errno (pfile, inc->name);
645 /* Do not try to read this file again. */
648 inc->cmacro = NEVER_REREAD;
650 cpp_pop_buffer (pfile);
656 read_file (fp, fd, size)
661 static int pagesize = -1;
667 pagesize = getpagesize ();
670 if (size / pagesize >= MMAP_THRESHOLD)
673 = (const U_CHAR *) mmap (0, size, PROT_READ, MAP_PRIVATE, fd, 0);
674 if (result != (const U_CHAR *)-1)
681 /* If mmap fails, try read. If there's really a problem, read will
685 return read_with_read (fp, fd, size);
689 read_with_read (fp, fd, size)
694 ssize_t offset, count;
697 buf = (U_CHAR *) xmalloc (size);
699 while ((count = read (fd, buf + offset, size - offset)) > 0)
703 buf = xrealloc (buf, (size *= 2));
717 buf = xrealloc (buf, offset);
723 /* The file_name_map structure holds a mapping of file names for a
724 particular directory. This mapping is read from the file named
725 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
726 map filenames on a file system with severe filename restrictions,
727 such as DOS. The format of the file name map file is just a series
728 of lines with two tokens on each line. The first token is the name
729 to map, and the second token is the actual name to use. */
733 struct file_name_map *map_next;
738 #define FILE_NAME_MAP_FILE "header.gcc"
740 /* Read a space delimited string of unlimited length from a stdio
744 read_filename_string (ch, f)
752 set = alloc = xmalloc (len + 1);
756 while ((ch = getc (f)) != EOF && ! is_space(ch))
758 if (set - alloc == len)
761 alloc = xrealloc (alloc, len + 1);
762 set = alloc + len / 2;
772 /* This structure holds a linked list of file name maps, one per directory. */
774 struct file_name_map_list
776 struct file_name_map_list *map_list_next;
778 struct file_name_map *map_list_map;
781 /* Read the file name map file for DIRNAME. */
783 static struct file_name_map *
784 read_name_map (pfile, dirname)
788 register struct file_name_map_list *map_list_ptr;
792 for (map_list_ptr = CPP_OPTION (pfile, map_list); map_list_ptr;
793 map_list_ptr = map_list_ptr->map_list_next)
794 if (! strcmp (map_list_ptr->map_list_name, dirname))
795 return map_list_ptr->map_list_map;
797 map_list_ptr = ((struct file_name_map_list *)
798 xmalloc (sizeof (struct file_name_map_list)));
799 map_list_ptr->map_list_name = xstrdup (dirname);
801 name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
802 strcpy (name, dirname);
805 strcat (name, FILE_NAME_MAP_FILE);
806 f = fopen (name, "r");
808 map_list_ptr->map_list_map = (struct file_name_map *)-1;
812 int dirlen = strlen (dirname);
814 while ((ch = getc (f)) != EOF)
817 struct file_name_map *ptr;
821 from = read_filename_string (ch, f);
822 while ((ch = getc (f)) != EOF && is_hspace(ch))
824 to = read_filename_string (ch, f);
826 ptr = ((struct file_name_map *)
827 xmalloc (sizeof (struct file_name_map)));
828 ptr->map_from = from;
830 /* Make the real filename absolute. */
835 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
836 strcpy (ptr->map_to, dirname);
837 ptr->map_to[dirlen] = '/';
838 strcpy (ptr->map_to + dirlen + 1, to);
842 ptr->map_next = map_list_ptr->map_list_map;
843 map_list_ptr->map_list_map = ptr;
845 while ((ch = getc (f)) != '\n')
852 map_list_ptr->map_list_next = CPP_OPTION (pfile, map_list);
853 CPP_OPTION (pfile, map_list) = map_list_ptr;
855 return map_list_ptr->map_list_map;
858 /* Remap NAME based on the file_name_map (if any) for LOC. */
861 remap_filename (pfile, name, loc)
864 struct file_name_list *loc;
866 struct file_name_map *map;
867 const char *from, *p, *dir;
870 loc->name_map = read_name_map (pfile,
874 if (loc->name_map == (struct file_name_map *)-1)
877 from = name + strlen (loc->name) + 1;
879 for (map = loc->name_map; map; map = map->map_next)
880 if (!strcmp (map->map_from, from))
883 /* Try to find a mapping file for the particular directory we are
884 looking in. Thus #include <sys/types.h> will look up sys/types.h
885 in /usr/include/header.gcc and look up types.h in
886 /usr/include/sys/header.gcc. */
887 p = strrchr (name, '/');
891 && strlen (loc->name) == (size_t) (p - name)
892 && !strncmp (loc->name, name, p - name))
893 /* FILENAME is in SEARCHPTR, which we've already checked. */
903 char * newdir = (char *) alloca (p - name + 1);
904 memcpy (newdir, name, p - name);
905 newdir[p - name] = '\0';
910 for (map = read_name_map (pfile, dir); map; map = map->map_next)
911 if (! strcmp (map->map_from, name))
917 /* Given a path FNAME, extract the directory component and place it
918 onto the actual_dirs list. Return a pointer to the allocated
919 file_name_list structure. These structures are used to implement
920 current-directory "" include searching. */
922 static struct file_name_list *
923 actual_directory (pfile, fname)
927 char *last_slash, *dir;
929 struct file_name_list *x;
931 dir = xstrdup (fname);
932 last_slash = strrchr (dir, '/');
935 if (last_slash == dir)
938 last_slash[1] = '\0';
942 dlen = last_slash - dir;
953 if (dlen > pfile->max_include_len)
954 pfile->max_include_len = dlen;
956 for (x = pfile->actual_dirs; x; x = x->alloc)
957 if (!strcmp (x->name, dir))
963 /* Not found, make a new one. */
964 x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
967 x->next = CPP_OPTION (pfile, quote_include);
968 x->alloc = pfile->actual_dirs;
969 x->sysp = CPP_BUFFER (pfile)->inc->sysp;
972 pfile->actual_dirs = x;
976 /* Simplify a path name in place, deleting redundant components. This
977 reduces OS overhead and guarantees that equivalent paths compare
978 the same (modulo symlinks).
981 foo/bar/../quux foo/quux
985 //quux //quux (POSIX allows leading // as a namespace escape)
987 Guarantees no trailing slashes. All transforms reduce the length
991 _cpp_simplify_pathname (path)
998 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
999 /* Convert all backslashes to slashes. */
1000 for (from = path; *from; from++)
1001 if (*from == '\\') *from = '/';
1003 /* Skip over leading drive letter if present. */
1004 if (ISALPHA (path[0]) && path[1] == ':')
1005 from = to = &path[2];
1012 /* Remove redundant initial /s. */
1021 /* 3 or more initial /s are equivalent to 1 /. */
1022 while (*++from == '/');
1024 /* On some hosts // differs from /; Posix allows this. */
1032 while (*from == '/')
1035 if (from[0] == '.' && from[1] == '/')
1037 else if (from[0] == '.' && from[1] == '\0')
1039 else if (from[0] == '.' && from[1] == '.' && from[2] == '/')
1056 while (to > base && *to != '/') to--;
1062 else if (from[0] == '.' && from[1] == '.' && from[2] == '\0')
1075 while (to > base && *to != '/') to--;
1082 /* Copy this component and trailing /, if any. */
1083 while ((*to++ = *from++) != '/')
1095 /* Trim trailing slash */
1096 if (to[0] == '/' && (!absolute || to > path+1))
1099 /* Change the empty string to "." so that stat() on the result
1100 will always work. */
1109 /* It is not clear when this should be used if at all, so I've
1110 disabled it until someone who understands VMS can look at it. */
1113 /* Under VMS we need to fix up the "include" specification filename.
1115 Rules for possible conversions
1117 fullname tried paths
1120 ./dir/name [.dir]name
1122 /name [000000]name, name
1123 dir/name dir:[000000]name, dir:name, dir/name
1124 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
1125 path:/name path:[000000]name, path:name
1126 path:/dir/name path:[000000.dir]name, path:[dir]name
1127 path:dir/name path:[dir]name
1128 [path]:[dir]name [path.dir]name
1129 path/[dir]name [path.dir]name
1131 The path:/name input is constructed when expanding <> includes. */
1135 hack_vms_include_specification (fullname)
1138 register char *basename, *unixname, *local_ptr, *first_slash;
1139 int f, check_filename_before_returning, must_revert;
1142 check_filename_before_returning = 0;
1144 /* See if we can find a 1st slash. If not, there's no path information. */
1145 first_slash = strchr (fullname, '/');
1146 if (first_slash == 0)
1147 return 0; /* Nothing to do!!! */
1149 /* construct device spec if none given. */
1151 if (strchr (fullname, ':') == 0)
1154 /* If fullname has a slash, take it as device spec. */
1156 if (first_slash == fullname)
1158 first_slash = strchr (fullname + 1, '/'); /* 2nd slash ? */
1160 *first_slash = ':'; /* make device spec */
1161 for (basename = fullname; *basename != 0; basename++)
1162 *basename = *(basename+1); /* remove leading slash */
1164 else if ((first_slash[-1] != '.') /* keep ':/', './' */
1165 && (first_slash[-1] != ':')
1166 && (first_slash[-1] != ']')) /* or a vms path */
1170 else if ((first_slash[1] == '[') /* skip './' in './[dir' */
1171 && (first_slash[-1] == '.'))
1175 /* Get part after first ':' (basename[-1] == ':')
1176 or last '/' (basename[-1] == '/'). */
1178 basename = base_name (fullname);
1180 local_ptr = Local; /* initialize */
1182 /* We are trying to do a number of things here. First of all, we are
1183 trying to hammer the filenames into a standard format, such that later
1184 processing can handle them.
1186 If the file name contains something like [dir.], then it recognizes this
1187 as a root, and strips the ".]". Later processing will add whatever is
1188 needed to get things working properly.
1190 If no device is specified, then the first directory name is taken to be
1191 a device name (or a rooted logical). */
1193 /* Point to the UNIX filename part (which needs to be fixed!)
1194 but skip vms path information.
1195 [basename != fullname since first_slash != 0]. */
1197 if ((basename[-1] == ':') /* vms path spec. */
1198 || (basename[-1] == ']')
1199 || (basename[-1] == '>'))
1200 unixname = basename;
1202 unixname = fullname;
1204 if (*unixname == '/')
1207 /* If the directory spec is not rooted, we can just copy
1208 the UNIX filename part and we are done. */
1210 if (((basename - fullname) > 1)
1211 && ( (basename[-1] == ']')
1212 || (basename[-1] == '>')))
1214 if (basename[-2] != '.')
1217 /* The VMS part ends in a `]', and the preceding character is not a `.'.
1218 -> PATH]:/name (basename = '/name', unixname = 'name')
1219 We strip the `]', and then splice the two parts of the name in the
1220 usual way. Given the default locations for include files,
1221 we will only use this code if the user specifies alternate locations
1222 with the /include (-I) switch on the command line. */
1224 basename -= 1; /* Strip "]" */
1225 unixname--; /* backspace */
1230 /* The VMS part has a ".]" at the end, and this will not do. Later
1231 processing will add a second directory spec, and this would be a syntax
1232 error. Thus we strip the ".]", and thus merge the directory specs.
1233 We also backspace unixname, so that it points to a '/'. This inhibits the
1234 generation of the 000000 root directory spec (which does not belong here
1237 basename -= 2; /* Strip ".]" */
1238 unixname--; /* backspace */
1246 /* We drop in here if there is no VMS style directory specification yet.
1247 If there is no device specification either, we make the first dir a
1248 device and try that. If we do not do this, then we will be essentially
1249 searching the users default directory (as if they did a #include "asdf.h").
1251 Then all we need to do is to push a '[' into the output string. Later
1252 processing will fill this in, and close the bracket. */
1254 if ((unixname != fullname) /* vms path spec found. */
1255 && (basename[-1] != ':'))
1256 *local_ptr++ = ':'; /* dev not in spec. take first dir */
1258 *local_ptr++ = '['; /* Open the directory specification */
1261 if (unixname == fullname) /* no vms dir spec. */
1264 if ((first_slash != 0) /* unix dir spec. */
1265 && (*unixname != '/') /* not beginning with '/' */
1266 && (*unixname != '.')) /* or './' or '../' */
1267 *local_ptr++ = '.'; /* dir is local ! */
1270 /* at this point we assume that we have the device spec, and (at least
1271 the opening "[" for a directory specification. We may have directories
1274 If there are no other slashes then the filename will be
1275 in the "root" directory. Otherwise, we need to add
1276 directory specifications. */
1278 if (strchr (unixname, '/') == 0)
1280 /* if no directories specified yet and none are following. */
1281 if (local_ptr[-1] == '[')
1283 /* Just add "000000]" as the directory string */
1284 strcpy (local_ptr, "000000]");
1285 local_ptr += strlen (local_ptr);
1286 check_filename_before_returning = 1; /* we might need to fool with this later */
1292 /* As long as there are still subdirectories to add, do them. */
1293 while (strchr (unixname, '/') != 0)
1295 /* If this token is "." we can ignore it
1296 if it's not at the beginning of a path. */
1297 if ((unixname[0] == '.') && (unixname[1] == '/'))
1299 /* remove it at beginning of path. */
1300 if ( ((unixname == fullname) /* no device spec */
1301 && (fullname+2 != basename)) /* starts with ./ */
1303 || ((basename[-1] == ':') /* device spec */
1304 && (unixname-1 == basename))) /* and ./ afterwards */
1305 *local_ptr++ = '.'; /* make '[.' start of path. */
1310 /* Add a subdirectory spec. Do not duplicate "." */
1311 if ( local_ptr[-1] != '.'
1312 && local_ptr[-1] != '['
1313 && local_ptr[-1] != '<')
1316 /* If this is ".." then the spec becomes "-" */
1317 if ( (unixname[0] == '.')
1318 && (unixname[1] == '.')
1319 && (unixname[2] == '/'))
1321 /* Add "-" and skip the ".." */
1322 if ((local_ptr[-1] == '.')
1323 && (local_ptr[-2] == '['))
1324 local_ptr--; /* prevent [.- */
1330 /* Copy the subdirectory */
1331 while (*unixname != '/')
1332 *local_ptr++= *unixname++;
1334 unixname++; /* Skip the "/" */
1337 /* Close the directory specification */
1338 if (local_ptr[-1] == '.') /* no trailing periods */
1341 if (local_ptr[-1] == '[') /* no dir needed */
1347 /* Now add the filename. */
1350 *local_ptr++ = *unixname++;
1353 /* Now append it to the original VMS spec. */
1355 strcpy ((must_revert==1)?fullname:basename, Local);
1357 /* If we put a [000000] in the filename, try to open it first. If this fails,
1358 remove the [000000], and return that name. This provides flexibility
1359 to the user in that they can use both rooted and non-rooted logical names
1360 to point to the location of the file. */
1362 if (check_filename_before_returning)
1364 f = open (fullname, O_RDONLY|O_NONBLOCK);
1367 /* The file name is OK as it is, so return it as is. */
1372 /* The filename did not work. Try to remove the [000000] from the name,
1375 basename = strchr (fullname, '[');
1376 local_ptr = strchr (fullname, ']') + 1;
1377 strcpy (basename, local_ptr); /* this gets rid of it */