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 #ifndef INCLUDE_LEN_FUDGE
47 # define INCLUDE_LEN_FUDGE 0
50 /* If errno is inspected immediately after a system call fails, it will be
51 nonzero, and no error number will ever be zero. */
62 /* Suppress warning about function macros used w/o arguments in traditional
63 C. It is unlikely that glibc's strcmp macro helps this file at all. */
66 static struct file_name_map *read_name_map
67 PARAMS ((cpp_reader *, const char *));
68 static char *read_filename_string PARAMS ((int, FILE *));
69 static char *remap_filename PARAMS ((cpp_reader *, char *,
70 struct file_name_list *));
71 static struct file_name_list *actual_directory
72 PARAMS ((cpp_reader *, const char *));
73 static struct include_file *find_include_file
74 PARAMS ((cpp_reader *, const char *,
75 struct file_name_list *));
76 static struct include_file *open_file PARAMS ((cpp_reader *, const char *));
77 static int read_include_file PARAMS ((cpp_reader *, struct include_file *));
78 static int stack_include_file PARAMS ((cpp_reader *, struct include_file *));
79 static void purge_cache PARAMS ((struct include_file *));
80 static void destroy_include_file_node PARAMS ((splay_tree_value));
81 static int report_missing_guard PARAMS ((splay_tree_node, void *));
84 static void hack_vms_include_specification PARAMS ((char *));
87 /* We use a splay tree to store information about all the include
88 files seen in this compilation. The key of each tree node is the
89 physical path to the file. The value is 0 if the file does not
90 exist, or a struct include_file pointer. */
93 destroy_include_file_node (v)
96 struct include_file *f = (struct include_file *)v;
100 free (f); /* The tree is registered with free to free f->name. */
105 _cpp_init_includes (pfile)
108 pfile->all_include_files
109 = splay_tree_new ((splay_tree_compare_fn) strcmp,
110 (splay_tree_delete_key_fn) free,
111 destroy_include_file_node);
115 _cpp_cleanup_includes (pfile)
118 splay_tree_delete (pfile->all_include_files);
121 /* Given a file name, look it up in the cache; if there is no entry,
122 create one with a non-NULL value (regardless of success in opening
123 the file). If the file doesn't exist or is inaccessible, this
124 entry is flagged so we don't attempt to open it again in the
125 future. If the file isn't open, open it.
127 Returns an include_file structure with an open file descriptor on
128 success, or NULL on failure. */
130 static struct include_file *
131 open_file (pfile, filename)
133 const char *filename;
136 struct include_file *file;
138 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) filename);
142 file = (struct include_file *) nd->value;
144 /* Don't retry opening if we failed previously. */
148 /* -1 indicates a file we've opened previously, and since closed. */
154 file = xcnew (struct include_file);
155 file->name = xstrdup (filename);
156 splay_tree_insert (pfile->all_include_files,
157 (splay_tree_key) file->name,
158 (splay_tree_value) file);
161 /* We used to open files in nonblocking mode, but that caused more
162 problems than it solved. Do take care not to acquire a
163 controlling terminal by mistake (this can't happen on sane
164 systems, but paranoia is a virtue).
166 Use the three-argument form of open even though we aren't
167 specifying O_CREAT, to defend against broken system headers.
169 O_BINARY tells some runtime libraries (notably DJGPP) not to do
170 newline translation; we can handle DOS line breaks just fine
173 Special case: the empty string is translated to stdin. */
175 if (filename[0] == '\0')
178 file->fd = open (filename, O_RDONLY | O_NOCTTY | O_BINARY, 0666);
180 if (file->fd != -1 && fstat (file->fd, &file->st) == 0)
182 /* Mark a regular, zero-length file never-reread now. */
183 if (S_ISREG (file->st.st_mode) && file->st.st_size == 0)
184 file->cmacro = NEVER_REREAD;
189 /* Don't issue an error message if the file doesn't exist. */
190 if (errno != ENOENT && errno != ENOTDIR)
191 cpp_error_from_errno (pfile, filename);
193 /* Create a negative node for this path, and return null. */
199 /* Place the file referenced by INC into a new buffer on PFILE's stack.
200 Return 1 if successful, 0 if not. */
203 stack_include_file (pfile, inc)
205 struct include_file *inc;
209 if (DO_NOT_REREAD (inc))
212 if (inc->buffer == NULL)
213 if (read_include_file (pfile, inc) == 0)
216 fp = cpp_push_buffer (pfile, NULL, 0);
221 fp->nominal_fname = inc->name;
222 fp->buf = inc->buffer;
223 fp->rlimit = fp->buf + inc->st.st_size;
226 fp->line_base = fp->buf;
228 /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
230 if (!CPP_OPTION (pfile, ignore_srcdir))
231 fp->actual_dir = actual_directory (pfile, inc->name);
234 pfile->include_depth++;
235 pfile->input_stack_listing_current = 0;
236 if (pfile->cb.enter_file)
237 (*pfile->cb.enter_file) (pfile);
241 /* Read the file referenced by INC into the file cache.
243 If fd points to a plain file, we might be able to mmap it; we can
244 definitely allocate the buffer all at once. If fd is a pipe or
245 terminal, we can't do either. If fd is something weird, like a
246 block device or a directory, we don't want to read it at all.
248 Unfortunately, different systems use different st.st_mode values
249 for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and
250 zero the entire struct stat except a couple fields. Hence we don't
251 even try to figure out what something is, except for plain files,
252 directories, and block devices.
254 FIXME: Flush file cache and try again if we run out of memory. */
257 read_include_file (pfile, inc)
259 struct include_file *inc;
261 ssize_t size, offset, count;
264 static int pagesize = -1;
267 if (S_ISREG (inc->st.st_mode))
269 /* off_t might have a wider range than ssize_t - in other words,
270 the max size of a file might be bigger than the address
271 space. We can't handle a file that large. (Anyone with
272 a single source file bigger than 2GB needs to rethink
273 their coding style.) Some systems (e.g. AIX 4.1) define
274 SSIZE_MAX to be much smaller than the actual range of the
275 type. Use INTTYPE_MAXIMUM unconditionally to ensure this
277 if (inc->st.st_size > INTTYPE_MAXIMUM (ssize_t))
279 cpp_error (pfile, "%s is too large", inc->name);
282 size = inc->st.st_size;
287 pagesize = getpagesize ();
289 if (size / pagesize >= MMAP_THRESHOLD)
291 buf = (U_CHAR *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0);
292 if (buf == (U_CHAR *)-1)
299 buf = (U_CHAR *) xmalloc (size);
301 while (offset < size)
303 count = read (inc->fd, buf + offset, size - offset);
308 cpp_warning (pfile, "%s is shorter than expected", inc->name);
315 else if (S_ISBLK (inc->st.st_mode))
317 cpp_error (pfile, "%s is a block device", inc->name);
320 else if (S_ISDIR (inc->st.st_mode))
322 cpp_error (pfile, "%s is a directory", inc->name);
327 /* 8 kilobytes is a sensible starting size. It ought to be
328 bigger than the kernel pipe buffer, and it's definitely
329 bigger than the majority of C source files. */
332 buf = (U_CHAR *) xmalloc (size);
334 while ((count = read (inc->fd, buf + offset, size - offset)) > 0)
338 buf = xrealloc (buf, (size *= 2));
344 buf = xrealloc (buf, offset);
345 inc->st.st_size = offset;
354 cpp_error_from_errno (pfile, inc->name);
356 /* Do not try to read this file again. */
359 inc->cmacro = NEVER_REREAD;
365 struct include_file *inc;
371 munmap ((PTR) inc->buffer, inc->st.st_size);
374 free ((PTR) inc->buffer);
379 /* Return 1 if the file named by FNAME has been included before in
380 any context, 0 otherwise. */
382 cpp_included (pfile, fname)
386 struct file_name_list *path;
392 /* Just look it up. */
393 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) fname);
394 return (nd && nd->value);
397 /* Search directory path for the file. */
398 name = (char *) alloca (strlen (fname) + pfile->max_include_len
399 + 2 + INCLUDE_LEN_FUDGE);
400 for (path = CPP_OPTION (pfile, quote_include); path; path = path->next)
402 memcpy (name, path->name, path->nlen);
403 name[path->nlen] = '/';
404 strcpy (&name[path->nlen+1], fname);
405 _cpp_simplify_pathname (name);
406 if (CPP_OPTION (pfile, remap))
407 name = remap_filename (pfile, name, path);
409 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name);
416 /* Search for include file FNAME in the include chain starting at
417 SEARCH_START. Return 0 if there is no such file (or it's un-openable),
418 otherwise an include_file structure. */
420 static struct include_file *
421 find_include_file (pfile, fname, search_start)
424 struct file_name_list *search_start;
426 struct file_name_list *path;
428 struct include_file *file;
431 return open_file (pfile, fname);
433 /* Search directory path for the file. */
434 name = (char *) alloca (strlen (fname) + pfile->max_include_len
435 + 2 + INCLUDE_LEN_FUDGE);
436 for (path = search_start; path; path = path->next)
438 memcpy (name, path->name, path->nlen);
439 name[path->nlen] = '/';
440 strcpy (&name[path->nlen+1], fname);
441 _cpp_simplify_pathname (name);
442 if (CPP_OPTION (pfile, remap))
443 name = remap_filename (pfile, name, path);
445 file = open_file (pfile, name);
448 file->sysp = path->sysp;
449 file->foundhere = path;
456 /* #line uses this to save artificial file names. We have to stat the
457 file because an all_include_files entry is always either + or -,
458 there's no 'I don't know' value. */
460 _cpp_fake_include (pfile, fname)
465 struct include_file *file;
468 file = find_include_file (pfile, fname, CPP_OPTION (pfile, quote_include));
479 name = xstrdup (fname);
480 _cpp_simplify_pathname (name);
482 /* We cannot just blindly insert a node, because there's still the
483 chance that the node already exists but isn't on the search path. */
484 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name);
488 return (const char *) nd->key;
491 file = xcnew (struct include_file);
494 splay_tree_insert (pfile->all_include_files, (splay_tree_key) name,
495 (splay_tree_value) file);
500 /* Not everyone who wants to set system-header-ness on a buffer can
501 see the details of struct include_file. This is an exported interface
502 because fix-header needs it. */
504 cpp_make_system_header (pfile, pbuf, flag)
509 if (flag < 0 || flag > 2)
510 cpp_ice (pfile, "cpp_make_system_header: bad flag %d\n", flag);
512 cpp_ice (pfile, "cpp_make_system_header called on non-file buffer");
514 pbuf->inc->sysp = flag;
518 cpp_syshdr_flags (pfile, pbuf)
519 cpp_reader *pfile ATTRIBUTE_UNUSED;
522 #ifndef NO_IMPLICIT_EXTERN_C
523 if (CPP_OPTION (pfile, cplusplus) && pbuf->inc->sysp == 2)
531 /* Report on all files that might benefit from a multiple include guard.
534 _cpp_report_missing_guards (pfile)
538 splay_tree_foreach (pfile->all_include_files, report_missing_guard,
543 report_missing_guard (n, b)
547 struct include_file *f = (struct include_file *) n->value;
548 int *bannerp = (int *)b;
550 if (f && f->cmacro == 0 && f->include_count == 1)
554 fputs (_("Multiple include guards may be useful for:\n"), stderr);
557 fputs (f->name, stderr);
563 #define PRINT_THIS_DEP(p, b) (CPP_PRINT_DEPS(p) > (b||p->system_include_depth))
565 _cpp_execute_include (pfile, f, len, no_reinclude, search_start, angle_brackets)
570 struct file_name_list *search_start;
573 struct include_file *inc;
579 search_start = CPP_OPTION (pfile, bracket_include);
580 else if (CPP_OPTION (pfile, ignore_srcdir))
581 search_start = CPP_OPTION (pfile, quote_include);
583 search_start = CPP_BUFFER (pfile)->actual_dir;
588 cpp_error (pfile, "No include path in which to find %s", f);
592 fname = alloca (len + 1);
593 memcpy (fname, f, len);
596 inc = find_include_file (pfile, fname, search_start);
600 /* For -M, add the file to the dependencies on its first inclusion. */
601 if (!inc->include_count && PRINT_THIS_DEP (pfile, angle_brackets))
602 deps_add_dep (pfile->deps, inc->name);
603 inc->include_count++;
605 /* Actually process the file. */
606 if (stack_include_file (pfile, inc))
609 pfile->system_include_depth++;
612 inc->cmacro = NEVER_REREAD;
614 /* Handle -H option. */
615 if (CPP_OPTION (pfile, print_include_names))
617 cpp_buffer *fp = CPP_BUFFER (pfile);
618 while ((fp = CPP_PREV_BUFFER (fp)) != NULL)
620 fprintf (stderr, " %s\n", inc->name);
626 if (CPP_OPTION (pfile, print_deps_missing_files)
627 && PRINT_THIS_DEP (pfile, angle_brackets))
630 deps_add_dep (pfile->deps, fname);
634 struct file_name_list *ptr;
635 /* If requested as a system header, assume it belongs in
636 the first system header directory. */
637 if (CPP_OPTION (pfile, bracket_include))
638 ptr = CPP_OPTION (pfile, bracket_include);
640 ptr = CPP_OPTION (pfile, quote_include);
642 p = (char *) alloca (strlen (ptr->name)
643 + strlen (fname) + 2);
644 if (*ptr->name != '\0')
646 strcpy (p, ptr->name);
650 _cpp_simplify_pathname (p);
651 deps_add_dep (pfile->deps, p);
654 /* If -M was specified, and this header file won't be added to
655 the dependency list, then don't count this as an error,
656 because we can still produce correct output. Otherwise, we
657 can't produce correct output, because there may be
658 dependencies we need inside the missing file, and we don't
659 know what directory this missing file exists in. */
660 else if (CPP_PRINT_DEPS (pfile)
661 && ! PRINT_THIS_DEP (pfile, angle_brackets))
662 cpp_warning (pfile, "No include path in which to find %s", fname);
664 cpp_error_from_errno (pfile, fname);
667 /* Locate file F, and determine whether it is newer than PFILE. Return -1,
668 if F cannot be located or dated, 1, if it is newer and 0 if older. */
671 _cpp_compare_file_date (pfile, f, len, angle_brackets)
678 struct file_name_list *search_start;
679 struct include_file *inc;
680 struct include_file *current_include = CPP_BUFFER (pfile)->inc;
683 search_start = CPP_OPTION (pfile, bracket_include);
684 else if (CPP_OPTION (pfile, ignore_srcdir))
685 search_start = CPP_OPTION (pfile, quote_include);
687 search_start = CPP_BUFFER (pfile)->actual_dir;
689 fname = alloca (len + 1);
690 memcpy (fname, f, len);
692 inc = find_include_file (pfile, fname, search_start);
702 return inc->st.st_mtime > current_include->st.st_mtime;
706 /* Push an input buffer and load it up with the contents of FNAME.
707 If FNAME is "" or NULL, read standard input. */
709 cpp_read_file (pfile, fname)
713 struct include_file *f;
718 f = open_file (pfile, fname);
722 cpp_error_from_errno (pfile, fname);
726 return stack_include_file (pfile, f);
729 /* Do appropriate cleanup when a file buffer is popped off the input
732 _cpp_pop_file_buffer (pfile, buf)
736 struct include_file *inc = buf->inc;
738 if (pfile->system_include_depth)
739 pfile->system_include_depth--;
740 if (pfile->include_depth)
741 pfile->include_depth--;
742 if (pfile->potential_control_macro)
744 if (inc->cmacro != NEVER_REREAD)
745 inc->cmacro = pfile->potential_control_macro;
746 pfile->potential_control_macro = 0;
748 pfile->input_stack_listing_current = 0;
751 if (inc->refcnt == 0 && DO_NOT_REREAD (inc))
755 /* The file_name_map structure holds a mapping of file names for a
756 particular directory. This mapping is read from the file named
757 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
758 map filenames on a file system with severe filename restrictions,
759 such as DOS. The format of the file name map file is just a series
760 of lines with two tokens on each line. The first token is the name
761 to map, and the second token is the actual name to use. */
765 struct file_name_map *map_next;
770 #define FILE_NAME_MAP_FILE "header.gcc"
772 /* Read a space delimited string of unlimited length from a stdio
776 read_filename_string (ch, f)
784 set = alloc = xmalloc (len + 1);
788 while ((ch = getc (f)) != EOF && ! is_space(ch))
790 if (set - alloc == len)
793 alloc = xrealloc (alloc, len + 1);
794 set = alloc + len / 2;
804 /* This structure holds a linked list of file name maps, one per directory. */
806 struct file_name_map_list
808 struct file_name_map_list *map_list_next;
810 struct file_name_map *map_list_map;
813 /* Read the file name map file for DIRNAME. */
815 static struct file_name_map *
816 read_name_map (pfile, dirname)
820 register struct file_name_map_list *map_list_ptr;
824 for (map_list_ptr = CPP_OPTION (pfile, map_list); map_list_ptr;
825 map_list_ptr = map_list_ptr->map_list_next)
826 if (! strcmp (map_list_ptr->map_list_name, dirname))
827 return map_list_ptr->map_list_map;
829 map_list_ptr = ((struct file_name_map_list *)
830 xmalloc (sizeof (struct file_name_map_list)));
831 map_list_ptr->map_list_name = xstrdup (dirname);
832 map_list_ptr->map_list_map = NULL;
834 name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
835 strcpy (name, dirname);
838 strcat (name, FILE_NAME_MAP_FILE);
839 f = fopen (name, "r");
841 map_list_ptr->map_list_map = (struct file_name_map *)-1;
845 int dirlen = strlen (dirname);
847 while ((ch = getc (f)) != EOF)
850 struct file_name_map *ptr;
854 from = read_filename_string (ch, f);
855 while ((ch = getc (f)) != EOF && is_hspace(ch))
857 to = read_filename_string (ch, f);
859 ptr = ((struct file_name_map *)
860 xmalloc (sizeof (struct file_name_map)));
861 ptr->map_from = from;
863 /* Make the real filename absolute. */
868 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
869 strcpy (ptr->map_to, dirname);
870 ptr->map_to[dirlen] = '/';
871 strcpy (ptr->map_to + dirlen + 1, to);
875 ptr->map_next = map_list_ptr->map_list_map;
876 map_list_ptr->map_list_map = ptr;
878 while ((ch = getc (f)) != '\n')
885 map_list_ptr->map_list_next = CPP_OPTION (pfile, map_list);
886 CPP_OPTION (pfile, map_list) = map_list_ptr;
888 return map_list_ptr->map_list_map;
891 /* Remap NAME based on the file_name_map (if any) for LOC. */
894 remap_filename (pfile, name, loc)
897 struct file_name_list *loc;
899 struct file_name_map *map;
900 const char *from, *p, *dir;
903 loc->name_map = read_name_map (pfile,
907 if (loc->name_map == (struct file_name_map *)-1)
910 from = name + strlen (loc->name) + 1;
912 for (map = loc->name_map; map; map = map->map_next)
913 if (!strcmp (map->map_from, from))
916 /* Try to find a mapping file for the particular directory we are
917 looking in. Thus #include <sys/types.h> will look up sys/types.h
918 in /usr/include/header.gcc and look up types.h in
919 /usr/include/sys/header.gcc. */
920 p = strrchr (name, '/');
924 && strlen (loc->name) == (size_t) (p - name)
925 && !strncmp (loc->name, name, p - name))
926 /* FILENAME is in SEARCHPTR, which we've already checked. */
936 char * newdir = (char *) alloca (p - name + 1);
937 memcpy (newdir, name, p - name);
938 newdir[p - name] = '\0';
943 for (map = read_name_map (pfile, dir); map; map = map->map_next)
944 if (! strcmp (map->map_from, name))
950 /* Given a path FNAME, extract the directory component and place it
951 onto the actual_dirs list. Return a pointer to the allocated
952 file_name_list structure. These structures are used to implement
953 current-directory "" include searching. */
955 static struct file_name_list *
956 actual_directory (pfile, fname)
960 char *last_slash, *dir;
962 struct file_name_list *x;
964 dir = xstrdup (fname);
965 last_slash = strrchr (dir, '/');
968 if (last_slash == dir)
971 last_slash[1] = '\0';
975 dlen = last_slash - dir;
986 if (dlen > pfile->max_include_len)
987 pfile->max_include_len = dlen;
989 for (x = pfile->actual_dirs; x; x = x->alloc)
990 if (!strcmp (x->name, dir))
996 /* Not found, make a new one. */
997 x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
1000 x->next = CPP_OPTION (pfile, quote_include);
1001 x->alloc = pfile->actual_dirs;
1002 x->sysp = CPP_BUFFER (pfile)->inc->sysp;
1005 pfile->actual_dirs = x;
1009 /* Simplify a path name in place, deleting redundant components. This
1010 reduces OS overhead and guarantees that equivalent paths compare
1011 the same (modulo symlinks).
1014 foo/bar/../quux foo/quux
1018 //quux //quux (POSIX allows leading // as a namespace escape)
1020 Guarantees no trailing slashes. All transforms reduce the length
1024 _cpp_simplify_pathname (path)
1031 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
1032 /* Convert all backslashes to slashes. */
1033 for (from = path; *from; from++)
1034 if (*from == '\\') *from = '/';
1036 /* Skip over leading drive letter if present. */
1037 if (ISALPHA (path[0]) && path[1] == ':')
1038 from = to = &path[2];
1045 /* Remove redundant initial /s. */
1054 /* 3 or more initial /s are equivalent to 1 /. */
1055 while (*++from == '/');
1057 /* On some hosts // differs from /; Posix allows this. */
1065 while (*from == '/')
1068 if (from[0] == '.' && from[1] == '/')
1070 else if (from[0] == '.' && from[1] == '\0')
1072 else if (from[0] == '.' && from[1] == '.' && from[2] == '/')
1089 while (to > base && *to != '/') to--;
1095 else if (from[0] == '.' && from[1] == '.' && from[2] == '\0')
1108 while (to > base && *to != '/') to--;
1115 /* Copy this component and trailing /, if any. */
1116 while ((*to++ = *from++) != '/')
1128 /* Trim trailing slash */
1129 if (to[0] == '/' && (!absolute || to > path+1))
1132 /* Change the empty string to "." so that stat() on the result
1133 will always work. */
1142 /* It is not clear when this should be used if at all, so I've
1143 disabled it until someone who understands VMS can look at it. */
1146 /* Under VMS we need to fix up the "include" specification filename.
1148 Rules for possible conversions
1150 fullname tried paths
1153 ./dir/name [.dir]name
1155 /name [000000]name, name
1156 dir/name dir:[000000]name, dir:name, dir/name
1157 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
1158 path:/name path:[000000]name, path:name
1159 path:/dir/name path:[000000.dir]name, path:[dir]name
1160 path:dir/name path:[dir]name
1161 [path]:[dir]name [path.dir]name
1162 path/[dir]name [path.dir]name
1164 The path:/name input is constructed when expanding <> includes. */
1168 hack_vms_include_specification (fullname)
1171 register char *basename, *unixname, *local_ptr, *first_slash;
1172 int f, check_filename_before_returning, must_revert;
1175 check_filename_before_returning = 0;
1177 /* See if we can find a 1st slash. If not, there's no path information. */
1178 first_slash = strchr (fullname, '/');
1179 if (first_slash == 0)
1180 return 0; /* Nothing to do!!! */
1182 /* construct device spec if none given. */
1184 if (strchr (fullname, ':') == 0)
1187 /* If fullname has a slash, take it as device spec. */
1189 if (first_slash == fullname)
1191 first_slash = strchr (fullname + 1, '/'); /* 2nd slash ? */
1193 *first_slash = ':'; /* make device spec */
1194 for (basename = fullname; *basename != 0; basename++)
1195 *basename = *(basename+1); /* remove leading slash */
1197 else if ((first_slash[-1] != '.') /* keep ':/', './' */
1198 && (first_slash[-1] != ':')
1199 && (first_slash[-1] != ']')) /* or a vms path */
1203 else if ((first_slash[1] == '[') /* skip './' in './[dir' */
1204 && (first_slash[-1] == '.'))
1208 /* Get part after first ':' (basename[-1] == ':')
1209 or last '/' (basename[-1] == '/'). */
1211 basename = base_name (fullname);
1213 local_ptr = Local; /* initialize */
1215 /* We are trying to do a number of things here. First of all, we are
1216 trying to hammer the filenames into a standard format, such that later
1217 processing can handle them.
1219 If the file name contains something like [dir.], then it recognizes this
1220 as a root, and strips the ".]". Later processing will add whatever is
1221 needed to get things working properly.
1223 If no device is specified, then the first directory name is taken to be
1224 a device name (or a rooted logical). */
1226 /* Point to the UNIX filename part (which needs to be fixed!)
1227 but skip vms path information.
1228 [basename != fullname since first_slash != 0]. */
1230 if ((basename[-1] == ':') /* vms path spec. */
1231 || (basename[-1] == ']')
1232 || (basename[-1] == '>'))
1233 unixname = basename;
1235 unixname = fullname;
1237 if (*unixname == '/')
1240 /* If the directory spec is not rooted, we can just copy
1241 the UNIX filename part and we are done. */
1243 if (((basename - fullname) > 1)
1244 && ( (basename[-1] == ']')
1245 || (basename[-1] == '>')))
1247 if (basename[-2] != '.')
1250 /* The VMS part ends in a `]', and the preceding character is not a `.'.
1251 -> PATH]:/name (basename = '/name', unixname = 'name')
1252 We strip the `]', and then splice the two parts of the name in the
1253 usual way. Given the default locations for include files,
1254 we will only use this code if the user specifies alternate locations
1255 with the /include (-I) switch on the command line. */
1257 basename -= 1; /* Strip "]" */
1258 unixname--; /* backspace */
1263 /* The VMS part has a ".]" at the end, and this will not do. Later
1264 processing will add a second directory spec, and this would be a syntax
1265 error. Thus we strip the ".]", and thus merge the directory specs.
1266 We also backspace unixname, so that it points to a '/'. This inhibits the
1267 generation of the 000000 root directory spec (which does not belong here
1270 basename -= 2; /* Strip ".]" */
1271 unixname--; /* backspace */
1279 /* We drop in here if there is no VMS style directory specification yet.
1280 If there is no device specification either, we make the first dir a
1281 device and try that. If we do not do this, then we will be essentially
1282 searching the users default directory (as if they did a #include "asdf.h").
1284 Then all we need to do is to push a '[' into the output string. Later
1285 processing will fill this in, and close the bracket. */
1287 if ((unixname != fullname) /* vms path spec found. */
1288 && (basename[-1] != ':'))
1289 *local_ptr++ = ':'; /* dev not in spec. take first dir */
1291 *local_ptr++ = '['; /* Open the directory specification */
1294 if (unixname == fullname) /* no vms dir spec. */
1297 if ((first_slash != 0) /* unix dir spec. */
1298 && (*unixname != '/') /* not beginning with '/' */
1299 && (*unixname != '.')) /* or './' or '../' */
1300 *local_ptr++ = '.'; /* dir is local ! */
1303 /* at this point we assume that we have the device spec, and (at least
1304 the opening "[" for a directory specification. We may have directories
1307 If there are no other slashes then the filename will be
1308 in the "root" directory. Otherwise, we need to add
1309 directory specifications. */
1311 if (strchr (unixname, '/') == 0)
1313 /* if no directories specified yet and none are following. */
1314 if (local_ptr[-1] == '[')
1316 /* Just add "000000]" as the directory string */
1317 strcpy (local_ptr, "000000]");
1318 local_ptr += strlen (local_ptr);
1319 check_filename_before_returning = 1; /* we might need to fool with this later */
1325 /* As long as there are still subdirectories to add, do them. */
1326 while (strchr (unixname, '/') != 0)
1328 /* If this token is "." we can ignore it
1329 if it's not at the beginning of a path. */
1330 if ((unixname[0] == '.') && (unixname[1] == '/'))
1332 /* remove it at beginning of path. */
1333 if ( ((unixname == fullname) /* no device spec */
1334 && (fullname+2 != basename)) /* starts with ./ */
1336 || ((basename[-1] == ':') /* device spec */
1337 && (unixname-1 == basename))) /* and ./ afterwards */
1338 *local_ptr++ = '.'; /* make '[.' start of path. */
1343 /* Add a subdirectory spec. Do not duplicate "." */
1344 if ( local_ptr[-1] != '.'
1345 && local_ptr[-1] != '['
1346 && local_ptr[-1] != '<')
1349 /* If this is ".." then the spec becomes "-" */
1350 if ( (unixname[0] == '.')
1351 && (unixname[1] == '.')
1352 && (unixname[2] == '/'))
1354 /* Add "-" and skip the ".." */
1355 if ((local_ptr[-1] == '.')
1356 && (local_ptr[-2] == '['))
1357 local_ptr--; /* prevent [.- */
1363 /* Copy the subdirectory */
1364 while (*unixname != '/')
1365 *local_ptr++= *unixname++;
1367 unixname++; /* Skip the "/" */
1370 /* Close the directory specification */
1371 if (local_ptr[-1] == '.') /* no trailing periods */
1374 if (local_ptr[-1] == '[') /* no dir needed */
1380 /* Now add the filename. */
1383 *local_ptr++ = *unixname++;
1386 /* Now append it to the original VMS spec. */
1388 strcpy ((must_revert==1)?fullname:basename, Local);
1390 /* If we put a [000000] in the filename, try to open it first. If this fails,
1391 remove the [000000], and return that name. This provides flexibility
1392 to the user in that they can use both rooted and non-rooted logical names
1393 to point to the location of the file. */
1395 if (check_filename_before_returning)
1397 f = open (fullname, O_RDONLY|O_NONBLOCK);
1400 /* The file name is OK as it is, so return it as is. */
1405 /* The filename did not work. Try to remove the [000000] from the name,
1408 basename = strchr (fullname, '[');
1409 local_ptr = strchr (fullname, ']') + 1;
1410 strcpy (basename, local_ptr); /* this gets rid of it */