This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: splitting up cpplib, revised


OK. I approve this patch. If you send me the diff as a separate file, I'll install it. I seem to have trouble matching
hunks of code taken from email. Probably a problem with tabs & other whitespace.

Dave

Zack Weinberg wrote:

> Here is a much less invasive patch to split up cpplib.  It just breaks
> out all the file handling code to cppfiles.c.  A bunch of the code in
> do_include has been moved out to a separate function, find_include_file.
> This should make it much easier to merge in the rewrite of file
> handling from cpplib.
>
> I also fixed a number of bugs related to pathnames and VMS.  A VMSie
> should probably look at that part, but considering that cpplib
> wouldn't even link on VMS before, it has to be an improvement.
>
> `make bootstrap' completes successfully.  I don't have a system on
> which fix-header is useful, but it links.
>
> zw
>
> 1998-10-25 15:06 -0500  Zack Weinberg  <zack@rabi.phys.columbia.edu>
>
>         * cpplib.c: Merge do_once into do_pragma.  Break file handling
>           code out of do_include.
>           Move append_include_chain, deps_output,
>           file_cleanup, redundant_include_p, import_hash,
>           lookup_import, add_import, read_filename_string, read_name_map,
>           open_include_file, finclude, safe_read to cppfiles.c.
>           Move prototypes for deps_output, append_include_chain,
>           finclude to cpplib.h.  Move definition of struct
>           file_name_list there also.
>
>         * cppfiles.c: New file.  Contains all the above functions
>           broken out of cpplib.c; also hack_vms_include_specification
>           from cccp.c and find_include_file, a new function broken out of
>           do_include.
>
>         * Makefile.in (cppmain): Depend on cppfiles.o.
>           (fix-header): Likewise.
>           (cppfiles.o): New target.
>         * configure.in (--enable-c-cpplib): Add cppfiles.o to
>           extra_c_objs.  Add ../cppfiles.o to extra_cxx_objs.
>
> ============================================================
> Index: Makefile.in
> --- Makefile.in 1998/10/22 14:47:52     1.187
> +++ Makefile.in 1998/10/25 20:01:07
> @@ -1881,9 +1881,9 @@
>           -c `echo $(srcdir)/cccp.c | sed 's,^\./,,'`
>
>  cppmain$(exeext): cppmain.o cpplib.o cpphash.o cppalloc.o cpperror.o cppexp.o \
> -  prefix.o version.o mbchar.o @extra_cpp_objs@ $(LIBDEPS)
> +  cppfiles.o prefix.o version.o mbchar.o @extra_cpp_objs@ $(LIBDEPS)
>         $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ cppmain.o cpplib.o cpphash.o \
> -         mbchar.o @extra_cpp_objs@ \
> +         cppfiles.o mbchar.o @extra_cpp_objs@ \
>           cppalloc.o cpperror.o cppexp.o prefix.o version.o $(LIBS)
>
>  cppmain.o: cppmain.c $(CONFIG_H) cpplib.h system.h gansidecl.h
> @@ -1902,6 +1902,8 @@
>
>  cppexp.o: cppexp.c $(CONFIG_H) cpplib.h system.h gansidecl.h
>
> +cppfiles.o: cppfiles.c $(CONFIG_H) cpplib.h system.h gansidecl.h
> +
>  cpphash.o: cpphash.c cpplib.h cpphash.h $(CONFIG_H) system.h gansidecl.h
>
>  cppalloc.o: cppalloc.c $(CONFIG_H) cpplib.h system.h gansidecl.h
> @@ -2116,10 +2118,10 @@
>         rm -rf fixtmp.c
>
>  fix-header: fix-header.o scan-decls.o scan.o xsys-protos.h $(HOST_LIBDEPS) \
> -   cpplib.o cpphash.o cppalloc.o cppexp.o prefix.o version.o
> +   cpplib.o cpphash.o cppfiles.o cppalloc.o cppexp.o prefix.o version.o
>         $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ fix-header.o \
>            scan-decls.o scan.o cpplib.o cpphash.o cppalloc.o prefix.o \
> -          version.o cppexp.o $(HOST_LIBS)
> +          version.o cppexp.o cppfiles.o $(HOST_LIBS)
>
>  fix-header.o: fix-header.c $(srcdir)/../include/obstack.h scan.h \
>         xsys-protos.h $(build_xm_file) system.h cpplib.h cpphash.h
> ============================================================
> Index: configure.in
> --- configure.in        1998/10/12 11:14:11     1.166
> +++ configure.in        1998/10/25 20:01:08
> @@ -190,9 +190,9 @@
>  [  --enable-c-cpplib       link cpplib directly into C and C++ compilers
>                            (implies --enable-cpplib).],
>  if test x$enable_c_cpplib != xno; then
> -  extra_c_objs="${extra_c_objs} cpplib.o cppexp.o cpphash.o cpperror.o"
> +  extra_c_objs="${extra_c_objs} cpplib.o cppexp.o cpphash.o cppfiles.o cpperror.o"
>    extra_c_objs="${extra_c_objs} prefix.o"
> -  extra_cxx_objs="${extra_cxx_objs} ../cpplib.o ../cppexp.o ../cpphash.o ../cpperror.o ../prefix.o"
> +  extra_cxx_objs="${extra_cxx_objs} ../cpplib.o ../cppexp.o ../cpphash.o ../cppfiles.o ../cpperror.o ../prefix.o"
>    extra_c_flags=-DUSE_CPPLIB=1
>    cpp_main=cppmain
>  fi)
> ============================================================
> Index: cpplib.c
> --- cpplib.c    1998/10/17 20:26:10     1.39
> +++ cpplib.c    1998/10/25 20:01:09
> @@ -88,9 +88,6 @@
>  #ifndef STANDARD_INCLUDE_DIR
>  #define STANDARD_INCLUDE_DIR "/usr/include"
>  #endif
> -#ifndef INCLUDE_LEN_FUDGE
> -#define INCLUDE_LEN_FUDGE 0
> -#endif
>
>  /* Symbols to predefine.  */
>
> @@ -199,10 +196,6 @@
>  extern void cpp_hash_cleanup PARAMS ((cpp_reader *));
>
>  static char *my_strerror               PROTO ((int));
> -static void add_import                 PROTO ((cpp_reader *, int, char *));
> -static void append_include_chain       PROTO ((cpp_reader *,
> -                                               struct file_name_list *,
> -                                               struct file_name_list *));
>  static void make_assertion             PROTO ((cpp_reader *, char *, U_CHAR *));
>  static void path_include               PROTO ((cpp_reader *, char *));
>  static void initialize_builtins                PROTO ((cpp_reader *));
> @@ -210,38 +203,27 @@
>  #if 0
>  static void trigraph_pcp ();
>  #endif
> -static int finclude                    PROTO ((cpp_reader *, int, char *,
> -                                               int, struct file_name_list *));
>  static void validate_else              PROTO ((cpp_reader *, char *));
>  static int comp_def_part               PROTO ((int, U_CHAR *, int, U_CHAR *,
>                                                 int, int));
>  #ifdef abort
>  extern void fancy_abort ();
>  #endif
> -static int lookup_import               PROTO ((cpp_reader *, char *,
> -                                               struct file_name_list *));
> -static int redundant_include_p         PROTO ((cpp_reader *, char *));
> -static int is_system_include           PROTO ((cpp_reader *, char *));
> -static struct file_name_map *read_name_map     PROTO ((cpp_reader *, char *));
> -static char *read_filename_string      PROTO ((int, FILE *));
> -static int open_include_file           PROTO ((cpp_reader *, char *,
> -                                               struct file_name_list *));
>  static int check_macro_name            PROTO ((cpp_reader *, U_CHAR *, char *));
>  static int compare_defs                        PROTO ((cpp_reader *,
>                                                 DEFINITION *, DEFINITION *));
>  static int compare_token_lists         PROTO ((struct arglist *,
>                                                 struct arglist *));
> +static int is_system_include           PROTO ((cpp_reader *, char *));
>  static HOST_WIDE_INT eval_if_expression        PROTO ((cpp_reader *, U_CHAR *, int));
>  static int change_newlines             PROTO ((U_CHAR *, int));
>  static struct arglist *read_token_list PROTO ((cpp_reader *, int *));
>  static void free_token_list            PROTO ((struct arglist *));
> -static int safe_read                   PROTO ((int, char *, int));
>  static void push_macro_expansion PARAMS ((cpp_reader *,
>                                           U_CHAR *, int, HASHNODE *));
>  static struct cpp_pending *nreverse_pending PARAMS ((struct cpp_pending *));
>  extern char *xrealloc ();
>  static char *xcalloc                   PROTO ((unsigned, unsigned));
> -static char *savestring                        PROTO ((char *));
>
>  static void conditional_skip           PROTO ((cpp_reader *, int,
>                                                enum node_type, U_CHAR *));
> @@ -259,25 +241,6 @@
>  extern char *version_string;
>  extern struct tm *localtime ();
>
> -struct file_name_list
> -  {
> -    struct file_name_list *next;
> -    char *fname;
> -    /* If the following is nonzero, it is a macro name.
> -       Don't include the file again if that macro is defined.  */
> -    U_CHAR *control_macro;
> -    /* If the following is nonzero, it is a C-language system include
> -       directory.  */
> -    int c_system_include_path;
> -    /* Mapping of file names for this directory.  */
> -    struct file_name_map *name_map;
> -    /* Non-zero if name_map is valid.  */
> -    int got_name_map;
> -  };
> -
> -/* If a buffer's dir field is SELF_DIR_DUMMY, it means the file was found
> -   via the same directory as the file that #included it.  */
> -#define SELF_DIR_DUMMY ((struct file_name_list *) (~0))
>
>  /* #include "file" looks in source file dir, then stack.  */
>  /* #include <file> just looks in the stack.  */
> @@ -365,7 +328,6 @@
>  #ifdef SCCS_DIRECTIVE
>  static int do_sccs PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
>  #endif
> -static int do_once PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
>  static int do_assert PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
>  static int do_unassert PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
>  static int do_warning PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
> @@ -402,13 +364,13 @@
>  };
>
>  /* table to tell if char can be part of a C identifier.  */
> -U_CHAR is_idchar[256];
> +U_CHAR is_idchar[256] = { 0 };
>  /* table to tell if char can be first char of a c identifier.  */
> -U_CHAR is_idstart[256];
> +U_CHAR is_idstart[256] = { 0 };
>  /* table to tell if c is horizontal space.  */
> -U_CHAR is_hor_space[256];
> +U_CHAR is_hor_space[256] = { 0 };
>  /* table to tell if c is horizontal or vertical space.  */
> -static U_CHAR is_space[256];
> +U_CHAR is_space[256] = { 0 };
>
>  /* Initialize syntactic classifications of characters.  */
>
> @@ -614,85 +576,7 @@
>        cpp_pop_buffer (pfile);
>      }
>  }
> -
> -/* Append a chain of `struct file_name_list's
> -   to the end of the main include chain.
> -   FIRST is the beginning of the chain to append, and LAST is the end.  */
> -
> -static void
> -append_include_chain (pfile, first, last)
> -     cpp_reader *pfile;
> -     struct file_name_list *first, *last;
> -{
> -  struct cpp_options *opts = CPP_OPTIONS (pfile);
> -  struct file_name_list *dir;
> -
> -  if (!first || !last)
> -    return;
> -
> -  if (opts->include == 0)
> -    opts->include = first;
> -  else
> -    opts->last_include->next = first;
> -
> -  if (opts->first_bracket_include == 0)
> -    opts->first_bracket_include = first;
> -
> -  for (dir = first; ; dir = dir->next) {
> -    int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
> -    if (len > pfile->max_include_len)
> -      pfile->max_include_len = len;
> -    if (dir == last)
> -      break;
> -  }
> -
> -  last->next = NULL;
> -  opts->last_include = last;
> -}
> -
> -/* Add output to `deps_buffer' for the -M switch.
> -   STRING points to the text to be output.
> -   SPACER is ':' for targets, ' ' for dependencies, zero for text
> -   to be inserted literally.  */
>
> -static void
> -deps_output (pfile, string, spacer)
> -     cpp_reader *pfile;
> -     char *string;
> -     int spacer;
> -{
> -  int size = strlen (string);
> -
> -  if (size == 0)
> -    return;
> -
> -#ifndef MAX_OUTPUT_COLUMNS
> -#define MAX_OUTPUT_COLUMNS 72
> -#endif
> -  if (spacer
> -      && pfile->deps_column > 0
> -      && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS)
> -    {
> -      deps_output (pfile, " \\\n  ", 0);
> -      pfile->deps_column = 0;
> -    }
> -
> -  if (pfile->deps_size + size + 8 > pfile->deps_allocated_size)
> -    {
> -      pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2;
> -      pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer,
> -                                             pfile->deps_allocated_size);
> -    }
> -  if (spacer == ' ' && pfile->deps_column > 0)
> -    pfile->deps_buffer[pfile->deps_size++] = ' ';
> -  bcopy (string, &pfile->deps_buffer[pfile->deps_size], size);
> -  pfile->deps_size += size;
> -  pfile->deps_column += size;
> -  if (spacer == ':')
> -    pfile->deps_buffer[pfile->deps_size++] = ':';
> -  pfile->deps_buffer[pfile->deps_size] = 0;
> -}
> -
>  /* Given a colon-separated list of file names PATH,
>     add all the names to the search path for include files.  */
>
> @@ -805,19 +689,6 @@
>    return 0;
>  }
>
> -int
> -file_cleanup (pbuf, pfile)
> -     cpp_buffer *pbuf;
> -     cpp_reader *pfile ATTRIBUTE_UNUSED;
> -{
> -  if (pbuf->buf)
> -    {
> -      free (pbuf->buf);
> -      pbuf->buf = 0;
> -    }
> -  return 0;
> -}
> -
>  /* Assuming we have read '/'.
>     If this is the start of a comment (followed by '*' or '/'),
>     skip to the end of the comment, and return ' '.
> @@ -3076,29 +2947,21 @@
>  {
>    int importing = (keyword->type == T_IMPORT);
>    int skip_dirs = (keyword->type == T_INCLUDE_NEXT);
> +  int angle_brackets = 0;      /* 0 for "...", 1 for <...> */
>    char *fname;         /* Dynamically allocated fname buffer */
> -  char *pcftry;
> -  U_CHAR *fbeg, *fend;         /* Beginning and end of fname */
> +  char *fbeg, *fend;           /* Beginning and end of fname */
> +  long flen;
> +
>    enum cpp_token token;
>
>    /* Chain of dirs to search */
>    struct file_name_list *search_start = CPP_OPTIONS (pfile)->include;
> -  struct file_name_list dsp[1];        /* First in chain, if #include "..." */
> -  struct file_name_list *searchptr = 0;
> +  struct file_name_list dsp;   /* First in chain, if #include "..." */
> +  struct file_name_list *foundhere, *ptr;
> +
>    long old_written = CPP_WRITTEN (pfile);
> -
> -  int flen;
>
> -  int f;                       /* file number */
> -
> -  int angle_brackets = 0;      /* 0 for "...", 1 for <...> */
> -  char *pcfbuf;
> -#if 0
> -  int pcf = -1;
> -  char *pcfbuflimit;
> -#endif
> -  int pcfnum;
> -  f= -1;                       /* JF we iz paranoid! */
> +  int fd;
>
>    if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
>      {
> @@ -3132,9 +2995,9 @@
>
>    if (token == CPP_STRING)
>      {
> -      /* FIXME - check no trailing garbage */
>        fbeg = pfile->token_buffer + old_written + 1;
>        fend = CPP_PWRITTEN (pfile) - 1;
> +      *fend = '\0';
>        if (fbeg[-1] == '<')
>         {
>           angle_brackets = 1;
> @@ -3158,8 +3021,8 @@
>                 {
>                   /* Found a named file.  Figure out dir of the file,
>                      and put it in front of the search list.  */
> -                 dsp[0].next = search_start;
> -                 search_start = dsp;
> +                 dsp.next = search_start;
> +                 search_start = &dsp;
>  #ifndef VMS
>                   ep = rindex (nam, '/');
>  #else                          /* VMS */
> @@ -3171,17 +3034,17 @@
>                   if (ep != NULL)
>                     {
>                       n = ep - nam;
> -                     dsp[0].fname = (char *) alloca (n + 1);
> -                     strncpy (dsp[0].fname, nam, n);
> -                     dsp[0].fname[n] = '\0';
> +                     dsp.fname = (char *) alloca (n + 1);
> +                     strncpy (dsp.fname, nam, n);
> +                     dsp.fname[n] = '\0';
>                       if (n + INCLUDE_LEN_FUDGE > pfile->max_include_len)
>                         pfile->max_include_len = n + INCLUDE_LEN_FUDGE;
>                     }
>                   else
>                     {
> -                     dsp[0].fname = 0; /* Current directory */
> +                     dsp.fname = 0; /* Current directory */
>                     }
> -                 dsp[0].got_name_map = 0;
> +                 dsp.got_name_map = 0;
>                   break;
>                 }
>             }
> @@ -3201,6 +3064,11 @@
>        /* If -I-, start with the first -I dir after the -I-.  */
>        if (CPP_OPTIONS (pfile)->first_bracket_include)
>         search_start = CPP_OPTIONS (pfile)->first_bracket_include;
> +
> +      /* Append the missing `.h' to the name. */
> +      CPP_PUTS (pfile, ".h", 3)
> +      CPP_NUL_TERMINATE_Q (pfile);
> +
>        fbeg = pfile->token_buffer + old_written;
>        fend = CPP_PWRITTEN (pfile);
>      }
> @@ -3214,14 +3082,11 @@
>        return 0;
>      }
>
> -  *fend = 0;
> -
>    token = get_directive_token (pfile);
>    if (token != CPP_VSPACE)
>      {
>        cpp_error (pfile, "junk at end of `#include'");
> -      while (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP)
> -       token = get_directive_token (pfile);
> +      skip_rest_of_line (pfile);
>      }
>
>    /* For #include_next, skip in the search path
> @@ -3254,127 +3119,57 @@
>
>    /* Allocate this permanently, because it gets stored in the definitions
>       of macros.  */
> -  fname = (char *) xmalloc (pfile->max_include_len + flen + 4);
>    /* + 2 above for slash and terminating null.  */
> -  /* + 2 added for '.h' on VMS (to support '#include filename') */
> +  fname = (char *) xmalloc (pfile->max_include_len + flen + 2);
>
> -  /* If specified file name is absolute, just open it.  */
> +  fd = find_include_file (pfile, fbeg, flen, fname,
> +                         importing, search_start, &foundhere);
>
> -  if (*fbeg == '/') {
> -    strncpy (fname, fbeg, flen);
> -    fname[flen] = 0;
> -    if (redundant_include_p (pfile, fname))
> +  if (fd == -2)
> +    {
> +      free (fname);
>        return 0;
> -    if (importing)
> -      f = lookup_import (pfile, fname, NULL_PTR);
> -    else
> -      f = open_include_file (pfile, fname, NULL_PTR);
> -    if (f == -2)
> -      return 0;                /* Already included this file */
> -  } else {
> -    /* Search directory path, trying to open the file.
> -       Copy each filename tried into FNAME.  */
> -
> -    for (searchptr = search_start; searchptr; searchptr = searchptr->next) {
> -      if (searchptr->fname) {
> -       /* The empty string in a search path is ignored.
> -          This makes it possible to turn off entirely
> -          a standard piece of the list.  */
> -       if (searchptr->fname[0] == 0)
> -         continue;
> -       strcpy (fname, searchptr->fname);
> -       strcat (fname, "/");
> -       fname[strlen (fname) + flen] = 0;
> -      } else {
> -       fname[0] = 0;
> -      }
> -      strncat (fname, fbeg, flen);
> -#ifdef VMS
> -      /* Change this 1/2 Unix 1/2 VMS file specification into a
> -         full VMS file specification */
> -      if (searchptr->fname && (searchptr->fname[0] != 0)) {
> -       /* Fix up the filename */
> -       hack_vms_include_specification (fname);
> -      } else {
> -       /* This is a normal VMS filespec, so use it unchanged.  */
> -       strncpy (fname, fbeg, flen);
> -       fname[flen] = 0;
> -       /* if it's '#include filename', add the missing .h */
> -       if (index(fname,'.')==NULL) {
> -         strcat (fname, ".h");
> -       }
> -      }
> -#endif /* VMS */
> -      /* ??? There are currently 3 separate mechanisms for avoiding processing
> -        of redundant include files: #import, #pragma once, and
> -        redundant_include_p.  It would be nice if they were unified.  */
> -      if (redundant_include_p (pfile, fname))
> -       return 0;
> -      if (importing)
> -       f = lookup_import (pfile, fname, searchptr);
> -      else
> -       f = open_include_file (pfile, fname, searchptr);
> -      if (f == -2)
> -       return 0;                       /* Already included this file */
> -#ifdef EACCES
> -      else if (f == -1 && errno == EACCES)
> -       cpp_warning (pfile, "Header file %s exists, but is not readable",
> -                    fname);
> -#endif
> -      if (f >= 0)
> -       break;
>      }
> -  }
> -
> -  if (f < 0)
> +
> +  if (fd == -1)
>      {
> -      /* A file that was not found.  */
> -      strncpy (fname, fbeg, flen);
> -      fname[flen] = 0;
> -      /* If generating dependencies and -MG was specified, we assume missing
> -        files are leaf files, living in the same directory as the source file
> -        or other similar place; these missing files may be generated from
> -        other files and may not exist yet (eg: y.tab.h).  */
> -
> -      if (CPP_OPTIONS(pfile)->print_deps_missing_files
> -         && CPP_PRINT_DEPS (pfile)
> -         > (angle_brackets || (pfile->system_include_depth > 0)))
> -       {
> -         /* If it was requested as a system header file,
> -            then assume it belongs in the first place to look for such.  */
> -         if (angle_brackets)
> +      if (CPP_OPTIONS (pfile)->print_deps_missing_files
> +         && CPP_PRINT_DEPS (pfile) > (angle_brackets ||
> +                                      (pfile->system_include_depth > 0)))
> +        {
> +         if (!angle_brackets)
> +           deps_output (pfile, fbeg, ' ');
> +         else
>             {
> -             for (searchptr = search_start; searchptr;
> -                  searchptr = searchptr->next)
> -               {
> -                 if (searchptr->fname)
> +             /* If requested as a system header, assume it belongs in
> +                the first system header directory. */
> +             if (CPP_OPTIONS (pfile)->first_bracket_include)
> +               ptr = CPP_OPTIONS (pfile)->first_bracket_include;
> +             else
> +               ptr = CPP_OPTIONS (pfile)->include;
> +             for (; ptr; ptr = ptr->next)
> +                 if (ptr->fname)
>                     {
>                       char *p;
>
> -                     if (searchptr->fname[0] == 0)
> +                     if (ptr->fname[0] == 0)
>                         continue;
> -                     p = (char *) alloca (strlen (searchptr->fname)
> +                     p = (char *) alloca (strlen (ptr->fname)
>                                            + strlen (fname) + 2);
> -                     strcpy (p, searchptr->fname);
> +                     strcpy (p, ptr->fname);
>                       strcat (p, "/");
>                       strcat (p, fname);
>                       deps_output (pfile, p, ' ');
>                       break;
>                     }
> -               }
> -           }
> -         else
> -           {
> -             /* Otherwise, omit the directory, as if the file existed
> -                in the directory with the source.  */
> -             deps_output (pfile, fname, ' ');
>             }
>         }
> -      /* If -M was specified, and this header file won't be added to the
> -        dependency list, then don't count this as an error, because we can
> -        still produce correct output.  Otherwise, we can't produce correct
> -        output, because there may be dependencies we need inside the missing
> -        file, and we don't know what directory this missing file exists in.*/
> +      /* If -M was specified, and this header file won't be added to
> +        the dependency list, then don't count this as an error,
> +        because we can still produce correct output.  Otherwise, we
> +        can't produce correct output, because there may be
> +        dependencies we need inside the missing file, and we don't
> +        know what directory this missing file exists in. */
>        else if (CPP_PRINT_DEPS (pfile)
>                && (CPP_PRINT_DEPS (pfile)
>                    <= (angle_brackets || (pfile->system_include_depth > 0))))
> @@ -3383,26 +3178,19 @@
>         cpp_error_from_errno (pfile, fname);
>        else
>         cpp_error (pfile, "No include path in which to find %s", fname);
> -    }
> -  else {
> -    /* Check to see if this include file is a once-only include file.
> -       If so, give up.  */
> -
> -    struct file_name_list *ptr;
>
> -    for (ptr = pfile->dont_repeat_files; ptr; ptr = ptr->next) {
> -      if (!strcmp (ptr->fname, fname)) {
> -       close (f);
> -        return 0;                              /* This file was once'd.  */
> -      }
> +      free (fname);
> +      return 0;
>      }
>
> -    for (ptr = pfile->all_include_files; ptr; ptr = ptr->next) {
> -      if (!strcmp (ptr->fname, fname))
> -        break;                         /* This file was included before.  */
> -    }
> +  /* If we get here, we have a file to process. */
> +
> +  for (ptr = pfile->all_include_files; ptr; ptr = ptr->next)
> +    if (!strcmp (ptr->fname, fname))
> +      break;                           /* This file was included before.  */
>
> -    if (ptr == 0) {
> +  if (ptr == 0)
> +    {
>        /* This is the first time for this file.  */
>        /* Add it to list of files included.  */
>
> @@ -3418,95 +3206,38 @@
>        if (CPP_PRINT_DEPS (pfile)
>           > (angle_brackets || (pfile->system_include_depth > 0)))
>         deps_output (pfile, fname, ' ');
> -    }
> -
> -    /* Handle -H option.  */
> -    if (CPP_OPTIONS(pfile)->print_include_names)
> -      {
> -       cpp_buffer *buf = CPP_BUFFER (pfile);
> -       while ((buf = CPP_PREV_BUFFER (buf)) != CPP_NULL_BUFFER (pfile))
> -         putc ('.', stderr);
> -       fprintf (stderr, "%s\n", fname);
> -      }
> -
> -    if (angle_brackets)
> -      pfile->system_include_depth++;
> -
> -    /* Actually process the file.  */
> -
> -    /* Record file on "seen" list for #import.  */
> -    add_import (pfile, f, fname);
> -
> -    pcftry = (char *) alloca (strlen (fname) + 30);
> -    pcfbuf = 0;
> -    pcfnum = 0;
> -
> -#if 0
> -    if (!no_precomp)
> -      {
> -       struct stat stat_f;
> -
> -       fstat (f, &stat_f);
> -
> -       do {
> -         sprintf (pcftry, "%s%d", fname, pcfnum++);
> +    }
>
> -         pcf = open (pcftry, O_RDONLY, 0666);
> -         if (pcf != -1)
> -           {
> -             struct stat s;
> +  /* Handle -H option.  */
> +  if (CPP_OPTIONS(pfile)->print_include_names)
> +    {
> +      cpp_buffer *buf = CPP_BUFFER (pfile);
> +      while ((buf = CPP_PREV_BUFFER (buf)) != CPP_NULL_BUFFER (pfile))
> +       putc ('.', stderr);
> +      fprintf (stderr, "%s\n", fname);
> +    }
>
> -             fstat (pcf, &s);
> -             if (bcmp ((char *) &stat_f.st_ino, (char *) &s.st_ino,
> -                       sizeof (s.st_ino))
> -                 || stat_f.st_dev != s.st_dev)
> -               {
> -                 pcfbuf = check_precompiled (pcf, fname, &pcfbuflimit);
> -                 /* Don't need it any more.  */
> -                 close (pcf);
> -               }
> -             else
> -               {
> -                 /* Don't need it at all.  */
> -                 close (pcf);
> -                 break;
> -               }
> -           }
> -       } while (pcf != -1 && !pcfbuf);
> -      }
> -#endif
> -
> -    /* Actually process the file */
> -    if (cpp_push_buffer (pfile, NULL, 0) == NULL)
> +  /* Actually process the file */
> +  if (cpp_push_buffer (pfile, NULL, 0) == NULL)
> +    {
> +      close (fd);
> +      free (fname);
>        return 0;
> -    if (finclude (pfile, f, fname, is_system_include (pfile, fname),
> -                 searchptr != dsp ? searchptr : SELF_DIR_DUMMY))
> -      {
> -       output_line_command (pfile, 0, enter_file);
> -       pfile->only_seen_white = 2;
> -      }
> +    }
>
> -    if (angle_brackets)
> -      pfile->system_include_depth--;
> -  }
> -  return 0;
> -}
> +  if (angle_brackets)
> +    pfile->system_include_depth++;
>
> -/* Return nonzero if there is no need to include file NAME
> -   because it has already been included and it contains a conditional
> -   to make a repeated include do nothing.  */
> +  if (finclude (pfile, fd, fname, is_system_include (pfile, fname),
> +               foundhere != &dsp ? foundhere : SELF_DIR_DUMMY))
> +    {
> +      output_line_command (pfile, 0, enter_file);
> +      pfile->only_seen_white = 2;
> +    }
> +
> +  if (angle_brackets)
> +    pfile->system_include_depth--;
>
> -static int
> -redundant_include_p (pfile, name)
> -     cpp_reader *pfile;
> -     char *name;
> -{
> -  struct file_name_list *l = pfile->all_include_files;
> -  for (; l; l = l->next)
> -    if (! strcmp (name, l->fname)
> -       && l->control_macro
> -       && cpp_lookup (pfile, l->control_macro, -1, -1))
> -      return 1;
>    return 0;
>  }
>
> @@ -3545,7 +3276,6 @@
>    return 0;
>  }
>
> -
>  /*
>   * Install a name in the assertion hash table.
>   *
> @@ -3910,38 +3640,6 @@
>    return 0;
>  }
>
> -/* Remember the name of the current file being read from so that we can
> -   avoid ever including it again.  */
> -
> -static int
> -do_once (pfile, keyword, unused1, unused2)
> -     cpp_reader *pfile;
> -     struct directive *keyword ATTRIBUTE_UNUSED;
> -     U_CHAR *unused1 ATTRIBUTE_UNUSED, *unused2 ATTRIBUTE_UNUSED;
> -{
> -  cpp_buffer *ip = NULL;
> -  struct file_name_list *new;
> -
> -  for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
> -    {
> -      if (ip == CPP_NULL_BUFFER (pfile))
> -       return 0;
> -      if (ip->fname != NULL)
> -       break;
> -    }
> -
> -
> -  new = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
> -  new->next = pfile->dont_repeat_files;
> -  pfile->dont_repeat_files = new;
> -  new->fname = savestring (ip->fname);
> -  new->control_macro = 0;
> -  new->got_name_map = 0;
> -  new->c_system_include_path = 0;
> -
> -  return 0;
> -}
> -
>  /* Report program identification.  */
>
>  static int
> @@ -3972,14 +3670,33 @@
>  {
>    while (*buf == ' ' || *buf == '\t')
>      buf++;
> -  if (!strncmp (buf, "once", 4)) {
> -    /* Allow #pragma once in system headers, since that's not the user's
> -       fault.  */
> -    if (!CPP_BUFFER (pfile)->system_header_p)
> -      cpp_warning (pfile, "`#pragma once' is obsolete");
> -    do_once (pfile, NULL, NULL, NULL);
> -  }
> +  if (!strncmp (buf, "once", 4))
> +    {
> +      cpp_buffer *ip = NULL;
> +      struct file_name_list *new;
>
> +      /* Allow #pragma once in system headers, since that's not the user's
> +        fault.  */
> +      if (!CPP_BUFFER (pfile)->system_header_p)
> +       cpp_warning (pfile, "`#pragma once' is obsolete");
> +
> +      for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
> +        {
> +         if (ip == CPP_NULL_BUFFER (pfile))
> +           return 0;
> +         if (ip->fname != NULL)
> +           break;
> +       }
> +
> +      new = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
> +      new->next = pfile->dont_repeat_files;
> +      new->fname = savestring (ip->fname);
> +      new->control_macro = 0;
> +      new->got_name_map = 0;
> +      new->c_system_include_path = 0;
> +      pfile->dont_repeat_files = new;
> +    }
> +
>    if (!strncmp (buf, "implementation", 14)) {
>      /* Be quiet about `#pragma implementation' for a file only if it hasn't
>         been included yet.  */
> @@ -5270,444 +4987,6 @@
>    return 1;
>  }
>
> -
> -/* Maintain and search list of included files, for #import.  */
> -
> -/* Hash a file name for import_hash_table.  */
> -
> -static int
> -import_hash (f)
> -     char *f;
> -{
> -  int val = 0;
> -
> -  while (*f) val += *f++;
> -  return (val%IMPORT_HASH_SIZE);
> -}
> -
> -/* Search for file FILENAME in import_hash_table.
> -   Return -2 if found, either a matching name or a matching inode.
> -   Otherwise, open the file and return a file descriptor if successful
> -   or -1 if unsuccessful.  */
> -
> -static int
> -lookup_import (pfile, filename, searchptr)
> -     cpp_reader *pfile;
> -     char *filename;
> -     struct file_name_list *searchptr;
> -{
> -  struct import_file *i;
> -  int h;
> -  int hashval;
> -  struct stat sb;
> -  int fd;
> -
> -  hashval = import_hash (filename);
> -
> -  /* Attempt to find file in list of already included files */
> -  i = pfile->import_hash_table[hashval];
> -
> -  while (i) {
> -    if (!strcmp (filename, i->name))
> -      return -2;               /* return found */
> -    i = i->next;
> -  }
> -  /* Open it and try a match on inode/dev */
> -  fd = open_include_file (pfile, filename, searchptr);
> -  if (fd < 0)
> -    return fd;
> -  fstat (fd, &sb);
> -  for (h = 0; h < IMPORT_HASH_SIZE; h++) {
> -    i = pfile->import_hash_table[h];
> -    while (i) {
> -      /* Compare the inode and the device.
> -        Supposedly on some systems the inode is not a scalar.  */
> -      if (!bcmp ((char *) &i->inode, (char *) &sb.st_ino, sizeof (sb.st_ino))
> -         && i->dev == sb.st_dev) {
> -        close (fd);
> -        return -2;             /* return found */
> -      }
> -      i = i->next;
> -    }
> -  }
> -  return fd;                   /* Not found, return open file */
> -}
> -
> -/* Add the file FNAME, open on descriptor FD, to import_hash_table.  */
> -
> -static void
> -add_import (pfile, fd, fname)
> -     cpp_reader *pfile;
> -     int fd;
> -     char *fname;
> -{
> -  struct import_file *i;
> -  int hashval;
> -  struct stat sb;
> -
> -  hashval = import_hash (fname);
> -  fstat (fd, &sb);
> -  i = (struct import_file *)xmalloc (sizeof (struct import_file));
> -  i->name = (char *)xmalloc (strlen (fname)+1);
> -  strcpy (i->name, fname);
> -  bcopy ((char *) &sb.st_ino, (char *) &i->inode, sizeof (sb.st_ino));
> -  i->dev = sb.st_dev;
> -  i->next = pfile->import_hash_table[hashval];
> -  pfile->import_hash_table[hashval] = i;
> -}
> -
> -/* The file_name_map structure holds a mapping of file names for a
> -   particular directory.  This mapping is read from the file named
> -   FILE_NAME_MAP_FILE in that directory.  Such a file can be used to
> -   map filenames on a file system with severe filename restrictions,
> -   such as DOS.  The format of the file name map file is just a series
> -   of lines with two tokens on each line.  The first token is the name
> -   to map, and the second token is the actual name to use.  */
> -
> -struct file_name_map
> -{
> -  struct file_name_map *map_next;
> -  char *map_from;
> -  char *map_to;
> -};
> -
> -#define FILE_NAME_MAP_FILE "header.gcc"
> -
> -/* Read a space delimited string of unlimited length from a stdio
> -   file.  */
> -
> -static char *
> -read_filename_string (ch, f)
> -     int ch;
> -     FILE *f;
> -{
> -  char *alloc, *set;
> -  int len;
> -
> -  len = 20;
> -  set = alloc = xmalloc (len + 1);
> -  if (! is_space[ch])
> -    {
> -      *set++ = ch;
> -      while ((ch = getc (f)) != EOF && ! is_space[ch])
> -       {
> -         if (set - alloc == len)
> -           {
> -             len *= 2;
> -             alloc = xrealloc (alloc, len + 1);
> -             set = alloc + len / 2;
> -           }
> -         *set++ = ch;
> -       }
> -    }
> -  *set = '\0';
> -  ungetc (ch, f);
> -  return alloc;
> -}
> -
> -/* This structure holds a linked list of file name maps, one per directory.  */
> -
> -struct file_name_map_list
> -{
> -  struct file_name_map_list *map_list_next;
> -  char *map_list_name;
> -  struct file_name_map *map_list_map;
> -};
> -
> -/* Read the file name map file for DIRNAME.  */
> -
> -static struct file_name_map *
> -read_name_map (pfile, dirname)
> -     cpp_reader *pfile;
> -     char *dirname;
> -{
> -  register struct file_name_map_list *map_list_ptr;
> -  char *name;
> -  FILE *f;
> -
> -  for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
> -       map_list_ptr = map_list_ptr->map_list_next)
> -    if (! strcmp (map_list_ptr->map_list_name, dirname))
> -      return map_list_ptr->map_list_map;
> -
> -  map_list_ptr = ((struct file_name_map_list *)
> -                 xmalloc (sizeof (struct file_name_map_list)));
> -  map_list_ptr->map_list_name = savestring (dirname);
> -  map_list_ptr->map_list_map = NULL;
> -
> -  name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
> -  strcpy (name, dirname);
> -  if (*dirname)
> -    strcat (name, "/");
> -  strcat (name, FILE_NAME_MAP_FILE);
> -  f = fopen (name, "r");
> -  if (!f)
> -    map_list_ptr->map_list_map = NULL;
> -  else
> -    {
> -      int ch;
> -      int dirlen = strlen (dirname);
> -
> -      while ((ch = getc (f)) != EOF)
> -       {
> -         char *from, *to;
> -         struct file_name_map *ptr;
> -
> -         if (is_space[ch])
> -           continue;
> -         from = read_filename_string (ch, f);
> -         while ((ch = getc (f)) != EOF && is_hor_space[ch])
> -           ;
> -         to = read_filename_string (ch, f);
> -
> -         ptr = ((struct file_name_map *)
> -                xmalloc (sizeof (struct file_name_map)));
> -         ptr->map_from = from;
> -
> -         /* Make the real filename absolute.  */
> -         if (*to == '/')
> -           ptr->map_to = to;
> -         else
> -           {
> -             ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
> -             strcpy (ptr->map_to, dirname);
> -             ptr->map_to[dirlen] = '/';
> -             strcpy (ptr->map_to + dirlen + 1, to);
> -             free (to);
> -           }
> -
> -         ptr->map_next = map_list_ptr->map_list_map;
> -         map_list_ptr->map_list_map = ptr;
> -
> -         while ((ch = getc (f)) != '\n')
> -           if (ch == EOF)
> -             break;
> -       }
> -      fclose (f);
> -    }
> -
> -  map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
> -  CPP_OPTIONS (pfile)->map_list = map_list_ptr;
> -
> -  return map_list_ptr->map_list_map;
> -}
> -
> -/* Try to open include file FILENAME.  SEARCHPTR is the directory
> -   being tried from the include file search path.  This function maps
> -   filenames on file systems based on information read by
> -   read_name_map.  */
> -
> -static int
> -open_include_file (pfile, filename, searchptr)
> -     cpp_reader *pfile;
> -     char *filename;
> -     struct file_name_list *searchptr;
> -{
> -  if (CPP_OPTIONS (pfile)->remap)
> -    {
> -      register struct file_name_map *map;
> -      register char *from;
> -      char *p, *dir;
> -
> -      if (searchptr && ! searchptr->got_name_map)
> -       {
> -         searchptr->name_map = read_name_map (pfile,
> -                                              searchptr->fname
> -                                              ? searchptr->fname : ".");
> -         searchptr->got_name_map = 1;
> -       }
> -
> -      /* First check the mapping for the directory we are using.  */
> -      if (searchptr && searchptr->name_map)
> -       {
> -         from = filename;
> -         if (searchptr->fname)
> -           from += strlen (searchptr->fname) + 1;
> -         for (map = searchptr->name_map; map; map = map->map_next)
> -           {
> -             if (! strcmp (map->map_from, from))
> -               {
> -                 /* Found a match.  */
> -                 return open (map->map_to, O_RDONLY, 0666);
> -               }
> -           }
> -       }
> -
> -      /* Try to find a mapping file for the particular directory we are
> -        looking in.  Thus #include <sys/types.h> will look up sys/types.h
> -        in /usr/include/header.gcc and look up types.h in
> -        /usr/include/sys/header.gcc.  */
> -      p = rindex (filename, '/');
> -      if (! p)
> -       p = filename;
> -      if (searchptr
> -         && searchptr->fname
> -         && strlen (searchptr->fname) == (size_t) (p - filename)
> -         && ! strncmp (searchptr->fname, filename, p - filename))
> -       {
> -         /* FILENAME is in SEARCHPTR, which we've already checked.  */
> -         return open (filename, O_RDONLY, 0666);
> -       }
> -
> -      if (p == filename)
> -       {
> -         dir = ".";
> -         from = filename;
> -       }
> -      else
> -       {
> -         dir = (char *) alloca (p - filename + 1);
> -         bcopy (filename, dir, p - filename);
> -         dir[p - filename] = '\0';
> -         from = p + 1;
> -       }
> -      for (map = read_name_map (pfile, dir); map; map = map->map_next)
> -       if (! strcmp (map->map_from, from))
> -         return open (map->map_to, O_RDONLY, 0666);
> -    }
> -
> -  return open (filename, O_RDONLY, 0666);
> -}
> -
> -/* Process the contents of include file FNAME, already open on descriptor F,
> -   with output to OP.
> -   SYSTEM_HEADER_P is 1 if this file resides in any one of the known
> -   "system" include directories (as decided by the `is_system_include'
> -   function above).
> -   DIRPTR is the link in the dir path through which this file was found,
> -   or 0 if the file name was absolute or via the current directory.
> -   Return 1 on success, 0 on failure.
> -
> -   The caller is responsible for the cpp_push_buffer.  */
> -
> -static int
> -finclude (pfile, f, fname, system_header_p, dirptr)
> -     cpp_reader *pfile;
> -     int f;
> -     char *fname;
> -     int system_header_p;
> -     struct file_name_list *dirptr;
> -{
> -  struct stat st;
> -  size_t st_size;
> -  long i;
> -  int length;
> -  cpp_buffer *fp;                      /* For input stack frame */
> -#if 0
> -  int missing_newline = 0;
> -#endif
> -
> -  if (fstat (f, &st) < 0)
> -    {
> -      cpp_perror_with_name (pfile, fname);
> -      close (f);
> -      cpp_pop_buffer (pfile);
> -      return 0;
> -    }
> -
> -  fp = CPP_BUFFER (pfile);
> -  fp->nominal_fname = fp->fname = fname;
> -#if 0
> -  fp->length = 0;
> -#endif
> -  fp->dir = dirptr;
> -  fp->system_header_p = system_header_p;
> -  fp->lineno = 1;
> -  fp->colno = 1;
> -  fp->cleanup = file_cleanup;
> -
> -  if (S_ISREG (st.st_mode)) {
> -    st_size = (size_t) st.st_size;
> -    if (st_size != st.st_size || st_size + 2 < st_size) {
> -      cpp_error (pfile, "file `%s' too large", fname);
> -      close (f);
> -      return 0;
> -    }
> -    fp->buf = (U_CHAR *) xmalloc (st_size + 2);
> -    fp->alimit = fp->buf + st_size + 2;
> -    fp->cur = fp->buf;
> -
> -    /* Read the file contents, knowing that st_size is an upper bound
> -       on the number of bytes we can read.  */
> -    length = safe_read (f, fp->buf, st_size);
> -    fp->rlimit = fp->buf + length;
> -    if (length < 0) goto nope;
> -  }
> -  else if (S_ISDIR (st.st_mode)) {
> -    cpp_error (pfile, "directory `%s' specified in #include", fname);
> -    close (f);
> -    return 0;
> -  } else {
> -    /* Cannot count its file size before reading.
> -       First read the entire file into heap and
> -       copy them into buffer on stack.  */
> -
> -    size_t bsize = 2000;
> -
> -    st_size = 0;
> -    fp->buf = (U_CHAR *) xmalloc (bsize + 2);
> -
> -    for (;;) {
> -      i = safe_read (f, fp->buf + st_size, bsize - st_size);
> -      if (i < 0)
> -       goto nope;      /* error! */
> -      st_size += i;
> -      if (st_size != bsize)
> -       break;  /* End of file */
> -      bsize *= 2;
> -      fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
> -    }
> -    fp->cur = fp->buf;
> -    length = st_size;
> -  }
> -
> -  if ((length > 0 && fp->buf[length - 1] != '\n')
> -      /* Backslash-newline at end is not good enough.  */
> -      || (length > 1 && fp->buf[length - 2] == '\\')) {
> -    fp->buf[length++] = '\n';
> -#if 0
> -    missing_newline = 1;
> -#endif
> -  }
> -  fp->buf[length] = '\0';
> -  fp->rlimit = fp->buf + length;
> -
> -  /* Close descriptor now, so nesting does not use lots of descriptors.  */
> -  close (f);
> -
> -  /* Must do this before calling trigraph_pcp, so that the correct file name
> -     will be printed in warning messages.  */
> -
> -  pfile->input_stack_listing_current = 0;
> -
> -#if 0
> -  if (!no_trigraphs)
> -    trigraph_pcp (fp);
> -#endif
> -
> -#if 0
> -  rescan (op, 0);
> -
> -  if (missing_newline)
> -    fp->lineno--;
> -
> -  if (CPP_PEDANTIC (pfile) && missing_newline)
> -    pedwarn ("file does not end in newline");
> -
> -  indepth--;
> -  input_file_stack_tick++;
> -  free (fp->buf);
> -#endif
> -  return 1;
> -
> - nope:
> -
> -  cpp_perror_with_name (pfile, fname);
> -  close (f);
> -  free (fp->buf);
> -  return 1;
> -}
> -
>  /* This is called after options have been processed.
>   * Check options for consistency, and setup for processing input
>   * from the file named FNAME.  (Use standard input if FNAME==NULL.)
> @@ -7297,45 +6576,11 @@
>      tokens = next;
>    }
>  }
> -
> -/* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
> -   retrying if necessary.  If MAX_READ_LEN is defined, read at most
> -   that bytes at a time.  Return a negative value if an error occurs,
> -   otherwise return the actual number of bytes read,
> -   which must be LEN unless end-of-file was reached.  */
> -
> -static int
> -safe_read (desc, ptr, len)
> -     int desc;
> -     char *ptr;
> -     int len;
> -{
> -  int left, rcount, nchars;
> -
> -  left = len;
> -  while (left > 0) {
> -    rcount = left;
> -#ifdef MAX_READ_LEN
> -    if (rcount > MAX_READ_LEN)
> -      rcount = MAX_READ_LEN;
> -#endif
> -    nchars = read (desc, ptr, rcount);
> -    if (nchars < 0)
> -      {
> -#ifdef EINTR
> -       if (errno == EINTR)
> -         continue;
> -#endif
> -       return nchars;
> -      }
> -    if (nchars == 0)
> -      break;
> -    ptr += nchars;
> -    left -= nchars;
> -  }
> -  return len - left;
> -}
>
> +/* FIXME: savestring() should be renamed strdup() and both should
> +   be moved into cppalloc.c.  We can't do that right now because
> +   then we'd get multiple-symbol clashes with toplev.c and several
> +   other people. */
>  static char *
>  xcalloc (number, size)
>       unsigned number, size;
> @@ -7346,7 +6591,7 @@
>    return ptr;
>  }
>
> -static char *
> +char *
>  savestring (input)
>       char *input;
>  {
> ============================================================
> Index: cpplib.h
> --- cpplib.h    1998/10/11 00:05:11     1.10
> +++ cpplib.h    1998/10/25 20:01:09
> @@ -510,6 +510,27 @@
>  #define CPP_PEDANTIC(PFILE) (CPP_OPTIONS (PFILE)->pedantic)
>  #define CPP_PRINT_DEPS(PFILE) (CPP_OPTIONS (PFILE)->print_deps)
>
> +struct file_name_list
> +  {
> +    struct file_name_list *next;
> +    char *fname;
> +    /* If the following is nonzero, it is a macro name.
> +       Don't include the file again if that macro is defined.  */
> +    U_CHAR *control_macro;
> +    /* If the following is nonzero, it is a C-language system include
> +       directory.  */
> +    int c_system_include_path;
> +    /* Mapping of file names for this directory.  */
> +    struct file_name_map *name_map;
> +    /* Non-zero if name_map is valid.  */
> +    int got_name_map;
> +  };
> +
> +/* If a buffer's dir field is SELF_DIR_DUMMY, it means the file was found
> +   via the same directory as the file that #included it.  */
> +#define SELF_DIR_DUMMY ((struct file_name_list *) (~0))
> +
> +
>  /* Name under which this program was invoked.  */
>
>  extern char *progname;
> @@ -623,6 +644,8 @@
>  };
>
>  extern unsigned char is_idchar[256];
> +extern unsigned char is_hor_space[256];
> +extern unsigned char is_space[256];
>
>  /* Stack of conditionals currently in progress
>     (including both successful and failing conditionals).  */
> @@ -685,6 +708,25 @@
>  extern void cpp_file_line_for_message PROTO ((cpp_reader *, char *, int, int));
>  extern void cpp_print_containing_files PROTO ((cpp_reader *));
>
> +/* In cppfiles.c */
> +extern void append_include_chain       PROTO ((cpp_reader *,
> +                                               struct file_name_list *,
> +                                               struct file_name_list *));
> +extern int finclude                    PROTO ((cpp_reader *, int, char *,
> +                                               int, struct file_name_list *));
> +extern int find_include_file           PROTO ((cpp_reader *, char *,
> +                                               unsigned long, char *, int,
> +                                               struct file_name_list *,
> +                                               struct file_name_list **));
> +extern void deps_output                        PROTO ((cpp_reader *, char *, int));
> +
> +/* Bleargh. */
> +extern char *savestring                        PROTO ((char *));
> +#ifndef INCLUDE_LEN_FUDGE
> +#define INCLUDE_LEN_FUDGE 0
> +#endif
> +
> +
>  #ifdef __cplusplus
>  }
>  #endif
> ============================================================
> Index: cppfiles.c
> --- cppfiles.c  Wed Dec 31 19:00:00 1969
> +++ cppfiles.c  Sun Oct 25 14:31:39 1998        1.1
> @@ -0,0 +1,1023 @@
> +/* Part of CPP library.  (include file handling)
> +   Copyright (C) 1986, 87, 89, 92 - 95, 1998 Free Software Foundation, Inc.
> +   Written by Per Bothner, 1994.
> +   Based on CCCP program by Paul Rubin, June 1986
> +   Adapted to ANSI C, Richard Stallman, Jan 1987
> +   Split out of cpplib.c, Zack Weinberg, Oct 1998
> +
> +This program is free software; you can redistribute it and/or modify it
> +under the terms of the GNU General Public License as published by the
> +Free Software Foundation; either version 2, or (at your option) any
> +later version.
> +
> +This program is distributed in the hope that it will be useful,
> +but WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +GNU General Public License for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with this program; if not, write to the Free Software
> +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> +
> + In other words, you are welcome to use, share and improve this program.
> + You are forbidden to forbid anyone else to use, share and improve
> + what you give them.   Help stamp out software-hoarding!  */
> +
> +#include "config.h"
> +#include "system.h"
> +#include "gansidecl.h"
> +#include "cpplib.h"
> +
> +/* The entry points to this file are: find_include_file, finclude,
> +   append_include_chain, deps_output, and file_cleanup.
> +   file_cleanup is only called through CPP_BUFFER(pfile)->cleanup,
> +   so it's static anyway. */
> +
> +static void add_import                 PROTO ((cpp_reader *, int, char *));
> +static int lookup_import               PROTO ((cpp_reader *, char *,
> +                                               struct file_name_list *));
> +static int redundant_include_p         PROTO ((cpp_reader *, char *));
> +static struct file_name_map *read_name_map     PROTO ((cpp_reader *, char *));
> +static char *read_filename_string      PROTO ((int, FILE *));
> +static int open_include_file           PROTO ((cpp_reader *, char *,
> +                                               struct file_name_list *));
> +static int safe_read                   PROTO ((int, char *, int));
> +
> +/* Not safe to prototype these. */
> +extern char *xmalloc();
> +extern char *xrealloc();
> +
> +/* Append a chain of `struct file_name_list's
> +   to the end of the main include chain.
> +   FIRST is the beginning of the chain to append, and LAST is the end.  */
> +
> +void
> +append_include_chain (pfile, first, last)
> +     cpp_reader *pfile;
> +     struct file_name_list *first, *last;
> +{
> +  struct cpp_options *opts = CPP_OPTIONS (pfile);
> +  struct file_name_list *dir;
> +
> +  if (!first || !last)
> +    return;
> +
> +  if (opts->include == 0)
> +    opts->include = first;
> +  else
> +    opts->last_include->next = first;
> +
> +  if (opts->first_bracket_include == 0)
> +    opts->first_bracket_include = first;
> +
> +  for (dir = first; ; dir = dir->next) {
> +    int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
> +    if (len > pfile->max_include_len)
> +      pfile->max_include_len = len;
> +    if (dir == last)
> +      break;
> +  }
> +
> +  last->next = NULL;
> +  opts->last_include = last;
> +}
> +
> +/* Add output to `deps_buffer' for the -M switch.
> +   STRING points to the text to be output.
> +   SPACER is ':' for targets, ' ' for dependencies, zero for text
> +   to be inserted literally.  */
> +
> +void
> +deps_output (pfile, string, spacer)
> +     cpp_reader *pfile;
> +     char *string;
> +     int spacer;
> +{
> +  int size;
> +
> +  if (!*string)
> +    return;
> +
> +#ifdef VMS
> +  hack_vms_include_specification (string);
> +#endif
> +
> +  size = strlen (string);
> +
> +#ifndef MAX_OUTPUT_COLUMNS
> +#define MAX_OUTPUT_COLUMNS 72
> +#endif
> +  if (spacer
> +      && pfile->deps_column > 0
> +      && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS)
> +    {
> +      deps_output (pfile, " \\\n  ", 0);
> +      pfile->deps_column = 0;
> +    }
> +
> +  if (pfile->deps_size + size + 8 > pfile->deps_allocated_size)
> +    {
> +      pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2;
> +      pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer,
> +                                             pfile->deps_allocated_size);
> +    }
> +  if (spacer == ' ' && pfile->deps_column > 0)
> +    pfile->deps_buffer[pfile->deps_size++] = ' ';
> +  bcopy (string, &pfile->deps_buffer[pfile->deps_size], size);
> +  pfile->deps_size += size;
> +  pfile->deps_column += size;
> +  if (spacer == ':')
> +    pfile->deps_buffer[pfile->deps_size++] = ':';
> +  pfile->deps_buffer[pfile->deps_size] = 0;
> +}
> +
> +static int
> +file_cleanup (pbuf, pfile)
> +     cpp_buffer *pbuf;
> +     cpp_reader *pfile ATTRIBUTE_UNUSED;
> +{
> +  if (pbuf->buf)
> +    {
> +      free (pbuf->buf);
> +      pbuf->buf = 0;
> +    }
> +  return 0;
> +}
> +
> +int
> +find_include_file (pfile, fbeg, flen, fname,
> +                  importing, search_start, foundhere)
> +     cpp_reader *pfile;
> +     char *fbeg;
> +     unsigned long flen;
> +     char *fname;
> +     int importing;
> +     struct file_name_list *search_start;
> +     struct file_name_list **foundhere;
> +{
> +  struct file_name_list *searchptr;
> +  int f;
> +
> +  /* If specified file name is absolute, just open it.  */
> +
> +  if (*fbeg == '/')
> +  {
> +    strcpy (fname, fbeg);
> +#ifdef VMS
> +    hack_vms_include_specification (fname);
> +#endif
> +    if (redundant_include_p (pfile, fname))
> +      return -2;
> +    if (importing)
> +      f = lookup_import (pfile, fname, NULL_PTR);
> +    else
> +      f = open_include_file (pfile, fname, NULL_PTR);
> +    if (f == -2)
> +      return -2;       /* Already included this file */
> +  }
> +  else
> +  {
> +    /* Search directory path, trying to open the file.
> +       Copy each filename tried into FNAME.  */
> +
> +    for (searchptr = search_start; searchptr; searchptr = searchptr->next)
> +    {
> +      unsigned int l = 0;
> +      if (searchptr->fname)
> +      {
> +       /* The empty string in a search path is ignored.
> +          This makes it possible to turn off entirely
> +          a standard piece of the list.  */
> +       if (searchptr->fname[0] == 0)
> +         continue;
> +
> +       l = strlen (searchptr->fname);
> +
> +       bcopy (searchptr->fname, fname, l);
> +       fname[l++] = '/';
> +      }
> +
> +      bcopy (fbeg, &fname[l], flen);
> +      fname[flen+l] = '\0';
> +#ifdef VMS
> +      hack_vms_include_specification (fname);
> +#endif /* VMS */
> +      /* ??? There are currently 3 separate mechanisms for avoiding processing
> +        of redundant include files: #import, #pragma once, and
> +        redundant_include_p.  It would be nice if they were unified.  */
> +      if (redundant_include_p (pfile, fname))
> +       return -2;
> +      if (importing)
> +       f = lookup_import (pfile, fname, searchptr);
> +      else
> +       f = open_include_file (pfile, fname, searchptr);
> +      if (f == -2)
> +       return -2;                      /* Already included this file */
> +#ifdef EACCES
> +      else if (f == -1 && errno == EACCES)
> +       cpp_warning (pfile, "Header file %s exists, but is not readable",
> +                    fname);
> +#endif
> +      if (f >= 0)
> +       break;
> +    }
> +  }
> +
> +  if (f < 0)
> +    {
> +      /* A file that was not found.  */
> +      bcopy (fbeg, fname, flen);
> +      fname[flen] = 0;
> +
> +      return -1;
> +    }
> +  else
> +    {
> +      /* Check to see if this include file is a once-only include file.
> +        If so, give up.  */
> +
> +      struct file_name_list *ptr;
> +
> +      for (ptr = pfile->dont_repeat_files; ptr; ptr = ptr->next)
> +         if (!strcmp (ptr->fname, fname))
> +           {
> +             close (f);
> +             return -2;                /* This file was once'd.  */
> +           }
> +    }
> +
> +    /* Record file on "seen" list for #import.  */
> +    add_import (pfile, f, fname);
> +
> +    *foundhere = searchptr;
> +    return f;
> +}
> +
> +/* Return nonzero if there is no need to include file NAME
> +   because it has already been included and it contains a conditional
> +   to make a repeated include do nothing.  */
> +
> +static int
> +redundant_include_p (pfile, name)
> +     cpp_reader *pfile;
> +     char *name;
> +{
> +  struct file_name_list *l = pfile->all_include_files;
> +  for (; l; l = l->next)
> +    if (! strcmp (name, l->fname)
> +       && l->control_macro
> +       && cpp_lookup (pfile, l->control_macro, -1, -1))
> +      return 1;
> +  return 0;
> +}
> +
> +
> +
> +/* Maintain and search list of included files, for #import.  */
> +
> +/* Hash a file name for import_hash_table.  */
> +
> +static int
> +import_hash (f)
> +     char *f;
> +{
> +  int val = 0;
> +
> +  while (*f) val += *f++;
> +  return (val%IMPORT_HASH_SIZE);
> +}
> +
> +/* Search for file FILENAME in import_hash_table.
> +   Return -2 if found, either a matching name or a matching inode.
> +   Otherwise, open the file and return a file descriptor if successful
> +   or -1 if unsuccessful.  */
> +
> +static int
> +lookup_import (pfile, filename, searchptr)
> +     cpp_reader *pfile;
> +     char *filename;
> +     struct file_name_list *searchptr;
> +{
> +  struct import_file *i;
> +  int h;
> +  int hashval;
> +  struct stat sb;
> +  int fd;
> +
> +  hashval = import_hash (filename);
> +
> +  /* Attempt to find file in list of already included files */
> +  i = pfile->import_hash_table[hashval];
> +
> +  while (i) {
> +    if (!strcmp (filename, i->name))
> +      return -2;               /* return found */
> +    i = i->next;
> +  }
> +  /* Open it and try a match on inode/dev */
> +  fd = open_include_file (pfile, filename, searchptr);
> +  if (fd < 0)
> +    return fd;
> +  fstat (fd, &sb);
> +  for (h = 0; h < IMPORT_HASH_SIZE; h++) {
> +    i = pfile->import_hash_table[h];
> +    while (i) {
> +      /* Compare the inode and the device.
> +        Supposedly on some systems the inode is not a scalar.  */
> +      if (!bcmp ((char *) &i->inode, (char *) &sb.st_ino, sizeof (sb.st_ino))
> +         && i->dev == sb.st_dev) {
> +        close (fd);
> +        return -2;             /* return found */
> +      }
> +      i = i->next;
> +    }
> +  }
> +  return fd;                   /* Not found, return open file */
> +}
> +
> +/* Add the file FNAME, open on descriptor FD, to import_hash_table.  */
> +
> +static void
> +add_import (pfile, fd, fname)
> +     cpp_reader *pfile;
> +     int fd;
> +     char *fname;
> +{
> +  struct import_file *i;
> +  int hashval;
> +  struct stat sb;
> +
> +  hashval = import_hash (fname);
> +  fstat (fd, &sb);
> +  i = (struct import_file *)xmalloc (sizeof (struct import_file));
> +  i->name = (char *)xmalloc (strlen (fname)+1);
> +  strcpy (i->name, fname);
> +  bcopy ((char *) &sb.st_ino, (char *) &i->inode, sizeof (sb.st_ino));
> +  i->dev = sb.st_dev;
> +  i->next = pfile->import_hash_table[hashval];
> +  pfile->import_hash_table[hashval] = i;
> +}
> +
> +/* The file_name_map structure holds a mapping of file names for a
> +   particular directory.  This mapping is read from the file named
> +   FILE_NAME_MAP_FILE in that directory.  Such a file can be used to
> +   map filenames on a file system with severe filename restrictions,
> +   such as DOS.  The format of the file name map file is just a series
> +   of lines with two tokens on each line.  The first token is the name
> +   to map, and the second token is the actual name to use.  */
> +
> +struct file_name_map
> +{
> +  struct file_name_map *map_next;
> +  char *map_from;
> +  char *map_to;
> +};
> +
> +#define FILE_NAME_MAP_FILE "header.gcc"
> +
> +/* Read a space delimited string of unlimited length from a stdio
> +   file.  */
> +
> +static char *
> +read_filename_string (ch, f)
> +     int ch;
> +     FILE *f;
> +{
> +  char *alloc, *set;
> +  int len;
> +
> +  len = 20;
> +  set = alloc = xmalloc (len + 1);
> +  if (! is_space[ch])
> +    {
> +      *set++ = ch;
> +      while ((ch = getc (f)) != EOF && ! is_space[ch])
> +       {
> +         if (set - alloc == len)
> +           {
> +             len *= 2;
> +             alloc = xrealloc (alloc, len + 1);
> +             set = alloc + len / 2;
> +           }
> +         *set++ = ch;
> +       }
> +    }
> +  *set = '\0';
> +  ungetc (ch, f);
> +  return alloc;
> +}
> +
> +/* This structure holds a linked list of file name maps, one per directory.  */
> +
> +struct file_name_map_list
> +{
> +  struct file_name_map_list *map_list_next;
> +  char *map_list_name;
> +  struct file_name_map *map_list_map;
> +};
> +
> +/* Read the file name map file for DIRNAME.  */
> +
> +static struct file_name_map *
> +read_name_map (pfile, dirname)
> +     cpp_reader *pfile;
> +     char *dirname;
> +{
> +  register struct file_name_map_list *map_list_ptr;
> +  char *name;
> +  FILE *f;
> +
> +  for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
> +       map_list_ptr = map_list_ptr->map_list_next)
> +    if (! strcmp (map_list_ptr->map_list_name, dirname))
> +      return map_list_ptr->map_list_map;
> +
> +  map_list_ptr = ((struct file_name_map_list *)
> +                 xmalloc (sizeof (struct file_name_map_list)));
> +  map_list_ptr->map_list_name = savestring (dirname);
> +  map_list_ptr->map_list_map = NULL;
> +
> +  name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
> +  strcpy (name, dirname);
> +  if (*dirname)
> +    strcat (name, "/");
> +  strcat (name, FILE_NAME_MAP_FILE);
> +  f = fopen (name, "r");
> +  if (!f)
> +    map_list_ptr->map_list_map = NULL;
> +  else
> +    {
> +      int ch;
> +      int dirlen = strlen (dirname);
> +
> +      while ((ch = getc (f)) != EOF)
> +       {
> +         char *from, *to;
> +         struct file_name_map *ptr;
> +
> +         if (is_space[ch])
> +           continue;
> +         from = read_filename_string (ch, f);
> +         while ((ch = getc (f)) != EOF && is_hor_space[ch])
> +           ;
> +         to = read_filename_string (ch, f);
> +
> +         ptr = ((struct file_name_map *)
> +                xmalloc (sizeof (struct file_name_map)));
> +         ptr->map_from = from;
> +
> +         /* Make the real filename absolute.  */
> +         if (*to == '/')
> +           ptr->map_to = to;
> +         else
> +           {
> +             ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
> +             strcpy (ptr->map_to, dirname);
> +             ptr->map_to[dirlen] = '/';
> +             strcpy (ptr->map_to + dirlen + 1, to);
> +             free (to);
> +           }
> +
> +         ptr->map_next = map_list_ptr->map_list_map;
> +         map_list_ptr->map_list_map = ptr;
> +
> +         while ((ch = getc (f)) != '\n')
> +           if (ch == EOF)
> +             break;
> +       }
> +      fclose (f);
> +    }
> +
> +  map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
> +  CPP_OPTIONS (pfile)->map_list = map_list_ptr;
> +
> +  return map_list_ptr->map_list_map;
> +}
> +
> +/* Try to open include file FILENAME.  SEARCHPTR is the directory
> +   being tried from the include file search path.  This function maps
> +   filenames on file systems based on information read by
> +   read_name_map.  */
> +
> +static int
> +open_include_file (pfile, filename, searchptr)
> +     cpp_reader *pfile;
> +     char *filename;
> +     struct file_name_list *searchptr;
> +{
> +  if (CPP_OPTIONS (pfile)->remap)
> +    {
> +      register struct file_name_map *map;
> +      register char *from;
> +      char *p, *dir;
> +
> +      if (searchptr && ! searchptr->got_name_map)
> +       {
> +         searchptr->name_map = read_name_map (pfile,
> +                                              searchptr->fname
> +                                              ? searchptr->fname : ".");
> +         searchptr->got_name_map = 1;
> +       }
> +
> +      /* First check the mapping for the directory we are using.  */
> +      if (searchptr && searchptr->name_map)
> +       {
> +         from = filename;
> +         if (searchptr->fname)
> +           from += strlen (searchptr->fname) + 1;
> +         for (map = searchptr->name_map; map; map = map->map_next)
> +           {
> +             if (! strcmp (map->map_from, from))
> +               {
> +                 /* Found a match.  */
> +                 return open (map->map_to, O_RDONLY, 0666);
> +               }
> +           }
> +       }
> +
> +      /* Try to find a mapping file for the particular directory we are
> +        looking in.  Thus #include <sys/types.h> will look up sys/types.h
> +        in /usr/include/header.gcc and look up types.h in
> +        /usr/include/sys/header.gcc.  */
> +      p = rindex (filename, '/');
> +      if (! p)
> +       p = filename;
> +      if (searchptr
> +         && searchptr->fname
> +         && strlen (searchptr->fname) == (size_t) (p - filename)
> +         && ! strncmp (searchptr->fname, filename, p - filename))
> +       {
> +         /* FILENAME is in SEARCHPTR, which we've already checked.  */
> +         return open (filename, O_RDONLY, 0666);
> +       }
> +
> +      if (p == filename)
> +       {
> +         dir = ".";
> +         from = filename;
> +       }
> +      else
> +       {
> +         dir = (char *) alloca (p - filename + 1);
> +         bcopy (filename, dir, p - filename);
> +         dir[p - filename] = '\0';
> +         from = p + 1;
> +       }
> +      for (map = read_name_map (pfile, dir); map; map = map->map_next)
> +       if (! strcmp (map->map_from, from))
> +         return open (map->map_to, O_RDONLY, 0666);
> +    }
> +
> +  return open (filename, O_RDONLY, 0666);
> +}
> +
> +/* Process the contents of include file FNAME, already open on descriptor F,
> +   with output to OP.
> +   SYSTEM_HEADER_P is 1 if this file resides in any one of the known
> +   "system" include directories (as decided by the `is_system_include'
> +   function above).
> +   DIRPTR is the link in the dir path through which this file was found,
> +   or 0 if the file name was absolute or via the current directory.
> +   Return 1 on success, 0 on failure.
> +
> +   The caller is responsible for the cpp_push_buffer.  */
> +
> +int
> +finclude (pfile, f, fname, system_header_p, dirptr)
> +     cpp_reader *pfile;
> +     int f;
> +     char *fname;
> +     int system_header_p;
> +     struct file_name_list *dirptr;
> +{
> +  struct stat st;
> +  size_t st_size;
> +  long i;
> +  int length;
> +  cpp_buffer *fp;                      /* For input stack frame */
> +#if 0
> +  int missing_newline = 0;
> +#endif
> +
> +  if (fstat (f, &st) < 0)
> +    {
> +      cpp_perror_with_name (pfile, fname);
> +      close (f);
> +      cpp_pop_buffer (pfile);
> +      return 0;
> +    }
> +
> +  fp = CPP_BUFFER (pfile);
> +  fp->nominal_fname = fp->fname = fname;
> +#if 0
> +  fp->length = 0;
> +#endif
> +  fp->dir = dirptr;
> +  fp->system_header_p = system_header_p;
> +  fp->lineno = 1;
> +  fp->colno = 1;
> +  fp->cleanup = file_cleanup;
> +
> +  if (S_ISREG (st.st_mode)) {
> +    st_size = (size_t) st.st_size;
> +    if (st_size != st.st_size || st_size + 2 < st_size) {
> +      cpp_error (pfile, "file `%s' too large", fname);
> +      close (f);
> +      return 0;
> +    }
> +    fp->buf = (U_CHAR *) xmalloc (st_size + 2);
> +    fp->alimit = fp->buf + st_size + 2;
> +    fp->cur = fp->buf;
> +
> +    /* Read the file contents, knowing that st_size is an upper bound
> +       on the number of bytes we can read.  */
> +    length = safe_read (f, fp->buf, st_size);
> +    fp->rlimit = fp->buf + length;
> +    if (length < 0) goto nope;
> +  }
> +  else if (S_ISDIR (st.st_mode)) {
> +    cpp_error (pfile, "directory `%s' specified in #include", fname);
> +    close (f);
> +    return 0;
> +  } else {
> +    /* Cannot count its file size before reading.
> +       First read the entire file into heap and
> +       copy them into buffer on stack.  */
> +
> +    size_t bsize = 2000;
> +
> +    st_size = 0;
> +    fp->buf = (U_CHAR *) xmalloc (bsize + 2);
> +
> +    for (;;) {
> +      i = safe_read (f, fp->buf + st_size, bsize - st_size);
> +      if (i < 0)
> +       goto nope;      /* error! */
> +      st_size += i;
> +      if (st_size != bsize)
> +       break;  /* End of file */
> +      bsize *= 2;
> +      fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
> +    }
> +    fp->cur = fp->buf;
> +    length = st_size;
> +  }
> +
> +  if ((length > 0 && fp->buf[length - 1] != '\n')
> +      /* Backslash-newline at end is not good enough.  */
> +      || (length > 1 && fp->buf[length - 2] == '\\')) {
> +    fp->buf[length++] = '\n';
> +#if 0
> +    missing_newline = 1;
> +#endif
> +  }
> +  fp->buf[length] = '\0';
> +  fp->rlimit = fp->buf + length;
> +
> +  /* Close descriptor now, so nesting does not use lots of descriptors.  */
> +  close (f);
> +
> +  /* Must do this before calling trigraph_pcp, so that the correct file name
> +     will be printed in warning messages.  */
> +
> +  pfile->input_stack_listing_current = 0;
> +
> +#if 0
> +  if (!no_trigraphs)
> +    trigraph_pcp (fp);
> +#endif
> +
> +#if 0
> +  rescan (op, 0);
> +
> +  if (missing_newline)
> +    fp->lineno--;
> +
> +  if (CPP_PEDANTIC (pfile) && missing_newline)
> +    pedwarn ("file does not end in newline");
> +
> +  indepth--;
> +  input_file_stack_tick++;
> +  free (fp->buf);
> +#endif
> +  return 1;
> +
> + nope:
> +
> +  cpp_perror_with_name (pfile, fname);
> +  close (f);
> +  free (fp->buf);
> +  return 1;
> +}
> +
> +/* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
> +   retrying if necessary.  If MAX_READ_LEN is defined, read at most
> +   that bytes at a time.  Return a negative value if an error occurs,
> +   otherwise return the actual number of bytes read,
> +   which must be LEN unless end-of-file was reached.  */
> +
> +static int
> +safe_read (desc, ptr, len)
> +     int desc;
> +     char *ptr;
> +     int len;
> +{
> +  int left, rcount, nchars;
> +
> +  left = len;
> +  while (left > 0) {
> +    rcount = left;
> +#ifdef MAX_READ_LEN
> +    if (rcount > MAX_READ_LEN)
> +      rcount = MAX_READ_LEN;
> +#endif
> +    nchars = read (desc, ptr, rcount);
> +    if (nchars < 0)
> +      {
> +#ifdef EINTR
> +       if (errno == EINTR)
> +         continue;
> +#endif
> +       return nchars;
> +      }
> +    if (nchars == 0)
> +      break;
> +    ptr += nchars;
> +    left -= nchars;
> +  }
> +  return len - left;
> +}
> +
> +#ifdef VMS
> +
> +/* Under VMS we need to fix up the "include" specification filename.
> +
> +   Rules for possible conversions
> +
> +       fullname                tried paths
> +
> +       name                    name
> +       ./dir/name              [.dir]name
> +       /dir/name               dir:name
> +       /name                   [000000]name, name
> +       dir/name                dir:[000000]name, dir:name, dir/name
> +       dir1/dir2/name          dir1:[dir2]name, dir1:[000000.dir2]name
> +       path:/name              path:[000000]name, path:name
> +       path:/dir/name          path:[000000.dir]name, path:[dir]name
> +       path:dir/name           path:[dir]name
> +       [path]:[dir]name        [path.dir]name
> +       path/[dir]name          [path.dir]name
> +
> +   The path:/name input is constructed when expanding <> includes. */
> +
> +
> +static void
> +hack_vms_include_specification (fullname)
> +     char *fullname;
> +{
> +  register char *basename, *unixname, *local_ptr, *first_slash;
> +  int f, check_filename_before_returning, must_revert;
> +  char Local[512];
> +
> +  check_filename_before_returning = 0;
> +  must_revert = 0;
> +  /* See if we can find a 1st slash. If not, there's no path information.  */
> +  first_slash = index (fullname, '/');
> +  if (first_slash == 0)
> +    return 0;                          /* Nothing to do!!! */
> +
> +  /* construct device spec if none given.  */
> +
> +  if (index (fullname, ':') == 0)
> +    {
> +
> +      /* If fullname has a slash, take it as device spec.  */
> +
> +      if (first_slash == fullname)
> +       {
> +         first_slash = index (fullname+1, '/');        /* 2nd slash ? */
> +         if (first_slash)
> +           *first_slash = ':';                         /* make device spec  */
> +         for (basename = fullname; *basename != 0; basename++)
> +           *basename = *(basename+1);                  /* remove leading slash  */
> +       }
> +      else if ((first_slash[-1] != '.')                /* keep ':/', './' */
> +           && (first_slash[-1] != ':')
> +           && (first_slash[-1] != ']'))        /* or a vms path  */
> +       {
> +         *first_slash = ':';
> +       }
> +      else if ((first_slash[1] == '[')         /* skip './' in './[dir'  */
> +           && (first_slash[-1] == '.'))
> +       fullname += 2;
> +    }
> +
> +  /* Get part after first ':' (basename[-1] == ':')
> +     or last '/' (basename[-1] == '/').  */
> +
> +  basename = base_name (fullname);
> +
> +  local_ptr = Local;                   /* initialize */
> +
> +  /* We are trying to do a number of things here.  First of all, we are
> +     trying to hammer the filenames into a standard format, such that later
> +     processing can handle them.
> +
> +     If the file name contains something like [dir.], then it recognizes this
> +     as a root, and strips the ".]".  Later processing will add whatever is
> +     needed to get things working properly.
> +
> +     If no device is specified, then the first directory name is taken to be
> +     a device name (or a rooted logical).  */
> +
> +  /* Point to the UNIX filename part (which needs to be fixed!)
> +     but skip vms path information.
> +     [basename != fullname since first_slash != 0].  */
> +
> +  if ((basename[-1] == ':')            /* vms path spec.  */
> +      || (basename[-1] == ']')
> +      || (basename[-1] == '>'))
> +    unixname = basename;
> +  else
> +    unixname = fullname;
> +
> +  if (*unixname == '/')
> +    unixname++;
> +
> +  /* If the directory spec is not rooted, we can just copy
> +     the UNIX filename part and we are done.  */
> +
> +  if (((basename - fullname) > 1)
> +     && (  (basename[-1] == ']')
> +        || (basename[-1] == '>')))
> +    {
> +      if (basename[-2] != '.')
> +       {
> +
> +       /* The VMS part ends in a `]', and the preceding character is not a `.'.
> +          -> PATH]:/name (basename = '/name', unixname = 'name')
> +          We strip the `]', and then splice the two parts of the name in the
> +          usual way.  Given the default locations for include files in cccp.c,
> +          we will only use this code if the user specifies alternate locations
> +          with the /include (-I) switch on the command line.  */
> +
> +         basename -= 1;        /* Strip "]" */
> +         unixname--;           /* backspace */
> +       }
> +      else
> +       {
> +
> +       /* The VMS part has a ".]" at the end, and this will not do.  Later
> +          processing will add a second directory spec, and this would be a syntax
> +          error.  Thus we strip the ".]", and thus merge the directory specs.
> +          We also backspace unixname, so that it points to a '/'.  This inhibits the
> +          generation of the 000000 root directory spec (which does not belong here
> +          in this case).  */
> +
> +         basename -= 2;        /* Strip ".]" */
> +         unixname--;           /* backspace */
> +       }
> +    }
> +
> +  else
> +
> +    {
> +
> +      /* We drop in here if there is no VMS style directory specification yet.
> +         If there is no device specification either, we make the first dir a
> +         device and try that.  If we do not do this, then we will be essentially
> +         searching the users default directory (as if they did a #include "asdf.h").
> +
> +         Then all we need to do is to push a '[' into the output string. Later
> +         processing will fill this in, and close the bracket.  */
> +
> +      if ((unixname != fullname)       /* vms path spec found.  */
> +        && (basename[-1] != ':'))
> +       *local_ptr++ = ':';             /* dev not in spec.  take first dir */
> +
> +      *local_ptr++ = '[';              /* Open the directory specification */
> +    }
> +
> +    if (unixname == fullname)          /* no vms dir spec.  */
> +      {
> +       must_revert = 1;
> +       if ((first_slash != 0)          /* unix dir spec.  */
> +           && (*unixname != '/')       /* not beginning with '/'  */
> +           && (*unixname != '.'))      /* or './' or '../'  */
> +         *local_ptr++ = '.';           /* dir is local !  */
> +      }
> +
> +  /* at this point we assume that we have the device spec, and (at least
> +     the opening "[" for a directory specification.  We may have directories
> +     specified already.
> +
> +     If there are no other slashes then the filename will be
> +     in the "root" directory.  Otherwise, we need to add
> +     directory specifications.  */
> +
> +  if (index (unixname, '/') == 0)
> +    {
> +      /* if no directories specified yet and none are following.  */
> +      if (local_ptr[-1] == '[')
> +       {
> +         /* Just add "000000]" as the directory string */
> +         strcpy (local_ptr, "000000]");
> +         local_ptr += strlen (local_ptr);
> +         check_filename_before_returning = 1; /* we might need to fool with this later */
> +       }
> +    }
> +  else
> +    {
> +
> +      /* As long as there are still subdirectories to add, do them.  */
> +      while (index (unixname, '/') != 0)
> +       {
> +         /* If this token is "." we can ignore it
> +              if it's not at the beginning of a path.  */
> +         if ((unixname[0] == '.') && (unixname[1] == '/'))
> +           {
> +             /* remove it at beginning of path.  */
> +             if (  ((unixname == fullname)             /* no device spec  */
> +                   && (fullname+2 != basename))        /* starts with ./ */
> +                                                       /* or  */
> +                || ((basename[-1] == ':')              /* device spec  */
> +                   && (unixname-1 == basename)))       /* and ./ afterwards  */
> +               *local_ptr++ = '.';                     /* make '[.' start of path.  */
> +             unixname += 2;
> +             continue;
> +           }
> +
> +         /* Add a subdirectory spec. Do not duplicate "." */
> +         if (  local_ptr[-1] != '.'
> +            && local_ptr[-1] != '['
> +            && local_ptr[-1] != '<')
> +           *local_ptr++ = '.';
> +
> +         /* If this is ".." then the spec becomes "-" */
> +         if (  (unixname[0] == '.')
> +            && (unixname[1] == '.')
> +            && (unixname[2] == '/'))
> +           {
> +             /* Add "-" and skip the ".." */
> +             if ((local_ptr[-1] == '.')
> +                 && (local_ptr[-2] == '['))
> +               local_ptr--;                    /* prevent [.-  */
> +             *local_ptr++ = '-';
> +             unixname += 3;
> +             continue;
> +           }
> +
> +         /* Copy the subdirectory */
> +         while (*unixname != '/')
> +           *local_ptr++= *unixname++;
> +
> +         unixname++;                   /* Skip the "/" */
> +       }
> +
> +      /* Close the directory specification */
> +      if (local_ptr[-1] == '.')                /* no trailing periods */
> +       local_ptr--;
> +
> +      if (local_ptr[-1] == '[')                /* no dir needed */
> +       local_ptr--;
> +      else
> +       *local_ptr++ = ']';
> +    }
> +
> +  /* Now add the filename.  */
> +
> +  while (*unixname)
> +    *local_ptr++ = *unixname++;
> +  *local_ptr = 0;
> +
> +  /* Now append it to the original VMS spec.  */
> +
> +  strcpy ((must_revert==1)?fullname:basename, Local);
> +
> +  /* If we put a [000000] in the filename, try to open it first. If this fails,
> +     remove the [000000], and return that name.  This provides flexibility
> +     to the user in that they can use both rooted and non-rooted logical names
> +     to point to the location of the file.  */
> +
> +  if (check_filename_before_returning)
> +    {
> +      f = open (fullname, O_RDONLY, 0666);
> +      if (f >= 0)
> +       {
> +         /* The file name is OK as it is, so return it as is.  */
> +         close (f);
> +         return 1;
> +       }
> +
> +      /* The filename did not work.  Try to remove the [000000] from the name,
> +        and return it.  */
> +
> +      basename = index (fullname, '[');
> +      local_ptr = index (fullname, ']') + 1;
> +      strcpy (basename, local_ptr);            /* this gets rid of it */
> +
> +    }
> +
> +  return 1;
> +}
> +#endif /* VMS */





Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]