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.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding! */
35 static IHASH
*redundant_include_p
PARAMS ((cpp_reader
*, IHASH
*,
36 struct file_name_list
*));
37 static struct file_name_map
*read_name_map
38 PARAMS ((cpp_reader
*, const char *));
39 static char *read_filename_string
PARAMS ((int, FILE *));
40 static char *remap_filename
PARAMS ((cpp_reader
*, char *,
41 struct file_name_list
*));
42 static struct file_name_list
*actual_directory
43 PARAMS ((cpp_reader
*, const char *));
44 static unsigned int hash_IHASH
PARAMS ((const void *));
45 static int eq_IHASH
PARAMS ((const void *, const void *));
46 static int file_cleanup
PARAMS ((cpp_buffer
*, cpp_reader
*));
47 static int find_include_file
PARAMS ((cpp_reader
*, const char *,
48 struct file_name_list
*,
50 static int read_include_file
PARAMS ((cpp_reader
*, int, IHASH
*));
51 static inline int open_include_file
PARAMS ((cpp_reader
*, const char *));
54 static void hack_vms_include_specification
PARAMS ((char *));
57 /* Initial size of include hash table. */
60 #ifndef INCLUDE_LEN_FUDGE
61 #define INCLUDE_LEN_FUDGE 0
64 /* Calculate hash of an IHASH entry. */
69 IHASH
*i
= (IHASH
*)x
;
70 unsigned int r
= 0, len
= 0;
71 const U_CHAR
*s
= i
->nshort
;
73 if (i
->hash
!= (unsigned long)-1)
77 len
++, r
= r
* 67 + (*s
++ - 113);
78 while (*s
&& *s
!= '.');
83 /* Compare an existing IHASH structure with a potential one. */
89 const U_CHAR
*a
= ((const IHASH
*)x
)->nshort
;
90 const U_CHAR
*b
= ((const IHASH
*)y
)->nshort
;
91 return !strcmp (a
, b
);
94 /* Init the hash table. In here so it can see the hash and eq functions. */
96 _cpp_init_include_hash (pfile
)
99 pfile
->all_include_files
100 = htab_create (IHASHSIZE
, hash_IHASH
, eq_IHASH
, free
);
103 /* Return 0 if the file pointed to by IHASH has never been included before,
104 -1 if it has been included before and need not be again,
105 or a pointer to an IHASH entry which is the file to be reread.
106 "Never before" is with respect to the position in ILIST.
108 This will not detect redundancies involving odd uses of the
109 `current directory' rule for "" includes. They aren't quite
110 pathological, but I think they are rare enough not to worry about.
111 The simplest example is:
120 and the problem is that for `current directory' includes,
121 ihash->foundhere is not on any of the global include chains,
122 so the test below (i->foundhere == l) may be false even when
123 the directories are in fact the same. */
126 redundant_include_p (pfile
, ihash
, ilist
)
129 struct file_name_list
*ilist
;
131 struct file_name_list
*l
;
134 if (! ihash
->foundhere
)
137 for (i
= ihash
; i
; i
= i
->next_this_file
)
138 for (l
= ilist
; l
; l
= l
->next
)
139 if (i
->foundhere
== l
)
140 /* The control_macro works like this: If it's NULL, the file
141 is to be included again. If it's "", the file is never to
142 be included again. If it's a string, the file is not to be
143 included again if the string is the name of a defined macro. */
144 return (i
->control_macro
145 && (i
->control_macro
[0] == '\0'
146 || cpp_defined (pfile
, i
->control_macro
, -1)))
152 /* Return 1 if the file named by FNAME has been included before in
153 any context, 0 otherwise. */
155 cpp_included (pfile
, fname
)
160 dummy
.nshort
= fname
;
162 ptr
= htab_find (pfile
->all_include_files
, (const void *)&dummy
);
163 return (ptr
!= NULL
);
167 file_cleanup (pbuf
, pfile
)
172 free ((PTR
) pbuf
->buf
);
173 if (pfile
->system_include_depth
)
174 pfile
->system_include_depth
--;
178 /* Centralize calls to open(2) here. This provides a hook for future
179 changes which might, e.g. look for and open a precompiled version
180 of the header. It also means all the magic currently associated
181 with calling open is in one place, and if we ever need more, it'll
184 Open files in nonblocking mode, so we don't get stuck if someone
185 clever has asked cpp to process /dev/rmt0. read_include_file
186 will check that we have a real file to work with. Also take care
187 not to acquire a controlling terminal by mistake (this can't happen
188 on sane systems, but paranoia is a virtue).
190 Use the three-argument form of open even though we aren't
191 specifying O_CREAT, to defend against broken system headers. */
194 open_include_file (pfile
, filename
)
195 cpp_reader
*pfile ATTRIBUTE_UNUSED
;
196 const char *filename
;
198 return open (filename
, O_RDONLY
|O_NONBLOCK
|O_NOCTTY
, 0666);
201 /* Search for include file FNAME in the include chain starting at
202 SEARCH_START. Return -2 if this file doesn't need to be included
203 (because it was included already and it's marked idempotent),
204 -1 if an error occurred, or a file descriptor open on the file.
205 *IHASH is set to point to the include hash entry for this file, and
206 *BEFORE is set to 1 if the file was included before (but needs to be read
209 find_include_file (pfile
, fname
, search_start
, ihash
, before
)
212 struct file_name_list
*search_start
;
216 struct file_name_list
*path
;
223 dummy
.nshort
= fname
;
224 path
= (fname
[0] == '/') ? ABSOLUTE_PATH
: search_start
;
225 slot
= (IHASH
**) htab_find_slot (pfile
->all_include_files
,
226 (const void *)&dummy
, 1);
228 if (*slot
&& (ih
= redundant_include_p (pfile
, *slot
, path
)))
230 if (ih
== (IHASH
*)-1)
235 return open_include_file (pfile
, ih
->name
);
238 if (path
== ABSOLUTE_PATH
)
240 name
= (char *) fname
;
241 f
= open_include_file (pfile
, name
);
245 /* Search directory path, trying to open the file. */
246 name
= alloca (strlen (fname
) + pfile
->max_include_len
247 + 2 + INCLUDE_LEN_FUDGE
);
250 memcpy (name
, path
->name
, path
->nlen
);
251 name
[path
->nlen
] = '/';
252 strcpy (&name
[path
->nlen
+1], fname
);
253 _cpp_simplify_pathname (name
);
254 if (CPP_OPTIONS (pfile
)->remap
)
255 name
= remap_filename (pfile
, name
, path
);
257 f
= open_include_file (pfile
, name
);
259 if (f
== -1 && errno
== EACCES
)
262 "included file `%s' exists but is not readable",
276 if (path
== ABSOLUTE_PATH
)
278 ih
= (IHASH
*) xmalloc (sizeof (IHASH
) + strlen (name
));
279 ih
->nshort
= ih
->name
;
283 ih
= (IHASH
*) xmalloc (sizeof (IHASH
) + strlen (name
)
284 + strlen (fname
) + 1);
285 ih
->nshort
= ih
->name
+ strlen (fname
) + 1;
286 strcpy ((char *)ih
->nshort
, fname
);
288 strcpy ((char *)ih
->name
, name
);
289 ih
->foundhere
= path
;
290 ih
->control_macro
= NULL
;
291 ih
->hash
= dummy
.hash
;
293 ih
->next_this_file
= *slot
;
301 /* The file_name_map structure holds a mapping of file names for a
302 particular directory. This mapping is read from the file named
303 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
304 map filenames on a file system with severe filename restrictions,
305 such as DOS. The format of the file name map file is just a series
306 of lines with two tokens on each line. The first token is the name
307 to map, and the second token is the actual name to use. */
311 struct file_name_map
*map_next
;
316 #define FILE_NAME_MAP_FILE "header.gcc"
318 /* Read a space delimited string of unlimited length from a stdio
322 read_filename_string (ch
, f
)
330 set
= alloc
= xmalloc (len
+ 1);
334 while ((ch
= getc (f
)) != EOF
&& ! is_space(ch
))
336 if (set
- alloc
== len
)
339 alloc
= xrealloc (alloc
, len
+ 1);
340 set
= alloc
+ len
/ 2;
350 /* This structure holds a linked list of file name maps, one per directory. */
352 struct file_name_map_list
354 struct file_name_map_list
*map_list_next
;
356 struct file_name_map
*map_list_map
;
359 /* Read the file name map file for DIRNAME. */
361 static struct file_name_map
*
362 read_name_map (pfile
, dirname
)
366 register struct file_name_map_list
*map_list_ptr
;
370 for (map_list_ptr
= CPP_OPTIONS (pfile
)->map_list
; map_list_ptr
;
371 map_list_ptr
= map_list_ptr
->map_list_next
)
372 if (! strcmp (map_list_ptr
->map_list_name
, dirname
))
373 return map_list_ptr
->map_list_map
;
375 map_list_ptr
= ((struct file_name_map_list
*)
376 xmalloc (sizeof (struct file_name_map_list
)));
377 map_list_ptr
->map_list_name
= xstrdup (dirname
);
379 name
= (char *) alloca (strlen (dirname
) + strlen (FILE_NAME_MAP_FILE
) + 2);
380 strcpy (name
, dirname
);
383 strcat (name
, FILE_NAME_MAP_FILE
);
384 f
= fopen (name
, "r");
386 map_list_ptr
->map_list_map
= (struct file_name_map
*)-1;
390 int dirlen
= strlen (dirname
);
392 while ((ch
= getc (f
)) != EOF
)
395 struct file_name_map
*ptr
;
399 from
= read_filename_string (ch
, f
);
400 while ((ch
= getc (f
)) != EOF
&& is_hspace(ch
))
402 to
= read_filename_string (ch
, f
);
404 ptr
= ((struct file_name_map
*)
405 xmalloc (sizeof (struct file_name_map
)));
406 ptr
->map_from
= from
;
408 /* Make the real filename absolute. */
413 ptr
->map_to
= xmalloc (dirlen
+ strlen (to
) + 2);
414 strcpy (ptr
->map_to
, dirname
);
415 ptr
->map_to
[dirlen
] = '/';
416 strcpy (ptr
->map_to
+ dirlen
+ 1, to
);
420 ptr
->map_next
= map_list_ptr
->map_list_map
;
421 map_list_ptr
->map_list_map
= ptr
;
423 while ((ch
= getc (f
)) != '\n')
430 map_list_ptr
->map_list_next
= CPP_OPTIONS (pfile
)->map_list
;
431 CPP_OPTIONS (pfile
)->map_list
= map_list_ptr
;
433 return map_list_ptr
->map_list_map
;
436 /* Remap NAME based on the file_name_map (if any) for LOC. */
439 remap_filename (pfile
, name
, loc
)
442 struct file_name_list
*loc
;
444 struct file_name_map
*map
;
445 const char *from
, *p
, *dir
;
448 loc
->name_map
= read_name_map (pfile
,
452 if (loc
->name_map
== (struct file_name_map
*)-1)
455 from
= name
+ strlen (loc
->name
) + 1;
457 for (map
= loc
->name_map
; map
; map
= map
->map_next
)
458 if (!strcmp (map
->map_from
, from
))
461 /* Try to find a mapping file for the particular directory we are
462 looking in. Thus #include <sys/types.h> will look up sys/types.h
463 in /usr/include/header.gcc and look up types.h in
464 /usr/include/sys/header.gcc. */
465 p
= strrchr (name
, '/');
469 && strlen (loc
->name
) == (size_t) (p
- name
)
470 && !strncmp (loc
->name
, name
, p
- name
))
471 /* FILENAME is in SEARCHPTR, which we've already checked. */
481 char * newdir
= (char *) alloca (p
- name
+ 1);
482 memcpy (newdir
, name
, p
- name
);
483 newdir
[p
- name
] = '\0';
488 for (map
= read_name_map (pfile
, dir
); map
; map
= map
->map_next
)
489 if (! strcmp (map
->map_from
, name
))
497 _cpp_execute_include (pfile
, fname
, len
, no_reinclude
, search_start
)
502 struct file_name_list
*search_start
;
506 int angle_brackets
= fname
[0] == '<';
512 search_start
= CPP_OPTIONS (pfile
)->bracket_include
;
513 else if (CPP_OPTIONS (pfile
)->ignore_srcdir
)
514 search_start
= CPP_OPTIONS (pfile
)->quote_include
;
516 search_start
= CPP_BUFFER (pfile
)->actual_dir
;
521 cpp_error (pfile
, "No include path in which to find %s", fname
);
525 /* Remove quote marks. */
530 fd
= find_include_file (pfile
, fname
, search_start
, &ihash
, &before
);
537 if (CPP_OPTIONS (pfile
)->print_deps_missing_files
538 && CPP_PRINT_DEPS (pfile
) > (angle_brackets
||
539 (pfile
->system_include_depth
> 0)))
542 deps_add_dep (pfile
->deps
, fname
);
546 struct file_name_list
*ptr
;
547 /* If requested as a system header, assume it belongs in
548 the first system header directory. */
549 if (CPP_OPTIONS (pfile
)->bracket_include
)
550 ptr
= CPP_OPTIONS (pfile
)->bracket_include
;
552 ptr
= CPP_OPTIONS (pfile
)->quote_include
;
554 p
= (char *) alloca (strlen (ptr
->name
)
555 + strlen (fname
) + 2);
556 if (*ptr
->name
!= '\0')
558 strcpy (p
, ptr
->name
);
562 deps_add_dep (pfile
->deps
, p
);
565 /* If -M was specified, and this header file won't be added to
566 the dependency list, then don't count this as an error,
567 because we can still produce correct output. Otherwise, we
568 can't produce correct output, because there may be
569 dependencies we need inside the missing file, and we don't
570 know what directory this missing file exists in. */
571 else if (CPP_PRINT_DEPS (pfile
)
572 && (CPP_PRINT_DEPS (pfile
)
573 <= (angle_brackets
|| (pfile
->system_include_depth
> 0))))
574 cpp_warning (pfile
, "No include path in which to find %s", fname
);
576 cpp_error_from_errno (pfile
, fname
);
581 /* For -M, add the file to the dependencies on its first inclusion. */
582 if (!before
&& (CPP_PRINT_DEPS (pfile
)
583 > (angle_brackets
|| (pfile
->system_include_depth
> 0))))
584 deps_add_dep (pfile
->deps
, ihash
->name
);
586 /* Handle -H option. */
587 if (CPP_OPTIONS(pfile
)->print_include_names
)
589 cpp_buffer
*fp
= CPP_BUFFER (pfile
);
590 while ((fp
= CPP_PREV_BUFFER (fp
)) != NULL
)
592 fprintf (stderr
, " %s\n", ihash
->name
);
595 /* Actually process the file */
598 ihash
->control_macro
= (const U_CHAR
*) "";
600 if (read_include_file (pfile
, fd
, ihash
))
602 _cpp_output_line_command (pfile
, enter_file
);
604 pfile
->system_include_depth
++; /* Decremented in file_cleanup. */
609 /* Push an input buffer and load it up with the contents of FNAME.
610 If FNAME is "" or NULL, read standard input. */
612 cpp_read_file (pfile
, fname
)
624 dummy
.nshort
= fname
;
625 slot
= (IHASH
**) htab_find_slot (pfile
->all_include_files
,
626 (const void *) &dummy
, 1);
627 if (*slot
&& (ih
= redundant_include_p (pfile
, *slot
, ABSOLUTE_PATH
)))
629 if (ih
== (IHASH
*)-1)
630 return 1; /* Already included. */
634 ih
= (IHASH
*) xmalloc (sizeof (IHASH
) + strlen (fname
));
635 ih
->control_macro
= 0;
636 ih
->foundhere
= ABSOLUTE_PATH
; /* well sort of ... */
637 ih
->hash
= dummy
.hash
;
638 strcpy ((char *)ih
->name
, fname
);
639 ih
->nshort
= ih
->name
;
641 ih
->next_this_file
= *slot
;
648 f
= open_include_file (pfile
, fname
);
650 return read_include_file (pfile
, f
, ih
);
653 /* Read the contents of FD into the buffer on the top of PFILE's stack.
654 IHASH points to the include hash entry for the file associated with
657 The caller is responsible for the cpp_push_buffer. */
660 read_include_file (pfile
, fd
, ihash
)
670 fp
= cpp_push_buffer (pfile
, NULL
, 0);
675 if (fstat (fd
, &st
) < 0)
677 if (fcntl (fd
, F_SETFL
, 0) == -1) /* turn off nonblocking mode */
680 /* If fd points to a plain file, we know how big it is, so we can
681 allocate the buffer all at once. If fd is a pipe or terminal, we
682 can't. Most C source files are 4k or less, so we guess that. If
683 fd is something weird, like a block device or a directory, we
684 don't want to read it at all.
686 Unfortunately, different systems use different st.st_mode values
687 for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and
688 zero the entire struct stat except a couple fields. Hence the
691 In all cases, read_and_prescan will resize the buffer if it
692 turns out there's more data than we thought. */
694 if (S_ISREG (st
.st_mode
))
696 /* off_t might have a wider range than size_t - in other words,
697 the max size of a file might be bigger than the address
698 space. We can't handle a file that large. (Anyone with
699 a single source file bigger than 4GB needs to rethink
700 their coding style.) */
701 st_size
= (size_t) st
.st_size
;
702 if ((unsigned HOST_WIDEST_INT
) st_size
703 != (unsigned HOST_WIDEST_INT
) st
.st_size
)
705 cpp_error (pfile
, "file `%s' is too large", ihash
->name
);
709 else if (S_ISFIFO (st
.st_mode
) || S_ISSOCK (st
.st_mode
)
710 /* Permit any kind of character device: the sensible ones are
711 ttys and /dev/null, but weeding out the others is too hard. */
712 || S_ISCHR (st
.st_mode
)
713 /* Some 4.x (x<4) derivatives have a bug that makes fstat() of a
714 socket or pipe return a stat struct with most fields zeroed. */
715 || (st
.st_mode
== 0 && st
.st_nlink
== 0 && st
.st_size
== 0))
717 /* Cannot get its file size before reading. 4k is a decent
723 cpp_error (pfile
, "`%s' is not a file, pipe, or tty", ihash
->name
);
727 /* Read the file, converting end-of-line characters and trigraphs
730 fp
->nominal_fname
= ihash
->name
;
731 length
= _cpp_read_and_prescan (pfile
, fp
, fd
, st_size
);
735 ihash
->control_macro
= (const U_CHAR
*) ""; /* never re-include */
738 fp
->rlimit
= fp
->alimit
= fp
->buf
+ length
;
740 if (ihash
->foundhere
!= ABSOLUTE_PATH
)
741 fp
->system_header_p
= ihash
->foundhere
->sysp
;
744 fp
->line_base
= fp
->buf
;
745 fp
->cleanup
= file_cleanup
;
747 /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
749 if (!CPP_OPTIONS (pfile
)->ignore_srcdir
)
750 fp
->actual_dir
= actual_directory (pfile
, ihash
->name
);
752 pfile
->input_stack_listing_current
= 0;
753 pfile
->only_seen_white
= 2;
757 cpp_error_from_errno (pfile
, ihash
->name
);
759 cpp_pop_buffer (pfile
);
765 /* Given a path FNAME, extract the directory component and place it
766 onto the actual_dirs list. Return a pointer to the allocated
767 file_name_list structure. These structures are used to implement
768 current-directory "" include searching. */
770 static struct file_name_list
*
771 actual_directory (pfile
, fname
)
775 char *last_slash
, *dir
;
777 struct file_name_list
*x
;
779 dir
= xstrdup (fname
);
780 last_slash
= strrchr (dir
, '/');
783 if (last_slash
== dir
)
786 last_slash
[1] = '\0';
790 dlen
= last_slash
- dir
;
801 if (dlen
> pfile
->max_include_len
)
802 pfile
->max_include_len
= dlen
;
804 for (x
= pfile
->actual_dirs
; x
; x
= x
->alloc
)
805 if (!strcmp (x
->name
, dir
))
811 /* Not found, make a new one. */
812 x
= (struct file_name_list
*) xmalloc (sizeof (struct file_name_list
));
815 x
->next
= CPP_OPTIONS (pfile
)->quote_include
;
816 x
->alloc
= pfile
->actual_dirs
;
817 x
->sysp
= CPP_BUFFER (pfile
)->system_header_p
;
820 pfile
->actual_dirs
= x
;
824 /* Simplify a path name in place, deleting redundant components. This
825 reduces OS overhead and guarantees that equivalent paths compare
826 the same (modulo symlinks).
829 foo/bar/../quux foo/quux
833 //quux //quux (POSIX allows leading // as a namespace escape)
835 Guarantees no trailing slashes. All transforms reduce the length
839 _cpp_simplify_pathname (path
)
846 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
847 /* Convert all backslashes to slashes. */
848 for (from
= path
; *from
; from
++)
849 if (*from
== '\\') *from
= '/';
851 /* Skip over leading drive letter if present. */
852 if (ISALPHA (path
[0]) && path
[1] == ':')
853 from
= to
= &path
[2];
860 /* Remove redundant initial /s. */
869 /* 3 or more initial /s are equivalent to 1 /. */
870 while (*++from
== '/');
872 /* On some hosts // differs from /; Posix allows this. */
883 if (from
[0] == '.' && from
[1] == '/')
885 else if (from
[0] == '.' && from
[1] == '\0')
887 else if (from
[0] == '.' && from
[1] == '.' && from
[2] == '/')
904 while (to
> base
&& *to
!= '/') to
--;
910 else if (from
[0] == '.' && from
[1] == '.' && from
[2] == '\0')
923 while (to
> base
&& *to
!= '/') to
--;
930 /* Copy this component and trailing /, if any. */
931 while ((*to
++ = *from
++) != '/')
943 /* Trim trailing slash */
944 if (to
[0] == '/' && (!absolute
|| to
> path
+1))
947 /* Change the empty string to "." so that stat() on the result
957 /* It is not clear when this should be used if at all, so I've
958 disabled it until someone who understands VMS can look at it. */
961 /* Under VMS we need to fix up the "include" specification filename.
963 Rules for possible conversions
968 ./dir/name [.dir]name
970 /name [000000]name, name
971 dir/name dir:[000000]name, dir:name, dir/name
972 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
973 path:/name path:[000000]name, path:name
974 path:/dir/name path:[000000.dir]name, path:[dir]name
975 path:dir/name path:[dir]name
976 [path]:[dir]name [path.dir]name
977 path/[dir]name [path.dir]name
979 The path:/name input is constructed when expanding <> includes. */
983 hack_vms_include_specification (fullname
)
986 register char *basename
, *unixname
, *local_ptr
, *first_slash
;
987 int f
, check_filename_before_returning
, must_revert
;
990 check_filename_before_returning
= 0;
992 /* See if we can find a 1st slash. If not, there's no path information. */
993 first_slash
= strchr (fullname
, '/');
994 if (first_slash
== 0)
995 return 0; /* Nothing to do!!! */
997 /* construct device spec if none given. */
999 if (strchr (fullname
, ':') == 0)
1002 /* If fullname has a slash, take it as device spec. */
1004 if (first_slash
== fullname
)
1006 first_slash
= strchr (fullname
+ 1, '/'); /* 2nd slash ? */
1008 *first_slash
= ':'; /* make device spec */
1009 for (basename
= fullname
; *basename
!= 0; basename
++)
1010 *basename
= *(basename
+1); /* remove leading slash */
1012 else if ((first_slash
[-1] != '.') /* keep ':/', './' */
1013 && (first_slash
[-1] != ':')
1014 && (first_slash
[-1] != ']')) /* or a vms path */
1018 else if ((first_slash
[1] == '[') /* skip './' in './[dir' */
1019 && (first_slash
[-1] == '.'))
1023 /* Get part after first ':' (basename[-1] == ':')
1024 or last '/' (basename[-1] == '/'). */
1026 basename
= base_name (fullname
);
1028 local_ptr
= Local
; /* initialize */
1030 /* We are trying to do a number of things here. First of all, we are
1031 trying to hammer the filenames into a standard format, such that later
1032 processing can handle them.
1034 If the file name contains something like [dir.], then it recognizes this
1035 as a root, and strips the ".]". Later processing will add whatever is
1036 needed to get things working properly.
1038 If no device is specified, then the first directory name is taken to be
1039 a device name (or a rooted logical). */
1041 /* Point to the UNIX filename part (which needs to be fixed!)
1042 but skip vms path information.
1043 [basename != fullname since first_slash != 0]. */
1045 if ((basename
[-1] == ':') /* vms path spec. */
1046 || (basename
[-1] == ']')
1047 || (basename
[-1] == '>'))
1048 unixname
= basename
;
1050 unixname
= fullname
;
1052 if (*unixname
== '/')
1055 /* If the directory spec is not rooted, we can just copy
1056 the UNIX filename part and we are done. */
1058 if (((basename
- fullname
) > 1)
1059 && ( (basename
[-1] == ']')
1060 || (basename
[-1] == '>')))
1062 if (basename
[-2] != '.')
1065 /* The VMS part ends in a `]', and the preceding character is not a `.'.
1066 -> PATH]:/name (basename = '/name', unixname = 'name')
1067 We strip the `]', and then splice the two parts of the name in the
1068 usual way. Given the default locations for include files in cccp.c,
1069 we will only use this code if the user specifies alternate locations
1070 with the /include (-I) switch on the command line. */
1072 basename
-= 1; /* Strip "]" */
1073 unixname
--; /* backspace */
1078 /* The VMS part has a ".]" at the end, and this will not do. Later
1079 processing will add a second directory spec, and this would be a syntax
1080 error. Thus we strip the ".]", and thus merge the directory specs.
1081 We also backspace unixname, so that it points to a '/'. This inhibits the
1082 generation of the 000000 root directory spec (which does not belong here
1085 basename
-= 2; /* Strip ".]" */
1086 unixname
--; /* backspace */
1094 /* We drop in here if there is no VMS style directory specification yet.
1095 If there is no device specification either, we make the first dir a
1096 device and try that. If we do not do this, then we will be essentially
1097 searching the users default directory (as if they did a #include "asdf.h").
1099 Then all we need to do is to push a '[' into the output string. Later
1100 processing will fill this in, and close the bracket. */
1102 if ((unixname
!= fullname
) /* vms path spec found. */
1103 && (basename
[-1] != ':'))
1104 *local_ptr
++ = ':'; /* dev not in spec. take first dir */
1106 *local_ptr
++ = '['; /* Open the directory specification */
1109 if (unixname
== fullname
) /* no vms dir spec. */
1112 if ((first_slash
!= 0) /* unix dir spec. */
1113 && (*unixname
!= '/') /* not beginning with '/' */
1114 && (*unixname
!= '.')) /* or './' or '../' */
1115 *local_ptr
++ = '.'; /* dir is local ! */
1118 /* at this point we assume that we have the device spec, and (at least
1119 the opening "[" for a directory specification. We may have directories
1122 If there are no other slashes then the filename will be
1123 in the "root" directory. Otherwise, we need to add
1124 directory specifications. */
1126 if (strchr (unixname
, '/') == 0)
1128 /* if no directories specified yet and none are following. */
1129 if (local_ptr
[-1] == '[')
1131 /* Just add "000000]" as the directory string */
1132 strcpy (local_ptr
, "000000]");
1133 local_ptr
+= strlen (local_ptr
);
1134 check_filename_before_returning
= 1; /* we might need to fool with this later */
1140 /* As long as there are still subdirectories to add, do them. */
1141 while (strchr (unixname
, '/') != 0)
1143 /* If this token is "." we can ignore it
1144 if it's not at the beginning of a path. */
1145 if ((unixname
[0] == '.') && (unixname
[1] == '/'))
1147 /* remove it at beginning of path. */
1148 if ( ((unixname
== fullname
) /* no device spec */
1149 && (fullname
+2 != basename
)) /* starts with ./ */
1151 || ((basename
[-1] == ':') /* device spec */
1152 && (unixname
-1 == basename
))) /* and ./ afterwards */
1153 *local_ptr
++ = '.'; /* make '[.' start of path. */
1158 /* Add a subdirectory spec. Do not duplicate "." */
1159 if ( local_ptr
[-1] != '.'
1160 && local_ptr
[-1] != '['
1161 && local_ptr
[-1] != '<')
1164 /* If this is ".." then the spec becomes "-" */
1165 if ( (unixname
[0] == '.')
1166 && (unixname
[1] == '.')
1167 && (unixname
[2] == '/'))
1169 /* Add "-" and skip the ".." */
1170 if ((local_ptr
[-1] == '.')
1171 && (local_ptr
[-2] == '['))
1172 local_ptr
--; /* prevent [.- */
1178 /* Copy the subdirectory */
1179 while (*unixname
!= '/')
1180 *local_ptr
++= *unixname
++;
1182 unixname
++; /* Skip the "/" */
1185 /* Close the directory specification */
1186 if (local_ptr
[-1] == '.') /* no trailing periods */
1189 if (local_ptr
[-1] == '[') /* no dir needed */
1195 /* Now add the filename. */
1198 *local_ptr
++ = *unixname
++;
1201 /* Now append it to the original VMS spec. */
1203 strcpy ((must_revert
==1)?fullname
:basename
, Local
);
1205 /* If we put a [000000] in the filename, try to open it first. If this fails,
1206 remove the [000000], and return that name. This provides flexibility
1207 to the user in that they can use both rooted and non-rooted logical names
1208 to point to the location of the file. */
1210 if (check_filename_before_returning
)
1212 f
= open (fullname
, O_RDONLY
|O_NONBLOCK
);
1215 /* The file name is OK as it is, so return it as is. */
1220 /* The filename did not work. Try to remove the [000000] from the name,
1223 basename
= strchr (fullname
, '[');
1224 local_ptr
= strchr (fullname
, ']') + 1;
1225 strcpy (basename
, local_ptr
); /* this gets rid of it */