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. */
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
42 static IHASH
*redundant_include_p
PARAMS ((cpp_reader
*, IHASH
*,
43 struct file_name_list
*));
44 static IHASH
*make_IHASH
PARAMS ((const char *, const char *,
45 struct file_name_list
*,
46 unsigned int, IHASH
**));
47 static struct file_name_map
*read_name_map
48 PARAMS ((cpp_reader
*, const char *));
49 static char *read_filename_string
PARAMS ((int, FILE *));
50 static char *remap_filename
PARAMS ((cpp_reader
*, char *,
51 struct file_name_list
*));
52 static struct file_name_list
*actual_directory
53 PARAMS ((cpp_reader
*, const char *));
54 static unsigned int hash_IHASH
PARAMS ((const void *));
55 static int eq_IHASH
PARAMS ((const void *, const void *));
56 static int find_include_file
PARAMS ((cpp_reader
*, const char *,
57 struct file_name_list
*,
59 static inline int open_include_file
PARAMS ((cpp_reader
*, const char *));
60 static int read_include_file
PARAMS ((cpp_reader
*, int, IHASH
*));
61 static ssize_t read_with_read
PARAMS ((cpp_buffer
*, int, ssize_t
));
62 static ssize_t read_file
PARAMS ((cpp_buffer
*, int, ssize_t
));
65 static void hack_vms_include_specification
PARAMS ((char *));
68 /* Initial size of include hash table. */
71 #ifndef INCLUDE_LEN_FUDGE
72 #define INCLUDE_LEN_FUDGE 0
75 /* Calculate hash of an IHASH entry. */
80 const IHASH
*i
= (const IHASH
*)x
;
84 /* Compare an existing IHASH structure with a potential one. */
90 const char *a
= ((const IHASH
*)x
)->nshort
;
91 const char *b
= ((const IHASH
*)y
)->nshort
;
92 return !strcmp (a
, b
);
95 /* Init the hash table. In here so it can see the hash and eq functions. */
97 _cpp_init_include_hash (pfile
)
100 pfile
->all_include_files
101 = htab_create (IHASHSIZE
, hash_IHASH
, eq_IHASH
, free
);
104 /* Return 0 if the file pointed to by IHASH has never been included before,
105 -1 if it has been included before and need not be again,
106 or a pointer to an IHASH entry which is the file to be reread.
107 "Never before" is with respect to the position in ILIST.
109 This will not detect redundancies involving odd uses of the
110 `current directory' rule for "" includes. They aren't quite
111 pathological, but I think they are rare enough not to worry about.
112 The simplest example is:
121 and the problem is that for `current directory' includes,
122 ihash->foundhere is not on any of the global include chains,
123 so the test below (i->foundhere == l) may be false even when
124 the directories are in fact the same. */
127 redundant_include_p (pfile
, ihash
, ilist
)
130 struct file_name_list
*ilist
;
132 struct file_name_list
*l
;
135 if (! ihash
->foundhere
)
138 for (i
= ihash
; i
; i
= i
->next_this_file
)
139 for (l
= ilist
; l
; l
= l
->next
)
140 if (i
->foundhere
== l
)
141 /* The control_macro works like this: If it's NULL, the file
142 is to be included again. If it's "", the file is never to
143 be included again. If it's a string, the file is not to be
144 included again if the string is the name of a defined macro. */
145 return (i
->control_macro
146 && (i
->control_macro
[0] == '\0'
147 || cpp_defined (pfile
, i
->control_macro
,
148 ustrlen (i
->control_macro
))))
154 /* Return 1 if the file named by FNAME has been included before in
155 any context, 0 otherwise. */
157 cpp_included (pfile
, fname
)
162 dummy
.nshort
= fname
;
163 dummy
.hash
= _cpp_calc_hash ((const U_CHAR
*)fname
, strlen (fname
));
164 ptr
= htab_find_with_hash (pfile
->all_include_files
,
165 (const void *)&dummy
, dummy
.hash
);
166 return (ptr
!= NULL
);
169 /* Create an IHASH entry and insert it in SLOT. */
171 make_IHASH (name
, fname
, path
, hash
, slot
)
172 const char *name
, *fname
;
173 struct file_name_list
*path
;
178 if (path
== ABSOLUTE_PATH
)
180 ih
= (IHASH
*) xmalloc (sizeof (IHASH
) + strlen (name
));
181 ih
->nshort
= ih
->name
;
187 if ((s
= strstr (name
, fname
)) != NULL
)
189 ih
= (IHASH
*) xmalloc (sizeof (IHASH
) + strlen (name
));
190 ih
->nshort
= ih
->name
+ (s
- name
);
194 ih
= (IHASH
*) xmalloc (sizeof (IHASH
) + strlen (name
)
195 + strlen (fname
) + 1);
196 ih
->nshort
= ih
->name
+ strlen (name
) + 1;
197 strcpy ((char *)ih
->nshort
, fname
);
200 strcpy ((char *)ih
->name
, name
);
201 ih
->foundhere
= path
;
202 ih
->control_macro
= NULL
;
204 ih
->next_this_file
= *slot
;
209 /* Centralize calls to open(2) here. This provides a hook for future
210 changes which might, e.g. look for and open a precompiled version
211 of the header. It also means all the magic currently associated
212 with calling open is in one place, and if we ever need more, it'll
215 We used to open files in nonblocking mode, but that caused more
216 problems than it solved. Do take care not to acquire a controlling
217 terminal by mistake (this can't happen on sane systems, but
218 paranoia is a virtue).
220 Use the three-argument form of open even though we aren't
221 specifying O_CREAT, to defend against broken system headers. */
224 open_include_file (pfile
, filename
)
225 cpp_reader
*pfile ATTRIBUTE_UNUSED
;
226 const char *filename
;
228 return open (filename
, O_RDONLY
|O_NOCTTY
, 0666);
231 /* Search for include file FNAME in the include chain starting at
232 SEARCH_START. Return -2 if this file doesn't need to be included
233 (because it was included already and it's marked idempotent),
234 -1 if an error occurred, or a file descriptor open on the file.
235 *IHASH is set to point to the include hash entry for this file, and
236 *BEFORE is set to 1 if the file was included before (but needs to be read
239 find_include_file (pfile
, fname
, search_start
, ihash
, before
)
242 struct file_name_list
*search_start
;
246 struct file_name_list
*path
;
252 dummy
.nshort
= fname
;
253 dummy
.hash
= _cpp_calc_hash ((const U_CHAR
*)fname
, strlen (fname
));
254 path
= (fname
[0] == '/') ? ABSOLUTE_PATH
: search_start
;
255 slot
= (IHASH
**) htab_find_slot_with_hash (pfile
->all_include_files
,
256 (const void *) &dummy
,
259 if (*slot
&& (ih
= redundant_include_p (pfile
, *slot
, path
)))
261 if (ih
== (IHASH
*)-1)
266 return open_include_file (pfile
, ih
->name
);
269 if (path
== ABSOLUTE_PATH
)
271 name
= (char *) fname
;
272 f
= open_include_file (pfile
, name
);
276 /* Search directory path, trying to open the file. */
277 name
= (char *) alloca (strlen (fname
) + pfile
->max_include_len
278 + 2 + INCLUDE_LEN_FUDGE
);
281 memcpy (name
, path
->name
, path
->nlen
);
282 name
[path
->nlen
] = '/';
283 strcpy (&name
[path
->nlen
+1], fname
);
284 _cpp_simplify_pathname (name
);
285 if (CPP_OPTION (pfile
, remap
))
286 name
= remap_filename (pfile
, name
, path
);
288 f
= open_include_file (pfile
, name
);
290 if (f
== -1 && errno
== EACCES
)
293 "included file `%s' exists but is not readable",
307 ih
= make_IHASH (name
, fname
, path
, dummy
.hash
, slot
);
313 /* Create a dummy IHASH entry for FNAME, and return its name pointer.
314 This is used by #line. */
316 _cpp_fake_ihash (pfile
, fname
)
323 dummy
.nshort
= fname
;
324 dummy
.hash
= _cpp_calc_hash ((const U_CHAR
*)fname
, strlen (fname
));
325 slot
= (IHASH
**) htab_find_slot_with_hash (pfile
->all_include_files
,
326 (const void *) &dummy
,
329 return (*slot
)->name
;
330 ih
= make_IHASH (fname
, 0, ABSOLUTE_PATH
, dummy
.hash
, slot
);
335 /* The file_name_map structure holds a mapping of file names for a
336 particular directory. This mapping is read from the file named
337 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
338 map filenames on a file system with severe filename restrictions,
339 such as DOS. The format of the file name map file is just a series
340 of lines with two tokens on each line. The first token is the name
341 to map, and the second token is the actual name to use. */
345 struct file_name_map
*map_next
;
350 #define FILE_NAME_MAP_FILE "header.gcc"
352 /* Read a space delimited string of unlimited length from a stdio
356 read_filename_string (ch
, f
)
364 set
= alloc
= xmalloc (len
+ 1);
368 while ((ch
= getc (f
)) != EOF
&& ! is_space(ch
))
370 if (set
- alloc
== len
)
373 alloc
= xrealloc (alloc
, len
+ 1);
374 set
= alloc
+ len
/ 2;
384 /* This structure holds a linked list of file name maps, one per directory. */
386 struct file_name_map_list
388 struct file_name_map_list
*map_list_next
;
390 struct file_name_map
*map_list_map
;
393 /* Read the file name map file for DIRNAME. */
395 static struct file_name_map
*
396 read_name_map (pfile
, dirname
)
400 register struct file_name_map_list
*map_list_ptr
;
404 for (map_list_ptr
= CPP_OPTION (pfile
, map_list
); map_list_ptr
;
405 map_list_ptr
= map_list_ptr
->map_list_next
)
406 if (! strcmp (map_list_ptr
->map_list_name
, dirname
))
407 return map_list_ptr
->map_list_map
;
409 map_list_ptr
= ((struct file_name_map_list
*)
410 xmalloc (sizeof (struct file_name_map_list
)));
411 map_list_ptr
->map_list_name
= xstrdup (dirname
);
413 name
= (char *) alloca (strlen (dirname
) + strlen (FILE_NAME_MAP_FILE
) + 2);
414 strcpy (name
, dirname
);
417 strcat (name
, FILE_NAME_MAP_FILE
);
418 f
= fopen (name
, "r");
420 map_list_ptr
->map_list_map
= (struct file_name_map
*)-1;
424 int dirlen
= strlen (dirname
);
426 while ((ch
= getc (f
)) != EOF
)
429 struct file_name_map
*ptr
;
433 from
= read_filename_string (ch
, f
);
434 while ((ch
= getc (f
)) != EOF
&& is_hspace(ch
))
436 to
= read_filename_string (ch
, f
);
438 ptr
= ((struct file_name_map
*)
439 xmalloc (sizeof (struct file_name_map
)));
440 ptr
->map_from
= from
;
442 /* Make the real filename absolute. */
447 ptr
->map_to
= xmalloc (dirlen
+ strlen (to
) + 2);
448 strcpy (ptr
->map_to
, dirname
);
449 ptr
->map_to
[dirlen
] = '/';
450 strcpy (ptr
->map_to
+ dirlen
+ 1, to
);
454 ptr
->map_next
= map_list_ptr
->map_list_map
;
455 map_list_ptr
->map_list_map
= ptr
;
457 while ((ch
= getc (f
)) != '\n')
464 map_list_ptr
->map_list_next
= CPP_OPTION (pfile
, map_list
);
465 CPP_OPTION (pfile
, map_list
) = map_list_ptr
;
467 return map_list_ptr
->map_list_map
;
470 /* Remap NAME based on the file_name_map (if any) for LOC. */
473 remap_filename (pfile
, name
, loc
)
476 struct file_name_list
*loc
;
478 struct file_name_map
*map
;
479 const char *from
, *p
, *dir
;
482 loc
->name_map
= read_name_map (pfile
,
486 if (loc
->name_map
== (struct file_name_map
*)-1)
489 from
= name
+ strlen (loc
->name
) + 1;
491 for (map
= loc
->name_map
; map
; map
= map
->map_next
)
492 if (!strcmp (map
->map_from
, from
))
495 /* Try to find a mapping file for the particular directory we are
496 looking in. Thus #include <sys/types.h> will look up sys/types.h
497 in /usr/include/header.gcc and look up types.h in
498 /usr/include/sys/header.gcc. */
499 p
= strrchr (name
, '/');
503 && strlen (loc
->name
) == (size_t) (p
- name
)
504 && !strncmp (loc
->name
, name
, p
- name
))
505 /* FILENAME is in SEARCHPTR, which we've already checked. */
515 char * newdir
= (char *) alloca (p
- name
+ 1);
516 memcpy (newdir
, name
, p
- name
);
517 newdir
[p
- name
] = '\0';
522 for (map
= read_name_map (pfile
, dir
); map
; map
= map
->map_next
)
523 if (! strcmp (map
->map_from
, name
))
531 _cpp_execute_include (pfile
, f
, len
, no_reinclude
, search_start
)
536 struct file_name_list
*search_start
;
539 char *fname
= (char *)f
;
541 int angle_brackets
= fname
[0] == '<';
547 search_start
= CPP_OPTION (pfile
, bracket_include
);
548 else if (CPP_OPTION (pfile
, ignore_srcdir
))
549 search_start
= CPP_OPTION (pfile
, quote_include
);
551 search_start
= CPP_BUFFER (pfile
)->actual_dir
;
556 cpp_error (pfile
, "No include path in which to find %s", fname
);
560 /* Remove quote marks. */
565 fd
= find_include_file (pfile
, fname
, search_start
, &ihash
, &before
);
572 if (CPP_OPTION (pfile
, print_deps_missing_files
)
573 && CPP_PRINT_DEPS (pfile
) > (angle_brackets
||
574 (pfile
->system_include_depth
> 0)))
577 deps_add_dep (pfile
->deps
, fname
);
581 struct file_name_list
*ptr
;
582 /* If requested as a system header, assume it belongs in
583 the first system header directory. */
584 if (CPP_OPTION (pfile
, bracket_include
))
585 ptr
= CPP_OPTION (pfile
, bracket_include
);
587 ptr
= CPP_OPTION (pfile
, quote_include
);
589 p
= (char *) alloca (strlen (ptr
->name
)
590 + strlen (fname
) + 2);
591 if (*ptr
->name
!= '\0')
593 strcpy (p
, ptr
->name
);
597 deps_add_dep (pfile
->deps
, p
);
600 /* If -M was specified, and this header file won't be added to
601 the dependency list, then don't count this as an error,
602 because we can still produce correct output. Otherwise, we
603 can't produce correct output, because there may be
604 dependencies we need inside the missing file, and we don't
605 know what directory this missing file exists in. */
606 else if (CPP_PRINT_DEPS (pfile
)
607 && (CPP_PRINT_DEPS (pfile
)
608 <= (angle_brackets
|| (pfile
->system_include_depth
> 0))))
609 cpp_warning (pfile
, "No include path in which to find %s", fname
);
611 cpp_error_from_errno (pfile
, fname
);
616 /* For -M, add the file to the dependencies on its first inclusion. */
617 if (!before
&& (CPP_PRINT_DEPS (pfile
)
618 > (angle_brackets
|| (pfile
->system_include_depth
> 0))))
619 deps_add_dep (pfile
->deps
, ihash
->name
);
621 /* Handle -H option. */
622 if (CPP_OPTION (pfile
, print_include_names
))
624 cpp_buffer
*fp
= CPP_BUFFER (pfile
);
625 while ((fp
= CPP_PREV_BUFFER (fp
)) != NULL
)
627 fprintf (stderr
, " %s\n", ihash
->name
);
630 /* Actually process the file. */
632 ihash
->control_macro
= U
"";
634 if (read_include_file (pfile
, fd
, ihash
))
637 pfile
->system_include_depth
++;
642 /* Push an input buffer and load it up with the contents of FNAME.
643 If FNAME is "" or NULL, read standard input. */
645 cpp_read_file (pfile
, fname
)
656 dummy
.nshort
= fname
;
657 /* _cpp_calc_hash doesn't like zero-length strings. */
661 dummy
.hash
= _cpp_calc_hash ((const U_CHAR
*)fname
, strlen (fname
));
662 slot
= (IHASH
**) htab_find_slot_with_hash (pfile
->all_include_files
,
663 (const void *) &dummy
,
665 if (*slot
&& (ih
= redundant_include_p (pfile
, *slot
, ABSOLUTE_PATH
)))
667 if (ih
== (IHASH
*) -1)
668 return 1; /* Already included. */
671 ih
= make_IHASH (fname
, 0, ABSOLUTE_PATH
, dummy
.hash
, slot
);
676 f
= open_include_file (pfile
, fname
);
678 return read_include_file (pfile
, f
, ih
);
681 /* Read the contents of FD into the buffer on the top of PFILE's stack.
682 IHASH points to the include hash entry for the file associated with
685 The caller is responsible for the cpp_push_buffer. */
688 read_include_file (pfile
, fd
, ihash
)
697 fp
= cpp_push_buffer (pfile
, NULL
, 0);
702 if (fstat (fd
, &st
) < 0)
705 /* If fd points to a plain file, we might be able to mmap it; we can
706 definitely allocate the buffer all at once. If fd is a pipe or
707 terminal, we can't do either. If fd is something weird, like a
708 block device or a directory, we don't want to read it at all.
710 Unfortunately, different systems use different st.st_mode values
711 for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and
712 zero the entire struct stat except a couple fields. Hence we don't
713 even try to figure out what something is, except for plain files,
714 directories, and block devices. */
716 if (S_ISREG (st
.st_mode
))
720 /* off_t might have a wider range than ssize_t - in other words,
721 the max size of a file might be bigger than the address
722 space. We can't handle a file that large. (Anyone with
723 a single source file bigger than 2GB needs to rethink
724 their coding style.) */
725 if (st
.st_size
> SSIZE_MAX
)
727 cpp_error (pfile
, "%s is too large", ihash
->name
);
730 st_size
= st
.st_size
;
731 length
= read_file (fp
, fd
, st_size
);
734 if (length
< st_size
)
735 cpp_warning (pfile
, "%s is shorter than expected\n", ihash
->name
);
737 else if (S_ISBLK (st
.st_mode
))
739 cpp_error (pfile
, "%s is a block device", ihash
->name
);
742 else if (S_ISDIR (st
.st_mode
))
744 cpp_error (pfile
, "%s is a directory", ihash
->name
);
749 /* 8 kilobytes is a sensible starting size. It ought to be
750 bigger than the kernel pipe buffer, and it's definitely
751 bigger than the majority of C source files. */
752 length
= read_with_read (fp
, fd
, 8 * 1024);
757 /* These must be set before prescan. */
759 fp
->nominal_fname
= ihash
->name
;
762 ihash
->control_macro
= U
""; /* never re-include */
764 /* Temporary - I hope. */
765 length
= _cpp_prescan (pfile
, fp
, length
);
767 fp
->rlimit
= fp
->buf
+ length
;
769 if (ihash
->foundhere
!= ABSOLUTE_PATH
)
770 fp
->system_header_p
= ihash
->foundhere
->sysp
;
772 fp
->line_base
= fp
->buf
;
774 /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
776 if (!CPP_OPTION (pfile
, ignore_srcdir
))
777 fp
->actual_dir
= actual_directory (pfile
, ihash
->name
);
779 pfile
->input_stack_listing_current
= 0;
780 pfile
->only_seen_white
= 2;
785 cpp_error_from_errno (pfile
, ihash
->name
);
787 cpp_pop_buffer (pfile
);
794 read_file (fp
, fd
, size
)
799 static int pagesize
= -1;
805 pagesize
= getpagesize ();
808 if (size
/ pagesize
>= MMAP_THRESHOLD
)
811 = (const U_CHAR
*) mmap (0, size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
812 if (result
!= (const U_CHAR
*)-1)
819 /* If mmap fails, try read. If there's really a problem, read will
823 return read_with_read (fp
, fd
, size
);
827 read_with_read (fp
, fd
, size
)
832 ssize_t offset
, count
;
835 buf
= (U_CHAR
*) xmalloc (size
);
837 while ((count
= read (fd
, buf
+ offset
, size
- offset
)) > 0)
841 buf
= xrealloc (buf
, (size
*= 2));
855 buf
= xrealloc (buf
, offset
);
861 /* Given a path FNAME, extract the directory component and place it
862 onto the actual_dirs list. Return a pointer to the allocated
863 file_name_list structure. These structures are used to implement
864 current-directory "" include searching. */
866 static struct file_name_list
*
867 actual_directory (pfile
, fname
)
871 char *last_slash
, *dir
;
873 struct file_name_list
*x
;
875 dir
= xstrdup (fname
);
876 last_slash
= strrchr (dir
, '/');
879 if (last_slash
== dir
)
882 last_slash
[1] = '\0';
886 dlen
= last_slash
- dir
;
897 if (dlen
> pfile
->max_include_len
)
898 pfile
->max_include_len
= dlen
;
900 for (x
= pfile
->actual_dirs
; x
; x
= x
->alloc
)
901 if (!strcmp (x
->name
, dir
))
907 /* Not found, make a new one. */
908 x
= (struct file_name_list
*) xmalloc (sizeof (struct file_name_list
));
911 x
->next
= CPP_OPTION (pfile
, quote_include
);
912 x
->alloc
= pfile
->actual_dirs
;
913 x
->sysp
= CPP_BUFFER (pfile
)->system_header_p
;
916 pfile
->actual_dirs
= x
;
920 /* Simplify a path name in place, deleting redundant components. This
921 reduces OS overhead and guarantees that equivalent paths compare
922 the same (modulo symlinks).
925 foo/bar/../quux foo/quux
929 //quux //quux (POSIX allows leading // as a namespace escape)
931 Guarantees no trailing slashes. All transforms reduce the length
935 _cpp_simplify_pathname (path
)
942 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
943 /* Convert all backslashes to slashes. */
944 for (from
= path
; *from
; from
++)
945 if (*from
== '\\') *from
= '/';
947 /* Skip over leading drive letter if present. */
948 if (ISALPHA (path
[0]) && path
[1] == ':')
949 from
= to
= &path
[2];
956 /* Remove redundant initial /s. */
965 /* 3 or more initial /s are equivalent to 1 /. */
966 while (*++from
== '/');
968 /* On some hosts // differs from /; Posix allows this. */
979 if (from
[0] == '.' && from
[1] == '/')
981 else if (from
[0] == '.' && from
[1] == '\0')
983 else if (from
[0] == '.' && from
[1] == '.' && from
[2] == '/')
1000 while (to
> base
&& *to
!= '/') to
--;
1006 else if (from
[0] == '.' && from
[1] == '.' && from
[2] == '\0')
1019 while (to
> base
&& *to
!= '/') to
--;
1026 /* Copy this component and trailing /, if any. */
1027 while ((*to
++ = *from
++) != '/')
1039 /* Trim trailing slash */
1040 if (to
[0] == '/' && (!absolute
|| to
> path
+1))
1043 /* Change the empty string to "." so that stat() on the result
1044 will always work. */
1053 /* It is not clear when this should be used if at all, so I've
1054 disabled it until someone who understands VMS can look at it. */
1057 /* Under VMS we need to fix up the "include" specification filename.
1059 Rules for possible conversions
1061 fullname tried paths
1064 ./dir/name [.dir]name
1066 /name [000000]name, name
1067 dir/name dir:[000000]name, dir:name, dir/name
1068 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
1069 path:/name path:[000000]name, path:name
1070 path:/dir/name path:[000000.dir]name, path:[dir]name
1071 path:dir/name path:[dir]name
1072 [path]:[dir]name [path.dir]name
1073 path/[dir]name [path.dir]name
1075 The path:/name input is constructed when expanding <> includes. */
1079 hack_vms_include_specification (fullname
)
1082 register char *basename
, *unixname
, *local_ptr
, *first_slash
;
1083 int f
, check_filename_before_returning
, must_revert
;
1086 check_filename_before_returning
= 0;
1088 /* See if we can find a 1st slash. If not, there's no path information. */
1089 first_slash
= strchr (fullname
, '/');
1090 if (first_slash
== 0)
1091 return 0; /* Nothing to do!!! */
1093 /* construct device spec if none given. */
1095 if (strchr (fullname
, ':') == 0)
1098 /* If fullname has a slash, take it as device spec. */
1100 if (first_slash
== fullname
)
1102 first_slash
= strchr (fullname
+ 1, '/'); /* 2nd slash ? */
1104 *first_slash
= ':'; /* make device spec */
1105 for (basename
= fullname
; *basename
!= 0; basename
++)
1106 *basename
= *(basename
+1); /* remove leading slash */
1108 else if ((first_slash
[-1] != '.') /* keep ':/', './' */
1109 && (first_slash
[-1] != ':')
1110 && (first_slash
[-1] != ']')) /* or a vms path */
1114 else if ((first_slash
[1] == '[') /* skip './' in './[dir' */
1115 && (first_slash
[-1] == '.'))
1119 /* Get part after first ':' (basename[-1] == ':')
1120 or last '/' (basename[-1] == '/'). */
1122 basename
= base_name (fullname
);
1124 local_ptr
= Local
; /* initialize */
1126 /* We are trying to do a number of things here. First of all, we are
1127 trying to hammer the filenames into a standard format, such that later
1128 processing can handle them.
1130 If the file name contains something like [dir.], then it recognizes this
1131 as a root, and strips the ".]". Later processing will add whatever is
1132 needed to get things working properly.
1134 If no device is specified, then the first directory name is taken to be
1135 a device name (or a rooted logical). */
1137 /* Point to the UNIX filename part (which needs to be fixed!)
1138 but skip vms path information.
1139 [basename != fullname since first_slash != 0]. */
1141 if ((basename
[-1] == ':') /* vms path spec. */
1142 || (basename
[-1] == ']')
1143 || (basename
[-1] == '>'))
1144 unixname
= basename
;
1146 unixname
= fullname
;
1148 if (*unixname
== '/')
1151 /* If the directory spec is not rooted, we can just copy
1152 the UNIX filename part and we are done. */
1154 if (((basename
- fullname
) > 1)
1155 && ( (basename
[-1] == ']')
1156 || (basename
[-1] == '>')))
1158 if (basename
[-2] != '.')
1161 /* The VMS part ends in a `]', and the preceding character is not a `.'.
1162 -> PATH]:/name (basename = '/name', unixname = 'name')
1163 We strip the `]', and then splice the two parts of the name in the
1164 usual way. Given the default locations for include files,
1165 we will only use this code if the user specifies alternate locations
1166 with the /include (-I) switch on the command line. */
1168 basename
-= 1; /* Strip "]" */
1169 unixname
--; /* backspace */
1174 /* The VMS part has a ".]" at the end, and this will not do. Later
1175 processing will add a second directory spec, and this would be a syntax
1176 error. Thus we strip the ".]", and thus merge the directory specs.
1177 We also backspace unixname, so that it points to a '/'. This inhibits the
1178 generation of the 000000 root directory spec (which does not belong here
1181 basename
-= 2; /* Strip ".]" */
1182 unixname
--; /* backspace */
1190 /* We drop in here if there is no VMS style directory specification yet.
1191 If there is no device specification either, we make the first dir a
1192 device and try that. If we do not do this, then we will be essentially
1193 searching the users default directory (as if they did a #include "asdf.h").
1195 Then all we need to do is to push a '[' into the output string. Later
1196 processing will fill this in, and close the bracket. */
1198 if ((unixname
!= fullname
) /* vms path spec found. */
1199 && (basename
[-1] != ':'))
1200 *local_ptr
++ = ':'; /* dev not in spec. take first dir */
1202 *local_ptr
++ = '['; /* Open the directory specification */
1205 if (unixname
== fullname
) /* no vms dir spec. */
1208 if ((first_slash
!= 0) /* unix dir spec. */
1209 && (*unixname
!= '/') /* not beginning with '/' */
1210 && (*unixname
!= '.')) /* or './' or '../' */
1211 *local_ptr
++ = '.'; /* dir is local ! */
1214 /* at this point we assume that we have the device spec, and (at least
1215 the opening "[" for a directory specification. We may have directories
1218 If there are no other slashes then the filename will be
1219 in the "root" directory. Otherwise, we need to add
1220 directory specifications. */
1222 if (strchr (unixname
, '/') == 0)
1224 /* if no directories specified yet and none are following. */
1225 if (local_ptr
[-1] == '[')
1227 /* Just add "000000]" as the directory string */
1228 strcpy (local_ptr
, "000000]");
1229 local_ptr
+= strlen (local_ptr
);
1230 check_filename_before_returning
= 1; /* we might need to fool with this later */
1236 /* As long as there are still subdirectories to add, do them. */
1237 while (strchr (unixname
, '/') != 0)
1239 /* If this token is "." we can ignore it
1240 if it's not at the beginning of a path. */
1241 if ((unixname
[0] == '.') && (unixname
[1] == '/'))
1243 /* remove it at beginning of path. */
1244 if ( ((unixname
== fullname
) /* no device spec */
1245 && (fullname
+2 != basename
)) /* starts with ./ */
1247 || ((basename
[-1] == ':') /* device spec */
1248 && (unixname
-1 == basename
))) /* and ./ afterwards */
1249 *local_ptr
++ = '.'; /* make '[.' start of path. */
1254 /* Add a subdirectory spec. Do not duplicate "." */
1255 if ( local_ptr
[-1] != '.'
1256 && local_ptr
[-1] != '['
1257 && local_ptr
[-1] != '<')
1260 /* If this is ".." then the spec becomes "-" */
1261 if ( (unixname
[0] == '.')
1262 && (unixname
[1] == '.')
1263 && (unixname
[2] == '/'))
1265 /* Add "-" and skip the ".." */
1266 if ((local_ptr
[-1] == '.')
1267 && (local_ptr
[-2] == '['))
1268 local_ptr
--; /* prevent [.- */
1274 /* Copy the subdirectory */
1275 while (*unixname
!= '/')
1276 *local_ptr
++= *unixname
++;
1278 unixname
++; /* Skip the "/" */
1281 /* Close the directory specification */
1282 if (local_ptr
[-1] == '.') /* no trailing periods */
1285 if (local_ptr
[-1] == '[') /* no dir needed */
1291 /* Now add the filename. */
1294 *local_ptr
++ = *unixname
++;
1297 /* Now append it to the original VMS spec. */
1299 strcpy ((must_revert
==1)?fullname
:basename
, Local
);
1301 /* If we put a [000000] in the filename, try to open it first. If this fails,
1302 remove the [000000], and return that name. This provides flexibility
1303 to the user in that they can use both rooted and non-rooted logical names
1304 to point to the location of the file. */
1306 if (check_filename_before_returning
)
1308 f
= open (fullname
, O_RDONLY
|O_NONBLOCK
);
1311 /* The file name is OK as it is, so return it as is. */
1316 /* The filename did not work. Try to remove the [000000] from the name,
1319 basename
= strchr (fullname
, '[');
1320 local_ptr
= strchr (fullname
, ']') + 1;
1321 strcpy (basename
, local_ptr
); /* this gets rid of it */