]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cppfiles.c
Daily bump.
[thirdparty/gcc.git] / gcc / cppfiles.c
CommitLineData
add7091b 1/* Part of CPP library. (include file handling)
5e7b4e25
JL
2 Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998,
3 1999, 2000 Free Software Foundation, Inc.
add7091b
ZW
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
8
9This program is free software; you can redistribute it and/or modify it
10under the terms of the GNU General Public License as published by the
11Free Software Foundation; either version 2, or (at your option) any
12later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
e38992e8 21Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
add7091b
ZW
22
23#include "config.h"
24#include "system.h"
add7091b 25#include "cpplib.h"
88ae23e7 26#include "cpphash.h"
c1212d2f 27#include "intl.h"
168d3732 28#include "mkdeps.h"
c31a6508 29#include "splay-tree.h"
add7091b 30
f8f769ea
ZW
31#ifdef HAVE_MMAP_FILE
32# include <sys/mman.h>
33# ifndef MMAP_THRESHOLD
34# define MMAP_THRESHOLD 3 /* Minimum page count to mmap the file. */
35# endif
36
37#else /* No MMAP_FILE */
38# undef MMAP_THRESHOLD
39# define MMAP_THRESHOLD 0
40#endif
41
d7a2e0f7
ZW
42#ifndef O_BINARY
43# define O_BINARY 0
44#endif
45
a58d32c2
ZW
46#ifndef INCLUDE_LEN_FUDGE
47# define INCLUDE_LEN_FUDGE 0
48#endif
49
50/* If errno is inspected immediately after a system call fails, it will be
51 nonzero, and no error number will ever be zero. */
52#ifndef ENOENT
53# define ENOENT 0
54#endif
55#ifndef ENOTDIR
56# define ENOTDIR 0
57#endif
58#ifndef ENOMEM
59# define ENOMEM 0
60#endif
61
f9a0e96c
ZW
62/* Suppress warning about function macros used w/o arguments in traditional
63 C. It is unlikely that glibc's strcmp macro helps this file at all. */
64#undef strcmp
65
a73ac7a5 66static struct file_name_map *read_name_map
38b24ee2
ZW
67 PARAMS ((cpp_reader *, const char *));
68static char *read_filename_string PARAMS ((int, FILE *));
69static char *remap_filename PARAMS ((cpp_reader *, char *,
70 struct file_name_list *));
a73ac7a5 71static struct file_name_list *actual_directory
38b24ee2 72 PARAMS ((cpp_reader *, const char *));
c31a6508
ZW
73static struct include_file *find_include_file
74 PARAMS ((cpp_reader *, const char *,
75 struct file_name_list *));
2047e26f 76static struct include_file *open_file PARAMS ((cpp_reader *, const char *));
c31a6508 77static int read_include_file PARAMS ((cpp_reader *, struct include_file *));
a58d32c2
ZW
78static int stack_include_file PARAMS ((cpp_reader *, struct include_file *));
79static void purge_cache PARAMS ((struct include_file *));
c31a6508 80static void destroy_include_file_node PARAMS ((splay_tree_value));
c71f835b 81static int report_missing_guard PARAMS ((splay_tree_node, void *));
c31a6508 82
0b3d776a 83#if 0
f84c2018 84static void hack_vms_include_specification PARAMS ((char *));
0b3d776a 85#endif
add7091b 86
c31a6508
ZW
87/* We use a splay tree to store information about all the include
88 files seen in this compilation. The key of each tree node is the
89 physical path to the file. The value is 0 if the file does not
90 exist, or a struct include_file pointer. */
add7091b 91
c31a6508
ZW
92static void
93destroy_include_file_node (v)
94 splay_tree_value v;
d35364d1 95{
c31a6508
ZW
96 struct include_file *f = (struct include_file *)v;
97 if (f)
98 {
a58d32c2 99 purge_cache (f);
2047e26f 100 free (f); /* The tree is registered with free to free f->name. */
c31a6508 101 }
d35364d1 102}
add7091b 103
d35364d1 104void
c71f835b 105_cpp_init_includes (pfile)
d35364d1
ZW
106 cpp_reader *pfile;
107{
108 pfile->all_include_files
c31a6508
ZW
109 = splay_tree_new ((splay_tree_compare_fn) strcmp,
110 (splay_tree_delete_key_fn) free,
111 destroy_include_file_node);
0b3d776a 112}
add7091b 113
c71f835b
ZW
114void
115_cpp_cleanup_includes (pfile)
116 cpp_reader *pfile;
117{
118 splay_tree_delete (pfile->all_include_files);
119}
120
a58d32c2 121/* Given a file name, look it up in the cache; if there is no entry,
2047e26f
NB
122 create one with a non-NULL value (regardless of success in opening
123 the file). If the file doesn't exist or is inaccessible, this
124 entry is flagged so we don't attempt to open it again in the
125 future. If the file isn't open, open it.
126
127 Returns an include_file structure with an open file descriptor on
128 success, or NULL on failure. */
add7091b 129
c31a6508 130static struct include_file *
2047e26f 131open_file (pfile, filename)
c31a6508
ZW
132 cpp_reader *pfile;
133 const char *filename;
2047e26f 134{
c31a6508 135 splay_tree_node nd;
2047e26f 136 struct include_file *file;
add7091b 137
a58d32c2 138 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) filename);
add7091b 139
c31a6508 140 if (nd)
2047e26f
NB
141 {
142 file = (struct include_file *) nd->value;
143
144 /* Don't retry opening if we failed previously. */
145 if (file->fd == -2)
146 return 0;
147
148 /* -1 indicates a file we've opened previously, and since closed. */
149 if (file->fd != -1)
150 return file;
151 }
152 else
153 {
154 file = xcnew (struct include_file);
155 file->name = xstrdup (filename);
156 splay_tree_insert (pfile->all_include_files,
157 (splay_tree_key) file->name,
158 (splay_tree_value) file);
159 }
add7091b 160
c31a6508
ZW
161 /* We used to open files in nonblocking mode, but that caused more
162 problems than it solved. Do take care not to acquire a
163 controlling terminal by mistake (this can't happen on sane
164 systems, but paranoia is a virtue).
add7091b 165
c31a6508
ZW
166 Use the three-argument form of open even though we aren't
167 specifying O_CREAT, to defend against broken system headers.
add7091b 168
c31a6508
ZW
169 O_BINARY tells some runtime libraries (notably DJGPP) not to do
170 newline translation; we can handle DOS line breaks just fine
171 ourselves.
b0699dad 172
c31a6508 173 Special case: the empty string is translated to stdin. */
d4506961 174
c31a6508 175 if (filename[0] == '\0')
2047e26f 176 file->fd = 0;
f2d5f0cc 177 else
2047e26f 178 file->fd = open (filename, O_RDONLY | O_NOCTTY | O_BINARY, 0666);
a58d32c2 179
2047e26f
NB
180 if (file->fd != -1 && fstat (file->fd, &file->st) == 0)
181 {
182 /* Mark a regular, zero-length file never-reread now. */
183 if (S_ISREG (file->st.st_mode) && file->st.st_size == 0)
184 file->cmacro = NEVER_REREAD;
a58d32c2 185
2047e26f
NB
186 return file;
187 }
a58d32c2
ZW
188
189 /* Don't issue an error message if the file doesn't exist. */
190 if (errno != ENOENT && errno != ENOTDIR)
191 cpp_error_from_errno (pfile, filename);
192
2047e26f
NB
193 /* Create a negative node for this path, and return null. */
194 file->fd = -2;
195
a58d32c2
ZW
196 return 0;
197}
198
199/* Place the file referenced by INC into a new buffer on PFILE's stack.
200 Return 1 if successful, 0 if not. */
201
202static int
203stack_include_file (pfile, inc)
204 cpp_reader *pfile;
205 struct include_file *inc;
206{
207 cpp_buffer *fp;
208
209 if (DO_NOT_REREAD (inc))
210 return 0;
211
212 if (inc->buffer == NULL)
213 if (read_include_file (pfile, inc) == 0)
214 return 0;
215
216 fp = cpp_push_buffer (pfile, NULL, 0);
217 if (fp == 0)
218 return 0;
219
220 fp->inc = inc;
221 fp->nominal_fname = inc->name;
222 fp->buf = inc->buffer;
223 fp->rlimit = fp->buf + inc->st.st_size;
224 fp->cur = fp->buf;
225 fp->lineno = 1;
226 fp->line_base = fp->buf;
227
228 /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
229 see do_include */
230 if (!CPP_OPTION (pfile, ignore_srcdir))
231 fp->actual_dir = actual_directory (pfile, inc->name);
232
233 fp->inc->refcnt++;
234 pfile->include_depth++;
235 pfile->input_stack_listing_current = 0;
236 if (pfile->cb.enter_file)
237 (*pfile->cb.enter_file) (pfile);
238 return 1;
239}
240
241/* Read the file referenced by INC into the file cache.
242
243 If fd points to a plain file, we might be able to mmap it; we can
244 definitely allocate the buffer all at once. If fd is a pipe or
245 terminal, we can't do either. If fd is something weird, like a
246 block device or a directory, we don't want to read it at all.
247
248 Unfortunately, different systems use different st.st_mode values
249 for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and
250 zero the entire struct stat except a couple fields. Hence we don't
251 even try to figure out what something is, except for plain files,
252 directories, and block devices.
253
254 FIXME: Flush file cache and try again if we run out of memory. */
255
256static int
257read_include_file (pfile, inc)
258 cpp_reader *pfile;
259 struct include_file *inc;
260{
261 ssize_t size, offset, count;
262 U_CHAR *buf;
263#if MMAP_THRESHOLD
264 static int pagesize = -1;
265#endif
266
267 if (S_ISREG (inc->st.st_mode))
f2d5f0cc 268 {
a58d32c2
ZW
269 /* off_t might have a wider range than ssize_t - in other words,
270 the max size of a file might be bigger than the address
271 space. We can't handle a file that large. (Anyone with
272 a single source file bigger than 2GB needs to rethink
273 their coding style.) Some systems (e.g. AIX 4.1) define
274 SSIZE_MAX to be much smaller than the actual range of the
275 type. Use INTTYPE_MAXIMUM unconditionally to ensure this
276 does not bite us. */
277 if (inc->st.st_size > INTTYPE_MAXIMUM (ssize_t))
f2d5f0cc 278 {
a58d32c2
ZW
279 cpp_error (pfile, "%s is too large", inc->name);
280 goto fail;
f2d5f0cc 281 }
a58d32c2
ZW
282 size = inc->st.st_size;
283
ae0f4dee 284 inc->mapped = 0;
a58d32c2
ZW
285#if MMAP_THRESHOLD
286 if (pagesize == -1)
287 pagesize = getpagesize ();
288
289 if (size / pagesize >= MMAP_THRESHOLD)
290 {
291 buf = (U_CHAR *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0);
292 if (buf == (U_CHAR *)-1)
293 goto perror_fail;
294 inc->mapped = 1;
295 }
296 else
c31a6508 297#endif
d4506961 298 {
a58d32c2
ZW
299 buf = (U_CHAR *) xmalloc (size);
300 offset = 0;
301 while (offset < size)
302 {
303 count = read (inc->fd, buf + offset, size - offset);
304 if (count < 0)
305 goto perror_fail;
306 if (count == 0)
307 {
308 cpp_warning (pfile, "%s is shorter than expected", inc->name);
309 break;
310 }
311 offset += count;
312 }
d4506961 313 }
a58d32c2
ZW
314 }
315 else if (S_ISBLK (inc->st.st_mode))
316 {
317 cpp_error (pfile, "%s is a block device", inc->name);
318 goto fail;
319 }
320 else if (S_ISDIR (inc->st.st_mode))
321 {
322 cpp_error (pfile, "%s is a directory", inc->name);
323 goto fail;
324 }
325 else
326 {
327 /* 8 kilobytes is a sensible starting size. It ought to be
328 bigger than the kernel pipe buffer, and it's definitely
329 bigger than the majority of C source files. */
330 size = 8 * 1024;
d4506961 331
a58d32c2
ZW
332 buf = (U_CHAR *) xmalloc (size);
333 offset = 0;
334 while ((count = read (inc->fd, buf + offset, size - offset)) > 0)
f2d5f0cc 335 {
a58d32c2
ZW
336 offset += count;
337 if (offset == size)
338 buf = xrealloc (buf, (size *= 2));
f2d5f0cc 339 }
a58d32c2
ZW
340 if (count < 0)
341 goto perror_fail;
342
a58d32c2
ZW
343 if (offset < size)
344 buf = xrealloc (buf, offset);
345 inc->st.st_size = offset;
f2d5f0cc 346 }
d7a2e0f7 347
a58d32c2
ZW
348 close (inc->fd);
349 inc->buffer = buf;
350 inc->fd = -1;
351 return 1;
352
353 perror_fail:
354 cpp_error_from_errno (pfile, inc->name);
355 fail:
356 /* Do not try to read this file again. */
357 close (inc->fd);
358 inc->fd = -1;
359 inc->cmacro = NEVER_REREAD;
360 return 0;
361}
362
363static void
364purge_cache (inc)
365 struct include_file *inc;
366{
367 if (inc->buffer)
c31a6508 368 {
ae0f4dee 369#if MMAP_THRESHOLD
a58d32c2 370 if (inc->mapped)
6f84c9bd 371 munmap ((PTR) inc->buffer, inc->st.st_size);
a58d32c2 372 else
ae0f4dee 373#endif
a58d32c2
ZW
374 free ((PTR) inc->buffer);
375 inc->buffer = NULL;
c31a6508 376 }
e576beb0
ZW
377}
378
c31a6508
ZW
379/* Return 1 if the file named by FNAME has been included before in
380 any context, 0 otherwise. */
381int
382cpp_included (pfile, fname)
add7091b 383 cpp_reader *pfile;
bcc5cac9 384 const char *fname;
add7091b 385{
d35364d1 386 struct file_name_list *path;
0b3d776a 387 char *name;
c31a6508 388 splay_tree_node nd;
0b3d776a 389
c31a6508 390 if (fname[0] == '/')
0b3d776a 391 {
c31a6508
ZW
392 /* Just look it up. */
393 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) fname);
394 return (nd && nd->value);
0b3d776a 395 }
c31a6508
ZW
396
397 /* Search directory path for the file. */
398 name = (char *) alloca (strlen (fname) + pfile->max_include_len
399 + 2 + INCLUDE_LEN_FUDGE);
400 for (path = CPP_OPTION (pfile, quote_include); path; path = path->next)
0b3d776a 401 {
c31a6508
ZW
402 memcpy (name, path->name, path->nlen);
403 name[path->nlen] = '/';
404 strcpy (&name[path->nlen+1], fname);
405 _cpp_simplify_pathname (name);
406 if (CPP_OPTION (pfile, remap))
407 name = remap_filename (pfile, name, path);
408
409 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name);
410 if (nd && nd->value)
411 return 1;
0b3d776a 412 }
c31a6508 413 return 0;
add7091b
ZW
414}
415
c31a6508
ZW
416/* Search for include file FNAME in the include chain starting at
417 SEARCH_START. Return 0 if there is no such file (or it's un-openable),
a58d32c2 418 otherwise an include_file structure. */
c31a6508
ZW
419
420static struct include_file *
421find_include_file (pfile, fname, search_start)
f2d5f0cc
ZW
422 cpp_reader *pfile;
423 const char *fname;
c31a6508 424 struct file_name_list *search_start;
f2d5f0cc 425{
c31a6508
ZW
426 struct file_name_list *path;
427 char *name;
428 struct include_file *file;
add7091b 429
c31a6508 430 if (fname[0] == '/')
2047e26f 431 return open_file (pfile, fname);
c31a6508
ZW
432
433 /* Search directory path for the file. */
434 name = (char *) alloca (strlen (fname) + pfile->max_include_len
435 + 2 + INCLUDE_LEN_FUDGE);
436 for (path = search_start; path; path = path->next)
add7091b 437 {
c31a6508
ZW
438 memcpy (name, path->name, path->nlen);
439 name[path->nlen] = '/';
440 strcpy (&name[path->nlen+1], fname);
441 _cpp_simplify_pathname (name);
442 if (CPP_OPTION (pfile, remap))
443 name = remap_filename (pfile, name, path);
444
2047e26f 445 file = open_file (pfile, name);
c31a6508 446 if (file)
add7091b 447 {
c31a6508
ZW
448 file->sysp = path->sysp;
449 file->foundhere = path;
450 return file;
add7091b
ZW
451 }
452 }
c31a6508 453 return 0;
add7091b
ZW
454}
455
a58d32c2
ZW
456/* #line uses this to save artificial file names. We have to stat the
457 file because an all_include_files entry is always either + or -,
458 there's no 'I don't know' value. */
c31a6508
ZW
459const char *
460_cpp_fake_include (pfile, fname)
add7091b 461 cpp_reader *pfile;
c31a6508 462 const char *fname;
add7091b 463{
c31a6508
ZW
464 splay_tree_node nd;
465 struct include_file *file;
add7091b 466 char *name;
add7091b 467
c31a6508
ZW
468 file = find_include_file (pfile, fname, CPP_OPTION (pfile, quote_include));
469 if (file)
a58d32c2
ZW
470 {
471 if (file->fd > 0)
472 {
473 close (file->fd);
474 file->fd = -1;
475 }
476 return file->name;
477 }
add7091b 478
c31a6508
ZW
479 name = xstrdup (fname);
480 _cpp_simplify_pathname (name);
add7091b 481
c31a6508
ZW
482 /* We cannot just blindly insert a node, because there's still the
483 chance that the node already exists but isn't on the search path. */
484 nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name);
485 if (nd)
add7091b 486 {
c31a6508
ZW
487 free (name);
488 return (const char *) nd->key;
add7091b 489 }
0b3d776a 490
2047e26f
NB
491 file = xcnew (struct include_file);
492 file->name = name;
493 file->fd = -2;
494 splay_tree_insert (pfile->all_include_files, (splay_tree_key) name,
495 (splay_tree_value) file);
496
497 return file->name;
add7091b
ZW
498}
499
e605b040
ZW
500/* Not everyone who wants to set system-header-ness on a buffer can
501 see the details of struct include_file. This is an exported interface
502 because fix-header needs it. */
503void
504cpp_make_system_header (pfile, pbuf, flag)
505 cpp_reader *pfile;
506 cpp_buffer *pbuf;
507 int flag;
508{
509 if (flag < 0 || flag > 2)
510 cpp_ice (pfile, "cpp_make_system_header: bad flag %d\n", flag);
511 else if (!pbuf->inc)
512 cpp_ice (pfile, "cpp_make_system_header called on non-file buffer");
513 else
514 pbuf->inc->sysp = flag;
515}
516
58fea6af
ZW
517const char *
518cpp_syshdr_flags (pfile, pbuf)
519 cpp_reader *pfile ATTRIBUTE_UNUSED;
520 cpp_buffer *pbuf;
521{
522#ifndef NO_IMPLICIT_EXTERN_C
523 if (CPP_OPTION (pfile, cplusplus) && pbuf->inc->sysp == 2)
524 return " 3 4";
525#endif
526 if (pbuf->inc->sysp)
527 return " 3";
528 return "";
529}
530
c71f835b
ZW
531/* Report on all files that might benefit from a multiple include guard.
532 Triggered by -H. */
533void
534_cpp_report_missing_guards (pfile)
535 cpp_reader *pfile;
536{
537 int banner = 0;
538 splay_tree_foreach (pfile->all_include_files, report_missing_guard,
539 (PTR) &banner);
540}
541
542static int
543report_missing_guard (n, b)
544 splay_tree_node n;
545 void *b;
546{
547 struct include_file *f = (struct include_file *) n->value;
548 int *bannerp = (int *)b;
549
550 if (f && f->cmacro == 0 && f->include_count == 1)
551 {
552 if (*bannerp == 0)
553 {
554 fputs (_("Multiple include guards may be useful for:\n"), stderr);
555 *bannerp = 1;
556 }
557 fputs (f->name, stderr);
558 putc ('\n', stderr);
559 }
560 return 0;
561}
562
c31a6508 563#define PRINT_THIS_DEP(p, b) (CPP_PRINT_DEPS(p) > (b||p->system_include_depth))
168d3732 564void
041c3194 565_cpp_execute_include (pfile, f, len, no_reinclude, search_start, angle_brackets)
168d3732 566 cpp_reader *pfile;
041c3194 567 const U_CHAR *f;
168d3732
ZW
568 unsigned int len;
569 int no_reinclude;
570 struct file_name_list *search_start;
041c3194 571 int angle_brackets;
168d3732 572{
c31a6508 573 struct include_file *inc;
041c3194 574 char *fname;
168d3732
ZW
575
576 if (!search_start)
577 {
578 if (angle_brackets)
ae79697b
ZW
579 search_start = CPP_OPTION (pfile, bracket_include);
580 else if (CPP_OPTION (pfile, ignore_srcdir))
581 search_start = CPP_OPTION (pfile, quote_include);
168d3732
ZW
582 else
583 search_start = CPP_BUFFER (pfile)->actual_dir;
584 }
585
586 if (!search_start)
587 {
f9a0e96c 588 cpp_error (pfile, "No include path in which to find %s", f);
168d3732
ZW
589 return;
590 }
591
041c3194
ZW
592 fname = alloca (len + 1);
593 memcpy (fname, f, len);
168d3732
ZW
594 fname[len] = '\0';
595
c31a6508 596 inc = find_include_file (pfile, fname, search_start);
168d3732 597
c31a6508 598 if (inc)
168d3732 599 {
c31a6508 600 /* For -M, add the file to the dependencies on its first inclusion. */
d4506961 601 if (!inc->include_count && PRINT_THIS_DEP (pfile, angle_brackets))
c31a6508 602 deps_add_dep (pfile->deps, inc->name);
d4506961 603 inc->include_count++;
c31a6508 604
c31a6508 605 /* Actually process the file. */
a58d32c2 606 if (stack_include_file (pfile, inc))
c31a6508
ZW
607 {
608 if (angle_brackets)
609 pfile->system_include_depth++;
a58d32c2
ZW
610
611 if (no_reinclude)
612 inc->cmacro = NEVER_REREAD;
613
614 /* Handle -H option. */
615 if (CPP_OPTION (pfile, print_include_names))
616 {
617 cpp_buffer *fp = CPP_BUFFER (pfile);
618 while ((fp = CPP_PREV_BUFFER (fp)) != NULL)
619 putc ('.', stderr);
620 fprintf (stderr, " %s\n", inc->name);
621 }
c31a6508 622 }
168d3732
ZW
623 return;
624 }
c31a6508
ZW
625
626 if (CPP_OPTION (pfile, print_deps_missing_files)
627 && PRINT_THIS_DEP (pfile, angle_brackets))
168d3732 628 {
c31a6508
ZW
629 if (!angle_brackets)
630 deps_add_dep (pfile->deps, fname);
631 else
632 {
633 char *p;
634 struct file_name_list *ptr;
635 /* If requested as a system header, assume it belongs in
636 the first system header directory. */
637 if (CPP_OPTION (pfile, bracket_include))
638 ptr = CPP_OPTION (pfile, bracket_include);
639 else
640 ptr = CPP_OPTION (pfile, quote_include);
168d3732 641
c31a6508
ZW
642 p = (char *) alloca (strlen (ptr->name)
643 + strlen (fname) + 2);
644 if (*ptr->name != '\0')
645 {
646 strcpy (p, ptr->name);
647 strcat (p, "/");
648 }
649 strcat (p, fname);
650 _cpp_simplify_pathname (p);
651 deps_add_dep (pfile->deps, p);
652 }
168d3732 653 }
c31a6508
ZW
654 /* If -M was specified, and this header file won't be added to
655 the dependency list, then don't count this as an error,
656 because we can still produce correct output. Otherwise, we
657 can't produce correct output, because there may be
658 dependencies we need inside the missing file, and we don't
659 know what directory this missing file exists in. */
660 else if (CPP_PRINT_DEPS (pfile)
661 && ! PRINT_THIS_DEP (pfile, angle_brackets))
662 cpp_warning (pfile, "No include path in which to find %s", fname);
663 else
664 cpp_error_from_errno (pfile, fname);
168d3732
ZW
665}
666
f3f751ad
NS
667/* Locate file F, and determine whether it is newer than PFILE. Return -1,
668 if F cannot be located or dated, 1, if it is newer and 0 if older. */
669
670int
041c3194 671_cpp_compare_file_date (pfile, f, len, angle_brackets)
f3f751ad 672 cpp_reader *pfile;
041c3194 673 const U_CHAR *f;
f3f751ad 674 unsigned int len;
041c3194 675 int angle_brackets;
f3f751ad 676{
041c3194
ZW
677 char *fname;
678 struct file_name_list *search_start;
f3f751ad 679 struct include_file *inc;
041c3194 680 struct include_file *current_include = CPP_BUFFER (pfile)->inc;
f3f751ad 681
041c3194
ZW
682 if (angle_brackets)
683 search_start = CPP_OPTION (pfile, bracket_include);
684 else if (CPP_OPTION (pfile, ignore_srcdir))
685 search_start = CPP_OPTION (pfile, quote_include);
686 else
687 search_start = CPP_BUFFER (pfile)->actual_dir;
f3f751ad 688
041c3194
ZW
689 fname = alloca (len + 1);
690 memcpy (fname, f, len);
f3f751ad 691 fname[len] = '\0';
f3f751ad
NS
692 inc = find_include_file (pfile, fname, search_start);
693
694 if (!inc)
695 return -1;
a58d32c2 696 if (inc->fd > 0)
f3f751ad 697 {
f3f751ad
NS
698 close (inc->fd);
699 inc->fd = -1;
700 }
a58d32c2
ZW
701
702 return inc->st.st_mtime > current_include->st.st_mtime;
f3f751ad
NS
703}
704
705
c45da1ca
ZW
706/* Push an input buffer and load it up with the contents of FNAME.
707 If FNAME is "" or NULL, read standard input. */
708int
709cpp_read_file (pfile, fname)
710 cpp_reader *pfile;
711 const char *fname;
712{
c31a6508 713 struct include_file *f;
c45da1ca 714
d35364d1
ZW
715 if (fname == NULL)
716 fname = "";
717
2047e26f 718 f = open_file (pfile, fname);
c45da1ca 719
041c3194
ZW
720 if (f == NULL)
721 {
722 cpp_error_from_errno (pfile, fname);
723 return 0;
724 }
725
a58d32c2 726 return stack_include_file (pfile, f);
f8f769ea
ZW
727}
728
f9a0e96c
ZW
729/* Do appropriate cleanup when a file buffer is popped off the input
730 stack. */
731void
732_cpp_pop_file_buffer (pfile, buf)
733 cpp_reader *pfile;
734 cpp_buffer *buf;
735{
736 struct include_file *inc = buf->inc;
737
738 if (pfile->system_include_depth)
739 pfile->system_include_depth--;
740 if (pfile->include_depth)
741 pfile->include_depth--;
742 if (pfile->potential_control_macro)
743 {
744 if (inc->cmacro != NEVER_REREAD)
745 inc->cmacro = pfile->potential_control_macro;
746 pfile->potential_control_macro = 0;
747 }
748 pfile->input_stack_listing_current = 0;
749
a58d32c2
ZW
750 inc->refcnt--;
751 if (inc->refcnt == 0 && DO_NOT_REREAD (inc))
752 purge_cache (inc);
f9a0e96c
ZW
753}
754
c31a6508
ZW
755/* The file_name_map structure holds a mapping of file names for a
756 particular directory. This mapping is read from the file named
757 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
758 map filenames on a file system with severe filename restrictions,
759 such as DOS. The format of the file name map file is just a series
760 of lines with two tokens on each line. The first token is the name
761 to map, and the second token is the actual name to use. */
762
763struct file_name_map
764{
765 struct file_name_map *map_next;
766 char *map_from;
767 char *map_to;
768};
769
770#define FILE_NAME_MAP_FILE "header.gcc"
771
772/* Read a space delimited string of unlimited length from a stdio
773 file. */
774
775static char *
776read_filename_string (ch, f)
777 int ch;
778 FILE *f;
779{
780 char *alloc, *set;
781 int len;
782
783 len = 20;
784 set = alloc = xmalloc (len + 1);
785 if (! is_space(ch))
786 {
787 *set++ = ch;
788 while ((ch = getc (f)) != EOF && ! is_space(ch))
789 {
790 if (set - alloc == len)
791 {
792 len *= 2;
793 alloc = xrealloc (alloc, len + 1);
794 set = alloc + len / 2;
795 }
796 *set++ = ch;
797 }
798 }
799 *set = '\0';
800 ungetc (ch, f);
801 return alloc;
802}
803
804/* This structure holds a linked list of file name maps, one per directory. */
805
806struct file_name_map_list
807{
808 struct file_name_map_list *map_list_next;
809 char *map_list_name;
810 struct file_name_map *map_list_map;
811};
812
813/* Read the file name map file for DIRNAME. */
814
815static struct file_name_map *
816read_name_map (pfile, dirname)
817 cpp_reader *pfile;
818 const char *dirname;
819{
820 register struct file_name_map_list *map_list_ptr;
821 char *name;
822 FILE *f;
823
824 for (map_list_ptr = CPP_OPTION (pfile, map_list); map_list_ptr;
825 map_list_ptr = map_list_ptr->map_list_next)
826 if (! strcmp (map_list_ptr->map_list_name, dirname))
827 return map_list_ptr->map_list_map;
828
829 map_list_ptr = ((struct file_name_map_list *)
830 xmalloc (sizeof (struct file_name_map_list)));
831 map_list_ptr->map_list_name = xstrdup (dirname);
4b588241 832 map_list_ptr->map_list_map = NULL;
c31a6508
ZW
833
834 name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
835 strcpy (name, dirname);
836 if (*dirname)
837 strcat (name, "/");
838 strcat (name, FILE_NAME_MAP_FILE);
839 f = fopen (name, "r");
840 if (!f)
841 map_list_ptr->map_list_map = (struct file_name_map *)-1;
842 else
843 {
844 int ch;
845 int dirlen = strlen (dirname);
846
847 while ((ch = getc (f)) != EOF)
848 {
849 char *from, *to;
850 struct file_name_map *ptr;
851
852 if (is_space(ch))
853 continue;
854 from = read_filename_string (ch, f);
855 while ((ch = getc (f)) != EOF && is_hspace(ch))
856 ;
857 to = read_filename_string (ch, f);
858
859 ptr = ((struct file_name_map *)
860 xmalloc (sizeof (struct file_name_map)));
861 ptr->map_from = from;
862
863 /* Make the real filename absolute. */
864 if (*to == '/')
865 ptr->map_to = to;
866 else
867 {
868 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
869 strcpy (ptr->map_to, dirname);
870 ptr->map_to[dirlen] = '/';
871 strcpy (ptr->map_to + dirlen + 1, to);
872 free (to);
873 }
874
875 ptr->map_next = map_list_ptr->map_list_map;
876 map_list_ptr->map_list_map = ptr;
877
878 while ((ch = getc (f)) != '\n')
879 if (ch == EOF)
880 break;
881 }
882 fclose (f);
883 }
884
885 map_list_ptr->map_list_next = CPP_OPTION (pfile, map_list);
886 CPP_OPTION (pfile, map_list) = map_list_ptr;
887
888 return map_list_ptr->map_list_map;
889}
890
891/* Remap NAME based on the file_name_map (if any) for LOC. */
892
893static char *
894remap_filename (pfile, name, loc)
895 cpp_reader *pfile;
896 char *name;
897 struct file_name_list *loc;
898{
899 struct file_name_map *map;
900 const char *from, *p, *dir;
901
902 if (! loc->name_map)
903 loc->name_map = read_name_map (pfile,
904 loc->name
905 ? loc->name : ".");
906
907 if (loc->name_map == (struct file_name_map *)-1)
908 return name;
909
910 from = name + strlen (loc->name) + 1;
911
912 for (map = loc->name_map; map; map = map->map_next)
913 if (!strcmp (map->map_from, from))
914 return map->map_to;
915
916 /* Try to find a mapping file for the particular directory we are
917 looking in. Thus #include <sys/types.h> will look up sys/types.h
918 in /usr/include/header.gcc and look up types.h in
919 /usr/include/sys/header.gcc. */
920 p = strrchr (name, '/');
921 if (!p)
922 p = name;
923 if (loc && loc->name
924 && strlen (loc->name) == (size_t) (p - name)
925 && !strncmp (loc->name, name, p - name))
926 /* FILENAME is in SEARCHPTR, which we've already checked. */
927 return name;
928
929 if (p == name)
930 {
931 dir = ".";
932 from = name;
933 }
934 else
935 {
936 char * newdir = (char *) alloca (p - name + 1);
937 memcpy (newdir, name, p - name);
938 newdir[p - name] = '\0';
939 dir = newdir;
940 from = p + 1;
941 }
942
943 for (map = read_name_map (pfile, dir); map; map = map->map_next)
944 if (! strcmp (map->map_from, name))
945 return map->map_to;
946
947 return name;
948}
949
6458033d
ZW
950/* Given a path FNAME, extract the directory component and place it
951 onto the actual_dirs list. Return a pointer to the allocated
952 file_name_list structure. These structures are used to implement
953 current-directory "" include searching. */
954
f1a86df6
ZW
955static struct file_name_list *
956actual_directory (pfile, fname)
957 cpp_reader *pfile;
bcc5cac9 958 const char *fname;
f1a86df6
ZW
959{
960 char *last_slash, *dir;
961 size_t dlen;
962 struct file_name_list *x;
963
c49445e0 964 dir = xstrdup (fname);
7ceb3598 965 last_slash = strrchr (dir, '/');
f1a86df6
ZW
966 if (last_slash)
967 {
968 if (last_slash == dir)
969 {
970 dlen = 1;
971 last_slash[1] = '\0';
972 }
973 else
974 {
975 dlen = last_slash - dir;
976 *last_slash = '\0';
977 }
978 }
979 else
980 {
87ae0c74
GM
981 free (dir);
982 dir = xstrdup (".");
f1a86df6
ZW
983 dlen = 1;
984 }
985
986 if (dlen > pfile->max_include_len)
987 pfile->max_include_len = dlen;
988
989 for (x = pfile->actual_dirs; x; x = x->alloc)
990 if (!strcmp (x->name, dir))
991 {
992 free (dir);
993 return x;
994 }
995
996 /* Not found, make a new one. */
997 x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
998 x->name = dir;
999 x->nlen = dlen;
ae79697b 1000 x->next = CPP_OPTION (pfile, quote_include);
f1a86df6 1001 x->alloc = pfile->actual_dirs;
c31a6508 1002 x->sysp = CPP_BUFFER (pfile)->inc->sysp;
f1a86df6
ZW
1003 x->name_map = NULL;
1004
1005 pfile->actual_dirs = x;
1006 return x;
1007}
1008
0b3d776a
ZW
1009/* Simplify a path name in place, deleting redundant components. This
1010 reduces OS overhead and guarantees that equivalent paths compare
1011 the same (modulo symlinks).
1012
1013 Transforms made:
1014 foo/bar/../quux foo/quux
1015 foo/./bar foo/bar
1016 foo//bar foo/bar
1017 /../quux /quux
1018 //quux //quux (POSIX allows leading // as a namespace escape)
1019
1020 Guarantees no trailing slashes. All transforms reduce the length
1021 of the string.
1022 */
0b22d65c 1023void
b0699dad 1024_cpp_simplify_pathname (path)
21380ab0 1025 char *path;
0b3d776a
ZW
1026{
1027 char *from, *to;
1028 char *base;
1029 int absolute = 0;
1030
509781a4 1031#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
0b3d776a
ZW
1032 /* Convert all backslashes to slashes. */
1033 for (from = path; *from; from++)
1034 if (*from == '\\') *from = '/';
1035
1036 /* Skip over leading drive letter if present. */
1037 if (ISALPHA (path[0]) && path[1] == ':')
1038 from = to = &path[2];
1039 else
1040 from = to = path;
1041#else
1042 from = to = path;
1043#endif
1044
1045 /* Remove redundant initial /s. */
1046 if (*from == '/')
1047 {
1048 absolute = 1;
1049 to++;
1050 from++;
1051 if (*from == '/')
1052 {
1053 if (*++from == '/')
1054 /* 3 or more initial /s are equivalent to 1 /. */
1055 while (*++from == '/');
1056 else
1057 /* On some hosts // differs from /; Posix allows this. */
1058 to++;
1059 }
1060 }
1061 base = to;
1062
1063 for (;;)
1064 {
1065 while (*from == '/')
1066 from++;
1067
1068 if (from[0] == '.' && from[1] == '/')
1069 from += 2;
1070 else if (from[0] == '.' && from[1] == '\0')
1071 goto done;
1072 else if (from[0] == '.' && from[1] == '.' && from[2] == '/')
1073 {
1074 if (base == to)
1075 {
1076 if (absolute)
1077 from += 3;
1078 else
1079 {
1080 *to++ = *from++;
1081 *to++ = *from++;
1082 *to++ = *from++;
1083 base = to;
1084 }
1085 }
1086 else
1087 {
1088 to -= 2;
1089 while (to > base && *to != '/') to--;
1090 if (*to == '/')
1091 to++;
1092 from += 3;
1093 }
1094 }
1095 else if (from[0] == '.' && from[1] == '.' && from[2] == '\0')
1096 {
1097 if (base == to)
1098 {
1099 if (!absolute)
1100 {
1101 *to++ = *from++;
1102 *to++ = *from++;
1103 }
1104 }
1105 else
1106 {
1107 to -= 2;
1108 while (to > base && *to != '/') to--;
1109 if (*to == '/')
1110 to++;
1111 }
1112 goto done;
1113 }
1114 else
1115 /* Copy this component and trailing /, if any. */
1116 while ((*to++ = *from++) != '/')
1117 {
1118 if (!to[-1])
1119 {
1120 to--;
1121 goto done;
1122 }
1123 }
1124
1125 }
1126
1127 done:
1128 /* Trim trailing slash */
1129 if (to[0] == '/' && (!absolute || to > path+1))
1130 to--;
1131
1132 /* Change the empty string to "." so that stat() on the result
1133 will always work. */
1134 if (to == path)
1135 *to++ = '.';
1136
1137 *to = '\0';
1138
1139 return;
1140}
1141
1142/* It is not clear when this should be used if at all, so I've
1143 disabled it until someone who understands VMS can look at it. */
1144#if 0
add7091b
ZW
1145
1146/* Under VMS we need to fix up the "include" specification filename.
1147
1148 Rules for possible conversions
1149
1150 fullname tried paths
1151
1152 name name
1153 ./dir/name [.dir]name
1154 /dir/name dir:name
1155 /name [000000]name, name
1156 dir/name dir:[000000]name, dir:name, dir/name
1157 dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
1158 path:/name path:[000000]name, path:name
1159 path:/dir/name path:[000000.dir]name, path:[dir]name
1160 path:dir/name path:[dir]name
1161 [path]:[dir]name [path.dir]name
1162 path/[dir]name [path.dir]name
1163
1164 The path:/name input is constructed when expanding <> includes. */
1165
1166
1167static void
1168hack_vms_include_specification (fullname)
1169 char *fullname;
1170{
1171 register char *basename, *unixname, *local_ptr, *first_slash;
1172 int f, check_filename_before_returning, must_revert;
1173 char Local[512];
1174
1175 check_filename_before_returning = 0;
1176 must_revert = 0;
1177 /* See if we can find a 1st slash. If not, there's no path information. */
7ceb3598 1178 first_slash = strchr (fullname, '/');
add7091b
ZW
1179 if (first_slash == 0)
1180 return 0; /* Nothing to do!!! */
1181
1182 /* construct device spec if none given. */
1183
7ceb3598 1184 if (strchr (fullname, ':') == 0)
add7091b
ZW
1185 {
1186
1187 /* If fullname has a slash, take it as device spec. */
1188
1189 if (first_slash == fullname)
1190 {
7ceb3598 1191 first_slash = strchr (fullname + 1, '/'); /* 2nd slash ? */
add7091b
ZW
1192 if (first_slash)
1193 *first_slash = ':'; /* make device spec */
1194 for (basename = fullname; *basename != 0; basename++)
1195 *basename = *(basename+1); /* remove leading slash */
1196 }
1197 else if ((first_slash[-1] != '.') /* keep ':/', './' */
1198 && (first_slash[-1] != ':')
1199 && (first_slash[-1] != ']')) /* or a vms path */
1200 {
1201 *first_slash = ':';
1202 }
1203 else if ((first_slash[1] == '[') /* skip './' in './[dir' */
1204 && (first_slash[-1] == '.'))
1205 fullname += 2;
1206 }
1207
1208 /* Get part after first ':' (basename[-1] == ':')
1209 or last '/' (basename[-1] == '/'). */
1210
1211 basename = base_name (fullname);
1212
1213 local_ptr = Local; /* initialize */
1214
1215 /* We are trying to do a number of things here. First of all, we are
1216 trying to hammer the filenames into a standard format, such that later
1217 processing can handle them.
1218
1219 If the file name contains something like [dir.], then it recognizes this
1220 as a root, and strips the ".]". Later processing will add whatever is
1221 needed to get things working properly.
1222
1223 If no device is specified, then the first directory name is taken to be
1224 a device name (or a rooted logical). */
1225
1226 /* Point to the UNIX filename part (which needs to be fixed!)
1227 but skip vms path information.
1228 [basename != fullname since first_slash != 0]. */
1229
1230 if ((basename[-1] == ':') /* vms path spec. */
1231 || (basename[-1] == ']')
1232 || (basename[-1] == '>'))
1233 unixname = basename;
1234 else
1235 unixname = fullname;
1236
1237 if (*unixname == '/')
1238 unixname++;
1239
1240 /* If the directory spec is not rooted, we can just copy
1241 the UNIX filename part and we are done. */
1242
1243 if (((basename - fullname) > 1)
1244 && ( (basename[-1] == ']')
1245 || (basename[-1] == '>')))
1246 {
1247 if (basename[-2] != '.')
1248 {
1249
1250 /* The VMS part ends in a `]', and the preceding character is not a `.'.
1251 -> PATH]:/name (basename = '/name', unixname = 'name')
1252 We strip the `]', and then splice the two parts of the name in the
86702e31 1253 usual way. Given the default locations for include files,
add7091b
ZW
1254 we will only use this code if the user specifies alternate locations
1255 with the /include (-I) switch on the command line. */
1256
1257 basename -= 1; /* Strip "]" */
1258 unixname--; /* backspace */
1259 }
1260 else
1261 {
1262
1263 /* The VMS part has a ".]" at the end, and this will not do. Later
1264 processing will add a second directory spec, and this would be a syntax
1265 error. Thus we strip the ".]", and thus merge the directory specs.
1266 We also backspace unixname, so that it points to a '/'. This inhibits the
1267 generation of the 000000 root directory spec (which does not belong here
1268 in this case). */
1269
1270 basename -= 2; /* Strip ".]" */
1271 unixname--; /* backspace */
1272 }
1273 }
1274
1275 else
1276
1277 {
1278
1279 /* We drop in here if there is no VMS style directory specification yet.
1280 If there is no device specification either, we make the first dir a
1281 device and try that. If we do not do this, then we will be essentially
1282 searching the users default directory (as if they did a #include "asdf.h").
1283
1284 Then all we need to do is to push a '[' into the output string. Later
1285 processing will fill this in, and close the bracket. */
1286
1287 if ((unixname != fullname) /* vms path spec found. */
1288 && (basename[-1] != ':'))
1289 *local_ptr++ = ':'; /* dev not in spec. take first dir */
1290
1291 *local_ptr++ = '['; /* Open the directory specification */
1292 }
1293
1294 if (unixname == fullname) /* no vms dir spec. */
1295 {
1296 must_revert = 1;
1297 if ((first_slash != 0) /* unix dir spec. */
1298 && (*unixname != '/') /* not beginning with '/' */
1299 && (*unixname != '.')) /* or './' or '../' */
1300 *local_ptr++ = '.'; /* dir is local ! */
1301 }
1302
1303 /* at this point we assume that we have the device spec, and (at least
1304 the opening "[" for a directory specification. We may have directories
1305 specified already.
1306
1307 If there are no other slashes then the filename will be
1308 in the "root" directory. Otherwise, we need to add
1309 directory specifications. */
1310
7ceb3598 1311 if (strchr (unixname, '/') == 0)
add7091b
ZW
1312 {
1313 /* if no directories specified yet and none are following. */
1314 if (local_ptr[-1] == '[')
1315 {
1316 /* Just add "000000]" as the directory string */
1317 strcpy (local_ptr, "000000]");
1318 local_ptr += strlen (local_ptr);
1319 check_filename_before_returning = 1; /* we might need to fool with this later */
1320 }
1321 }
1322 else
1323 {
1324
1325 /* As long as there are still subdirectories to add, do them. */
7ceb3598 1326 while (strchr (unixname, '/') != 0)
add7091b
ZW
1327 {
1328 /* If this token is "." we can ignore it
1329 if it's not at the beginning of a path. */
1330 if ((unixname[0] == '.') && (unixname[1] == '/'))
1331 {
1332 /* remove it at beginning of path. */
1333 if ( ((unixname == fullname) /* no device spec */
1334 && (fullname+2 != basename)) /* starts with ./ */
1335 /* or */
1336 || ((basename[-1] == ':') /* device spec */
1337 && (unixname-1 == basename))) /* and ./ afterwards */
1338 *local_ptr++ = '.'; /* make '[.' start of path. */
1339 unixname += 2;
1340 continue;
1341 }
1342
1343 /* Add a subdirectory spec. Do not duplicate "." */
1344 if ( local_ptr[-1] != '.'
1345 && local_ptr[-1] != '['
1346 && local_ptr[-1] != '<')
1347 *local_ptr++ = '.';
1348
1349 /* If this is ".." then the spec becomes "-" */
1350 if ( (unixname[0] == '.')
1351 && (unixname[1] == '.')
1352 && (unixname[2] == '/'))
1353 {
1354 /* Add "-" and skip the ".." */
1355 if ((local_ptr[-1] == '.')
1356 && (local_ptr[-2] == '['))
1357 local_ptr--; /* prevent [.- */
1358 *local_ptr++ = '-';
1359 unixname += 3;
1360 continue;
1361 }
1362
1363 /* Copy the subdirectory */
1364 while (*unixname != '/')
1365 *local_ptr++= *unixname++;
1366
1367 unixname++; /* Skip the "/" */
1368 }
1369
1370 /* Close the directory specification */
1371 if (local_ptr[-1] == '.') /* no trailing periods */
1372 local_ptr--;
1373
1374 if (local_ptr[-1] == '[') /* no dir needed */
1375 local_ptr--;
1376 else
1377 *local_ptr++ = ']';
1378 }
1379
1380 /* Now add the filename. */
1381
1382 while (*unixname)
1383 *local_ptr++ = *unixname++;
1384 *local_ptr = 0;
1385
1386 /* Now append it to the original VMS spec. */
1387
1388 strcpy ((must_revert==1)?fullname:basename, Local);
1389
1390 /* If we put a [000000] in the filename, try to open it first. If this fails,
1391 remove the [000000], and return that name. This provides flexibility
1392 to the user in that they can use both rooted and non-rooted logical names
1393 to point to the location of the file. */
1394
1395 if (check_filename_before_returning)
1396 {
e576beb0 1397 f = open (fullname, O_RDONLY|O_NONBLOCK);
add7091b
ZW
1398 if (f >= 0)
1399 {
1400 /* The file name is OK as it is, so return it as is. */
1401 close (f);
1402 return 1;
1403 }
1404
1405 /* The filename did not work. Try to remove the [000000] from the name,
1406 and return it. */
1407
7ceb3598
NB
1408 basename = strchr (fullname, '[');
1409 local_ptr = strchr (fullname, ']') + 1;
add7091b
ZW
1410 strcpy (basename, local_ptr); /* this gets rid of it */
1411
1412 }
1413
1414 return 1;
1415}
1416#endif /* VMS */