1 /* Part of CPP library. (include file handling)
2 Copyright (C) 1986, 87, 89, 92 - 95, 98, 1999 Free Software Foundation, Inc.
3 Written by Per Bothner, 1994.
4 Based on CCCP program by Paul Rubin, June 1986
5 Adapted to ANSI C, Richard Stallman, Jan 1987
6 Split out of cpplib.c, Zack Weinberg, Oct 1998
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding! */
30 /* The entry points to this file are: find_include_file, finclude,
31 include_hash, append_include_chain, deps_output, and file_cleanup.
32 file_cleanup is only called through CPP_BUFFER(pfile)->cleanup,
33 so it's static anyway. */
35 static struct include_hash *redundant_include_p
37 struct include_hash *,
38 struct file_name_list *));
39 static struct file_name_map *read_name_map PROTO ((cpp_reader *,
41 static char *read_filename_string PROTO ((int, FILE *));
42 static char *remap_filename PROTO ((cpp_reader *, char *,
43 struct file_name_list *));
44 static long read_and_prescan PROTO ((cpp_reader *, cpp_buffer *,
46 static void simplify_pathname PROTO ((char *));
47 static struct file_name_list *actual_directory PROTO ((cpp_reader *, char *));
50 static void hack_vms_include_specification PROTO ((char *));
53 /* Windows does not natively support inodes, and neither does MSDOS.
54 VMS has non-numeric inodes. */
56 #define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a)))
57 #elif (defined _WIN32 && !defined CYGWIN) || defined __MSDOS__
58 #define INO_T_EQ(a, b) 0
60 #define INO_T_EQ(a, b) ((a) == (b))
63 /* Append an entry for dir DIR to list LIST, simplifying it if
64 possible. SYS says whether this is a system include directory.
65 *** DIR is modified in place. It must be writable and permanently
66 allocated. LIST is a pointer to the head pointer, because we actually
67 *prepend* the dir, and reverse the list later (in merge_include_chains). */
69 append_include_chain (pfile, list, dir, sysp)
71 struct file_name_list **list;
75 struct file_name_list *new;
78 char * newdir = xstrdup (dir);
80 simplify_pathname (newdir);
81 if (stat (newdir, &st))
83 /* Dirs that don't exist are silently ignored. */
85 cpp_perror_with_name (pfile, newdir);
89 if (!S_ISDIR (st.st_mode))
91 cpp_message (pfile, 1, "%s: %s: Not a directory", progname, newdir);
96 if (len > pfile->max_include_len)
97 pfile->max_include_len = len;
99 new = (struct file_name_list *)xmalloc (sizeof (struct file_name_list));
103 new->ino = st.st_ino;
104 new->dev = st.st_dev;
106 new->name_map = NULL;
111 /* Merge the four include chains together in the order quote, bracket,
112 system, after. Remove duplicate dirs (as determined by
113 INO_T_EQ()). The system_include and after_include chains are never
114 referred to again after this function; all access is through the
115 bracket_include path.
117 For the future: Check if the directory is empty (but
118 how?) and possibly preload the include hash. */
121 merge_include_chains (opts)
122 struct cpp_options *opts;
124 struct file_name_list *prev, *next, *cur, *other;
125 struct file_name_list *quote, *brack, *systm, *after;
126 struct file_name_list *qtail, *btail, *stail, *atail;
128 qtail = opts->quote_include;
129 btail = opts->bracket_include;
130 stail = opts->system_include;
131 atail = opts->after_include;
133 /* Nreverse the four lists. */
135 for (cur = qtail; cur; cur = next)
144 for (cur = btail; cur; cur = next)
153 for (cur = stail; cur; cur = next)
162 for (cur = atail; cur; cur = next)
170 /* Paste together bracket, system, and after include chains. */
180 /* This is a bit tricky.
181 First we drop dupes from the quote-include list.
182 Then we drop dupes from the bracket-include list.
183 Finally, if qtail and brack are the same directory,
186 We can't just merge the lists and then uniquify them because
187 then we may lose directories from the <> search path that should
188 be there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however
189 safe to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written
190 -Ibar -I- -Ifoo -Iquux. */
192 for (cur = quote; cur; cur = cur->next)
194 for (other = quote; other != cur; other = other->next)
195 if (INO_T_EQ (cur->ino, other->ino)
196 && cur->dev == other->dev)
198 prev->next = cur->next;
208 for (cur = brack; cur; cur = cur->next)
210 for (other = brack; other != cur; other = other->next)
211 if (INO_T_EQ (cur->ino, other->ino)
212 && cur->dev == other->dev)
214 prev->next = cur->next;
225 if (INO_T_EQ (qtail->ino, brack->ino) && qtail->dev == brack->dev)
236 while (cur->next != qtail)
249 opts->quote_include = quote;
250 opts->bracket_include = brack;
251 opts->system_include = NULL;
252 opts->after_include = NULL;
255 /* Look up or add an entry to the table of all includes. This table
256 is indexed by the name as it appears in the #include line. The
257 ->next_this_file chain stores all different files with the same
258 #include name (there are at least three ways this can happen). The
259 hash function could probably be improved a bit. */
261 struct include_hash *
262 include_hash (pfile, fname, add)
267 unsigned int hash = 0;
268 struct include_hash *l, *m;
274 l = pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE];
276 for (; l; m = l, l = l->next)
277 if (!strcmp (l->nshort, fname))
283 l = (struct include_hash *) xmalloc (sizeof (struct include_hash));
285 l->next_this_file = NULL;
292 pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE] = l;
297 /* Return 0 if the file pointed to by IHASH has never been included before,
298 -1 if it has been included before and need not be again,
299 or a pointer to an IHASH entry which is the file to be reread.
300 "Never before" is with respect to the position in ILIST.
302 This will not detect redundancies involving odd uses of the
303 `current directory' rule for "" includes. They aren't quite
304 pathological, but I think they are rare enough not to worry about.
305 The simplest example is:
314 and the problem is that for `current directory' includes,
315 ihash->foundhere is not on any of the global include chains,
316 so the test below (i->foundhere == l) may be false even when
317 the directories are in fact the same. */
319 static struct include_hash *
320 redundant_include_p (pfile, ihash, ilist)
322 struct include_hash *ihash;
323 struct file_name_list *ilist;
325 struct file_name_list *l;
326 struct include_hash *i;
328 if (! ihash->foundhere)
331 for (i = ihash; i; i = i->next_this_file)
332 for (l = ilist; l; l = l->next)
333 if (i->foundhere == l)
334 /* The control_macro works like this: If it's NULL, the file
335 is to be included again. If it's "", the file is never to
336 be included again. If it's a string, the file is not to be
337 included again if the string is the name of a defined macro. */
338 return (i->control_macro
339 && (i->control_macro[0] == '\0'
340 || cpp_lookup (pfile, i->control_macro, -1, -1)))
341 ? (struct include_hash *)-1 : i;
347 file_cleanup (pbuf, pfile)
356 if (pfile->system_include_depth)
357 pfile->system_include_depth--;
361 /* Search for include file FNAME in the include chain starting at
362 SEARCH_START. Return -2 if this file doesn't need to be included
363 (because it was included already and it's marked idempotent),
364 -1 if an error occurred, or a file descriptor open on the file.
365 *IHASH is set to point to the include hash entry for this file, and
366 *BEFORE is 1 if the file was included before (but needs to be read
369 find_include_file (pfile, fname, search_start, ihash, before)
372 struct file_name_list *search_start;
373 struct include_hash **ihash;
376 struct file_name_list *l;
377 struct include_hash *ih, *jh;
381 ih = include_hash (pfile, fname, 1);
382 jh = redundant_include_p (pfile, ih,
383 fname[0] == '/' ? ABSOLUTE_PATH : search_start);
390 if (jh == (struct include_hash *)-1)
393 return open (jh->name, O_RDONLY, 0666);
397 /* A file is already known by this name, but it's not the same file.
398 Allocate another include_hash block and add it to the next_this_file
401 jh = (struct include_hash *)xmalloc (sizeof (struct include_hash));
402 while (ih->next_this_file) ih = ih->next_this_file;
404 ih->next_this_file = jh;
406 ih = ih->next_this_file;
409 ih->next_this_file = NULL;
415 ih->nshort = xstrdup (fname);
416 ih->control_macro = NULL;
418 /* If the pathname is absolute, just open it. */
421 ih->foundhere = ABSOLUTE_PATH;
422 ih->name = ih->nshort;
423 return open (ih->name, O_RDONLY, 0666);
426 /* Search directory path, trying to open the file. */
428 len = strlen (fname);
429 name = xmalloc (len + pfile->max_include_len + 2 + INCLUDE_LEN_FUDGE);
431 for (l = search_start; l; l = l->next)
433 bcopy (l->name, name, l->nlen);
435 strcpy (&name[l->nlen+1], fname);
436 simplify_pathname (name);
437 if (CPP_OPTIONS (pfile)->remap)
438 name = remap_filename (pfile, name, l);
440 f = open (name, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666);
442 if (f == -1 && errno == EACCES)
444 cpp_error(pfile, "included file `%s' exists but is not readable",
453 ih->name = xrealloc (name, strlen (name)+1);
460 jh->next_this_file = NULL;
464 *ihash = (struct include_hash *)-1;
468 /* The file_name_map structure holds a mapping of file names for a
469 particular directory. This mapping is read from the file named
470 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
471 map filenames on a file system with severe filename restrictions,
472 such as DOS. The format of the file name map file is just a series
473 of lines with two tokens on each line. The first token is the name
474 to map, and the second token is the actual name to use. */
478 struct file_name_map *map_next;
483 #define FILE_NAME_MAP_FILE "header.gcc"
485 /* Read a space delimited string of unlimited length from a stdio
489 read_filename_string (ch, f)
497 set = alloc = xmalloc (len + 1);
501 while ((ch = getc (f)) != EOF && ! is_space[ch])
503 if (set - alloc == len)
506 alloc = xrealloc (alloc, len + 1);
507 set = alloc + len / 2;
517 /* This structure holds a linked list of file name maps, one per directory. */
519 struct file_name_map_list
521 struct file_name_map_list *map_list_next;
523 struct file_name_map *map_list_map;
526 /* Read the file name map file for DIRNAME. */
528 static struct file_name_map *
529 read_name_map (pfile, dirname)
533 register struct file_name_map_list *map_list_ptr;
537 for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
538 map_list_ptr = map_list_ptr->map_list_next)
539 if (! strcmp (map_list_ptr->map_list_name, dirname))
540 return map_list_ptr->map_list_map;
542 map_list_ptr = ((struct file_name_map_list *)
543 xmalloc (sizeof (struct file_name_map_list)));
544 map_list_ptr->map_list_name = xstrdup (dirname);
546 name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
547 strcpy (name, dirname);
550 strcat (name, FILE_NAME_MAP_FILE);
551 f = fopen (name, "r");
553 map_list_ptr->map_list_map = (struct file_name_map *)-1;
557 int dirlen = strlen (dirname);
559 while ((ch = getc (f)) != EOF)
562 struct file_name_map *ptr;
566 from = read_filename_string (ch, f);
567 while ((ch = getc (f)) != EOF && is_hor_space[ch])
569 to = read_filename_string (ch, f);
571 ptr = ((struct file_name_map *)
572 xmalloc (sizeof (struct file_name_map)));
573 ptr->map_from = from;
575 /* Make the real filename absolute. */
580 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
581 strcpy (ptr->map_to, dirname);
582 ptr->map_to[dirlen] = '/';
583 strcpy (ptr->map_to + dirlen + 1, to);
587 ptr->map_next = map_list_ptr->map_list_map;
588 map_list_ptr->map_list_map = ptr;
590 while ((ch = getc (f)) != '\n')
597 map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
598 CPP_OPTIONS (pfile)->map_list = map_list_ptr;
600 return map_list_ptr->map_list_map;
603 /* Remap NAME based on the file_name_map (if any) for LOC. */
606 remap_filename (pfile, name, loc)
609 struct file_name_list *loc;
611 struct file_name_map *map;
612 const char *from, *p, *dir;
615 loc->name_map = read_name_map (pfile,
619 if (loc->name_map == (struct file_name_map *)-1)
622 from = name + strlen (loc->name) + 1;
624 for (map = loc->name_map; map; map = map->map_next)
625 if (!strcmp (map->map_from, from))
628 /* Try to find a mapping file for the particular directory we are
629 looking in. Thus #include <sys/types.h> will look up sys/types.h
630 in /usr/include/header.gcc and look up types.h in
631 /usr/include/sys/header.gcc. */
632 p = rindex (name, '/');
636 && strlen (loc->name) == (size_t) (p - name)
637 && !strncmp (loc->name, name, p - name))
638 /* FILENAME is in SEARCHPTR, which we've already checked. */
648 char * newdir = (char *) alloca (p - name + 1);
649 bcopy (name, newdir, p - name);
650 newdir[p - name] = '\0';
655 for (map = read_name_map (pfile, dir); map; map = map->map_next)
656 if (! strcmp (map->map_from, name))
662 /* Read the contents of FD into the buffer on the top of PFILE's stack.
663 IHASH points to the include hash entry for the file associated with
666 The caller is responsible for the cpp_push_buffer. */
669 finclude (pfile, fd, ihash)
672 struct include_hash *ihash;
679 if (fstat (fd, &st) < 0)
681 if (fcntl (fd, F_SETFL, 0) == -1) /* turn off nonblocking mode */
684 fp = CPP_BUFFER (pfile);
686 if (S_ISREG (st.st_mode))
688 /* off_t might have a wider range than size_t - in other words,
689 the max size of a file might be bigger than the address
690 space, and we need to detect that now. */
691 st_size = (size_t) st.st_size;
692 if ((unsigned HOST_WIDE_INT) st_size
693 != (unsigned HOST_WIDE_INT) st.st_size)
695 cpp_error (pfile, "file `%s' is too large", ihash->name);
699 else if (S_ISFIFO (st.st_mode) || (S_ISCHR (st.st_mode) && isatty (fd)))
701 /* Cannot get its file size before reading. 4k is a decent
707 cpp_error (pfile, "`%s' is not a file, pipe, or tty", ihash->name);
711 /* Read the file, converting end-of-line characters and trigraphs
714 fp->nominal_fname = fp->fname = ihash->name;
715 length = read_and_prescan (pfile, fp, fd, st_size);
719 ihash->control_macro = ""; /* never re-include */
722 fp->rlimit = fp->alimit = fp->buf + length;
724 fp->system_header_p = (ihash->foundhere != ABSOLUTE_PATH
725 && ihash->foundhere->sysp);
728 fp->cleanup = file_cleanup;
730 /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
732 if (!CPP_OPTIONS (pfile)->ignore_srcdir)
733 fp->actual_dir = actual_directory (pfile, fp->fname);
735 pfile->input_stack_listing_current = 0;
739 cpp_error_from_errno (pfile, ihash->name);
741 cpp_pop_buffer (pfile);
746 static struct file_name_list *
747 actual_directory (pfile, fname)
751 char *last_slash, *dir;
753 struct file_name_list *x;
755 dir = xstrdup (fname);
756 last_slash = rindex (dir, '/');
759 if (last_slash == dir)
762 last_slash[1] = '\0';
766 dlen = last_slash - dir;
777 if (dlen > pfile->max_include_len)
778 pfile->max_include_len = dlen;
780 for (x = pfile->actual_dirs; x; x = x->alloc)
781 if (!strcmp (x->name, dir))
787 /* Not found, make a new one. */
788 x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
791 x->next = CPP_OPTIONS (pfile)->quote_include;
792 x->alloc = pfile->actual_dirs;
796 pfile->actual_dirs = x;
800 /* Read the entire contents of file DESC into buffer BUF, convert end-of-line
801 markers to canonical form, and convert trigraphs if enabled. Also, make
802 sure there is a newline at the end of the file. LEN is how much room we
803 have to start with (this can be expanded if necessary).
804 Returns -1 on failure, or the actual length of the data to be scanned.
806 N.B. This function has been rearranged to out-of-line the uncommon cases
807 as much as possible; this is important to prevent it from being a
808 performance bottleneck. */
811 read_and_prescan (pfile, fp, desc, len)
817 U_CHAR *buf = (U_CHAR *) xmalloc (len);
818 U_CHAR *ip, *op, *line_base;
823 /* 4096 bytes of buffer proper, 2 to detect running off the end without
824 address arithmetic all the time, and 2 for pushback in the case there's
825 a potential trigraph or end-of-line digraph at the end of a block. */
826 #define INTERMED_BUFFER_SIZE 4096
827 U_CHAR intermed[INTERMED_BUFFER_SIZE + 2 + 2];
833 ibase = intermed + 2;
839 count = read (desc, intermed + 2, INTERMED_BUFFER_SIZE);
847 ibase = intermed + 2;
848 ibase[count] = ibase[count+1] = '\0';
853 size_t delta_line_base;
857 This could happen if the file is larger than half the
858 maximum address space of the machine. */
862 delta_line_base = line_base - buf;
863 buf = (U_CHAR *) xrealloc (buf, len);
865 line_base = buf + delta_line_base;
874 /* The default case is at the top so gcc will realize
875 it's the common case, and leave c in a register.
876 Also, cache utilization is a little better this way. */
884 if (*ip == '\n') ip++;
885 else if (*ip == '\0')
897 if (*ip == '\r') ip++;
898 else if (*ip == '\0')
910 if (CPP_OPTIONS (pfile)->trigraphs
911 || CPP_OPTIONS (pfile)->warn_trigraphs)
914 /* If we're at the end of the intermediate buffer,
915 we have to shift the ?'s down to the start and
916 come back next pass. */
933 intermed[0] = intermed[1] = '?';
936 if (!trigraph_table[d])
942 if (CPP_OPTIONS (pfile)->warn_trigraphs)
943 cpp_warning_with_line (pfile, line, op-line_base,
944 "trigraph ??%c encountered", d);
945 if (CPP_OPTIONS (pfile)->trigraphs)
946 *op++ = trigraph_table[d];
964 /* Deal with pushed-back chars at true EOF.
965 If two chars were pushed back, they must both be ?'s.
966 If one was, it might be ?, \r, or \n, and \r needs to
968 We know we have space already. */
969 if (ibase == intermed)
974 else if (ibase == intermed + 1)
982 if (op[-1] != '\n' || op[-2] == '\\')
984 if (CPP_PEDANTIC (pfile))
985 cpp_pedwarn_with_line (pfile, line, op - line_base,
986 "no newline at end of file");
987 if (offset + 2 > len)
990 if (offset + 2 > len)
992 buf = (U_CHAR *) xrealloc (buf, len);
1001 (U_CHAR *) ((len - offset < 20) ? (PTR) buf : xrealloc (buf, op - buf));
1005 cpp_error (pfile, "file is too large");
1010 cpp_error_from_errno (pfile, fp->fname);
1015 /* Add output to `deps_buffer' for the -M switch.
1016 STRING points to the text to be output.
1017 SPACER is ':' for targets, ' ' for dependencies, zero for text
1018 to be inserted literally. */
1021 deps_output (pfile, string, spacer)
1032 size = strlen (string);
1034 #ifndef MAX_OUTPUT_COLUMNS
1035 #define MAX_OUTPUT_COLUMNS 72
1037 if (pfile->deps_column > 0
1038 && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS)
1042 pfile->deps_column = 0;
1045 if (pfile->deps_size + size + 8 > pfile->deps_allocated_size)
1047 pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2;
1048 pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer,
1049 pfile->deps_allocated_size);
1054 bcopy (" \\\n ", &pfile->deps_buffer[pfile->deps_size], 5);
1055 pfile->deps_size += 5;
1058 if (spacer == ' ' && pfile->deps_column > 0)
1059 pfile->deps_buffer[pfile->deps_size++] = ' ';
1060 bcopy (string, &pfile->deps_buffer[pfile->deps_size], size);
1061 pfile->deps_size += size;
1062 pfile->deps_column += size;
1064 pfile->deps_buffer[pfile->deps_size++] = ':';
1065 pfile->deps_buffer[pfile->deps_size] = 0;
1068 /* Simplify a path name in place, deleting redundant components. This
1069 reduces OS overhead and guarantees that equivalent paths compare
1070 the same (modulo symlinks).
1073 foo/bar/../quux foo/quux
1077 //quux //quux (POSIX allows leading // as a namespace escape)
1079 Guarantees no trailing slashes. All transforms reduce the length
1083 simplify_pathname (path)
1090 #if defined _WIN32 || defined __MSDOS__
1091 /* Convert all backslashes to slashes. */
1092 for (from = path; *from; from++)
1093 if (*from == '\\') *from = '/';
1095 /* Skip over leading drive letter if present. */
1096 if (ISALPHA (path[0]) && path[1] == ':')
1097 from = to = &path[2];
1104 /* Remove redundant initial /s. */
1113 /* 3 or more initial /s are equivalent to 1 /. */
1114 while (*++from == '/');
1116 /* On some hosts // differs from /; Posix allows this. */
1124 while (*from == '/')
1127 if (from[0] == '.' && from[1] == '/')
1129 else if (from[0] == '.' && from[1] == '\0')
1131 else if (from[0] == '.' && from[1] == '.' && from[2] == '/')
1148 while (to > base && *to != '/') to--;
1154 else if (from[0] == '.' && from[1] == '.' && from[2] == '\0')
1167 while (to > base && *to != '/') to--;
1174 /* Copy this component and trailing /, if any. */
1175 while ((*to++ = *from++) != '/')
1187 /* Trim trailing slash */
1188 if (to[0] == '/' && (!absolute || to > path+1))
1191 /* Change the empty string to "." so that stat() on the result
1192 will always work. */
1201 /* It is not clear when this should be used if at all, so I've
1202 disabled it until someone who understands VMS can look at it. */
1205 /* Under VMS we need to fix up the "include" specification filename.
1207 Rules for possible conversions
1209 fullname tried paths
1212 ./dir/name [.dir]name
1214 /name [000000]name, name
1215 dir/name dir:[000000]name, dir:name, dir/name
1216 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
1217 path:/name path:[000000]name, path:name
1218 path:/dir/name path:[000000.dir]name, path:[dir]name
1219 path:dir/name path:[dir]name
1220 [path]:[dir]name [path.dir]name
1221 path/[dir]name [path.dir]name
1223 The path:/name input is constructed when expanding <> includes. */
1227 hack_vms_include_specification (fullname)
1230 register char *basename, *unixname, *local_ptr, *first_slash;
1231 int f, check_filename_before_returning, must_revert;
1234 check_filename_before_returning = 0;
1236 /* See if we can find a 1st slash. If not, there's no path information. */
1237 first_slash = index (fullname, '/');
1238 if (first_slash == 0)
1239 return 0; /* Nothing to do!!! */
1241 /* construct device spec if none given. */
1243 if (index (fullname, ':') == 0)
1246 /* If fullname has a slash, take it as device spec. */
1248 if (first_slash == fullname)
1250 first_slash = index (fullname+1, '/'); /* 2nd slash ? */
1252 *first_slash = ':'; /* make device spec */
1253 for (basename = fullname; *basename != 0; basename++)
1254 *basename = *(basename+1); /* remove leading slash */
1256 else if ((first_slash[-1] != '.') /* keep ':/', './' */
1257 && (first_slash[-1] != ':')
1258 && (first_slash[-1] != ']')) /* or a vms path */
1262 else if ((first_slash[1] == '[') /* skip './' in './[dir' */
1263 && (first_slash[-1] == '.'))
1267 /* Get part after first ':' (basename[-1] == ':')
1268 or last '/' (basename[-1] == '/'). */
1270 basename = base_name (fullname);
1272 local_ptr = Local; /* initialize */
1274 /* We are trying to do a number of things here. First of all, we are
1275 trying to hammer the filenames into a standard format, such that later
1276 processing can handle them.
1278 If the file name contains something like [dir.], then it recognizes this
1279 as a root, and strips the ".]". Later processing will add whatever is
1280 needed to get things working properly.
1282 If no device is specified, then the first directory name is taken to be
1283 a device name (or a rooted logical). */
1285 /* Point to the UNIX filename part (which needs to be fixed!)
1286 but skip vms path information.
1287 [basename != fullname since first_slash != 0]. */
1289 if ((basename[-1] == ':') /* vms path spec. */
1290 || (basename[-1] == ']')
1291 || (basename[-1] == '>'))
1292 unixname = basename;
1294 unixname = fullname;
1296 if (*unixname == '/')
1299 /* If the directory spec is not rooted, we can just copy
1300 the UNIX filename part and we are done. */
1302 if (((basename - fullname) > 1)
1303 && ( (basename[-1] == ']')
1304 || (basename[-1] == '>')))
1306 if (basename[-2] != '.')
1309 /* The VMS part ends in a `]', and the preceding character is not a `.'.
1310 -> PATH]:/name (basename = '/name', unixname = 'name')
1311 We strip the `]', and then splice the two parts of the name in the
1312 usual way. Given the default locations for include files in cccp.c,
1313 we will only use this code if the user specifies alternate locations
1314 with the /include (-I) switch on the command line. */
1316 basename -= 1; /* Strip "]" */
1317 unixname--; /* backspace */
1322 /* The VMS part has a ".]" at the end, and this will not do. Later
1323 processing will add a second directory spec, and this would be a syntax
1324 error. Thus we strip the ".]", and thus merge the directory specs.
1325 We also backspace unixname, so that it points to a '/'. This inhibits the
1326 generation of the 000000 root directory spec (which does not belong here
1329 basename -= 2; /* Strip ".]" */
1330 unixname--; /* backspace */
1338 /* We drop in here if there is no VMS style directory specification yet.
1339 If there is no device specification either, we make the first dir a
1340 device and try that. If we do not do this, then we will be essentially
1341 searching the users default directory (as if they did a #include "asdf.h").
1343 Then all we need to do is to push a '[' into the output string. Later
1344 processing will fill this in, and close the bracket. */
1346 if ((unixname != fullname) /* vms path spec found. */
1347 && (basename[-1] != ':'))
1348 *local_ptr++ = ':'; /* dev not in spec. take first dir */
1350 *local_ptr++ = '['; /* Open the directory specification */
1353 if (unixname == fullname) /* no vms dir spec. */
1356 if ((first_slash != 0) /* unix dir spec. */
1357 && (*unixname != '/') /* not beginning with '/' */
1358 && (*unixname != '.')) /* or './' or '../' */
1359 *local_ptr++ = '.'; /* dir is local ! */
1362 /* at this point we assume that we have the device spec, and (at least
1363 the opening "[" for a directory specification. We may have directories
1366 If there are no other slashes then the filename will be
1367 in the "root" directory. Otherwise, we need to add
1368 directory specifications. */
1370 if (index (unixname, '/') == 0)
1372 /* if no directories specified yet and none are following. */
1373 if (local_ptr[-1] == '[')
1375 /* Just add "000000]" as the directory string */
1376 strcpy (local_ptr, "000000]");
1377 local_ptr += strlen (local_ptr);
1378 check_filename_before_returning = 1; /* we might need to fool with this later */
1384 /* As long as there are still subdirectories to add, do them. */
1385 while (index (unixname, '/') != 0)
1387 /* If this token is "." we can ignore it
1388 if it's not at the beginning of a path. */
1389 if ((unixname[0] == '.') && (unixname[1] == '/'))
1391 /* remove it at beginning of path. */
1392 if ( ((unixname == fullname) /* no device spec */
1393 && (fullname+2 != basename)) /* starts with ./ */
1395 || ((basename[-1] == ':') /* device spec */
1396 && (unixname-1 == basename))) /* and ./ afterwards */
1397 *local_ptr++ = '.'; /* make '[.' start of path. */
1402 /* Add a subdirectory spec. Do not duplicate "." */
1403 if ( local_ptr[-1] != '.'
1404 && local_ptr[-1] != '['
1405 && local_ptr[-1] != '<')
1408 /* If this is ".." then the spec becomes "-" */
1409 if ( (unixname[0] == '.')
1410 && (unixname[1] == '.')
1411 && (unixname[2] == '/'))
1413 /* Add "-" and skip the ".." */
1414 if ((local_ptr[-1] == '.')
1415 && (local_ptr[-2] == '['))
1416 local_ptr--; /* prevent [.- */
1422 /* Copy the subdirectory */
1423 while (*unixname != '/')
1424 *local_ptr++= *unixname++;
1426 unixname++; /* Skip the "/" */
1429 /* Close the directory specification */
1430 if (local_ptr[-1] == '.') /* no trailing periods */
1433 if (local_ptr[-1] == '[') /* no dir needed */
1439 /* Now add the filename. */
1442 *local_ptr++ = *unixname++;
1445 /* Now append it to the original VMS spec. */
1447 strcpy ((must_revert==1)?fullname:basename, Local);
1449 /* If we put a [000000] in the filename, try to open it first. If this fails,
1450 remove the [000000], and return that name. This provides flexibility
1451 to the user in that they can use both rooted and non-rooted logical names
1452 to point to the location of the file. */
1454 if (check_filename_before_returning)
1456 f = open (fullname, O_RDONLY, 0666);
1459 /* The file name is OK as it is, so return it as is. */
1464 /* The filename did not work. Try to remove the [000000] from the name,
1467 basename = index (fullname, '[');
1468 local_ptr = index (fullname, ']') + 1;
1469 strcpy (basename, local_ptr); /* this gets rid of it */