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