OSDN Git Service

* regclass.c (record_reg_classes): In matching case, recompute
[pf3gnuchains/gcc-fork.git] / gcc / cppfiles.c
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
7
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
11 later version.
12
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.
17
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.
21
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!  */
25
26 #include "config.h"
27 #include "system.h"
28 #include "cpplib.h"
29
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. */
34
35 static struct include_hash *redundant_include_p
36                                         PROTO ((cpp_reader *,
37                                                 struct include_hash *,
38                                                 struct file_name_list *));
39 static struct file_name_map *read_name_map      PROTO ((cpp_reader *,
40                                                         const char *));
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 *,
45                                                 int, size_t));
46 static struct file_name_list *actual_directory PROTO ((cpp_reader *,
47                                                        const char *));
48 static void initialize_input_buffer     PROTO ((cpp_reader *, int,
49                                                 struct stat *));
50 static int file_cleanup                 PROTO ((cpp_buffer *, cpp_reader *));
51 static void find_position               PROTO ((U_CHAR *, U_CHAR *,
52                                                 unsigned long *,
53                                                 unsigned long *));
54
55 #if 0
56 static void hack_vms_include_specification PROTO ((char *));
57 #endif
58
59 /* Windows does not natively support inodes, and neither does MSDOS.
60    VMS has non-numeric inodes. */
61 #ifdef VMS
62 #define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a)))
63 #elif (defined _WIN32 && !defined CYGWIN && ! defined (_UWIN)) \
64        || defined __MSDOS__
65 #define INO_T_EQ(a, b) 0
66 #else
67 #define INO_T_EQ(a, b) ((a) == (b))
68 #endif
69
70 /* Merge the four include chains together in the order quote, bracket,
71    system, after.  Remove duplicate dirs (as determined by
72    INO_T_EQ()).  The system_include and after_include chains are never
73    referred to again after this function; all access is through the
74    bracket_include path.
75
76    For the future: Check if the directory is empty (but
77    how?) and possibly preload the include hash. */
78
79 void
80 merge_include_chains (opts)
81      struct cpp_options *opts;
82 {
83   struct file_name_list *prev, *cur, *other;
84   struct file_name_list *quote, *brack, *systm, *after;
85   struct file_name_list *qtail, *btail, *stail, *atail;
86
87   qtail = opts->pending->quote_tail;
88   btail = opts->pending->brack_tail;
89   stail = opts->pending->systm_tail;
90   atail = opts->pending->after_tail;
91
92   quote = opts->pending->quote_head;
93   brack = opts->pending->brack_head;
94   systm = opts->pending->systm_head;
95   after = opts->pending->after_head;
96
97   /* Paste together bracket, system, and after include chains. */
98   if (stail)
99     stail->next = after;
100   else
101     systm = after;
102   if (btail)
103     btail->next = systm;
104   else
105     brack = systm;
106
107   /* This is a bit tricky.
108      First we drop dupes from the quote-include list.
109      Then we drop dupes from the bracket-include list.
110      Finally, if qtail and brack are the same directory,
111      we cut out qtail.
112
113      We can't just merge the lists and then uniquify them because
114      then we may lose directories from the <> search path that should
115      be there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however
116      safe to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written
117      -Ibar -I- -Ifoo -Iquux.
118
119      Note that this algorithm is quadratic in the number of -I switches,
120      which is acceptable since there aren't usually that many of them.  */
121
122   for (cur = quote, prev = NULL; cur; cur = cur->next)
123     {
124       for (other = quote; other != cur; other = other->next)
125         if (INO_T_EQ (cur->ino, other->ino)
126             && cur->dev == other->dev)
127           {
128             if (opts->verbose)
129               cpp_notice ("ignoring duplicate directory `%s'\n", cur->name);
130
131             prev->next = cur->next;
132             free (cur->name);
133             free (cur);
134             cur = prev;
135             break;
136           }
137       prev = cur;
138     }
139   qtail = prev;
140
141   for (cur = brack; cur; cur = cur->next)
142     {
143       for (other = brack; other != cur; other = other->next)
144         if (INO_T_EQ (cur->ino, other->ino)
145             && cur->dev == other->dev)
146           {
147             if (opts->verbose)
148               cpp_notice ("ignoring duplicate directory `%s'\n", cur->name);
149
150             prev->next = cur->next;
151             free (cur->name);
152             free (cur);
153             cur = prev;
154             break;
155           }
156       prev = cur;
157     }
158
159   if (quote)
160     {
161       if (INO_T_EQ (qtail->ino, brack->ino) && qtail->dev == brack->dev)
162         {
163           if (quote == qtail)
164             {
165               if (opts->verbose)
166                 cpp_notice ("ignoring duplicate directory `%s'\n",
167                             quote->name);
168
169               free (quote->name);
170               free (quote);
171               quote = brack;
172             }
173           else
174             {
175               cur = quote;
176               while (cur->next != qtail)
177                   cur = cur->next;
178               cur->next = brack;
179               if (opts->verbose)
180                 cpp_notice ("ignoring duplicate directory `%s'\n",
181                             qtail->name);
182
183               free (qtail->name);
184               free (qtail);
185             }
186         }
187       else
188           qtail->next = brack;
189     }
190   else
191       quote = brack;
192
193   opts->quote_include = quote;
194   opts->bracket_include = brack;
195 }
196
197 /* Look up or add an entry to the table of all includes.  This table
198  is indexed by the name as it appears in the #include line.  The
199  ->next_this_file chain stores all different files with the same
200  #include name (there are at least three ways this can happen).  The
201  hash function could probably be improved a bit. */
202
203 struct include_hash *
204 include_hash (pfile, fname, add)
205      cpp_reader *pfile;
206      const char *fname;
207      int add;
208 {
209   unsigned int hash = 0;
210   struct include_hash *l, *m;
211   const char *f = fname;
212
213   while (*f)
214     hash += *f++;
215
216   l = pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE];
217   m = 0;
218   for (; l; m = l, l = l->next)
219     if (!strcmp (l->nshort, fname))
220       return l;
221
222   if (!add)
223     return 0;
224   
225   l = (struct include_hash *) xmalloc (sizeof (struct include_hash));
226   l->next = NULL;
227   l->next_this_file = NULL;
228   l->foundhere = NULL;
229   l->buf = NULL;
230   l->limit = NULL;
231   if (m)
232     m->next = l;
233   else
234     pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE] = l;
235   
236   return l;
237 }
238
239 /* Return 0 if the file pointed to by IHASH has never been included before,
240          -1 if it has been included before and need not be again,
241          or a pointer to an IHASH entry which is the file to be reread.
242    "Never before" is with respect to the position in ILIST.
243
244    This will not detect redundancies involving odd uses of the
245    `current directory' rule for "" includes.  They aren't quite
246    pathological, but I think they are rare enough not to worry about.
247    The simplest example is:
248
249    top.c:
250    #include "a/a.h"
251    #include "b/b.h"
252
253    a/a.h:
254    #include "../b/b.h"
255
256    and the problem is that for `current directory' includes,
257    ihash->foundhere is not on any of the global include chains,
258    so the test below (i->foundhere == l) may be false even when
259    the directories are in fact the same.  */
260
261 static struct include_hash *
262 redundant_include_p (pfile, ihash, ilist)
263      cpp_reader *pfile;
264      struct include_hash *ihash;
265      struct file_name_list *ilist;
266 {
267   struct file_name_list *l;
268   struct include_hash *i;
269
270   if (! ihash->foundhere)
271     return 0;
272
273   for (i = ihash; i; i = i->next_this_file)
274     for (l = ilist; l; l = l->next)
275        if (i->foundhere == l)
276          /* The control_macro works like this: If it's NULL, the file
277             is to be included again.  If it's "", the file is never to
278             be included again.  If it's a string, the file is not to be
279             included again if the string is the name of a defined macro. */
280          return (i->control_macro
281                  && (i->control_macro[0] == '\0'
282                      || cpp_lookup (pfile, i->control_macro, -1, -1)))
283              ? (struct include_hash *)-1 : i;
284
285   return 0;
286 }
287
288 static int
289 file_cleanup (pbuf, pfile)
290      cpp_buffer *pbuf;
291      cpp_reader *pfile;
292 {
293   if (pbuf->buf)
294     {
295       free (pbuf->buf);
296       pbuf->buf = 0;
297     }
298   if (pfile->system_include_depth)
299     pfile->system_include_depth--;
300   return 0;
301 }
302
303 /* Search for include file FNAME in the include chain starting at
304    SEARCH_START.  Return -2 if this file doesn't need to be included
305    (because it was included already and it's marked idempotent),
306    -1 if an error occurred, or a file descriptor open on the file.
307    *IHASH is set to point to the include hash entry for this file, and
308    *BEFORE is 1 if the file was included before (but needs to be read
309    again). */
310 int
311 find_include_file (pfile, fname, search_start, ihash, before)
312      cpp_reader *pfile;
313      const char *fname;
314      struct file_name_list *search_start;
315      struct include_hash **ihash;
316      int *before;
317 {
318   struct file_name_list *l;
319   struct include_hash *ih, *jh;
320   int f, len;
321   char *name;
322   
323   ih = include_hash (pfile, fname, 1);
324   jh = redundant_include_p (pfile, ih,
325                             fname[0] == '/' ? ABSOLUTE_PATH : search_start);
326
327   if (jh != 0)
328     {
329       *before = 1;
330       *ihash = jh;
331
332       if (jh == (struct include_hash *)-1)
333         return -2;
334       else
335         return open (jh->name, O_RDONLY, 0666);
336     }
337
338   if (ih->foundhere)
339     /* A file is already known by this name, but it's not the same file.
340        Allocate another include_hash block and add it to the next_this_file
341        chain. */
342     {
343       jh = (struct include_hash *)xmalloc (sizeof (struct include_hash));
344       while (ih->next_this_file) ih = ih->next_this_file;
345
346       ih->next_this_file = jh;
347       jh = ih;
348       ih = ih->next_this_file;
349
350       ih->next = NULL;
351       ih->next_this_file = NULL;
352       ih->buf = NULL;
353       ih->limit = NULL;
354     }
355   *before = 0;
356   *ihash = ih;
357   ih->nshort = xstrdup (fname);
358   ih->control_macro = NULL;
359   
360   /* If the pathname is absolute, just open it. */ 
361   if (fname[0] == '/')
362     {
363       ih->foundhere = ABSOLUTE_PATH;
364       ih->name = ih->nshort;
365       return open (ih->name, O_RDONLY, 0666);
366     }
367
368   /* Search directory path, trying to open the file. */
369
370   len = strlen (fname);
371   name = xmalloc (len + pfile->max_include_len + 2 + INCLUDE_LEN_FUDGE);
372
373   for (l = search_start; l; l = l->next)
374     {
375       bcopy (l->name, name, l->nlen);
376       name[l->nlen] = '/';
377       strcpy (&name[l->nlen+1], fname);
378       simplify_pathname (name);
379       if (CPP_OPTIONS (pfile)->remap)
380         name = remap_filename (pfile, name, l);
381
382       f = open (name, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666);
383 #ifdef EACCES
384       if (f == -1 && errno == EACCES)
385         {
386           cpp_error(pfile, "included file `%s' exists but is not readable",
387                     name);
388           return -1;
389         }
390 #endif
391
392       if (f >= 0)
393         {
394           ih->foundhere = l;
395           ih->name = xrealloc (name, strlen (name)+1);
396           return f;
397         }
398     }
399   
400     if (jh)
401       {
402         jh->next_this_file = NULL;
403         free (ih);
404       }
405     free (name);
406     *ihash = (struct include_hash *)-1;
407     return -1;
408 }
409
410 /* The file_name_map structure holds a mapping of file names for a
411    particular directory.  This mapping is read from the file named
412    FILE_NAME_MAP_FILE in that directory.  Such a file can be used to
413    map filenames on a file system with severe filename restrictions,
414    such as DOS.  The format of the file name map file is just a series
415    of lines with two tokens on each line.  The first token is the name
416    to map, and the second token is the actual name to use.  */
417
418 struct file_name_map
419 {
420   struct file_name_map *map_next;
421   char *map_from;
422   char *map_to;
423 };
424
425 #define FILE_NAME_MAP_FILE "header.gcc"
426
427 /* Read a space delimited string of unlimited length from a stdio
428    file.  */
429
430 static char *
431 read_filename_string (ch, f)
432      int ch;
433      FILE *f;
434 {
435   char *alloc, *set;
436   int len;
437
438   len = 20;
439   set = alloc = xmalloc (len + 1);
440   if (! is_space(ch))
441     {
442       *set++ = ch;
443       while ((ch = getc (f)) != EOF && ! is_space(ch))
444         {
445           if (set - alloc == len)
446             {
447               len *= 2;
448               alloc = xrealloc (alloc, len + 1);
449               set = alloc + len / 2;
450             }
451           *set++ = ch;
452         }
453     }
454   *set = '\0';
455   ungetc (ch, f);
456   return alloc;
457 }
458
459 /* This structure holds a linked list of file name maps, one per directory.  */
460
461 struct file_name_map_list
462 {
463   struct file_name_map_list *map_list_next;
464   char *map_list_name;
465   struct file_name_map *map_list_map;
466 };
467
468 /* Read the file name map file for DIRNAME.  */
469
470 static struct file_name_map *
471 read_name_map (pfile, dirname)
472      cpp_reader *pfile;
473      const char *dirname;
474 {
475   register struct file_name_map_list *map_list_ptr;
476   char *name;
477   FILE *f;
478
479   for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
480        map_list_ptr = map_list_ptr->map_list_next)
481     if (! strcmp (map_list_ptr->map_list_name, dirname))
482       return map_list_ptr->map_list_map;
483
484   map_list_ptr = ((struct file_name_map_list *)
485                   xmalloc (sizeof (struct file_name_map_list)));
486   map_list_ptr->map_list_name = xstrdup (dirname);
487
488   name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
489   strcpy (name, dirname);
490   if (*dirname)
491     strcat (name, "/");
492   strcat (name, FILE_NAME_MAP_FILE);
493   f = fopen (name, "r");
494   if (!f)
495     map_list_ptr->map_list_map = (struct file_name_map *)-1;
496   else
497     {
498       int ch;
499       int dirlen = strlen (dirname);
500
501       while ((ch = getc (f)) != EOF)
502         {
503           char *from, *to;
504           struct file_name_map *ptr;
505
506           if (is_space(ch))
507             continue;
508           from = read_filename_string (ch, f);
509           while ((ch = getc (f)) != EOF && is_hspace(ch))
510             ;
511           to = read_filename_string (ch, f);
512
513           ptr = ((struct file_name_map *)
514                  xmalloc (sizeof (struct file_name_map)));
515           ptr->map_from = from;
516
517           /* Make the real filename absolute.  */
518           if (*to == '/')
519             ptr->map_to = to;
520           else
521             {
522               ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
523               strcpy (ptr->map_to, dirname);
524               ptr->map_to[dirlen] = '/';
525               strcpy (ptr->map_to + dirlen + 1, to);
526               free (to);
527             }         
528
529           ptr->map_next = map_list_ptr->map_list_map;
530           map_list_ptr->map_list_map = ptr;
531
532           while ((ch = getc (f)) != '\n')
533             if (ch == EOF)
534               break;
535         }
536       fclose (f);
537     }
538   
539   map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
540   CPP_OPTIONS (pfile)->map_list = map_list_ptr;
541
542   return map_list_ptr->map_list_map;
543 }  
544
545 /* Remap NAME based on the file_name_map (if any) for LOC. */
546
547 static char *
548 remap_filename (pfile, name, loc)
549      cpp_reader *pfile;
550      char *name;
551      struct file_name_list *loc;
552 {
553   struct file_name_map *map;
554   const char *from, *p, *dir;
555
556   if (! loc->name_map)
557     loc->name_map = read_name_map (pfile,
558                                    loc->name
559                                    ? loc->name : ".");
560
561   if (loc->name_map == (struct file_name_map *)-1)
562     return name;
563   
564   from = name + strlen (loc->name) + 1;
565   
566   for (map = loc->name_map; map; map = map->map_next)
567     if (!strcmp (map->map_from, from))
568       return map->map_to;
569
570   /* Try to find a mapping file for the particular directory we are
571      looking in.  Thus #include <sys/types.h> will look up sys/types.h
572      in /usr/include/header.gcc and look up types.h in
573      /usr/include/sys/header.gcc.  */
574   p = rindex (name, '/');
575   if (!p)
576     p = name;
577   if (loc && loc->name
578       && strlen (loc->name) == (size_t) (p - name)
579       && !strncmp (loc->name, name, p - name))
580     /* FILENAME is in SEARCHPTR, which we've already checked.  */
581     return name;
582
583   if (p == name)
584     {
585       dir = ".";
586       from = name;
587     }
588   else
589     {
590       char * newdir = (char *) alloca (p - name + 1);
591       bcopy (name, newdir, p - name);
592       newdir[p - name] = '\0';
593       dir = newdir;
594       from = p + 1;
595     }
596   
597   for (map = read_name_map (pfile, dir); map; map = map->map_next)
598     if (! strcmp (map->map_from, name))
599       return map->map_to;
600
601   return name;
602 }
603
604 /* Read the contents of FD into the buffer on the top of PFILE's stack.
605    IHASH points to the include hash entry for the file associated with
606    FD.
607
608    The caller is responsible for the cpp_push_buffer.  */
609
610 int
611 finclude (pfile, fd, ihash)
612      cpp_reader *pfile;
613      int fd;
614      struct include_hash *ihash;
615 {
616   struct stat st;
617   size_t st_size;
618   long length;
619   cpp_buffer *fp;
620
621   if (fstat (fd, &st) < 0)
622     goto perror_fail;
623   if (fcntl (fd, F_SETFL, 0) == -1)  /* turn off nonblocking mode */
624     goto perror_fail;
625
626   fp = CPP_BUFFER (pfile);
627
628   /* If fd points to a plain file, we know how big it is, so we can
629      allocate the buffer all at once.  If fd is a pipe or terminal, we
630      can't.  Most C source files are 4k or less, so we guess that.  If
631      fd is something weird, like a block device or a directory, we
632      don't want to read it at all.
633
634      Unfortunately, different systems use different st.st_mode values
635      for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and
636      zero the entire struct stat except a couple fields.  Hence the
637      mess below.
638
639      In all cases, read_and_prescan will resize the buffer if it
640      turns out there's more data than we thought.  */
641
642   if (S_ISREG (st.st_mode))
643     {
644       /* off_t might have a wider range than size_t - in other words,
645          the max size of a file might be bigger than the address
646          space.  We can't handle a file that large.  (Anyone with
647          a single source file bigger than 4GB needs to rethink
648          their coding style.)  */
649       st_size = (size_t) st.st_size;
650       if ((unsigned HOST_WIDEST_INT) st_size
651           != (unsigned HOST_WIDEST_INT) st.st_size)
652         {
653           cpp_error (pfile, "file `%s' is too large", ihash->name);
654           goto fail;
655         }
656     }
657   else if (S_ISFIFO (st.st_mode) || S_ISSOCK (st.st_mode)
658            /* Permit any kind of character device: the sensible ones are
659               ttys and /dev/null, but weeding out the others is too hard.  */
660            || S_ISCHR (st.st_mode)
661            /* Some 4.x (x<4) derivatives have a bug that makes fstat() of a
662               socket or pipe return a stat struct with most fields zeroed.  */
663            || (st.st_mode == 0 && st.st_nlink == 0 && st.st_size == 0))
664     {
665       /* Cannot get its file size before reading.  4k is a decent
666          first guess. */
667       st_size = 4096;
668     }
669   else
670     {
671       cpp_error (pfile, "`%s' is not a file, pipe, or tty", ihash->name);
672       goto fail;
673     }
674
675   if (pfile->input_buffer == NULL)
676     initialize_input_buffer (pfile, fd, &st);
677
678   /* Read the file, converting end-of-line characters and trigraphs
679      (if enabled). */
680   fp->ihash = ihash;
681   fp->nominal_fname = fp->fname = ihash->name;
682   length = read_and_prescan (pfile, fp, fd, st_size);
683   if (length < 0)
684     goto fail;
685   if (length == 0)
686     ihash->control_macro = "";  /* never re-include */
687
688   close (fd);
689   fp->rlimit = fp->alimit = fp->buf + length;
690   fp->cur = fp->buf;
691   if (ihash->foundhere != ABSOLUTE_PATH)
692       fp->system_header_p = ihash->foundhere->sysp;
693   fp->lineno = 1;
694   fp->colno = 1;
695   fp->line_base = fp->buf;
696   fp->cleanup = file_cleanup;
697
698   /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
699      see do_include */
700   if (!CPP_OPTIONS (pfile)->ignore_srcdir)
701     fp->actual_dir = actual_directory (pfile, fp->fname);
702
703   pfile->input_stack_listing_current = 0;
704   return 1;
705
706  perror_fail:
707   cpp_error_from_errno (pfile, ihash->name);
708  fail:
709   cpp_pop_buffer (pfile);
710   close (fd);
711   return 0;
712 }
713
714 /* Given a path FNAME, extract the directory component and place it
715    onto the actual_dirs list.  Return a pointer to the allocated
716    file_name_list structure.  These structures are used to implement
717    current-directory "" include searching. */
718
719 static struct file_name_list *
720 actual_directory (pfile, fname)
721      cpp_reader *pfile;
722      const char *fname;
723 {
724   char *last_slash, *dir;
725   size_t dlen;
726   struct file_name_list *x;
727   
728   dir = xstrdup (fname);
729   last_slash = rindex (dir, '/');
730   if (last_slash)
731     {
732       if (last_slash == dir)
733         {
734           dlen = 1;
735           last_slash[1] = '\0';
736         }
737       else
738         {
739           dlen = last_slash - dir;
740           *last_slash = '\0';
741         }
742     }
743   else
744     {
745       dir[0] = '.';
746       dir[1] = '\0';
747       dlen = 1;
748     }
749
750   if (dlen > pfile->max_include_len)
751     pfile->max_include_len = dlen;
752
753   for (x = pfile->actual_dirs; x; x = x->alloc)
754     if (!strcmp (x->name, dir))
755       {
756         free (dir);
757         return x;
758       }
759
760   /* Not found, make a new one. */
761   x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
762   x->name = dir;
763   x->nlen = dlen;
764   x->next = CPP_OPTIONS (pfile)->quote_include;
765   x->alloc = pfile->actual_dirs;
766   x->sysp = CPP_BUFFER (pfile)->system_header_p;
767   x->name_map = NULL;
768
769   pfile->actual_dirs = x;
770   return x;
771 }
772
773 /* Determine the current line and column.  Used only by read_and_prescan. */
774 static void
775 find_position (start, limit, linep, colp)
776      U_CHAR *start;
777      U_CHAR *limit;
778      unsigned long *linep;
779      unsigned long *colp;
780 {
781   unsigned long line = *linep, col = 0;
782   while (start < limit)
783     {
784       U_CHAR ch = *start++;
785       if (ch == '\n' || ch == '\r')
786         line++, col = 1;
787       else
788         col++;
789     }
790   *linep = line, *colp = col;
791 }
792
793 /* Read the entire contents of file DESC into buffer BUF.  LEN is how
794    much memory to allocate initially; more will be allocated if
795    necessary.  Convert end-of-line markers (\n, \r, \r\n, \n\r) to
796    canonical form (\n).  If enabled, convert and/or warn about
797    trigraphs.  Convert backslash-newline to a one-character escape
798    (\r) and remove it from "embarrassing" places (i.e. the middle of a
799    token).  If there is no newline at the end of the file, add one and
800    warn.  Returns -1 on failure, or the actual length of the data to
801    be scanned.
802
803    This function does a lot of work, and can be a serious performance
804    bottleneck.  It has been tuned heavily; make sure you understand it
805    before hacking.  The common case - no trigraphs, Unix style line
806    breaks, backslash-newline set off by whitespace, newline at EOF -
807    has been optimized at the expense of the others.  The performance
808    penalty for DOS style line breaks (\r\n) is about 15%.
809    
810    Warnings lose particularly heavily since we have to determine the
811    line number, which involves scanning from the beginning of the file
812    or from the last warning.  The penalty for the absence of a newline
813    at the end of reload1.c is about 60%.  (reload1.c is 329k.)
814
815    If your file has more than one kind of end-of-line marker, you
816    will get messed-up line numbering.  */
817
818 /* Table of characters that can't be handled in the inner loop.
819    Keep these contiguous to optimize the performance of the code generated
820    for the switch that uses them.  */
821 #define SPECCASE_EMPTY     0
822 #define SPECCASE_NUL       1
823 #define SPECCASE_CR        2
824 #define SPECCASE_BACKSLASH 3
825 #define SPECCASE_QUESTION  4
826
827 static long
828 read_and_prescan (pfile, fp, desc, len)
829      cpp_reader *pfile;
830      cpp_buffer *fp;
831      int desc;
832      size_t len;
833 {
834   U_CHAR *buf = (U_CHAR *) xmalloc (len);
835   U_CHAR *ip, *op, *line_base;
836   U_CHAR *ibase;
837   U_CHAR *speccase = pfile->input_speccase;
838   unsigned long line;
839   unsigned int deferred_newlines;
840   int count;
841   size_t offset;
842
843   offset = 0;
844   op = buf;
845   line_base = buf;
846   line = 1;
847   ibase = pfile->input_buffer + 2;
848   deferred_newlines = 0;
849
850   for (;;)
851     {
852     read_next:
853
854       count = read (desc, pfile->input_buffer + 2, pfile->input_buffer_len);
855       if (count < 0)
856         goto error;
857       else if (count == 0)
858         break;
859
860       offset += count;
861       ip = ibase;
862       ibase = pfile->input_buffer + 2;
863       ibase[count] = ibase[count+1] = '\0';
864
865       if (offset > len)
866         {
867           size_t delta_op;
868           size_t delta_line_base;
869           len *= 2;
870           if (offset > len)
871             /* len overflowed.
872                This could happen if the file is larger than half the
873                maximum address space of the machine. */
874             goto too_big;
875
876           delta_op = op - buf;
877           delta_line_base = line_base - buf;
878           buf = (U_CHAR *) xrealloc (buf, len);
879           op = buf + delta_op;
880           line_base = buf + delta_line_base;
881         }
882
883       for (;;)
884         {
885           unsigned int span = 0;
886
887           /* Deal with \-newline in the middle of a token. */
888           if (deferred_newlines)
889             {
890               while (speccase[ip[span]] == SPECCASE_EMPTY
891                      && ip[span] != '\n'
892                      && ip[span] != '\t'
893                      && ip[span] != ' ')
894                 span++;
895               memcpy (op, ip, span);
896               op += span;
897               ip += span;
898               if (*ip == '\n' || *ip == '\t'
899                   || *ip == ' ' || *ip == ' ')
900                 while (deferred_newlines)
901                   deferred_newlines--, *op++ = '\r';
902               span = 0;
903             }
904
905           /* Copy as much as we can without special treatment. */
906           while (speccase[ip[span]] == SPECCASE_EMPTY) span++;
907           memcpy (op, ip, span);
908           op += span;
909           ip += span;
910
911           switch (speccase[*ip++])
912             {
913             case SPECCASE_NUL:  /* \0 */
914               ibase[-1] = op[-1];
915               goto read_next;
916
917             case SPECCASE_CR:  /* \r */
918               if (*ip == '\n')
919                 ip++;
920               else if (*ip == '\0')
921                 {
922                   *--ibase = '\r';
923                   goto read_next;
924                 }
925               else if (ip[-2] == '\n')
926                 continue;
927               *op++ = '\n';
928               break;
929
930             case SPECCASE_BACKSLASH:  /* \ */
931             backslash:
932             {
933               /* If we're at the end of the intermediate buffer,
934                  we have to shift the backslash down to the start
935                  and come back next pass. */
936               if (*ip == '\0')
937                 {
938                   *--ibase = '\\';
939                   goto read_next;
940                 }
941               else if (*ip == '\n')
942                 {
943                   ip++;
944                   if (*ip == '\r') ip++;
945                   if (*ip == '\n' || *ip == '\t' || *ip == ' ')
946                     *op++ = '\r';
947                   else if (op[-1] == '\t' || op[-1] == ' '
948                            || op[-1] == '\r' || op[-1] == '\n')
949                     *op++ = '\r';
950                   else
951                     deferred_newlines++;
952                   line++;
953                   line_base = op;
954                 }
955               else if (*ip == '\r')
956                 {
957                   ip++;
958                   if (*ip == '\n') ip++;
959                   else if (*ip == '\0')
960                     {
961                       *--ibase = '\r';
962                       *--ibase = '\\';
963                       goto read_next;
964                     }
965                   else if (*ip == '\r' || *ip == '\t' || *ip == ' ')
966                     *op++ = '\r';
967                   else
968                     deferred_newlines++;
969                   line++;
970                   line_base = op;
971                 }
972               else
973                 *op++ = '\\';
974             }
975             break;
976
977             case SPECCASE_QUESTION: /* ? */
978               {
979                 unsigned int d, t;
980                 /* If we're at the end of the intermediate buffer,
981                    we have to shift the ?'s down to the start and
982                    come back next pass. */
983                 d = ip[0];
984                 if (d == '\0')
985                   {
986                     *--ibase = '?';
987                     goto read_next;
988                   }
989                 if (d != '?')
990                   {
991                     *op++ = '?';
992                     break;
993                   }
994                 d = ip[1];
995                 if (d == '\0')
996                   {
997                     *--ibase = '?';
998                     *--ibase = '?';
999                     goto read_next;
1000                   }
1001
1002                 /* Trigraph map:
1003                  *      from    to      from    to      from    to
1004                  *      ?? =    #       ?? )    ]       ?? !    |
1005                  *      ?? (    [       ?? '    ^       ?? >    }
1006                  *      ?? /    \       ?? <    {       ?? -    ~
1007                  */
1008                 if (d == '=') t = '#';
1009                 else if (d == ')') t = ']';
1010                 else if (d == '!') t = '|';
1011                 else if (d == '(') t = '[';
1012                 else if (d == '\'') t = '^';
1013                 else if (d == '>') t = '}';
1014                 else if (d == '/') t = '\\';
1015                 else if (d == '<') t = '{';
1016                 else if (d == '-') t = '~';
1017                 else
1018                   {
1019                     *op++ = '?';
1020                     break;
1021                   }
1022                 if (CPP_OPTIONS (pfile)->warn_trigraphs)
1023                   {
1024                     unsigned long col;
1025                     find_position (line_base, op, &line, &col);
1026                     line_base = op - col;
1027                     cpp_warning_with_line (pfile, line, col,
1028                                            "trigraph ??%c encountered", d);
1029                   }
1030                 if (CPP_OPTIONS (pfile)->trigraphs)
1031                   {
1032                     if (t == '\\')
1033                       goto backslash;
1034                     else
1035                       *op++ = t;
1036                   }
1037                 else
1038                   {
1039                     *op++ = '?';
1040                     *op++ = '?';
1041                     *op++ = d;
1042                   }
1043                 ip += 2;
1044               }
1045             }
1046         }
1047     }
1048
1049   if (offset == 0)
1050     return 0;
1051
1052   /* Deal with pushed-back chars at true EOF.
1053      This may be any of:  ?? ? \ \r \n \\r \\n.
1054      \r must become \n, \\r or \\n must become \r.
1055      We know we have space already. */
1056   if (ibase == pfile->input_buffer)
1057     {
1058       if (*ibase == '?')
1059         {
1060           *op++ = '?';
1061           *op++ = '?';
1062         }
1063       else
1064         *op++ = '\r';
1065     }
1066   else if (ibase == pfile->input_buffer + 1)
1067     {
1068       if (*ibase == '\r')
1069         *op++ = '\n';
1070       else
1071         *op++ = *ibase;
1072     }
1073
1074   if (op[-1] != '\n')
1075     {
1076       unsigned long col;
1077       find_position (line_base, op, &line, &col);
1078       cpp_warning_with_line (pfile, line, col, "no newline at end of file\n");
1079       if (offset + 1 > len)
1080         {
1081           len += 1;
1082           if (offset + 1 > len)
1083             goto too_big;
1084           buf = (U_CHAR *) xrealloc (buf, len);
1085           op = buf + offset;
1086         }
1087       *op++ = '\n';
1088     }
1089
1090   fp->buf = ((len - offset < 20) ? buf : (U_CHAR *)xrealloc (buf, op - buf));
1091   return op - buf;
1092
1093  too_big:
1094   cpp_error (pfile, "file is too large (>%lu bytes)\n", (unsigned long)offset);
1095   free (buf);
1096   return -1;
1097
1098  error:
1099   cpp_error_from_errno (pfile, fp->fname);
1100   free (buf);
1101   return -1;
1102 }
1103
1104 /* Initialize the `input_buffer' and `input_speccase' tables.
1105    These are only used by read_and_prescan, but they're large and
1106    somewhat expensive to set up, so we want them allocated once for
1107    the duration of the cpp run.  */
1108
1109 static void
1110 initialize_input_buffer (pfile, fd, st)
1111      cpp_reader *pfile;
1112      int fd;
1113      struct stat *st;
1114 {
1115   long pipe_buf;
1116   U_CHAR *tmp;
1117
1118   /* Table of characters that cannot be handled by the
1119      read_and_prescan inner loop.  The number of non-EMPTY entries
1120      should be as small as humanly possible.  */
1121
1122   tmp = (U_CHAR *) xmalloc (1 << CHAR_BIT);
1123   memset (tmp, SPECCASE_EMPTY, 1 << CHAR_BIT);
1124   tmp['\0'] = SPECCASE_NUL;
1125   tmp['\r'] = SPECCASE_CR;
1126   tmp['\\'] = SPECCASE_BACKSLASH;
1127   if (CPP_OPTIONS (pfile)->trigraphs || CPP_OPTIONS (pfile)->warn_trigraphs)
1128     tmp['?'] = SPECCASE_QUESTION;
1129
1130   pfile->input_speccase = tmp;
1131
1132   /* Determine the appropriate size for the input buffer.  Normal C
1133      source files are smaller than eight K.  If we are reading a pipe,
1134      we want to make sure the input buffer is bigger than the kernel's
1135      pipe buffer.  */
1136   pipe_buf = -1;
1137
1138   if (! S_ISREG (st->st_mode))
1139     {
1140 #ifdef _PC_PIPE_BUF
1141       pipe_buf = fpathconf (fd, _PC_PIPE_BUF);
1142 #endif
1143       if (pipe_buf == -1)
1144         {
1145 #ifdef PIPE_BUF
1146           pipe_buf = PIPE_BUF;
1147 #else
1148           pipe_buf = 8192;
1149 #endif
1150         }
1151     }
1152
1153   if (pipe_buf < 8192)
1154     pipe_buf = 8192;
1155   /* PIPE_BUF bytes of buffer proper, 2 to detect running off the end
1156      without address arithmetic all the time, and 2 for pushback in
1157      the case there's a potential trigraph or end-of-line digraph at
1158      the end of a block. */
1159
1160   tmp = (U_CHAR *) xmalloc (pipe_buf + 2 + 2);
1161   pfile->input_buffer = tmp;
1162   pfile->input_buffer_len = pipe_buf;
1163 }
1164
1165 /* Add output to `deps_buffer' for the -M switch.
1166    STRING points to the text to be output.
1167    SPACER is ':' for targets, ' ' for dependencies, zero for text
1168    to be inserted literally.  */
1169
1170 void
1171 deps_output (pfile, string, spacer)
1172      cpp_reader *pfile;
1173      const char *string;
1174      int spacer;
1175 {
1176   int size;
1177   int cr = 0;
1178
1179   if (!*string)
1180     return;
1181
1182   size = strlen (string);
1183
1184 #ifndef MAX_OUTPUT_COLUMNS
1185 #define MAX_OUTPUT_COLUMNS 72
1186 #endif
1187   if (pfile->deps_column > 0
1188       && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS)
1189     {
1190       cr = 5;
1191       pfile->deps_column = 0;
1192     }
1193
1194   if (pfile->deps_size + size + cr + 8 > pfile->deps_allocated_size)
1195     {
1196       pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2;
1197       pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer,
1198                                               pfile->deps_allocated_size);
1199     }
1200
1201   if (cr)
1202     {
1203       bcopy (" \\\n  ", &pfile->deps_buffer[pfile->deps_size], 5);
1204       pfile->deps_size += 5;
1205     }
1206   
1207   if (spacer == ' ' && pfile->deps_column > 0)
1208     pfile->deps_buffer[pfile->deps_size++] = ' ';
1209   bcopy (string, &pfile->deps_buffer[pfile->deps_size], size);
1210   pfile->deps_size += size;
1211   pfile->deps_column += size;
1212   if (spacer == ':')
1213     pfile->deps_buffer[pfile->deps_size++] = ':';
1214   pfile->deps_buffer[pfile->deps_size] = 0;
1215 }
1216
1217 /* Simplify a path name in place, deleting redundant components.  This
1218    reduces OS overhead and guarantees that equivalent paths compare
1219    the same (modulo symlinks).
1220
1221    Transforms made:
1222    foo/bar/../quux      foo/quux
1223    foo/./bar            foo/bar
1224    foo//bar             foo/bar
1225    /../quux             /quux
1226    //quux               //quux  (POSIX allows leading // as a namespace escape)
1227
1228    Guarantees no trailing slashes. All transforms reduce the length
1229    of the string.
1230  */
1231 void
1232 simplify_pathname (path)
1233     char *path;
1234 {
1235     char *from, *to;
1236     char *base;
1237     int absolute = 0;
1238
1239 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
1240     /* Convert all backslashes to slashes. */
1241     for (from = path; *from; from++)
1242         if (*from == '\\') *from = '/';
1243     
1244     /* Skip over leading drive letter if present. */
1245     if (ISALPHA (path[0]) && path[1] == ':')
1246         from = to = &path[2];
1247     else
1248         from = to = path;
1249 #else
1250     from = to = path;
1251 #endif
1252     
1253     /* Remove redundant initial /s.  */
1254     if (*from == '/')
1255     {
1256         absolute = 1;
1257         to++;
1258         from++;
1259         if (*from == '/')
1260         {
1261             if (*++from == '/')
1262                 /* 3 or more initial /s are equivalent to 1 /.  */
1263                 while (*++from == '/');
1264             else
1265                 /* On some hosts // differs from /; Posix allows this.  */
1266                 to++;
1267         }
1268     }
1269     base = to;
1270     
1271     for (;;)
1272     {
1273         while (*from == '/')
1274             from++;
1275
1276         if (from[0] == '.' && from[1] == '/')
1277             from += 2;
1278         else if (from[0] == '.' && from[1] == '\0')
1279             goto done;
1280         else if (from[0] == '.' && from[1] == '.' && from[2] == '/')
1281         {
1282             if (base == to)
1283             {
1284                 if (absolute)
1285                     from += 3;
1286                 else
1287                 {
1288                     *to++ = *from++;
1289                     *to++ = *from++;
1290                     *to++ = *from++;
1291                     base = to;
1292                 }
1293             }
1294             else
1295             {
1296                 to -= 2;
1297                 while (to > base && *to != '/') to--;
1298                 if (*to == '/')
1299                     to++;
1300                 from += 3;
1301             }
1302         }
1303         else if (from[0] == '.' && from[1] == '.' && from[2] == '\0')
1304         {
1305             if (base == to)
1306             {
1307                 if (!absolute)
1308                 {
1309                     *to++ = *from++;
1310                     *to++ = *from++;
1311                 }
1312             }
1313             else
1314             {
1315                 to -= 2;
1316                 while (to > base && *to != '/') to--;
1317                 if (*to == '/')
1318                     to++;
1319             }
1320             goto done;
1321         }
1322         else
1323             /* Copy this component and trailing /, if any.  */
1324             while ((*to++ = *from++) != '/')
1325             {
1326                 if (!to[-1])
1327                 {
1328                     to--;
1329                     goto done;
1330                 }
1331             }
1332         
1333     }
1334     
1335  done:
1336     /* Trim trailing slash */
1337     if (to[0] == '/' && (!absolute || to > path+1))
1338         to--;
1339
1340     /* Change the empty string to "." so that stat() on the result
1341        will always work. */
1342     if (to == path)
1343       *to++ = '.';
1344     
1345     *to = '\0';
1346
1347     return;
1348 }
1349
1350 /* It is not clear when this should be used if at all, so I've
1351    disabled it until someone who understands VMS can look at it. */
1352 #if 0
1353
1354 /* Under VMS we need to fix up the "include" specification filename.
1355
1356    Rules for possible conversions
1357
1358         fullname                tried paths
1359
1360         name                    name
1361         ./dir/name              [.dir]name
1362         /dir/name               dir:name
1363         /name                   [000000]name, name
1364         dir/name                dir:[000000]name, dir:name, dir/name
1365         dir1/dir2/name          dir1:[dir2]name, dir1:[000000.dir2]name
1366         path:/name              path:[000000]name, path:name
1367         path:/dir/name          path:[000000.dir]name, path:[dir]name
1368         path:dir/name           path:[dir]name
1369         [path]:[dir]name        [path.dir]name
1370         path/[dir]name          [path.dir]name
1371
1372    The path:/name input is constructed when expanding <> includes. */
1373
1374
1375 static void
1376 hack_vms_include_specification (fullname)
1377      char *fullname;
1378 {
1379   register char *basename, *unixname, *local_ptr, *first_slash;
1380   int f, check_filename_before_returning, must_revert;
1381   char Local[512];
1382
1383   check_filename_before_returning = 0;
1384   must_revert = 0;
1385   /* See if we can find a 1st slash. If not, there's no path information.  */
1386   first_slash = index (fullname, '/');
1387   if (first_slash == 0)
1388     return 0;                           /* Nothing to do!!! */
1389
1390   /* construct device spec if none given.  */
1391
1392   if (index (fullname, ':') == 0)
1393     {
1394
1395       /* If fullname has a slash, take it as device spec.  */
1396
1397       if (first_slash == fullname)
1398         {
1399           first_slash = index (fullname+1, '/');        /* 2nd slash ? */
1400           if (first_slash)
1401             *first_slash = ':';                         /* make device spec  */
1402           for (basename = fullname; *basename != 0; basename++)
1403             *basename = *(basename+1);                  /* remove leading slash  */
1404         }
1405       else if ((first_slash[-1] != '.')         /* keep ':/', './' */
1406             && (first_slash[-1] != ':')
1407             && (first_slash[-1] != ']'))        /* or a vms path  */
1408         {
1409           *first_slash = ':';
1410         }
1411       else if ((first_slash[1] == '[')          /* skip './' in './[dir'  */
1412             && (first_slash[-1] == '.'))
1413         fullname += 2;
1414     }
1415
1416   /* Get part after first ':' (basename[-1] == ':')
1417      or last '/' (basename[-1] == '/').  */
1418
1419   basename = base_name (fullname);
1420
1421   local_ptr = Local;                    /* initialize */
1422
1423   /* We are trying to do a number of things here.  First of all, we are
1424      trying to hammer the filenames into a standard format, such that later
1425      processing can handle them.
1426      
1427      If the file name contains something like [dir.], then it recognizes this
1428      as a root, and strips the ".]".  Later processing will add whatever is
1429      needed to get things working properly.
1430      
1431      If no device is specified, then the first directory name is taken to be
1432      a device name (or a rooted logical).  */
1433
1434   /* Point to the UNIX filename part (which needs to be fixed!)
1435      but skip vms path information.
1436      [basename != fullname since first_slash != 0].  */
1437
1438   if ((basename[-1] == ':')             /* vms path spec.  */
1439       || (basename[-1] == ']')
1440       || (basename[-1] == '>'))
1441     unixname = basename;
1442   else
1443     unixname = fullname;
1444
1445   if (*unixname == '/')
1446     unixname++;
1447
1448   /* If the directory spec is not rooted, we can just copy
1449      the UNIX filename part and we are done.  */
1450
1451   if (((basename - fullname) > 1)
1452      && (  (basename[-1] == ']')
1453         || (basename[-1] == '>')))
1454     {
1455       if (basename[-2] != '.')
1456         {
1457
1458         /* The VMS part ends in a `]', and the preceding character is not a `.'.
1459            -> PATH]:/name (basename = '/name', unixname = 'name')
1460            We strip the `]', and then splice the two parts of the name in the
1461            usual way.  Given the default locations for include files in cccp.c,
1462            we will only use this code if the user specifies alternate locations
1463            with the /include (-I) switch on the command line.  */
1464
1465           basename -= 1;        /* Strip "]" */
1466           unixname--;           /* backspace */
1467         }
1468       else
1469         {
1470
1471         /* The VMS part has a ".]" at the end, and this will not do.  Later
1472            processing will add a second directory spec, and this would be a syntax
1473            error.  Thus we strip the ".]", and thus merge the directory specs.
1474            We also backspace unixname, so that it points to a '/'.  This inhibits the
1475            generation of the 000000 root directory spec (which does not belong here
1476            in this case).  */
1477
1478           basename -= 2;        /* Strip ".]" */
1479           unixname--;           /* backspace */
1480         }
1481     }
1482
1483   else
1484
1485     {
1486
1487       /* We drop in here if there is no VMS style directory specification yet.
1488          If there is no device specification either, we make the first dir a
1489          device and try that.  If we do not do this, then we will be essentially
1490          searching the users default directory (as if they did a #include "asdf.h").
1491         
1492          Then all we need to do is to push a '[' into the output string. Later
1493          processing will fill this in, and close the bracket.  */
1494
1495       if ((unixname != fullname)        /* vms path spec found.  */
1496          && (basename[-1] != ':'))
1497         *local_ptr++ = ':';             /* dev not in spec.  take first dir */
1498
1499       *local_ptr++ = '[';               /* Open the directory specification */
1500     }
1501
1502     if (unixname == fullname)           /* no vms dir spec.  */
1503       {
1504         must_revert = 1;
1505         if ((first_slash != 0)          /* unix dir spec.  */
1506             && (*unixname != '/')       /* not beginning with '/'  */
1507             && (*unixname != '.'))      /* or './' or '../'  */
1508           *local_ptr++ = '.';           /* dir is local !  */
1509       }
1510
1511   /* at this point we assume that we have the device spec, and (at least
1512      the opening "[" for a directory specification.  We may have directories
1513      specified already.
1514
1515      If there are no other slashes then the filename will be
1516      in the "root" directory.  Otherwise, we need to add
1517      directory specifications.  */
1518
1519   if (index (unixname, '/') == 0)
1520     {
1521       /* if no directories specified yet and none are following.  */
1522       if (local_ptr[-1] == '[')
1523         {
1524           /* Just add "000000]" as the directory string */
1525           strcpy (local_ptr, "000000]");
1526           local_ptr += strlen (local_ptr);
1527           check_filename_before_returning = 1; /* we might need to fool with this later */
1528         }
1529     }
1530   else
1531     {
1532
1533       /* As long as there are still subdirectories to add, do them.  */
1534       while (index (unixname, '/') != 0)
1535         {
1536           /* If this token is "." we can ignore it
1537                if it's not at the beginning of a path.  */
1538           if ((unixname[0] == '.') && (unixname[1] == '/'))
1539             {
1540               /* remove it at beginning of path.  */
1541               if (  ((unixname == fullname)             /* no device spec  */
1542                     && (fullname+2 != basename))        /* starts with ./ */
1543                                                         /* or  */
1544                  || ((basename[-1] == ':')              /* device spec  */
1545                     && (unixname-1 == basename)))       /* and ./ afterwards  */
1546                 *local_ptr++ = '.';                     /* make '[.' start of path.  */
1547               unixname += 2;
1548               continue;
1549             }
1550
1551           /* Add a subdirectory spec. Do not duplicate "." */
1552           if (  local_ptr[-1] != '.'
1553              && local_ptr[-1] != '['
1554              && local_ptr[-1] != '<')
1555             *local_ptr++ = '.';
1556
1557           /* If this is ".." then the spec becomes "-" */
1558           if (  (unixname[0] == '.')
1559              && (unixname[1] == '.')
1560              && (unixname[2] == '/'))
1561             {
1562               /* Add "-" and skip the ".." */
1563               if ((local_ptr[-1] == '.')
1564                   && (local_ptr[-2] == '['))
1565                 local_ptr--;                    /* prevent [.-  */
1566               *local_ptr++ = '-';
1567               unixname += 3;
1568               continue;
1569             }
1570
1571           /* Copy the subdirectory */
1572           while (*unixname != '/')
1573             *local_ptr++= *unixname++;
1574
1575           unixname++;                   /* Skip the "/" */
1576         }
1577
1578       /* Close the directory specification */
1579       if (local_ptr[-1] == '.')         /* no trailing periods */
1580         local_ptr--;
1581
1582       if (local_ptr[-1] == '[')         /* no dir needed */
1583         local_ptr--;
1584       else
1585         *local_ptr++ = ']';
1586     }
1587
1588   /* Now add the filename.  */
1589
1590   while (*unixname)
1591     *local_ptr++ = *unixname++;
1592   *local_ptr = 0;
1593
1594   /* Now append it to the original VMS spec.  */
1595
1596   strcpy ((must_revert==1)?fullname:basename, Local);
1597
1598   /* If we put a [000000] in the filename, try to open it first. If this fails,
1599      remove the [000000], and return that name.  This provides flexibility
1600      to the user in that they can use both rooted and non-rooted logical names
1601      to point to the location of the file.  */
1602
1603   if (check_filename_before_returning)
1604     {
1605       f = open (fullname, O_RDONLY, 0666);
1606       if (f >= 0)
1607         {
1608           /* The file name is OK as it is, so return it as is.  */
1609           close (f);
1610           return 1;
1611         }
1612
1613       /* The filename did not work.  Try to remove the [000000] from the name,
1614          and return it.  */
1615
1616       basename = index (fullname, '[');
1617       local_ptr = index (fullname, ']') + 1;
1618       strcpy (basename, local_ptr);             /* this gets rid of it */
1619
1620     }
1621
1622   return 1;
1623 }
1624 #endif  /* VMS */