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
46 static IHASH
*redundant_include_p
PARAMS ((IHASH
*, struct file_name_list
*));
47 static IHASH
*make_IHASH
PARAMS ((const char *, const char *,
48 struct file_name_list
*,
49 unsigned int, IHASH
**));
50 static struct file_name_map
*read_name_map
51 PARAMS ((cpp_reader
*, const char *));
52 static char *read_filename_string
PARAMS ((int, FILE *));
53 static char *remap_filename
PARAMS ((cpp_reader
*, char *,
54 struct file_name_list
*));
55 static struct file_name_list
*actual_directory
56 PARAMS ((cpp_reader
*, const char *));
57 static unsigned int hash_IHASH
PARAMS ((const void *));
58 static int eq_IHASH
PARAMS ((const void *, const void *));
59 static int find_include_file
PARAMS ((cpp_reader
*, const char *,
60 struct file_name_list
*,
62 static inline int open_include_file
PARAMS ((cpp_reader
*, const char *));
63 static int read_include_file
PARAMS ((cpp_reader
*, int, IHASH
*));
64 static ssize_t read_with_read
PARAMS ((cpp_buffer
*, int, ssize_t
));
65 static ssize_t read_file
PARAMS ((cpp_buffer
*, int, ssize_t
));
68 static void hack_vms_include_specification
PARAMS ((char *));
71 /* Initial size of include hash table. */
74 #ifndef INCLUDE_LEN_FUDGE
75 #define INCLUDE_LEN_FUDGE 0
78 /* Calculate hash of an IHASH entry. */
83 const IHASH
*i
= (const IHASH
*)x
;
87 /* Compare an existing IHASH structure with a potential one. */
93 const char *a
= ((const IHASH
*)x
)->nshort
;
94 const char *b
= ((const IHASH
*)y
)->nshort
;
95 return !strcmp (a
, b
);
98 /* Init the hash table. In here so it can see the hash and eq functions. */
100 _cpp_init_include_hash (pfile
)
103 pfile
->all_include_files
104 = htab_create (IHASHSIZE
, hash_IHASH
, eq_IHASH
, free
);
107 /* Return 0 if the file pointed to by IHASH has never been included before,
108 -1 if it has been included before and need not be again,
109 or a pointer to an IHASH entry which is the file to be reread.
110 "Never before" is with respect to the position in ILIST.
112 This will not detect redundancies involving odd uses of the
113 `current directory' rule for "" includes. They aren't quite
114 pathological, but I think they are rare enough not to worry about.
115 The simplest example is:
124 and the problem is that for `current directory' includes,
125 ihash->foundhere is not on any of the global include chains,
126 so the test below (i->foundhere == l) may be false even when
127 the directories are in fact the same. */
130 redundant_include_p (ihash
, ilist
)
132 struct file_name_list
*ilist
;
134 struct file_name_list
*l
;
137 if (! ihash
->foundhere
)
140 for (i
= ihash
; i
; i
= i
->next_this_file
)
141 for (l
= ilist
; l
; l
= l
->next
)
142 if (i
->foundhere
== l
)
143 /* The cmacro works like this: If it's NULL, the file is to
144 be included again. If it's NEVER_REINCLUDE, the file is
145 never to be included again. Otherwise it is a macro
146 hashnode, and the file is to be included again if the
147 macro is not defined. */
149 && (i
->cmacro
== NEVER_REINCLUDE
150 || i
->cmacro
->type
!= T_VOID
))
156 /* Return 1 if the file named by FNAME has been included before in
157 any context, 0 otherwise. */
159 cpp_included (pfile
, fname
)
164 dummy
.nshort
= fname
;
165 dummy
.hash
= _cpp_calc_hash ((const U_CHAR
*)fname
, strlen (fname
));
166 ptr
= htab_find_with_hash (pfile
->all_include_files
,
167 (const void *)&dummy
, dummy
.hash
);
168 return (ptr
!= NULL
);
171 /* Create an IHASH entry and insert it in SLOT. */
173 make_IHASH (name
, fname
, path
, hash
, slot
)
174 const char *name
, *fname
;
175 struct file_name_list
*path
;
180 if (path
== ABSOLUTE_PATH
)
182 ih
= (IHASH
*) xmalloc (sizeof (IHASH
) + strlen (name
));
183 ih
->nshort
= ih
->name
;
189 if ((s
= strstr (name
, fname
)) != NULL
)
191 ih
= (IHASH
*) xmalloc (sizeof (IHASH
) + strlen (name
));
192 ih
->nshort
= ih
->name
+ (s
- name
);
196 ih
= (IHASH
*) xmalloc (sizeof (IHASH
) + strlen (name
)
197 + strlen (fname
) + 1);
198 ih
->nshort
= ih
->name
+ strlen (name
) + 1;
199 strcpy ((char *)ih
->nshort
, fname
);
202 strcpy ((char *)ih
->name
, name
);
203 ih
->foundhere
= path
;
206 ih
->next_this_file
= *slot
;
211 /* Centralize calls to open(2) here. This provides a hook for future
212 changes which might, e.g. look for and open a precompiled version
213 of the header. It also means all the magic currently associated
214 with calling open is in one place, and if we ever need more, it'll
217 We used to open files in nonblocking mode, but that caused more
218 problems than it solved. Do take care not to acquire a controlling
219 terminal by mistake (this can't happen on sane systems, but
220 paranoia is a virtue).
222 Use the three-argument form of open even though we aren't
223 specifying O_CREAT, to defend against broken system headers.
225 O_BINARY tells some runtime libraries (notably DJGPP) not to do
226 newline translation; we can handle DOS line breaks just fine
230 open_include_file (pfile
, filename
)
231 cpp_reader
*pfile ATTRIBUTE_UNUSED
;
232 const char *filename
;
234 return open (filename
, O_RDONLY
|O_NOCTTY
|O_BINARY
, 0666);
237 /* Search for include file FNAME in the include chain starting at
238 SEARCH_START. Return -2 if this file doesn't need to be included
239 (because it was included already and it's marked idempotent),
240 -1 if an error occurred, or a file descriptor open on the file.
241 *IHASH is set to point to the include hash entry for this file, and
242 *BEFORE is set to 1 if the file was included before (but needs to be read
245 find_include_file (pfile
, fname
, search_start
, ihash
, before
)
248 struct file_name_list
*search_start
;
252 struct file_name_list
*path
;
258 dummy
.nshort
= fname
;
259 dummy
.hash
= _cpp_calc_hash ((const U_CHAR
*)fname
, strlen (fname
));
260 path
= (fname
[0] == '/') ? ABSOLUTE_PATH
: search_start
;
261 slot
= (IHASH
**) htab_find_slot_with_hash (pfile
->all_include_files
,
262 (const void *) &dummy
,
265 if (*slot
&& (ih
= redundant_include_p (*slot
, path
)))
267 if (ih
== (IHASH
*)-1)
272 return open_include_file (pfile
, ih
->name
);
275 if (path
== ABSOLUTE_PATH
)
277 name
= (char *) fname
;
278 f
= open_include_file (pfile
, name
);
282 /* Search directory path, trying to open the file. */
283 name
= (char *) alloca (strlen (fname
) + pfile
->max_include_len
284 + 2 + INCLUDE_LEN_FUDGE
);
287 memcpy (name
, path
->name
, path
->nlen
);
288 name
[path
->nlen
] = '/';
289 strcpy (&name
[path
->nlen
+1], fname
);
290 _cpp_simplify_pathname (name
);
291 if (CPP_OPTION (pfile
, remap
))
292 name
= remap_filename (pfile
, name
, path
);
294 f
= open_include_file (pfile
, name
);
296 if (f
== -1 && errno
== EACCES
)
299 "included file `%s' exists but is not readable",
313 ih
= make_IHASH (name
, fname
, path
, dummy
.hash
, slot
);
319 /* Create a dummy IHASH entry for FNAME, and return its name pointer.
320 This is used by #line. */
322 _cpp_fake_ihash (pfile
, fname
)
329 dummy
.nshort
= fname
;
330 dummy
.hash
= _cpp_calc_hash ((const U_CHAR
*)fname
, strlen (fname
));
331 slot
= (IHASH
**) htab_find_slot_with_hash (pfile
->all_include_files
,
332 (const void *) &dummy
,
335 return (*slot
)->name
;
336 ih
= make_IHASH (fname
, 0, ABSOLUTE_PATH
, dummy
.hash
, slot
);
341 /* The file_name_map structure holds a mapping of file names for a
342 particular directory. This mapping is read from the file named
343 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
344 map filenames on a file system with severe filename restrictions,
345 such as DOS. The format of the file name map file is just a series
346 of lines with two tokens on each line. The first token is the name
347 to map, and the second token is the actual name to use. */
351 struct file_name_map
*map_next
;
356 #define FILE_NAME_MAP_FILE "header.gcc"
358 /* Read a space delimited string of unlimited length from a stdio
362 read_filename_string (ch
, f
)
370 set
= alloc
= xmalloc (len
+ 1);
374 while ((ch
= getc (f
)) != EOF
&& ! is_space(ch
))
376 if (set
- alloc
== len
)
379 alloc
= xrealloc (alloc
, len
+ 1);
380 set
= alloc
+ len
/ 2;
390 /* This structure holds a linked list of file name maps, one per directory. */
392 struct file_name_map_list
394 struct file_name_map_list
*map_list_next
;
396 struct file_name_map
*map_list_map
;
399 /* Read the file name map file for DIRNAME. */
401 static struct file_name_map
*
402 read_name_map (pfile
, dirname
)
406 register struct file_name_map_list
*map_list_ptr
;
410 for (map_list_ptr
= CPP_OPTION (pfile
, map_list
); map_list_ptr
;
411 map_list_ptr
= map_list_ptr
->map_list_next
)
412 if (! strcmp (map_list_ptr
->map_list_name
, dirname
))
413 return map_list_ptr
->map_list_map
;
415 map_list_ptr
= ((struct file_name_map_list
*)
416 xmalloc (sizeof (struct file_name_map_list
)));
417 map_list_ptr
->map_list_name
= xstrdup (dirname
);
419 name
= (char *) alloca (strlen (dirname
) + strlen (FILE_NAME_MAP_FILE
) + 2);
420 strcpy (name
, dirname
);
423 strcat (name
, FILE_NAME_MAP_FILE
);
424 f
= fopen (name
, "r");
426 map_list_ptr
->map_list_map
= (struct file_name_map
*)-1;
430 int dirlen
= strlen (dirname
);
432 while ((ch
= getc (f
)) != EOF
)
435 struct file_name_map
*ptr
;
439 from
= read_filename_string (ch
, f
);
440 while ((ch
= getc (f
)) != EOF
&& is_hspace(ch
))
442 to
= read_filename_string (ch
, f
);
444 ptr
= ((struct file_name_map
*)
445 xmalloc (sizeof (struct file_name_map
)));
446 ptr
->map_from
= from
;
448 /* Make the real filename absolute. */
453 ptr
->map_to
= xmalloc (dirlen
+ strlen (to
) + 2);
454 strcpy (ptr
->map_to
, dirname
);
455 ptr
->map_to
[dirlen
] = '/';
456 strcpy (ptr
->map_to
+ dirlen
+ 1, to
);
460 ptr
->map_next
= map_list_ptr
->map_list_map
;
461 map_list_ptr
->map_list_map
= ptr
;
463 while ((ch
= getc (f
)) != '\n')
470 map_list_ptr
->map_list_next
= CPP_OPTION (pfile
, map_list
);
471 CPP_OPTION (pfile
, map_list
) = map_list_ptr
;
473 return map_list_ptr
->map_list_map
;
476 /* Remap NAME based on the file_name_map (if any) for LOC. */
479 remap_filename (pfile
, name
, loc
)
482 struct file_name_list
*loc
;
484 struct file_name_map
*map
;
485 const char *from
, *p
, *dir
;
488 loc
->name_map
= read_name_map (pfile
,
492 if (loc
->name_map
== (struct file_name_map
*)-1)
495 from
= name
+ strlen (loc
->name
) + 1;
497 for (map
= loc
->name_map
; map
; map
= map
->map_next
)
498 if (!strcmp (map
->map_from
, from
))
501 /* Try to find a mapping file for the particular directory we are
502 looking in. Thus #include <sys/types.h> will look up sys/types.h
503 in /usr/include/header.gcc and look up types.h in
504 /usr/include/sys/header.gcc. */
505 p
= strrchr (name
, '/');
509 && strlen (loc
->name
) == (size_t) (p
- name
)
510 && !strncmp (loc
->name
, name
, p
- name
))
511 /* FILENAME is in SEARCHPTR, which we've already checked. */
521 char * newdir
= (char *) alloca (p
- name
+ 1);
522 memcpy (newdir
, name
, p
- name
);
523 newdir
[p
- name
] = '\0';
528 for (map
= read_name_map (pfile
, dir
); map
; map
= map
->map_next
)
529 if (! strcmp (map
->map_from
, name
))
537 _cpp_execute_include (pfile
, f
, len
, no_reinclude
, search_start
)
542 struct file_name_list
*search_start
;
545 char *fname
= (char *)f
;
547 int angle_brackets
= fname
[0] == '<';
553 search_start
= CPP_OPTION (pfile
, bracket_include
);
554 else if (CPP_OPTION (pfile
, ignore_srcdir
))
555 search_start
= CPP_OPTION (pfile
, quote_include
);
557 search_start
= CPP_BUFFER (pfile
)->actual_dir
;
562 cpp_error (pfile
, "No include path in which to find %s", fname
);
566 /* Remove quote marks. */
571 fd
= find_include_file (pfile
, fname
, search_start
, &ihash
, &before
);
578 if (CPP_OPTION (pfile
, print_deps_missing_files
)
579 && CPP_PRINT_DEPS (pfile
) > (angle_brackets
||
580 (pfile
->system_include_depth
> 0)))
583 deps_add_dep (pfile
->deps
, fname
);
587 struct file_name_list
*ptr
;
588 /* If requested as a system header, assume it belongs in
589 the first system header directory. */
590 if (CPP_OPTION (pfile
, bracket_include
))
591 ptr
= CPP_OPTION (pfile
, bracket_include
);
593 ptr
= CPP_OPTION (pfile
, quote_include
);
595 p
= (char *) alloca (strlen (ptr
->name
)
596 + strlen (fname
) + 2);
597 if (*ptr
->name
!= '\0')
599 strcpy (p
, ptr
->name
);
603 deps_add_dep (pfile
->deps
, p
);
606 /* If -M was specified, and this header file won't be added to
607 the dependency list, then don't count this as an error,
608 because we can still produce correct output. Otherwise, we
609 can't produce correct output, because there may be
610 dependencies we need inside the missing file, and we don't
611 know what directory this missing file exists in. */
612 else if (CPP_PRINT_DEPS (pfile
)
613 && (CPP_PRINT_DEPS (pfile
)
614 <= (angle_brackets
|| (pfile
->system_include_depth
> 0))))
615 cpp_warning (pfile
, "No include path in which to find %s", fname
);
617 cpp_error_from_errno (pfile
, fname
);
622 /* For -M, add the file to the dependencies on its first inclusion. */
623 if (!before
&& (CPP_PRINT_DEPS (pfile
)
624 > (angle_brackets
|| (pfile
->system_include_depth
> 0))))
625 deps_add_dep (pfile
->deps
, ihash
->name
);
627 /* Handle -H option. */
628 if (CPP_OPTION (pfile
, print_include_names
))
630 cpp_buffer
*fp
= CPP_BUFFER (pfile
);
631 while ((fp
= CPP_PREV_BUFFER (fp
)) != NULL
)
633 fprintf (stderr
, " %s\n", ihash
->name
);
636 /* Actually process the file. */
638 ihash
->cmacro
= NEVER_REINCLUDE
;
640 if (read_include_file (pfile
, fd
, ihash
))
643 pfile
->system_include_depth
++;
648 /* Push an input buffer and load it up with the contents of FNAME.
649 If FNAME is "" or NULL, read standard input. */
651 cpp_read_file (pfile
, fname
)
662 dummy
.nshort
= fname
;
663 /* _cpp_calc_hash doesn't like zero-length strings. */
667 dummy
.hash
= _cpp_calc_hash ((const U_CHAR
*)fname
, strlen (fname
));
668 slot
= (IHASH
**) htab_find_slot_with_hash (pfile
->all_include_files
,
669 (const void *) &dummy
,
671 if (*slot
&& (ih
= redundant_include_p (*slot
, ABSOLUTE_PATH
)))
673 if (ih
== (IHASH
*) -1)
674 return 1; /* Already included. */
677 ih
= make_IHASH (fname
, 0, ABSOLUTE_PATH
, dummy
.hash
, slot
);
682 f
= open_include_file (pfile
, fname
);
684 return read_include_file (pfile
, f
, ih
);
687 /* Read the contents of FD into the buffer on the top of PFILE's stack.
688 IHASH points to the include hash entry for the file associated with
691 The caller is responsible for the cpp_push_buffer. */
694 read_include_file (pfile
, fd
, ihash
)
703 fp
= cpp_push_buffer (pfile
, NULL
, 0);
708 if (fstat (fd
, &st
) < 0)
711 /* If fd points to a plain file, we might be able to mmap it; we can
712 definitely allocate the buffer all at once. If fd is a pipe or
713 terminal, we can't do either. If fd is something weird, like a
714 block device or a directory, we don't want to read it at all.
716 Unfortunately, different systems use different st.st_mode values
717 for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and
718 zero the entire struct stat except a couple fields. Hence we don't
719 even try to figure out what something is, except for plain files,
720 directories, and block devices. */
722 if (S_ISREG (st
.st_mode
))
726 /* off_t might have a wider range than ssize_t - in other words,
727 the max size of a file might be bigger than the address
728 space. We can't handle a file that large. (Anyone with
729 a single source file bigger than 2GB needs to rethink
730 their coding style.) */
731 if (st
.st_size
> SSIZE_MAX
)
733 cpp_error (pfile
, "%s is too large", ihash
->name
);
736 st_size
= st
.st_size
;
737 length
= read_file (fp
, fd
, st_size
);
740 if (length
< st_size
)
741 cpp_warning (pfile
, "%s is shorter than expected\n", ihash
->name
);
743 else if (S_ISBLK (st
.st_mode
))
745 cpp_error (pfile
, "%s is a block device", ihash
->name
);
748 else if (S_ISDIR (st
.st_mode
))
750 cpp_error (pfile
, "%s is a directory", ihash
->name
);
755 /* 8 kilobytes is a sensible starting size. It ought to be
756 bigger than the kernel pipe buffer, and it's definitely
757 bigger than the majority of C source files. */
758 length
= read_with_read (fp
, fd
, 8 * 1024);
763 /* These must be set before prescan. */
765 fp
->nominal_fname
= ihash
->name
;
768 ihash
->cmacro
= NEVER_REINCLUDE
;
770 /* Temporary - I hope. */
771 length
= _cpp_prescan (pfile
, fp
, length
);
773 fp
->rlimit
= fp
->buf
+ length
;
775 if (ihash
->foundhere
!= ABSOLUTE_PATH
)
776 fp
->system_header_p
= ihash
->foundhere
->sysp
;
778 fp
->line_base
= fp
->buf
;
780 /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
782 if (!CPP_OPTION (pfile
, ignore_srcdir
))
783 fp
->actual_dir
= actual_directory (pfile
, ihash
->name
);
785 pfile
->input_stack_listing_current
= 0;
786 pfile
->only_seen_white
= 2;
791 cpp_error_from_errno (pfile
, ihash
->name
);
793 cpp_pop_buffer (pfile
);
800 read_file (fp
, fd
, size
)
805 static int pagesize
= -1;
811 pagesize
= getpagesize ();
814 if (size
/ pagesize
>= MMAP_THRESHOLD
)
817 = (const U_CHAR
*) mmap (0, size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
818 if (result
!= (const U_CHAR
*)-1)
825 /* If mmap fails, try read. If there's really a problem, read will
829 return read_with_read (fp
, fd
, size
);
833 read_with_read (fp
, fd
, size
)
838 ssize_t offset
, count
;
841 buf
= (U_CHAR
*) xmalloc (size
);
843 while ((count
= read (fd
, buf
+ offset
, size
- offset
)) > 0)
847 buf
= xrealloc (buf
, (size
*= 2));
861 buf
= xrealloc (buf
, offset
);
867 /* Given a path FNAME, extract the directory component and place it
868 onto the actual_dirs list. Return a pointer to the allocated
869 file_name_list structure. These structures are used to implement
870 current-directory "" include searching. */
872 static struct file_name_list
*
873 actual_directory (pfile
, fname
)
877 char *last_slash
, *dir
;
879 struct file_name_list
*x
;
881 dir
= xstrdup (fname
);
882 last_slash
= strrchr (dir
, '/');
885 if (last_slash
== dir
)
888 last_slash
[1] = '\0';
892 dlen
= last_slash
- dir
;
903 if (dlen
> pfile
->max_include_len
)
904 pfile
->max_include_len
= dlen
;
906 for (x
= pfile
->actual_dirs
; x
; x
= x
->alloc
)
907 if (!strcmp (x
->name
, dir
))
913 /* Not found, make a new one. */
914 x
= (struct file_name_list
*) xmalloc (sizeof (struct file_name_list
));
917 x
->next
= CPP_OPTION (pfile
, quote_include
);
918 x
->alloc
= pfile
->actual_dirs
;
919 x
->sysp
= CPP_BUFFER (pfile
)->system_header_p
;
922 pfile
->actual_dirs
= x
;
926 /* Simplify a path name in place, deleting redundant components. This
927 reduces OS overhead and guarantees that equivalent paths compare
928 the same (modulo symlinks).
931 foo/bar/../quux foo/quux
935 //quux //quux (POSIX allows leading // as a namespace escape)
937 Guarantees no trailing slashes. All transforms reduce the length
941 _cpp_simplify_pathname (path
)
948 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
949 /* Convert all backslashes to slashes. */
950 for (from
= path
; *from
; from
++)
951 if (*from
== '\\') *from
= '/';
953 /* Skip over leading drive letter if present. */
954 if (ISALPHA (path
[0]) && path
[1] == ':')
955 from
= to
= &path
[2];
962 /* Remove redundant initial /s. */
971 /* 3 or more initial /s are equivalent to 1 /. */
972 while (*++from
== '/');
974 /* On some hosts // differs from /; Posix allows this. */
985 if (from
[0] == '.' && from
[1] == '/')
987 else if (from
[0] == '.' && from
[1] == '\0')
989 else if (from
[0] == '.' && from
[1] == '.' && from
[2] == '/')
1006 while (to
> base
&& *to
!= '/') to
--;
1012 else if (from
[0] == '.' && from
[1] == '.' && from
[2] == '\0')
1025 while (to
> base
&& *to
!= '/') to
--;
1032 /* Copy this component and trailing /, if any. */
1033 while ((*to
++ = *from
++) != '/')
1045 /* Trim trailing slash */
1046 if (to
[0] == '/' && (!absolute
|| to
> path
+1))
1049 /* Change the empty string to "." so that stat() on the result
1050 will always work. */
1059 /* It is not clear when this should be used if at all, so I've
1060 disabled it until someone who understands VMS can look at it. */
1063 /* Under VMS we need to fix up the "include" specification filename.
1065 Rules for possible conversions
1067 fullname tried paths
1070 ./dir/name [.dir]name
1072 /name [000000]name, name
1073 dir/name dir:[000000]name, dir:name, dir/name
1074 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
1075 path:/name path:[000000]name, path:name
1076 path:/dir/name path:[000000.dir]name, path:[dir]name
1077 path:dir/name path:[dir]name
1078 [path]:[dir]name [path.dir]name
1079 path/[dir]name [path.dir]name
1081 The path:/name input is constructed when expanding <> includes. */
1085 hack_vms_include_specification (fullname
)
1088 register char *basename
, *unixname
, *local_ptr
, *first_slash
;
1089 int f
, check_filename_before_returning
, must_revert
;
1092 check_filename_before_returning
= 0;
1094 /* See if we can find a 1st slash. If not, there's no path information. */
1095 first_slash
= strchr (fullname
, '/');
1096 if (first_slash
== 0)
1097 return 0; /* Nothing to do!!! */
1099 /* construct device spec if none given. */
1101 if (strchr (fullname
, ':') == 0)
1104 /* If fullname has a slash, take it as device spec. */
1106 if (first_slash
== fullname
)
1108 first_slash
= strchr (fullname
+ 1, '/'); /* 2nd slash ? */
1110 *first_slash
= ':'; /* make device spec */
1111 for (basename
= fullname
; *basename
!= 0; basename
++)
1112 *basename
= *(basename
+1); /* remove leading slash */
1114 else if ((first_slash
[-1] != '.') /* keep ':/', './' */
1115 && (first_slash
[-1] != ':')
1116 && (first_slash
[-1] != ']')) /* or a vms path */
1120 else if ((first_slash
[1] == '[') /* skip './' in './[dir' */
1121 && (first_slash
[-1] == '.'))
1125 /* Get part after first ':' (basename[-1] == ':')
1126 or last '/' (basename[-1] == '/'). */
1128 basename
= base_name (fullname
);
1130 local_ptr
= Local
; /* initialize */
1132 /* We are trying to do a number of things here. First of all, we are
1133 trying to hammer the filenames into a standard format, such that later
1134 processing can handle them.
1136 If the file name contains something like [dir.], then it recognizes this
1137 as a root, and strips the ".]". Later processing will add whatever is
1138 needed to get things working properly.
1140 If no device is specified, then the first directory name is taken to be
1141 a device name (or a rooted logical). */
1143 /* Point to the UNIX filename part (which needs to be fixed!)
1144 but skip vms path information.
1145 [basename != fullname since first_slash != 0]. */
1147 if ((basename
[-1] == ':') /* vms path spec. */
1148 || (basename
[-1] == ']')
1149 || (basename
[-1] == '>'))
1150 unixname
= basename
;
1152 unixname
= fullname
;
1154 if (*unixname
== '/')
1157 /* If the directory spec is not rooted, we can just copy
1158 the UNIX filename part and we are done. */
1160 if (((basename
- fullname
) > 1)
1161 && ( (basename
[-1] == ']')
1162 || (basename
[-1] == '>')))
1164 if (basename
[-2] != '.')
1167 /* The VMS part ends in a `]', and the preceding character is not a `.'.
1168 -> PATH]:/name (basename = '/name', unixname = 'name')
1169 We strip the `]', and then splice the two parts of the name in the
1170 usual way. Given the default locations for include files,
1171 we will only use this code if the user specifies alternate locations
1172 with the /include (-I) switch on the command line. */
1174 basename
-= 1; /* Strip "]" */
1175 unixname
--; /* backspace */
1180 /* The VMS part has a ".]" at the end, and this will not do. Later
1181 processing will add a second directory spec, and this would be a syntax
1182 error. Thus we strip the ".]", and thus merge the directory specs.
1183 We also backspace unixname, so that it points to a '/'. This inhibits the
1184 generation of the 000000 root directory spec (which does not belong here
1187 basename
-= 2; /* Strip ".]" */
1188 unixname
--; /* backspace */
1196 /* We drop in here if there is no VMS style directory specification yet.
1197 If there is no device specification either, we make the first dir a
1198 device and try that. If we do not do this, then we will be essentially
1199 searching the users default directory (as if they did a #include "asdf.h").
1201 Then all we need to do is to push a '[' into the output string. Later
1202 processing will fill this in, and close the bracket. */
1204 if ((unixname
!= fullname
) /* vms path spec found. */
1205 && (basename
[-1] != ':'))
1206 *local_ptr
++ = ':'; /* dev not in spec. take first dir */
1208 *local_ptr
++ = '['; /* Open the directory specification */
1211 if (unixname
== fullname
) /* no vms dir spec. */
1214 if ((first_slash
!= 0) /* unix dir spec. */
1215 && (*unixname
!= '/') /* not beginning with '/' */
1216 && (*unixname
!= '.')) /* or './' or '../' */
1217 *local_ptr
++ = '.'; /* dir is local ! */
1220 /* at this point we assume that we have the device spec, and (at least
1221 the opening "[" for a directory specification. We may have directories
1224 If there are no other slashes then the filename will be
1225 in the "root" directory. Otherwise, we need to add
1226 directory specifications. */
1228 if (strchr (unixname
, '/') == 0)
1230 /* if no directories specified yet and none are following. */
1231 if (local_ptr
[-1] == '[')
1233 /* Just add "000000]" as the directory string */
1234 strcpy (local_ptr
, "000000]");
1235 local_ptr
+= strlen (local_ptr
);
1236 check_filename_before_returning
= 1; /* we might need to fool with this later */
1242 /* As long as there are still subdirectories to add, do them. */
1243 while (strchr (unixname
, '/') != 0)
1245 /* If this token is "." we can ignore it
1246 if it's not at the beginning of a path. */
1247 if ((unixname
[0] == '.') && (unixname
[1] == '/'))
1249 /* remove it at beginning of path. */
1250 if ( ((unixname
== fullname
) /* no device spec */
1251 && (fullname
+2 != basename
)) /* starts with ./ */
1253 || ((basename
[-1] == ':') /* device spec */
1254 && (unixname
-1 == basename
))) /* and ./ afterwards */
1255 *local_ptr
++ = '.'; /* make '[.' start of path. */
1260 /* Add a subdirectory spec. Do not duplicate "." */
1261 if ( local_ptr
[-1] != '.'
1262 && local_ptr
[-1] != '['
1263 && local_ptr
[-1] != '<')
1266 /* If this is ".." then the spec becomes "-" */
1267 if ( (unixname
[0] == '.')
1268 && (unixname
[1] == '.')
1269 && (unixname
[2] == '/'))
1271 /* Add "-" and skip the ".." */
1272 if ((local_ptr
[-1] == '.')
1273 && (local_ptr
[-2] == '['))
1274 local_ptr
--; /* prevent [.- */
1280 /* Copy the subdirectory */
1281 while (*unixname
!= '/')
1282 *local_ptr
++= *unixname
++;
1284 unixname
++; /* Skip the "/" */
1287 /* Close the directory specification */
1288 if (local_ptr
[-1] == '.') /* no trailing periods */
1291 if (local_ptr
[-1] == '[') /* no dir needed */
1297 /* Now add the filename. */
1300 *local_ptr
++ = *unixname
++;
1303 /* Now append it to the original VMS spec. */
1305 strcpy ((must_revert
==1)?fullname
:basename
, Local
);
1307 /* If we put a [000000] in the filename, try to open it first. If this fails,
1308 remove the [000000], and return that name. This provides flexibility
1309 to the user in that they can use both rooted and non-rooted logical names
1310 to point to the location of the file. */
1312 if (check_filename_before_returning
)
1314 f
= open (fullname
, O_RDONLY
|O_NONBLOCK
);
1317 /* The file name is OK as it is, so return it as is. */
1322 /* The filename did not work. Try to remove the [000000] from the name,
1325 basename
= strchr (fullname
, '[');
1326 local_ptr
= strchr (fullname
, ']') + 1;
1327 strcpy (basename
, local_ptr
); /* this gets rid of it */