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 /* Don't reopen an idempotent file. */
149 if (DO_NOT_REREAD (file))
152 /* Don't reopen one which is already loaded. */
153 if (file->buffer != NULL)
158 file = xcnew (struct include_file);
159 file->name = xstrdup (filename);
160 splay_tree_insert (pfile->all_include_files,
161 (splay_tree_key) file->name,
162 (splay_tree_value) file);
165 /* We used to open files in nonblocking mode, but that caused more
166 problems than it solved. Do take care not to acquire a
167 controlling terminal by mistake (this can't happen on sane
168 systems, but paranoia is a virtue).
170 Use the three-argument form of open even though we aren't
171 specifying O_CREAT, to defend against broken system headers.
173 O_BINARY tells some runtime libraries (notably DJGPP) not to do
174 newline translation; we can handle DOS line breaks just fine
177 Special case: the empty string is translated to stdin. */
179 if (filename[0] == '\0')
182 file->fd = open (filename, O_RDONLY | O_NOCTTY | O_BINARY, 0666);
184 if (file->fd != -1 && fstat (file->fd, &file->st) == 0)
186 /* Mark a regular, zero-length file never-reread now. */
187 if (S_ISREG (file->st.st_mode) && file->st.st_size == 0)
189 file->cmacro = NEVER_REREAD;
197 /* Don't issue an error message if the file doesn't exist. */
198 if (errno != ENOENT && errno != ENOTDIR)
199 cpp_error_from_errno (pfile, filename);
201 /* Create a negative node for this path, and return null. */
207 /* Place the file referenced by INC into a new buffer on PFILE's stack.
208 Return 1 if successful, 0 if not. */
211 stack_include_file (pfile, inc)
213 struct include_file *inc;
215 const char *filename = 0;
216 unsigned int lineno = 0;
221 filename = pfile->buffer->nominal_fname;
222 lineno = pfile->buffer->lineno;
225 if (pfile->context->prev)
226 cpp_ice (pfile, "attempt to push file buffer with contexts stacked");
228 if (DO_NOT_REREAD (inc))
231 if (inc->buffer == NULL)
232 if (read_include_file (pfile, inc) == 0)
235 fp = cpp_push_buffer (pfile, NULL, 0);
239 /* Initialise controlling macro state. */
240 pfile->mi_state = MI_OUTSIDE;
241 pfile->mi_cmacro = 0;
244 fp->nominal_fname = inc->name;
245 fp->buf = inc->buffer;
246 fp->rlimit = fp->buf + inc->st.st_size;
249 fp->line_base = fp->buf;
251 /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
253 if (!CPP_OPTION (pfile, ignore_srcdir))
254 fp->actual_dir = actual_directory (pfile, inc->name);
257 pfile->include_depth++;
258 pfile->input_stack_listing_current = 0;
260 _cpp_do_file_change (pfile, FC_ENTER, filename, lineno);
266 /* Read the file referenced by INC into the file cache.
268 If fd points to a plain file, we might be able to mmap it; we can
269 definitely allocate the buffer all at once. If fd is a pipe or
270 terminal, we can't do either. If fd is something weird, like a
271 block device or a directory, we don't want to read it at all.
273 Unfortunately, different systems use different st.st_mode values
274 for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and
275 zero the entire struct stat except a couple fields. Hence we don't
276 even try to figure out what something is, except for plain files,
277 directories, and block devices.
279 FIXME: Flush file cache and try again if we run out of memory. */
282 read_include_file (pfile, inc)
284 struct include_file *inc;
286 ssize_t size, offset, count;
289 static int pagesize = -1;
292 if (S_ISREG (inc->st.st_mode))
294 /* off_t might have a wider range than ssize_t - in other words,
295 the max size of a file might be bigger than the address
296 space. We can't handle a file that large. (Anyone with
297 a single source file bigger than 2GB needs to rethink
298 their coding style.) Some systems (e.g. AIX 4.1) define
299 SSIZE_MAX to be much smaller than the actual range of the
300 type. Use INTTYPE_MAXIMUM unconditionally to ensure this
302 if (inc->st.st_size > INTTYPE_MAXIMUM (ssize_t))
304 cpp_error (pfile, "%s is too large", inc->name);
307 size = inc->st.st_size;
312 pagesize = getpagesize ();
314 if (size / pagesize >= MMAP_THRESHOLD)
316 buf = (U_CHAR *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0);
317 if (buf == (U_CHAR *)-1)
324 buf = (U_CHAR *) xmalloc (size);
326 while (offset < size)
328 count = read (inc->fd, buf + offset, size - offset);
333 cpp_warning (pfile, "%s is shorter than expected", inc->name);
340 else if (S_ISBLK (inc->st.st_mode))
342 cpp_error (pfile, "%s is a block device", inc->name);
345 else if (S_ISDIR (inc->st.st_mode))
347 cpp_error (pfile, "%s is a directory", inc->name);
352 /* 8 kilobytes is a sensible starting size. It ought to be
353 bigger than the kernel pipe buffer, and it's definitely
354 bigger than the majority of C source files. */
357 buf = (U_CHAR *) xmalloc (size);
359 while ((count = read (inc->fd, buf + offset, size - offset)) > 0)
363 buf = xrealloc (buf, (size *= 2));
369 buf = xrealloc (buf, offset);
370 inc->st.st_size = offset;
379 cpp_error_from_errno (pfile, inc->name);
381 /* Do not try to read this file again. */
384 inc->cmacro = NEVER_REREAD;
390 struct include_file *inc;
396 munmap ((PTR) inc->buffer, inc->st.st_size);
399 free ((PTR) inc->buffer);
404 /* Return 1 if the file named by FNAME has been included before in
405 any context, 0 otherwise. */
407 cpp_included (pfile, fname)
411 struct file_name_list *path;
417 /* Just look it up. */
418 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) fname);
419 return (nd && nd->value);
422 /* Search directory path for the file. */
423 name = (char *) alloca (strlen (fname) + pfile->max_include_len
424 + 2 + INCLUDE_LEN_FUDGE);
425 for (path = CPP_OPTION (pfile, quote_include); path; path = path->next)
427 memcpy (name, path->name, path->nlen);
428 name[path->nlen] = '/';
429 strcpy (&name[path->nlen+1], fname);
430 _cpp_simplify_pathname (name);
431 if (CPP_OPTION (pfile, remap))
432 name = remap_filename (pfile, name, path);
434 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name);
441 /* Search for include file FNAME in the include chain starting at
442 SEARCH_START. Return 0 if there is no such file (or it's un-openable),
443 otherwise an include_file structure. */
445 static struct include_file *
446 find_include_file (pfile, fname, search_start)
449 struct file_name_list *search_start;
451 struct file_name_list *path;
453 struct include_file *file;
456 return open_file (pfile, fname);
458 /* Search directory path for the file. */
459 name = (char *) alloca (strlen (fname) + pfile->max_include_len
460 + 2 + INCLUDE_LEN_FUDGE);
461 for (path = search_start; path; path = path->next)
463 memcpy (name, path->name, path->nlen);
464 name[path->nlen] = '/';
465 strcpy (&name[path->nlen+1], fname);
466 _cpp_simplify_pathname (name);
467 if (CPP_OPTION (pfile, remap))
468 name = remap_filename (pfile, name, path);
470 file = open_file (pfile, name);
473 file->sysp = path->sysp;
474 file->foundhere = path;
481 /* #line uses this to save artificial file names. We have to stat the
482 file because an all_include_files entry is always either + or -,
483 there's no 'I don't know' value. */
485 _cpp_fake_include (pfile, fname)
490 struct include_file *file;
493 file = find_include_file (pfile, fname, CPP_OPTION (pfile, quote_include));
504 name = xstrdup (fname);
505 _cpp_simplify_pathname (name);
507 /* We cannot just blindly insert a node, because there's still the
508 chance that the node already exists but isn't on the search path. */
509 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name);
513 return (const char *) nd->key;
516 file = xcnew (struct include_file);
519 splay_tree_insert (pfile->all_include_files, (splay_tree_key) name,
520 (splay_tree_value) file);
525 /* Not everyone who wants to set system-header-ness on a buffer can
526 see the details of struct include_file. This is an exported interface
527 because fix-header needs it. */
529 cpp_make_system_header (pfile, pbuf, flag)
534 if (flag < 0 || flag > 2)
535 cpp_ice (pfile, "cpp_make_system_header: bad flag %d\n", flag);
537 cpp_ice (pfile, "cpp_make_system_header called on non-file buffer");
539 pbuf->inc->sysp = flag;
542 /* Report on all files that might benefit from a multiple include guard.
545 _cpp_report_missing_guards (pfile)
549 splay_tree_foreach (pfile->all_include_files, report_missing_guard,
554 report_missing_guard (n, b)
558 struct include_file *f = (struct include_file *) n->value;
559 int *bannerp = (int *)b;
561 if (f && f->cmacro == 0 && f->include_count == 1)
565 fputs (_("Multiple include guards may be useful for:\n"), stderr);
568 fputs (f->name, stderr);
574 #define PRINT_THIS_DEP(p, b) (CPP_PRINT_DEPS(p) > (b||p->system_include_depth))
576 _cpp_execute_include (pfile, header, no_reinclude, search_start)
578 const cpp_token *header;
580 struct file_name_list *search_start;
582 unsigned int len = header->val.str.len;
583 unsigned int angle_brackets = header->type == CPP_HEADER_NAME;
584 struct include_file *inc;
587 fname = alloca (len + 1);
588 memcpy (fname, header->val.str.text, len);
594 search_start = CPP_OPTION (pfile, bracket_include);
595 else if (CPP_OPTION (pfile, ignore_srcdir))
596 search_start = CPP_OPTION (pfile, quote_include);
598 search_start = CPP_BUFFER (pfile)->actual_dir;
602 cpp_error (pfile, "No include path in which to find %s", fname);
607 inc = find_include_file (pfile, fname, search_start);
611 /* For -M, add the file to the dependencies on its first inclusion. */
612 if (!inc->include_count && PRINT_THIS_DEP (pfile, angle_brackets))
613 deps_add_dep (pfile->deps, inc->name);
614 inc->include_count++;
616 /* Actually process the file. */
617 if (stack_include_file (pfile, inc))
620 pfile->system_include_depth++;
623 inc->cmacro = NEVER_REREAD;
625 /* Handle -H option. */
626 if (CPP_OPTION (pfile, print_include_names))
628 cpp_buffer *fp = CPP_BUFFER (pfile);
629 while ((fp = CPP_PREV_BUFFER (fp)) != NULL)
631 fprintf (stderr, " %s\n", inc->name);
637 if (CPP_OPTION (pfile, print_deps_missing_files)
638 && PRINT_THIS_DEP (pfile, angle_brackets))
641 deps_add_dep (pfile->deps, fname);
645 struct file_name_list *ptr;
646 /* If requested as a system header, assume it belongs in
647 the first system header directory. */
648 if (CPP_OPTION (pfile, bracket_include))
649 ptr = CPP_OPTION (pfile, bracket_include);
651 ptr = CPP_OPTION (pfile, quote_include);
653 p = (char *) alloca (strlen (ptr->name)
654 + strlen (fname) + 2);
655 if (*ptr->name != '\0')
657 strcpy (p, ptr->name);
661 _cpp_simplify_pathname (p);
662 deps_add_dep (pfile->deps, p);
665 /* If -M was specified, and this header file won't be added to
666 the dependency list, then don't count this as an error,
667 because we can still produce correct output. Otherwise, we
668 can't produce correct output, because there may be
669 dependencies we need inside the missing file, and we don't
670 know what directory this missing file exists in. */
671 else if (CPP_PRINT_DEPS (pfile)
672 && ! PRINT_THIS_DEP (pfile, angle_brackets))
673 cpp_warning (pfile, "No include path in which to find %s", fname);
675 cpp_error_from_errno (pfile, fname);
678 /* Locate file F, and determine whether it is newer than PFILE. Return -1,
679 if F cannot be located or dated, 1, if it is newer and 0 if older. */
681 _cpp_compare_file_date (pfile, f)
685 unsigned int len = f->val.str.len;
687 struct file_name_list *search_start;
688 struct include_file *inc;
690 if (f->type == CPP_HEADER_NAME)
691 search_start = CPP_OPTION (pfile, bracket_include);
692 else if (CPP_OPTION (pfile, ignore_srcdir))
693 search_start = CPP_OPTION (pfile, quote_include);
695 search_start = CPP_BUFFER (pfile)->actual_dir;
697 fname = alloca (len + 1);
698 memcpy (fname, f->val.str.text, len);
700 inc = find_include_file (pfile, fname, search_start);
710 return inc->st.st_mtime > CPP_BUFFER (pfile)->inc->st.st_mtime;
714 /* Push an input buffer and load it up with the contents of FNAME.
715 If FNAME is "" or NULL, read standard input. */
717 cpp_read_file (pfile, fname)
721 struct include_file *f;
726 f = open_file (pfile, fname);
730 cpp_error_from_errno (pfile, fname);
734 /* Return success for zero-length files. */
735 if (DO_NOT_REREAD (f))
738 return stack_include_file (pfile, f);
741 /* Do appropriate cleanup when a file buffer is popped off the input
744 _cpp_pop_file_buffer (pfile, buf)
748 struct include_file *inc = buf->inc;
750 if (pfile->system_include_depth)
751 pfile->system_include_depth--;
752 if (pfile->include_depth)
753 pfile->include_depth--;
754 pfile->input_stack_listing_current = 0;
756 /* Record the inclusion-preventing macro and its definedness. */
757 if (pfile->mi_state == MI_OUTSIDE && inc->cmacro != NEVER_REREAD)
759 /* This could be NULL meaning no controlling macro. */
760 inc->cmacro = pfile->mi_cmacro;
764 /* Invalidate control macros in the #including file. */
765 pfile->mi_state = MI_FAILED;
768 if (inc->refcnt == 0 && DO_NOT_REREAD (inc))
772 /* The file_name_map structure holds a mapping of file names for a
773 particular directory. This mapping is read from the file named
774 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
775 map filenames on a file system with severe filename restrictions,
776 such as DOS. The format of the file name map file is just a series
777 of lines with two tokens on each line. The first token is the name
778 to map, and the second token is the actual name to use. */
782 struct file_name_map *map_next;
787 #define FILE_NAME_MAP_FILE "header.gcc"
789 /* Read a space delimited string of unlimited length from a stdio
793 read_filename_string (ch, f)
801 set = alloc = xmalloc (len + 1);
805 while ((ch = getc (f)) != EOF && ! is_space(ch))
807 if (set - alloc == len)
810 alloc = xrealloc (alloc, len + 1);
811 set = alloc + len / 2;
821 /* This structure holds a linked list of file name maps, one per directory. */
823 struct file_name_map_list
825 struct file_name_map_list *map_list_next;
827 struct file_name_map *map_list_map;
830 /* Read the file name map file for DIRNAME. */
832 static struct file_name_map *
833 read_name_map (pfile, dirname)
837 register struct file_name_map_list *map_list_ptr;
841 for (map_list_ptr = CPP_OPTION (pfile, map_list); map_list_ptr;
842 map_list_ptr = map_list_ptr->map_list_next)
843 if (! strcmp (map_list_ptr->map_list_name, dirname))
844 return map_list_ptr->map_list_map;
846 map_list_ptr = ((struct file_name_map_list *)
847 xmalloc (sizeof (struct file_name_map_list)));
848 map_list_ptr->map_list_name = xstrdup (dirname);
849 map_list_ptr->map_list_map = NULL;
851 name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
852 strcpy (name, dirname);
855 strcat (name, FILE_NAME_MAP_FILE);
856 f = fopen (name, "r");
858 map_list_ptr->map_list_map = (struct file_name_map *)-1;
862 int dirlen = strlen (dirname);
864 while ((ch = getc (f)) != EOF)
867 struct file_name_map *ptr;
871 from = read_filename_string (ch, f);
872 while ((ch = getc (f)) != EOF && is_hspace(ch))
874 to = read_filename_string (ch, f);
876 ptr = ((struct file_name_map *)
877 xmalloc (sizeof (struct file_name_map)));
878 ptr->map_from = from;
880 /* Make the real filename absolute. */
885 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
886 strcpy (ptr->map_to, dirname);
887 ptr->map_to[dirlen] = '/';
888 strcpy (ptr->map_to + dirlen + 1, to);
892 ptr->map_next = map_list_ptr->map_list_map;
893 map_list_ptr->map_list_map = ptr;
895 while ((ch = getc (f)) != '\n')
902 map_list_ptr->map_list_next = CPP_OPTION (pfile, map_list);
903 CPP_OPTION (pfile, map_list) = map_list_ptr;
905 return map_list_ptr->map_list_map;
908 /* Remap NAME based on the file_name_map (if any) for LOC. */
911 remap_filename (pfile, name, loc)
914 struct file_name_list *loc;
916 struct file_name_map *map;
917 const char *from, *p, *dir;
920 loc->name_map = read_name_map (pfile,
924 if (loc->name_map == (struct file_name_map *)-1)
927 from = name + strlen (loc->name) + 1;
929 for (map = loc->name_map; map; map = map->map_next)
930 if (!strcmp (map->map_from, from))
933 /* Try to find a mapping file for the particular directory we are
934 looking in. Thus #include <sys/types.h> will look up sys/types.h
935 in /usr/include/header.gcc and look up types.h in
936 /usr/include/sys/header.gcc. */
937 p = strrchr (name, '/');
941 && strlen (loc->name) == (size_t) (p - name)
942 && !strncmp (loc->name, name, p - name))
943 /* FILENAME is in SEARCHPTR, which we've already checked. */
953 char * newdir = (char *) alloca (p - name + 1);
954 memcpy (newdir, name, p - name);
955 newdir[p - name] = '\0';
960 for (map = read_name_map (pfile, dir); map; map = map->map_next)
961 if (! strcmp (map->map_from, name))
967 /* Given a path FNAME, extract the directory component and place it
968 onto the actual_dirs list. Return a pointer to the allocated
969 file_name_list structure. These structures are used to implement
970 current-directory "" include searching. */
972 static struct file_name_list *
973 actual_directory (pfile, fname)
977 char *last_slash, *dir;
979 struct file_name_list *x;
981 dir = xstrdup (fname);
982 last_slash = strrchr (dir, '/');
985 if (last_slash == dir)
988 last_slash[1] = '\0';
992 dlen = last_slash - dir;
1003 if (dlen > pfile->max_include_len)
1004 pfile->max_include_len = dlen;
1006 for (x = pfile->actual_dirs; x; x = x->alloc)
1007 if (!strcmp (x->name, dir))
1013 /* Not found, make a new one. */
1014 x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
1017 x->next = CPP_OPTION (pfile, quote_include);
1018 x->alloc = pfile->actual_dirs;
1019 x->sysp = CPP_BUFFER (pfile)->inc->sysp;
1022 pfile->actual_dirs = x;
1026 /* Simplify a path name in place, deleting redundant components. This
1027 reduces OS overhead and guarantees that equivalent paths compare
1028 the same (modulo symlinks).
1031 foo/bar/../quux foo/quux
1035 //quux //quux (POSIX allows leading // as a namespace escape)
1037 Guarantees no trailing slashes. All transforms reduce the length
1041 _cpp_simplify_pathname (path)
1048 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
1049 /* Convert all backslashes to slashes. */
1050 for (from = path; *from; from++)
1051 if (*from == '\\') *from = '/';
1053 /* Skip over leading drive letter if present. */
1054 if (ISALPHA (path[0]) && path[1] == ':')
1055 from = to = &path[2];
1062 /* Remove redundant initial /s. */
1071 /* 3 or more initial /s are equivalent to 1 /. */
1072 while (*++from == '/');
1074 /* On some hosts // differs from /; Posix allows this. */
1082 while (*from == '/')
1085 if (from[0] == '.' && from[1] == '/')
1087 else if (from[0] == '.' && from[1] == '\0')
1089 else if (from[0] == '.' && from[1] == '.' && from[2] == '/')
1106 while (to > base && *to != '/') to--;
1112 else if (from[0] == '.' && from[1] == '.' && from[2] == '\0')
1125 while (to > base && *to != '/') to--;
1132 /* Copy this component and trailing /, if any. */
1133 while ((*to++ = *from++) != '/')
1145 /* Trim trailing slash */
1146 if (to[0] == '/' && (!absolute || to > path+1))
1149 /* Change the empty string to "." so that stat() on the result
1150 will always work. */
1159 /* It is not clear when this should be used if at all, so I've
1160 disabled it until someone who understands VMS can look at it. */
1163 /* Under VMS we need to fix up the "include" specification filename.
1165 Rules for possible conversions
1167 fullname tried paths
1170 ./dir/name [.dir]name
1172 /name [000000]name, name
1173 dir/name dir:[000000]name, dir:name, dir/name
1174 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
1175 path:/name path:[000000]name, path:name
1176 path:/dir/name path:[000000.dir]name, path:[dir]name
1177 path:dir/name path:[dir]name
1178 [path]:[dir]name [path.dir]name
1179 path/[dir]name [path.dir]name
1181 The path:/name input is constructed when expanding <> includes. */
1185 hack_vms_include_specification (fullname)
1188 register char *basename, *unixname, *local_ptr, *first_slash;
1189 int f, check_filename_before_returning, must_revert;
1192 check_filename_before_returning = 0;
1194 /* See if we can find a 1st slash. If not, there's no path information. */
1195 first_slash = strchr (fullname, '/');
1196 if (first_slash == 0)
1197 return 0; /* Nothing to do!!! */
1199 /* construct device spec if none given. */
1201 if (strchr (fullname, ':') == 0)
1204 /* If fullname has a slash, take it as device spec. */
1206 if (first_slash == fullname)
1208 first_slash = strchr (fullname + 1, '/'); /* 2nd slash ? */
1210 *first_slash = ':'; /* make device spec */
1211 for (basename = fullname; *basename != 0; basename++)
1212 *basename = *(basename+1); /* remove leading slash */
1214 else if ((first_slash[-1] != '.') /* keep ':/', './' */
1215 && (first_slash[-1] != ':')
1216 && (first_slash[-1] != ']')) /* or a vms path */
1220 else if ((first_slash[1] == '[') /* skip './' in './[dir' */
1221 && (first_slash[-1] == '.'))
1225 /* Get part after first ':' (basename[-1] == ':')
1226 or last '/' (basename[-1] == '/'). */
1228 basename = base_name (fullname);
1230 local_ptr = Local; /* initialize */
1232 /* We are trying to do a number of things here. First of all, we are
1233 trying to hammer the filenames into a standard format, such that later
1234 processing can handle them.
1236 If the file name contains something like [dir.], then it recognizes this
1237 as a root, and strips the ".]". Later processing will add whatever is
1238 needed to get things working properly.
1240 If no device is specified, then the first directory name is taken to be
1241 a device name (or a rooted logical). */
1243 /* Point to the UNIX filename part (which needs to be fixed!)
1244 but skip vms path information.
1245 [basename != fullname since first_slash != 0]. */
1247 if ((basename[-1] == ':') /* vms path spec. */
1248 || (basename[-1] == ']')
1249 || (basename[-1] == '>'))
1250 unixname = basename;
1252 unixname = fullname;
1254 if (*unixname == '/')
1257 /* If the directory spec is not rooted, we can just copy
1258 the UNIX filename part and we are done. */
1260 if (((basename - fullname) > 1)
1261 && ( (basename[-1] == ']')
1262 || (basename[-1] == '>')))
1264 if (basename[-2] != '.')
1267 /* The VMS part ends in a `]', and the preceding character is not a `.'.
1268 -> PATH]:/name (basename = '/name', unixname = 'name')
1269 We strip the `]', and then splice the two parts of the name in the
1270 usual way. Given the default locations for include files,
1271 we will only use this code if the user specifies alternate locations
1272 with the /include (-I) switch on the command line. */
1274 basename -= 1; /* Strip "]" */
1275 unixname--; /* backspace */
1280 /* The VMS part has a ".]" at the end, and this will not do. Later
1281 processing will add a second directory spec, and this would be a syntax
1282 error. Thus we strip the ".]", and thus merge the directory specs.
1283 We also backspace unixname, so that it points to a '/'. This inhibits the
1284 generation of the 000000 root directory spec (which does not belong here
1287 basename -= 2; /* Strip ".]" */
1288 unixname--; /* backspace */
1296 /* We drop in here if there is no VMS style directory specification yet.
1297 If there is no device specification either, we make the first dir a
1298 device and try that. If we do not do this, then we will be essentially
1299 searching the users default directory (as if they did a #include "asdf.h").
1301 Then all we need to do is to push a '[' into the output string. Later
1302 processing will fill this in, and close the bracket. */
1304 if ((unixname != fullname) /* vms path spec found. */
1305 && (basename[-1] != ':'))
1306 *local_ptr++ = ':'; /* dev not in spec. take first dir */
1308 *local_ptr++ = '['; /* Open the directory specification */
1311 if (unixname == fullname) /* no vms dir spec. */
1314 if ((first_slash != 0) /* unix dir spec. */
1315 && (*unixname != '/') /* not beginning with '/' */
1316 && (*unixname != '.')) /* or './' or '../' */
1317 *local_ptr++ = '.'; /* dir is local ! */
1320 /* at this point we assume that we have the device spec, and (at least
1321 the opening "[" for a directory specification. We may have directories
1324 If there are no other slashes then the filename will be
1325 in the "root" directory. Otherwise, we need to add
1326 directory specifications. */
1328 if (strchr (unixname, '/') == 0)
1330 /* if no directories specified yet and none are following. */
1331 if (local_ptr[-1] == '[')
1333 /* Just add "000000]" as the directory string */
1334 strcpy (local_ptr, "000000]");
1335 local_ptr += strlen (local_ptr);
1336 check_filename_before_returning = 1; /* we might need to fool with this later */
1342 /* As long as there are still subdirectories to add, do them. */
1343 while (strchr (unixname, '/') != 0)
1345 /* If this token is "." we can ignore it
1346 if it's not at the beginning of a path. */
1347 if ((unixname[0] == '.') && (unixname[1] == '/'))
1349 /* remove it at beginning of path. */
1350 if ( ((unixname == fullname) /* no device spec */
1351 && (fullname+2 != basename)) /* starts with ./ */
1353 || ((basename[-1] == ':') /* device spec */
1354 && (unixname-1 == basename))) /* and ./ afterwards */
1355 *local_ptr++ = '.'; /* make '[.' start of path. */
1360 /* Add a subdirectory spec. Do not duplicate "." */
1361 if ( local_ptr[-1] != '.'
1362 && local_ptr[-1] != '['
1363 && local_ptr[-1] != '<')
1366 /* If this is ".." then the spec becomes "-" */
1367 if ( (unixname[0] == '.')
1368 && (unixname[1] == '.')
1369 && (unixname[2] == '/'))
1371 /* Add "-" and skip the ".." */
1372 if ((local_ptr[-1] == '.')
1373 && (local_ptr[-2] == '['))
1374 local_ptr--; /* prevent [.- */
1380 /* Copy the subdirectory */
1381 while (*unixname != '/')
1382 *local_ptr++= *unixname++;
1384 unixname++; /* Skip the "/" */
1387 /* Close the directory specification */
1388 if (local_ptr[-1] == '.') /* no trailing periods */
1391 if (local_ptr[-1] == '[') /* no dir needed */
1397 /* Now add the filename. */
1400 *local_ptr++ = *unixname++;
1403 /* Now append it to the original VMS spec. */
1405 strcpy ((must_revert==1)?fullname:basename, Local);
1407 /* If we put a [000000] in the filename, try to open it first. If this fails,
1408 remove the [000000], and return that name. This provides flexibility
1409 to the user in that they can use both rooted and non-rooted logical names
1410 to point to the location of the file. */
1412 if (check_filename_before_returning)
1414 f = open (fullname, O_RDONLY|O_NONBLOCK);
1417 /* The file name is OK as it is, so return it as is. */
1422 /* The filename did not work. Try to remove the [000000] from the name,
1425 basename = strchr (fullname, '[');
1426 local_ptr = strchr (fullname, ']') + 1;
1427 strcpy (basename, local_ptr); /* this gets rid of it */