]> andersk Git - splint.git/blobdiff - src/cpplib.c
Changes for the OS/2 port: cpplib.c (fixed cstring_replaceAll()
[splint.git] / src / cpplib.c
index b12e4f7feebf528cb6ea22e9b162345500c006a6..8a069f098e4061b063e799cddd0c24acf743ad3c 100644 (file)
-/*
-See
-http://src.openresources.com/debian/src/devel/HTML/S/altgcc_2.7.2.2.orig%20altgcc-2.7.2.2.orig%20protoize.c.html
-static char *
-abspath (cwd, rel_filename)
-
-*/
-
-/*!!!!
-*** cpplib.c.old Tue Nov 28 2000 09:04:09 AM
---- cpplib.c Tue Nov 28 2000 08:55:18 AM
-***************
-*** 5715,5722 ****
-     c2 = cppReader_peekC (pfile)
-     if (c2 != '\n'
-       goto randomchar
-!    token = CPP_HSPACE
-!    goto op2any
---- 5714,5723 ----
-          case '\\'
-     c2 = cppReader_peekC (pfile)
-     if (c2 != '\n'
-       goto randomchar
-!    cppReader_forward (pfile, 1)
-!    pfile->lineno++
-!    return CPP_HSPACE
-  
-   case '\n'
-     cppReader_putChar (pfile, c)
-
-
-Carl J. Appellof ( mailto:cappello@legato.com <mailto:cappello@legato.com> )
-*/ /*@i8@*/
-
-/*
-** LCLint - annotation-assisted static program checker
-** Copyright (C) 1994-2001 University of Virginia,
-**         Massachusetts Institute of Technology
-**
-** 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 of the License, 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.
-** 
-** The GNU General Public License is available from http://www.gnu.org/ or
-** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-** MA 02111-1307, USA.
-**
-** For information on lclint: lclint-request@cs.virginia.edu
-** To report a bug: lclint-bug@cs.virginia.edu
-** For more information: http://lclint.cs.virginia.edu
-*/
-/*
-** cpplib.c
-*/
-/*
-   Copyright (C) 1986, 87, 89, 92-6, 1997 Free Software Foundation, Inc.
-   Contributed by Per Bothner, 1994-95.
-   Based on CCCP program by Paul Rubin, June 1986
-   Adapted to ANSI C, Richard Stallman, Jan 1987
-
-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!  */
-
-/*
- * Herbert 06/12/2000:
- * - OS2 drive specs like WIN32
- * - Includes for IBMs OS/2 compiler
- */
-
-# include <ctype.h>
-# include <stdio.h>
-# include <signal.h>
-# ifdef __STDC__
-# include <stdlib.h>
-# endif
-
-# include <string.h>
-
-# if !(defined (WIN32) || defined (OS2) && defined (__IBMC__))
-# include <unistd.h>
-# endif
-
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <fcntl.h>
-
-# if defined (WIN32) || defined (OS2) && defined (__IBMC__)
-# include <io.h>
-# include <sys/utime.h>                /* for __DATE__ and __TIME__ */
-# include <time.h>
-# else
-# ifndef VMS
-# ifndef USG
-# include <time.h> /* Reported by Paul Smith */
-# include <sys/time.h>
-# include <sys/resource.h>
-# else
-# include <sys/times.h>
-# include <time.h>
-# include <fcntl.h>
-# endif /* USG */
-# endif /* not VMS */
-# endif /* not WIN32 */
-
-/* This defines "errno" properly for VMS, and gives us EACCES.  */
-# include <errno.h>
-
-# include "lclintMacros.nf"
-# include "llbasic.h"
-# include "lcllib.h"
-# include "cpplib.h"
-# include "cpperror.h"
-# include "cpphash.h"
-# include "cppexp.h"
-# include "version.h"
-# include "portab.h"
-# include "osd.h"
-
-/*
-** This is really kludgey code...
-*/
-
-/*@+boolint@*/
-/*@+charint@*/
-
-#define NO_SHORTNAMES
-
-# ifdef open
-# undef open
-# undef read
-# undef write
-# endif /* open */
-
-/*@constant int IMPORT_FOUND@*/
-# define IMPORT_FOUND -2
-
-/*@constant int SKIP_INCLUDE@*/
-# define SKIP_INCLUDE IMPORT_FOUND
-
-/*@constant unused int IMPORT_NOT_FOUND@*/
-# define IMPORT_NOT_FOUND -1
-
-#ifndef STDC_VALUE
-/*@constant unused int STDC_VALUE@*/
-#define STDC_VALUE 1
-#endif
-
-/* By default, colon separates directories in a path.  */
-#ifndef PATH_SEPARATOR
-/*@constant char PATH_SEPARATOR@*/
-#define PATH_SEPARATOR ':'
-#endif
-
-static void parse_name (cppReader *, int);
-
-static int cpp_openIncludeFile (char *p_filename)
-     /*@modifies fileSystem @*/ ;
-
-static void cpp_setLocation (cppReader *p_pfile)
-     /*@modifies g_currentloc@*/ ;
-
-static enum cpp_token cpp_handleComment (cppReader *p_pfile,
-                                        struct parse_marker *p_smark)
-     /*@modifies p_pfile, p_smark@*/;
-
-static bool cpp_shouldCheckMacro (cppReader *p_pfile, char *p_p) /*@*/ ;
-
-static bool cpp_skipIncludeFile (cstring p_fname) /*@*/ ;
-
-#ifndef O_RDONLY
-#define O_RDONLY 0
-#endif
-
-/* Symbols to predefine.  */
-
-#ifdef CPP_PREDEFINES
-static /*@observer@*/ char *predefs = CPP_PREDEFINES;
-#else
-static /*@observer@*/ char *predefs = "";
-#endif
-
-/* We let tm.h override the types used here, to handle trivial differences
-   such as the choice of unsigned int or long unsigned int for size_t.
-   When machines start needing nontrivial differences in the size type,
-   it would be best to do something here to figure out automatically
-   from other information what type to use.  */
-
-/* The string value for __SIZE_TYPE__.  */
-
-#ifndef SIZE_TYPE
-/*@constant observer char *SIZE_TYPE@*/
-#define SIZE_TYPE "long unsigned int"
-#endif
-
-/* The string value for __PTRDIFF_TYPE__.  */
-
-#ifndef PTRDIFF_TYPE
-/*@constant observer char *PTRDIFF_TYPE@*/
-#define PTRDIFF_TYPE "long int"
-#endif
-
-/* The string value for __WCHAR_TYPE__.  */
-
-#ifndef WCHAR_TYPE
-/*@constant observer char *WCHAR_TYPE@*/
-#define WCHAR_TYPE "int"
-#endif
-
-/* The string value for __USER_LABEL_PREFIX__ */
-
-#ifndef USER_LABEL_PREFIX
-/*@constant observer char *USER_LABEL_PREFIX@*/
-#define USER_LABEL_PREFIX ""
-#endif
-
-/* The string value for __REGISTER_PREFIX__ */
-
-#ifndef REGISTER_PREFIX
-/*@constant observer char *REGISTER_PREFIX@*/
-#define REGISTER_PREFIX ""
-#endif
-
-/* table to tell if char can be part of a C identifier.  */
-static bool is_idchar[256];
-/* table to tell if char can be first char of a c identifier.  */
-static bool is_idstart[256];
-/* table to tell if c is horizontal space.  */
-static bool is_hor_space[256];
-/* table to tell if c is horizontal or vertical space.  */
-static bool is_space[256];
-
-static /*@exposed@*/ /*@null@*/ cppBuffer *
-cppReader_getBuffer (/*@special@*/ cppReader *p_pfile)
-     /*@uses p_pfile->buffer@*/
-     /*@modifies nothing@*/ ;
-
-/*@notfunction@*/
-# define SKIP_WHITE_SPACE(p) do { /*@access cstring@*/ while (is_hor_space[(int) *(p)]) { (p)++; } } /*@noaccess cstring@*/ while (0)
-
-/*@notfunction@*/
-# define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*(p)]) { (p)++; } } while (0)
-
-static int cpp_peekN (cppReader *p_pfile, int p_n) /*@*/ ;
-
-/*@function static int cppBuffer_get (sef cppBuffer *p_b) modifies *p_b ; @*/
-# define cppBuffer_get(BUFFER) \
-  ((BUFFER)->cur < (BUFFER)->rlimit ? *(BUFFER)->cur++ : EOF)
-
-/* Append string STR (of length N) to PFILE's output buffer.  Make space. */
-/*@function static void cppReader_puts (sef cppReader *p_file, char *p_str, sef size_t p_n)
-                     modifies *p_file; @*/
-# define cppReader_puts(PFILE, STR, N) \
-  cppReader_reserve(PFILE, N), cppReader_putStrN (PFILE, STR,N)
-
-/* Append character CH to PFILE's output buffer.  Assume sufficient space. */
-
-/*@function static void cppReader_putCharQ (cppReader *p_file, char p_ch)
-                    modifies *p_file; @*/
-# define cppReader_putCharQ(PFILE, CH) (*(PFILE)->limit++ = (CH))
-
-/* Append character CH to PFILE's output buffer.  Make space if need be. */
-
-/*@function static void cppReader_putChar (sef cppReader *p_file, char p_ch)
-                    modifies *p_file; @*/
-#define cppReader_putChar(PFILE, CH) (cppReader_reserve (PFILE, (size_t) 1), cppReader_putCharQ (PFILE, CH))
-
-/* Make sure PFILE->limit is followed by '\0'. */
-/*@function static void cppReader_nullTerminateQ (cppReader *p_file)
-      modifies *p_file; @*/
-
-#define cppReader_nullTerminateQ(PFILE) (*(PFILE)->limit = 0)
-
-/*@function static void cppReader_nullTerminate (sef cppReader *p_file)
-                           modifies *p_file; @*/
-# define cppReader_nullTerminate(PFILE) \
-  (cppReader_reserve (PFILE, (size_t) 1), *(PFILE)->limit = 0)
-
-/*@function static void cppReader_adjustWritten (cppReader *p_file, size_t)
-                           modifies *p_file; @*/
-#define cppReader_adjustWritten(PFILE,DELTA) ((PFILE)->limit += (DELTA))
-
-/*@function static bool cppReader_isC89 (cppReader *) modifies nothing; @*/
-#define cppReader_isC89(PFILE) (CPPOPTIONS(PFILE)->c89)
-
-/*@function static observer char *cppReader_wcharType (cppReader *)
-     modifies nothing; @*/
-
-# define cppReader_wcharType(PFILE) \
-  (CPPOPTIONS (PFILE)->cplusplus ? "__wchar_t" : WCHAR_TYPE)
-
-static void cppBuffer_forward (cppBuffer *p_buf, int p_n) /*@modifies *p_buf@*/ ;
-
-/*@function static void cppReader_forward (cppReader *p_pfile, int) modifies *p_pfile; @*/
-# define cppReader_forward(pfile, N) \
-  (cppBuffer_forward (cppReader_getBufferSafe (pfile), (N)))
-
-/*@function static int cppReader_getC (cppReader *p_pfile) modifies *p_pfile; @*/
-# define cppReader_getC(pfile)   (cppBuffer_get (cppReader_getBufferSafe (pfile)))
-
-/*@function static int cppReader_peekC (cppReader *) modifies nothing;@*/
-# define cppReader_peekC(pfile)  (cppBufPeek (cppReader_getBufferSafe (pfile)))
-
-/* Move all backslash-newline pairs out of embarrassing places.
-   Exchange all such pairs following BP
-   with any potentially-embarrassing characters that follow them.
-   Potentially-embarrassing characters are / and *
-   (because a backslash-newline inside a comment delimiter
-   would cause it not to be recognized).  */
-
-/*@notfunction@*/
-# define NEWLINE_FIX \
-   do { while (cppReader_peekC (pfile) == '\\' && cpp_peekN (pfile, 1) == '\n') { cppReader_forward (pfile, 2); } } while(FALSE)
-
-     /* Same, but assume we've already read the potential '\\' into C.  */
-/*@notfunction@*/
-# define NEWLINE_FIX1(C) do { \
-     while ((C) == '\\' && cppReader_peekC (pfile) == '\n') { cppReader_forward (pfile, 1); (C) = cppReader_getC (pfile); }\
-                                                                          } while(0)
-
-static void parseSetMark (/*@out@*/ struct parse_marker *,
-                         cppReader *);
-static void parseClearMark (struct parse_marker *);
-static void parseGotoMark (struct parse_marker *, cppReader *);
-static void parseMoveMark (struct parse_marker *, cppReader *);
-
-/* If we have a huge buffer, may need to cache more recent counts */
-static /*@exposed@*/ char *cppLineBase (/*@sef@*/ cppBuffer *);
-
-static /*@exposed@*/ /*@null@*/ cppBuffer *
-   cppReader_pushBuffer (cppReader *p_pfile,
-                        /*@owned@*/ /*@null@*/ char *, size_t)
-     /*@modifies p_pfile@*/ ;
-
-static void cppReader_appendIncludeChain
-(cppReader *p_pfile,
- /*@keep@*/ struct file_name_list *p_first,
- /*@dependent@*/ struct file_name_list *p_last);
-
-static void cppReader_macroCleanup (cppBuffer *p_pbuf, cppReader *p_pfile);
-static enum cpp_token cppReader_nullUnderflow (/*@unused@*/ cppReader *p_pfile);
-
-static void cppReader_nullCleanup (/*@unused@*/ cppBuffer *p_pbuf,
-                                  /*@unused@*/ cppReader *p_pfile);
-
-static void cppReader_fileCleanup (cppBuffer *p_pbuf,
-                                  /*@unused@*/ cppReader *p_pfile);
-
-static int cppReader_handleDirective (cppReader *p_pfile);
-
-static void cppReader_scanBuffer (cppReader *p_pfile);
-
-# if defined (WIN32) || defined (OS2) && defined (__IBMC__)
-
-/*
-** WIN32 (at least the VC++ include files) does not define mode_t.
-*/
-
-/*@-incondefs@*/ /*@-czechtypes@*/
-typedef unsigned int mode_t;
-/*@=incondefs@*/ /*@=czechtypes@*/
-
-# endif
-
-static int file_size_and_mode (int p_fd, /*@out@*/ mode_t *p_mode_pointer,
-                              /*@out@*/ size_t *p_size_pointer);
-static int safe_read (int p_desc, /*@out@*/ char *p_ptr, int p_len);
-
-
-/*
-** cppBuffer_isMacro is true if the buffer contains macro expansion.
-** (Note that it is false while we're expanding marco *arguments*.)
-*/
-
-static bool cppBuffer_isMacro (/*@null@*/ cppBuffer *) /*@*/ ;
-
-static void path_include (cppReader *p_pfile, char *p_path)
-     /*@modifies p_pfile@*/ ;
-
-static void initialize_builtins (cppReader *p_pfile)
-     /*@modifies p_pfile@*/ ;
-
-static void initialize_char_syntax (struct cppOptions *p_opts) ;
-
-static int /*@alt void@*/ finclude (cppReader *p_pfile, int p_f,
-                                   cstring p_fname,
-                                   bool p_system_header_p,
-                                   /*@dependent@*/ /*@null@*/ struct file_name_list *p_dirptr);
-
-static void validate_else (cppReader *p_pfile, cstring p_directive);
-
-static void conditional_skip (cppReader *p_pfile, int p_skip,
-                             enum node_type p_type,
-                             /*@dependent@*/ /*@null@*/ char *p_control_macro);
-
-static HOST_WIDE_INT eval_if_expression (cppReader *p_pfile,
-                                        char *p_buf,
-                                        int p_length);
-
-static void skip_if_group (cppReader *p_pfile, int p_any);
-
-static bool comp_def_part (bool p_first, char *p_beg1, int p_len1,
-                          char *p_beg2, int p_len2, bool p_last);
-
-#ifdef abort
-extern void fancy_abort ();
-#endif
-
-static bool redundant_include_p (cppReader *p_pfile, /*@null@*/ cstring p_name);
-static bool is_system_include (cppReader *p_pfile, cstring p_filename);
-
-static /*@observer@*/ /*@null@*/ struct file_name_map *
-read_name_map (cppReader *p_pfile, cstring p_dirname);
-
-static cstring read_filename_string (int p_ch, /*:open:*/ FILE *p_f);
-
-static int open_include_file (cppReader *p_pfile,
-                             /*@owned@*/ cstring p_fname,
-                             /*@null@*/ struct file_name_list *p_searchptr);
-
-static void push_macro_expansion (cppReader *,
-                                 /*@owned@*/ char *, size_t,
-                                 /*@dependent@*/ hashNode);
-
-/* Last arg to output_line_command.  */
-enum file_change_code {
-  same_file, enter_file, leave_file
-};
-
-/* `struct directive' defines one #-directive, including how to handle it.  */
-
-struct directive {
-  int length;                  /* Length of name */
-  /*@null@*/ int (*func)();    /* Function to handle directive */
-  /*@observer@*/ cstring name; /* Name of directive */
-  enum node_type type;         /* Code which describes which directive.  */
-  bool command_reads_line;      /* One if rest of line is read by func.  */
-  bool traditional_comments;   /* Nonzero: keep comments if -traditional.  */
-  bool pass_thru;              /* Copy preprocessed directive to output file.*/
-};
-
-/* These functions are declared to return int instead of void since they
-   are going to be placed in a table and some old compilers have trouble with
-   pointers to functions returning void.  */
-
-static int do_define (cppReader *, /*@null@*/ struct directive *, 
-                     char *, char *);
-static int do_defineAux (cppReader *, /*@null@*/ struct directive *,
-                        char *, char *, bool);
-     
-static int do_line (cppReader *, /*@null@*/ struct directive *);
-static int do_include (cppReader *, struct directive *, char *, char *);
-static int do_undef (cppReader *, struct directive *, char *, char *);
-static int do_error (cppReader *, struct directive *, char *, char *);
-static int do_pragma (cppReader *, struct directive *, char *, char *);
-static int do_ident (cppReader *, struct directive *, char *, char *);
-static int do_if (cppReader *, struct directive *, char *, char *);
-static int do_xifdef (cppReader *, struct directive *, char *, char *);
-static int do_else (cppReader *, struct directive *, char *, char *);
-static int do_elif (cppReader *, struct directive *, char *, char *);
-static int do_endif (cppReader *, struct directive *, char *, char *);
-static int do_warning (cppReader *, struct directive *, char *, char *);
-
-/* 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.  */
-
-/*@constant observer struct file_name_list *SELF_DIR_DUMMY@*/
-#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.  */
-/* -I directories are added to the end, then the defaults are added.  */
-
-/*@access cstring@*/
-
-static struct default_include {
-  /*@dependent@*/ /*@observer@*/ cstring fname;        /* The name of the directory.  */
-  int cplusplus;               /* Only look here if we're compiling C++.  */
-  int cxx_aware;               /* Includes in this directory don't need to
-                                  be wrapped in extern "C" when compiling
-                                  C++.  */
-} include_defaults_array[]
-= {
-  /* This is the dir for fixincludes.  Put it just before
-     the files that we fix.  */
-  { GCC_INCLUDE_DIR, 0, 0 },
-  { GCC_INCLUDE_DIR2, 0, 0 },
-  { cstring_undefined, 0, 0 }
-};
-
-/*@noaccess cstring@*/
-
-/* Here is the actual list of #-directives, most-often-used first.
-   The initialize_builtins function assumes #define is the very first.  */
-
-/*@access cstring@*/
-
-static struct directive directive_table[] = {
-  {  6, do_define, "define", T_DEFINE, FALSE, TRUE, FALSE },
-  {  5, do_xifdef, "ifdef", T_IFDEF, TRUE, FALSE, FALSE },
-  {  6, do_xifdef, "ifndef", T_IFNDEF, TRUE, FALSE, FALSE },
-  {  7, do_include, "include", T_INCLUDE, TRUE, FALSE, FALSE },
-  {  5, do_endif, "endif", T_ENDIF, TRUE, FALSE, FALSE },
-  {  4, do_else, "else", T_ELSE, TRUE, FALSE, FALSE },
-  {  2, do_if, "if", T_IF, TRUE, FALSE, FALSE },
-  {  4, do_elif, "elif", T_ELIF, TRUE, FALSE, FALSE },
-  {  5, do_undef, "undef", T_UNDEF, FALSE, FALSE, FALSE },
-  {  5, do_error, "error", T_ERROR, FALSE, FALSE, FALSE },
-  {  7, do_warning, "warning", T_WARNING, FALSE, FALSE, FALSE },
-  {  6, do_pragma, "pragma", T_PRAGMA, FALSE, FALSE, TRUE},
-  {  4, do_line, "line", T_LINE, TRUE, FALSE, FALSE },
-  {  5, do_ident, "ident", T_IDENT, TRUE, FALSE, TRUE },
-  /* {  8, do_unassert, "unassert", T_UNASSERT, TRUE, FALSE, FALSE }, */
-  {  -1, 0, "", T_UNUSED, FALSE, FALSE, FALSE },
-};
-/*@noaccess cstring@*/
-
-static cstring searchPath_unparse (struct file_name_list *search_start) 
-{
-  cstring res = cstring_newEmpty ();
-  struct file_name_list *searchptr = NULL;
-
-  for (searchptr = search_start; searchptr != NULL;
-       searchptr = searchptr->next)
-    {
-      if (!cstring_isEmpty (searchptr->fname)) {
-       res = cstring_concatFree1 (res, searchptr->fname);
-       if (searchptr->next != NULL) {
-         res = cstring_appendChar (res, ';');
-       }
-      }
-    }
-
-  return res;
-}
-
-/*@+charint@*/
-static void
-initialize_char_syntax (struct cppOptions *opts)
-{
-  char i;
-
-  /*
-   * Set up is_idchar and is_idstart tables.  These should be
-   * faster than saying (is_alpha (c) || c == '_'), etc.
-   * Set up these things before calling any routines tthat
-   * refer to them.
-   */
-
-  for (i = 'a'; i <= 'z'; i++) {
-    is_idchar[i - 'a' + 'A'] = TRUE;
-    is_idchar[(int) i] = TRUE;
-    is_idstart[i - 'a' + 'A'] = TRUE;
-    is_idstart[(int) i] = TRUE;
-  }
-
-  for (i = '0'; i <= '9'; i++)
-    {
-      is_idchar[(int) i] = TRUE;
-    }
-
-  is_idchar['_'] = TRUE;
-  is_idstart['_'] = TRUE;
-  is_idchar['$'] = opts->dollars_in_ident;
-  is_idstart['$'] = opts->dollars_in_ident;
-
-  /* horizontal space table */
-  is_hor_space[' '] = TRUE;
-  is_hor_space['\t'] = TRUE;
-  is_hor_space['\v'] = TRUE;
-  is_hor_space['\f'] = TRUE;
-  is_hor_space['\r'] = TRUE;
-
-  is_space[' '] = TRUE;
-  is_space['\t'] = TRUE;
-  is_space['\v'] = TRUE;
-  is_space['\f'] = TRUE;
-  is_space['\n'] = TRUE;
-  is_space['\r'] = TRUE;
-}
-
-bool isIdentifierChar (char c)
-{
-  return is_idchar[(int) c];
-}
-
-/* Place into P_PFILE a quoted string representing the string SRC.
-   Caller must reserve enough space in pfile->token_buffer.  */
-
-static void
-quote_string (cppReader *pfile, char *src)
-{
-  char c;
-
-  cppReader_putCharQ (pfile, '\"');
-  for (;;)
-    {
-      switch ((c = *src++))
-       {
-       default:
-         if (isprint (c))
-           cppReader_putCharQ (pfile, c);
-         else
-           {
-             sprintf (cppReader_getPWritten (pfile), "\\%03o",
-                      (unsigned int) c);
-             cppReader_adjustWritten (pfile, (size_t) 4);
-           }
-         /*@switchbreak@*/ break;
-
-       case '\"':
-       case '\\':
-         cppReader_putCharQ (pfile, '\\');
-         cppReader_putCharQ (pfile, c);
-         /*@switchbreak@*/ break;
-
-       case '\0':
-         cppReader_putCharQ (pfile, '\"');
-         cppReader_nullTerminateQ (pfile);
-         return;
-       }
-    }
-}
-
-/* Re-allocates PFILE->token_buffer so it will hold at least N more chars.  */
-
-void
-cppReader_growBuffer (cppReader *pfile, size_t n)
-{
-  size_t old_written = cppReader_getWritten (pfile);
-  pfile->token_buffer_size = n + 2 * pfile->token_buffer_size;
-  pfile->token_buffer = (char *)
-    drealloc (pfile->token_buffer, pfile->token_buffer_size);
-  cppReader_setWritten (pfile, old_written);
-}
-
-/*
- * process a given definition string, for initialization
- * If STR is just an identifier, define it with value 1.
- * If STR has anything after the identifier, then it should
- * be identifier=definition.
- */
-
-void
-cppReader_define (cppReader *pfile, char *str)
-{
-  char *buf = NULL;
-  char *p = str;
-
-  DPRINTF (("Cpp reader define: %s", str));
-
-  if (!is_idstart[(int) *p])
-    {
-      DPRINTF (("ERROR 1"));
-      cppReader_error (pfile,
-                      message ("Malformed option `-D%s'",
-                               cstring_fromChars (str)));
-      
-      return;
-    }
-
-  p++;
-
-  DPRINTF (("Here 2"));
-
-  while (is_idchar[(int) *p])
-    {
-      p++;
-    }
-
-  if (*p == '(') {
-    p++;
-    while (*p != ')' && *p != '\0') {
-      p++;
-    }
-
-    if (*p == ')') {
-      p++;
-    } else {
-      cppReader_error 
-       (pfile,
-        message ("Malformed option: -D%s (no closing parenthesis)", 
-                 cstring_fromChars (str)));
-    }
-  }
-
-  DPRINTF (("Here 2"));
-
-  if (*p == '\0')
-    {
-      buf = (char *) dmalloc (size_fromInt (p - str + 4));
-      strcpy ((char *) buf, str);
-      strcat ((char *) buf, " 1");
-    }
-  else if (*p != '=')
-    {
-      DPRINTF (("ERROR 2"));
-      cppReader_error (pfile,
-                      message ("Malformed option: -D%s (expected '=', found '%c')",
-                               cstring_fromChars (str),
-                               *p));
-      return;
-    }
-  else
-    {
-      char *q;
-      /* Copy the entire option so we can modify it.  */
-      DPRINTF (("Copying..."));
-      buf = (char *) dmalloc (2 * strlen (str) + 1);
-      strncpy (buf, str, size_fromInt (p - str));
-
-      /* Change the = to a space.  */
-      buf[p - str] = ' ';
-      /* Scan for any backslash-newline and remove it.  */
-      p++;
-      q = &buf[p - str];
-
-      while (*p != '\0')
-       {
-         if (*p == '\\' && p[1] == '\n')
-           p += 2;
-         else
-           *q++ = *p++;
-       }
-
-      DPRINTF (("Here we are..."));
-      *q = '\0';
-    }
-
-  llassert (buf != NULL);
-  DPRINTF (("Do define: %s / %ld", buf, size_toLong (strlen (buf))));
-  (void) do_define (pfile, NULL, buf, buf + strlen (buf));
-  sfree (buf);
-}
-
-/* Append a chain of `struct file_name_list's
-   to the end of the main include chain.
-   FIRST is gthe beginning of the chain to append, and LAST is the end.  */
-
-void
-cppReader_appendIncludeChain (cppReader *pfile,
-                     struct file_name_list *first,
-                     struct file_name_list *last)
-{
-  struct cppOptions *opts = CPPOPTIONS (pfile);
-  struct file_name_list *dir;
-
-  if (first == NULL || last == NULL)
-    {
-      return;
-    }
-
-  if (opts->include == 0)
-    {
-      opts->include = first;
-    }
-  else
-    {
-      llassert (opts->last_include->next == NULL);
-      opts->last_include->next = first;
-    }
-
-  if (opts->first_bracket_include == 0)
-    {
-      opts->first_bracket_include = first;
-
-      for (dir = first; ; dir = dir->next) {
-       int len = cstring_length (dir->fname) + INCLUDE_LEN_FUDGE;
-       if (len > pfile->max_include_len)
-         pfile->max_include_len = len;
-       if (dir == last)
-         break;
-      }
-    }
-
-  llassert (last->next == NULL);
-  /* last->next = NULL; */
-  opts->last_include = last;
-}
-
-# if 0
-static /*@unused@*/ void 
-cppReader_showIncludeChain (cppReader *pfile)
-{
-  struct file_name_list *dirs = CPPOPTIONS (pfile)->include;
-
-  if (dirs != NULL)
-    {
-      while (dirs != NULL)
-       {
-         fprintf (stderr, "*%s*:", cstring_toCharsSafe (dirs->fname));
-         dirs = dirs->next;
-       }
-
-      fprintf (stderr, "\n");
-    }
-  else
-    {
-      fprintf (stderr, "No includes\n");
-    }
-}
-# endif
-
-cstring 
-cppReader_getIncludePath ()
-{
-  cppReader *pfile = &g_cppState;
-  struct file_name_list *dirs = CPPOPTIONS (pfile)->include;
-  cstring res = cstring_undefined;
-
-  if (dirs != NULL)
-    {
-      while (dirs != NULL)
-       {
-         res = message ("%q%c%s", res, PATH_SEPARATOR, dirs->fname);
-         dirs = dirs->next;
-       }
-    }
-  else
-    {
-      res = cstring_makeLiteral ("<no include path>");
-    }
-
-  return res;
-}
-
-void
-cppReader_addIncludeChain (cppReader *pfile, struct file_name_list *dir)
-{
-  struct cppOptions *opts = CPPOPTIONS (pfile);
-
-  if (dir == 0)
-    {
-      return;
-    }
-
-  if (opts->include == 0)
-    {
-      opts->include = dir;
-    }
-  else
-    {
-      llassert (opts->last_include->next == NULL);
-      opts->last_include->next = dir;
-    }
-
-  if (opts->first_bracket_include == 0)
-    {
-      int len = cstring_length (dir->fname) + INCLUDE_LEN_FUDGE;
-      opts->first_bracket_include = dir;
-      if (len > pfile->max_include_len)
-       {
-         pfile->max_include_len = len;
-       }
-    }
-
-  dir->next = NULL;
-  opts->last_include = dir;
-  /* cppReader_showIncludeChain (pfile); */
-}
-
-/* Given a colon-separated list of file names PATH,
-   add all the names to the search path for include files.  */
-
-static void
-path_include (cppReader *pfile, char *path)
-{
-  char *p;
-
-#ifdef __CYGWIN32__
-  char *win32temp;
-
-  /* if we have a posix path list, convert to win32 path list */
-  win32temp = (char *) dmalloc /*@i4@*/
-    (cygwin32_posix_to_win32_path_list_buf_size (path));
-  cygwin32_posix_to_win32_path_list (path, win32temp);
-  path = win32temp;
-#endif
-
-  p = path;
-
-  if (*p != '\0')
-    while (1) {
-      char *q = p;
-      char *name;
-      struct file_name_list *dirtmp;
-
-      /* Find the end of this name.  */
-      while (*q != '\0' && *q != PATH_SEPARATOR)
-       {
-         q++;
-       }
-
-      if (p == q)
-       {
-         /* An empty name in the path stands for the current directory.  */
-         name = (char *) dmalloc ((size_t) 2);
-         name[0] = '.';
-         name[1] = '\0';
-       }
-      else
-       {
-         /* Otherwise use the directory that is named.  */
-         name = (char *) dmalloc (size_fromInt (q - p + 1));
-         memcpy (name, p, size_fromInt (q - p));
-         name[q - p] = '\0';
-       }
-
-      dirtmp = (struct file_name_list *) dmalloc (sizeof (*dirtmp));
-      dirtmp->next = 0;                /* New one goes on the end */
-      dirtmp->control_macro = 0;
-      dirtmp->c_system_include_path = 0;
-      dirtmp->fname = cstring_fromChars (name);
-      dirtmp->got_name_map = 0;
-      cppReader_addIncludeChain (pfile, dirtmp);
-
-      /* Advance past this name.  */
-      p = q;
-      if (*p == '\0')
-       break;
-      /* Skip the colon.  */
-      p++;
-    }
-}
-
-void
-cppOptions_init (cppOptions *opts)
-{
-  memset ((char *) opts, 0, sizeof *opts);
-  assertSet (opts);
-
-  opts->in_fname = NULL;
-  opts->out_fname = NULL;
-
-  /* Initialize is_idchar to allow $.  */
-  opts->dollars_in_ident = TRUE;
-
-  opts->no_line_commands = 0;
-  opts->no_trigraphs = TRUE;
-  opts->put_out_comments = 1;
-  opts->print_include_names = 0;
-  opts->dump_macros = DUMP_DEFINITIONS; /* DUMP_NONE; */
-  opts->no_output = 0;
-  opts->cplusplus = 0;
-
-  opts->cplusplus_comments = 1;
-  opts->verbose = 0;
-  opts->lang_asm = 0;
-  opts->for_lint = 0;
-  opts->chill = 0;
-  opts->pedantic_errors = 0;
-  opts->warn_comments = 0;
-  opts->warnings_are_errors = 0;
-
-  initialize_char_syntax (opts);
-}
-
-enum cpp_token
-cppReader_nullUnderflow (/*@unused@*/ cppReader *pfile)
-{
-  return CPP_EOF;
-}
-
-void
-cppReader_nullCleanup (/*@unused@*/ cppBuffer *pbuf,
-             /*@unused@*/ cppReader *pfile)
-{
-  ;
-}
-
-void
-cppReader_macroCleanup (cppBuffer *pbuf, /*@unused@*/ cppReader *pfile)
-{
-  hashNode macro = pbuf->hnode;
-
-  if (macro->type == T_DISABLED)
-    {
-      macro->type = T_MACRO;
-    }
-
-  if (macro->type != T_MACRO || pbuf->buf != macro->value.defn->expansion)
-    {
-      sfree (pbuf->buf);
-      pbuf->buf = NULL;
-    }
-}
-
-void
-cppReader_fileCleanup (cppBuffer *pbuf, /*@unused@*/ cppReader *pfile)
-{
-  if (pbuf->buf != NULL)
-    {
-      sfree (pbuf->buf);
-      pbuf->buf = NULL;
-    }
-}
-
-/* Assuming we have read '/'.
-   If this is the start of a comment (followed by '*' or '/'),
-   skip to the end of the comment, and return ' '.
-   Return EOF if we reached the end of file before the end of the comment.
-   If not the start of a comment, return '/'.  */
-
-static int
-skip_comment (cppReader *pfile, /*@null@*/ long *linep)
-{
-  int c = 0;
-
-  llassert (pfile->buffer != NULL);
-  llassert (pfile->buffer->cur != NULL);
-
-  while (cppReader_peekC (pfile) == '\\' && cpp_peekN (pfile, 1) == '\n')
-    {
-      if (linep != NULL)
-       {
-         (*linep)++;
-       }
-
-      cppReader_forward (pfile, 2);
-    }
-
-  if (cppReader_peekC (pfile) == '*')
-    {
-      cppReader_forward (pfile, 1);
-
-      for (;;)
-       {
-         int prev_c = c;
-         c = cppReader_getC (pfile);
-
-         if (c == EOF)
-           {
-             return EOF;
-           }
-
-         while (c == (int) '\\' && cppReader_peekC (pfile) == (int) '\n')
-           {
-             if (linep != NULL )
-               {
-                 (*linep)++;
-               }
-
-             cppReader_forward (pfile, 1), c = cppReader_getC (pfile);
-           }
-
-         if (prev_c == (int) '*' && c == (int) '/')
-           {
-             return (int) ' ';
-           }
-
-         if (c == (int) '\n' && (linep != NULL))
-           {
-             (*linep)++;
-           }
-       }
-    }
-  else if (cppReader_peekC (pfile) == '/' 
-          && CPPOPTIONS (pfile)->cplusplus_comments)
-    {
-      cppReader_forward (pfile, 1);
-
-      for (;;)
-       {
-         c = cppReader_getC (pfile);
-
-         if (c == EOF)
-           {
-             /* Allow hash comment to be terminated by EOF.  */
-             return (int) ' '; 
-           }
-
-         while (c == (int) '\\' && cppReader_peekC (pfile) == '\n')
-           {
-             cppReader_forward (pfile, 1);
-             c = cppReader_getC (pfile);
-
-             if (linep != NULL)
-               {
-                 (*linep)++;
-               }
-           }
-
-         if (c == (int) '\n')
-           {
-             /* Don't consider final '\n' to be part of comment.  */
-             cppReader_forward (pfile, -1);
-             return (int) ' ';
-           }
-       }
-    }
-  else
-    {
-      return (int) '/';
-    }
-}
-
-/* Skip whitespace \-newline and comments.  Does not macro-expand.  */
-int /*@alt void@*/
-cppSkipHspace (cppReader *pfile)
-{
-  int nspaces = 0;
-
-  while (TRUE)
-    {
-      int c;
-
-      llassert (pfile->buffer != NULL);
-
-      c = cppReader_peekC (pfile);
-
-      if (c == EOF)
-       {
-         return 0; /* FIXME */
-       }
-
-      if (is_hor_space[c])
-       {
-         if ((c == '\f' || c == '\v') && cppReader_isPedantic (pfile))
-           cppReader_pedwarn (pfile,
-                        message ("%s in preprocessing directive",
-                                 c == '\f'
-                                 ? cstring_makeLiteralTemp ("formfeed")
-                                 : cstring_makeLiteralTemp ("vertical tab")));
-
-         nspaces++;
-         cppReader_forward (pfile, 1);
-       }
-      else if (c == '/')
-       {
-         cppReader_forward (pfile, 1);
-         c = skip_comment (pfile, NULL);
-
-         if (c == '/')
-           {
-             cppReader_forward (pfile, -1);
-           }
-
-         if (c == EOF || c == '/')
-           {
-             return nspaces;
-           }
-       }
-      else if (c == '\\' && cpp_peekN (pfile, 1) == '\n')
-       {
-         cppReader_forward (pfile, 2);
-       }
-      else if (c == '@' && CPPBUFFER (pfile)->has_escapes
-              && is_hor_space [cpp_peekN (pfile, 1)])
-       {
-         cppReader_forward (pfile, 2);
-       }
-      else
-       {
-         return nspaces;
-       }
-    }
-}
-
-/* Read the rest of the current line.
-   The line is appended to PFILE's output buffer.  */
-
-static void
-copy_rest_of_line (cppReader *pfile)
-{
-  struct cppOptions *opts = CPPOPTIONS (pfile);
-
-  for (;;)
-    {
-      int c;
-      int nextc;
-
-      llassert (pfile->buffer != NULL);
-
-      c = cppReader_getC (pfile);
-      switch (c)
-       {
-       case EOF:
-         goto end_directive;
-       case '\\':
-         if (cppReader_peekC (pfile) == '\n')
-           {
-             cppReader_forward (pfile, 1);
-             continue;
-           }
-
-       /*@fallthrough@*/ case '\'': case '\"':
-         goto scan_directive_token;
-
-       case '/':
-         nextc = cppReader_peekC (pfile);
-
-         /*
-         ** was (opts->cplusplus_comments && nextc == '*')
-         ** yoikes!
-         */
-
-         if (nextc == '*'
-             || (opts->cplusplus_comments && nextc == '/'))
-           {
-             goto scan_directive_token;
-           }
-         /*@switchbreak@*/ break;
-       case '\f':
-       case '\v':
-         if (cppReader_isPedantic (pfile))
-           cppReader_pedwarn (pfile,
-                        message ("%s in preprocessing directive",
-                                 c == '\f'
-                                 ? cstring_makeLiteralTemp ("formfeed")
-                                 : cstring_makeLiteralTemp ("vertical tab")));
-         /*@switchbreak@*/ break;
-
-       case '\n':
-         cppReader_forward (pfile, -1);
-         goto end_directive;
-       scan_directive_token:
-         cppReader_forward (pfile, -1);
-         (void) cppGetToken (pfile);
-         continue;
-       }
-      cppReader_putChar (pfile, c);
-    }
-end_directive: ;
-  cppReader_nullTerminate (pfile);
-}
-
-void
-cppReader_skipRestOfLine (cppReader *pfile)
-{
-  size_t old = cppReader_getWritten (pfile);
-  copy_rest_of_line (pfile);
-  cppReader_setWritten (pfile, old);
-}
-
-/* Handle a possible # directive.
-   '#' has already been read.  */
-
-int
-cppReader_handleDirective (cppReader *pfile)
-{
-  int c;
-  struct directive *kt = NULL;
-  int ident_length;
-  size_t after_ident = 0;
-  char *ident = NULL;
-  char *line_end = NULL;
-  size_t old_written = cppReader_getWritten (pfile);
-  int nspaces = cppSkipHspace (pfile);
-
-  c = cppReader_peekC (pfile);
-
-  if (c >= '0' && c <= '9')
-    {
-      /* Handle # followed by a line number.  */
-      if (cppReader_isPedantic (pfile))
-       {
-         cppReader_pedwarnLit
-           (pfile,
-            cstring_makeLiteralTemp ("`#' followed by integer"));
-       }
-
-      (void) do_line (pfile, NULL);
-      goto done_a_directive;
-    }
-
-
-  /* Now find the directive name.  */
-
-  cppReader_putChar (pfile, '#');
-
-  parse_name (pfile, cppReader_getC (pfile));
-
-  llassert (pfile->token_buffer != NULL);
-  ident = pfile->token_buffer + old_written + 1;
-
-  ident_length = cppReader_getPWritten (pfile) - ident;
-
-  if (ident_length == 0 && cppReader_peekC (pfile) == '\n')
-    {
-      /* A line of just `#' becomes blank.  */
-      return 1; 
-    }
-
-  for (kt = directive_table; ; kt++) 
-    {
-      if (kt->length <= 0)
-       {
-         return 0; /* goto not_a_directive; */
-       }
-
-      if (kt->length == ident_length
-         && (cstring_equalPrefix (kt->name, cstring_fromChars (ident))))
-       {
-         break;
-       }
-    }
-
-  if (kt->command_reads_line)
-    {
-      after_ident = 0;
-    }
-  else
-    {
-      /* Nonzero means do not delete comments within the directive.
-        #define needs this when -traditional.  */
-      bool comments = 1; /*cppReader_isTraditional (pfile) && kt->traditional_comments;  */
-      int save_put_out_comments = CPPOPTIONS (pfile)->put_out_comments;
-      CPPOPTIONS (pfile)->put_out_comments = comments;
-      after_ident = cppReader_getWritten (pfile);
-      copy_rest_of_line (pfile);
-      CPPOPTIONS (pfile)->put_out_comments = save_put_out_comments;
-    }
-
-
-  /* For #pragma and #define, we may want to pass through the directive.
-     Other directives may create output, but we don't want the directive
-     itself out, so we pop it now.  For example #include may write a #line
-     command (see comment in do_include), and conditionals may emit
-     #failed ... #endfailed stuff.  But note that popping the buffer
-     means the parameters to kt->func may point after pfile->limit
-     so these parameters are invalid as soon as something gets appended
-     to the token_buffer.  */
-
-  line_end = cppReader_getPWritten (pfile);
-
-
-  if (!kt->pass_thru && kt->type != T_DEFINE)
-    {
-      cppReader_setWritten (pfile, old_written);
-    }
-
-  llassert (pfile->token_buffer != NULL);
-
-  /* was kt->pass_thru || */
-
-  if (kt->type == T_DEFINE
-      && cpp_shouldCheckMacro (pfile, pfile->token_buffer + old_written))
-    {
-      char *p = pfile->token_buffer + old_written;
-
-      /*
-      ** Still need to record value for preprocessing, so 
-      ** #ifdef's, etc. using the value behave correctly.
-      */
-      
-      (void) do_defineAux (pfile, kt, 
-                          pfile->token_buffer + after_ident,
-                          line_end,
-                          TRUE);
-      
-      if (*p == '#')
-       {
-         *p = ' ';
-       }
-
-      SKIP_WHITE_SPACE (p);
-
-      llassert (*p == 'd');
-      *p++ = LLMRCODE[0];
-
-      llassert (*p == 'e');
-      *p++ = LLMRCODE[1];
-
-      llassert (*p == 'f');
-      *p++ = LLMRCODE[2];
-
-      llassert (*p == 'i');
-      *p++ = LLMRCODE[3];
-
-      llassert (*p == 'n');
-      *p++ = LLMRCODE[4];
-
-      llassert (*p == 'e');
-
-      /*
-      ** This is way-bogus.  We use the last char to record the number of
-      ** spaces.  Its too hard to get them back into the input stream.
-      */
-
-      if (nspaces > 9) nspaces = 9;
-
-      *p++ = '0' + nspaces;
-
-      return 0; /* not_a_directive */
-    }
-  else if (kt->pass_thru)
-    {
-      /* Just leave the entire #define in the output stack.  */
-      return 0; /* not_a_directive */
-
-    }
-  else if (kt->type == T_DEFINE
-          && CPPOPTIONS (pfile)->dump_macros == DUMP_NAMES)
-    {
-      char *p = pfile->token_buffer + old_written + 7;  /* Skip "#define". */
-      SKIP_WHITE_SPACE (p);
-
-      while (is_idchar[(int) *p])
-       {
-         p++;
-       }
-
-      pfile->limit = p;
-      cppReader_putChar (pfile, '\n');
-    }
-  else if (kt->type == T_DEFINE)
-    {
-      cppReader_setWritten (pfile, old_written);
-    }
-  else
-    {
-      ;
-    }
-
-done_a_directive:
-  if (kt == NULL) {
-    return 1;
-  } else {
-    llassert (kt->func != NULL);
-    (void) (kt->func) (pfile, kt, pfile->token_buffer + after_ident, line_end);
-    return 1;
-  }
-}
-
-/* Pass a directive through to the output file.
-   BUF points to the contents of the directive, as a contiguous string.
-   LIMIT points to the first character past the end of the directive.
-   KEYWORD is the keyword-table entry for the directive.  */
-
-static void
-pass_thru_directive (char *buf, char *limit,
-                    cppReader *pfile,
-                    struct directive *keyword)
-{
-  int keyword_length = keyword->length;
-
-  cppReader_reserve (pfile,
-                    size_fromInt (2 + keyword_length + (limit - buf)));
-  cppReader_putCharQ (pfile, '#');
-  /*@-observertrans@*/
-  cppReader_putStrN (pfile, cstring_toCharsSafe (keyword->name),
-                    size_fromInt (keyword_length));
-  /*:=observertrans@*/
-
-  if (limit != buf && buf[0] != ' ')
-    {
-      /* Was a bug, since reserve only used 1 + ... */
-      cppReader_putCharQ (pfile, ' ');
-    }
-
-  cppReader_putStrN (pfile, buf, size_fromInt (limit - buf));
-}
-
-/* Read a replacement list for a macro with parameters.
-   Build the DEFINITION structure.
-   Reads characters of text starting at BUF until END.
-   ARGLIST specifies the formal parameters to look for
-   in the text of the definition; NARGS is the number of args
-   in that list, or -1 for a macro name that wants no argument list.
-   MACRONAME is the macro name itself (so we can avoid recursive expansion)
-   and NAMELEN is its length in characters.
-
-   Note that comments, backslash-newlines, and leading white space
-   have already been deleted from the argument.  */
-
-static DEFINITION *
-collect_expansion (cppReader *pfile, char *buf, char *limit,
-                  int nargs, /*@null@*/ struct arglist *arglist)
-{
-  DEFINITION *defn;
-  char *p, *lastp, *exp_p;
-  struct reflist *endpat = NULL;
-  /* Pointer to first nonspace after last ## seen.  */
-  char *concat = 0;
-  /* Pointer to first nonspace after last single-# seen.  */
-  char *stringify = 0;
-  size_t maxsize;
-  char expected_delimiter = '\0';
-
-
-  /* Scan thru the replacement list, ignoring comments and quoted
-     strings, picking up on the macro calls.  It does a linear search
-     thru the arg list on every potential symbol.  Profiling might say
-     that something smarter should happen.  */
-
-  if (limit < buf)
-    abort ();
-
-  /* Find the beginning of the trailing whitespace.  */
-  p = buf;
-
-  while (p < limit && is_space[(int) limit[-1]])
-    {
-      limit--;
-    }
-
-  /* Allocate space for the text in the macro definition.
-     Leading and trailing whitespace chars need 2 bytes each.
-     Each other input char may or may not need 1 byte,
-     so this is an upper bound.  The extra 5 are for invented
-     leading and trailing newline-marker and final null.  */
-  maxsize = (sizeof (*defn) + (limit - p) + 5);
-
-  /* Occurrences of '@' get doubled, so allocate extra space for them.  */
-  while (p < limit)
-    {
-      if (*p++ == '@')
-       {
-         maxsize++;
-       }
-    }
-
-  defn = (DEFINITION *) dmalloc (maxsize);
-  defn->noExpand = FALSE;
-  defn->file = NULL;
-  defn->pattern = NULL;
-  defn->nargs = nargs;
-  defn->predefined = NULL;
-
-  exp_p = defn->expansion = (char *) defn + sizeof (*defn);
-
-  defn->line = 0;
-  defn->rest_args = NULL;
-  defn->args.argnames = NULL;
-
-  lastp = exp_p;
-
-  p = buf;
-
-  /* Add one initial space escape-marker to prevent accidental
-     token-pasting (often removed by macroexpand).  */
-  *exp_p++ = '@';
-  *exp_p++ = ' ';
-
-  if (limit - p >= 2 && p[0] == '#' && p[1] == '#') {
-    cppReader_errorLit (pfile,
-                       cstring_makeLiteralTemp ("`##' at start of macro definition"));
-    p += 2;
-  }
-
-  /* Process the main body of the definition.  */
-  while (p < limit) {
-    int skipped_arg = 0;
-    register char c = *p++;
-
-    *exp_p++ = c;
-
-    if (!cppReader_isTraditional (pfile)) {
-      switch (c) {
-      case '\'':
-      case '\"':
-       if (expected_delimiter != '\0')
-         {
-           if (c == expected_delimiter)
-             expected_delimiter = '\0';
-         }
-       else
-         {
-           expected_delimiter = c;
-         }
-       /*@switchbreak@*/ break;
-
-      case '\\':
-       if (p < limit && (expected_delimiter != '\0'))
-         {
-           /* In a string, backslash goes through
-              and makes next char ordinary.  */
-           *exp_p++ = *p++;
-         }
-       /*@switchbreak@*/ break;
-
-      case '@':
-       /* An '@' in a string or character constant stands for itself,
-          and does not need to be escaped.  */
-       if (expected_delimiter == '\0')
-         {
-           *exp_p++ = c;
-         }
-
-       /*@switchbreak@*/ break;
-
-      case '#':
-       /* # is ordinary inside a string.  */
-       if (expected_delimiter != '\0')
-         {
-           /*@switchbreak@*/ break;
-         }
-
-       if (p < limit && *p == '#') {
-         /* ##: concatenate preceding and following tokens.  */
-         /* Take out the first #, discard preceding whitespace.  */
-         exp_p--;
-
-         /*@-usedef@*/
-         while (exp_p > lastp && is_hor_space[(int) exp_p[-1]])
-           {
-             --exp_p;
-           }
-         /*@=usedef@*/
-
-         /* Skip the second #.  */
-         p++;
-         /* Discard following whitespace.  */
-         SKIP_WHITE_SPACE (p);
-         concat = p;
-         if (p == limit)
-           {
-             cppReader_errorLit (pfile,
-                           cstring_makeLiteralTemp ("`##' at end of macro definition"));
-           }
-       } else if (nargs >= 0) {
-         /* Single #: stringify following argument ref.
-            Don't leave the # in the expansion.  */
-         exp_p--;
-         SKIP_WHITE_SPACE (p);
-         if (p == limit || ! is_idstart[(int) *p]
-             || (*p == 'L' && p + 1 < limit && (p[1] == '\'' || p[1] == '"')))
-           cppReader_errorLit (pfile,
-                         cstring_makeLiteralTemp ("`#' operator is not followed by a macro argument name"));
-         else
-           stringify = p;
-       } else {
-         ; /* BADBRANCH; */
-       }
-
-       /*@switchbreak@*/ break;
-      }
-    } else {
-      /* In -traditional mode, recognize arguments inside strings and
-        and character constants, and ignore special properties of #.
-        Arguments inside strings are considered "stringified", but no
-        extra quote marks are supplied.  */
-      switch (c) {
-      case '\'':
-      case '\"':
-       if (expected_delimiter != '\0') {
-         if (c == expected_delimiter)
-           expected_delimiter = '\0';
-       } else
-         expected_delimiter = c;
-       /*@switchbreak@*/ break;
-
-      case '\\':
-       /* Backslash quotes delimiters and itself, but not macro args.  */
-       if (expected_delimiter != '\0' && p < limit
-           && (*p == expected_delimiter || *p == '\\')) {
-         *exp_p++ = *p++;
-         continue;
-       }
-       /*@switchbreak@*/ break;
-
-      case '/':
-       if (expected_delimiter != '\0') /* No comments inside strings.  */
-         /*@switchbreak@*/ break;
-       if (*p == '*') {
-         /* If we find a comment that wasn't removed by cppReader_handleDirective,
-            this must be -traditional.  So replace the comment with
-            nothing at all.  */
-         exp_p--;
-         p += 1;
-         while (p < limit && !(p[-2] == '*' && p[-1] == '/'))
-           {
-             p++;
-           }
-       }
-       /*@switchbreak@*/ break;
-      }
-    }
-
-    /* Handle the start of a symbol.  */
-    if (is_idchar[(int) c] && nargs > 0) {
-      char *id_beg = p - 1;
-      int id_len;
-
-      --exp_p;
-      while (p != limit && is_idchar[(int) *p])
-       {
-         p++;
-       }
-
-      id_len = p - id_beg;
-
-      if (is_idstart[(int) c]
-         && ! (id_len == 1 && c == 'L' && (*p == '\'' || *p == '"'))) {
-       register struct arglist *arg;
-
-       for (arg = arglist; arg != NULL; arg = arg->next) {
-         struct reflist *tpat;
-
-         if (arg->name[0] == c
-             && arg->length == id_len
-             && strncmp (arg->name, id_beg, size_fromInt (id_len)) == 0) {
-           char *p1;
-
-           if (expected_delimiter && CPPOPTIONS (pfile)->warn_stringify) {
-             if (cppReader_isTraditional (pfile)) {
-               cppReader_warning (pfile,
-                                  message ("macro argument `%x' is stringified.",
-                                           cstring_prefix (cstring_fromChars (arg->name), id_len)));
-             } else {
-               cppReader_warning (pfile,
-                                  message ("macro arg `%x' would be stringified with -traditional.",
-                                           cstring_prefix (cstring_fromChars (arg->name), id_len)));
-             }
-           }
-           /* If ANSI, don't actually substitute inside a string.  */
-           if (!cppReader_isTraditional (pfile) && expected_delimiter)
-             /*@innerbreak@*/ break;
-           /* make a pat node for this arg and append it to the end of
-              the pat list */
-           tpat = (struct reflist *) dmalloc (sizeof (*tpat));
-           tpat->next = NULL;
-           tpat->raw_before = (concat == id_beg);
-           tpat->raw_after = 0;
-           tpat->rest_args = arg->rest_args;
-           tpat->stringify = (cppReader_isTraditional (pfile)
-                              ? expected_delimiter != '\0'
-                              : stringify == id_beg);
-
-           if (endpat == NULL)
-             {
-               defn->pattern = tpat;
-             }
-           else
-             {
-               endpat->next = tpat;
-               /*@-branchstate@*/
-             } /*@=branchstate@*/ /* evs 2000 was =branchstate */
-
-           endpat = tpat;
-
-           tpat->argno = arg->argno;
-           tpat->nchars = exp_p - lastp;
-
-           p1 = p;
-
-           SKIP_WHITE_SPACE (p1);
-
-           if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#')
-             {
-               tpat->raw_after = 1;
-             }
-
-           lastp = exp_p;      /* place to start copying from next time */
-           skipped_arg = 1;
-
-           /*@innerbreak@*/ break;
-         }
-       }
-      }
-
-      /* If this was not a macro arg, copy it into the expansion.  */
-      if (skipped_arg == 0) {
-       register char *lim1 = p;
-       p = id_beg;
-
-       while (p != lim1)
-         {
-           *exp_p++ = *p++;
-         }
-
-       if (stringify == id_beg)
-         cppReader_errorLit (pfile,
-                             cstring_makeLiteralTemp ("`#' operator should be followed by a macro argument name"));
-      }
-    }
-  }
-
-  if (!cppReader_isTraditional (pfile) && expected_delimiter == '\0')
-    {
-      /* If ANSI, put in a "@ " marker to prevent token pasting.
-        But not if "inside a string" (which in ANSI mode
-        happens only for -D option).  */
-      *exp_p++ = '@';
-      *exp_p++ = ' ';
-    }
-
-  *exp_p = '\0';
-
-  defn->length = size_fromInt (exp_p - defn->expansion);
-
-  /* Crash now if we overrun the allocated size.  */
-  if (defn->length + 1 > maxsize)
-    {
-      llfatalbug (cstring_makeLiteral ("Maximum definition size exceeded."));
-    }
-
-  return defn;
-}
-
-/*
- * special extension string that can be added to the last macro argument to
- * allow it to absorb the "rest" of the arguments when expanded.  Ex:
- *             #define wow(a, b...)            process (b, a, b)
- *             { wow (1, 2, 3); }      ->      { process (2, 3, 1, 2, 3); }
- *             { wow (one, two); }     ->      { process (two, one, two); }
- * if this "rest_arg" is used with the concat token '##' and if it is not
- * supplied then the token attached to with ## will not be outputted.  Ex:
- *             #define wow (a, b...)           process (b ## , a, ## b)
- *             { wow (1, 2); }         ->      { process (2, 1, 2); }
- *             { wow (one); }          ->      { process (one); {
- */
-
-/*@-readonlytrans@*/
-static char rest_extension[] = "...";
-/*:=readonlytrans@*/
-
-/*@notfunction@*/
-#define REST_EXTENSION_LENGTH  (sizeof (rest_extension) - 1)
-
-/* Create a DEFINITION node from a #define directive.  Arguments are
-   as for do_define.  */
-
-static /*@null@*/ MACRODEF
-create_definition (char *buf, char *limit,
-                  cppReader *pfile, bool predefinition,
-                  bool noExpand)
-{
-  char *bp;                    /* temp ptr into input buffer */
-  char *symname;               /* remember where symbol name starts */
-  int sym_length;              /* and how long it is */
-  int rest_args = 0;   /* really int! */
-  int line;
-  int col;
-  cstring file = (CPPBUFFER (pfile) != NULL)
-    ? CPPBUFFER (pfile)->nominal_fname : cstring_makeLiteralTemp ("");
-  DEFINITION *defn;
-  int arglengths = 0;          /* Accumulate lengths of arg names
-                                  plus number of args.  */
-  MACRODEF mdef;
-
-  cppBuffer_lineAndColumn (CPPBUFFER (pfile), &line, &col);
-
-  bp = buf;
-
-  while (is_hor_space[(int) *bp])
-    {
-      bp++;
-    }
-
-  symname = bp;                        /* remember where it starts */
-
-  sym_length = cppReader_checkMacroName (pfile, bp, cstring_makeLiteralTemp ("macro"));
-
-  bp += sym_length;
-
-  /* Lossage will occur if identifiers or control keywords are broken
-     across lines using backslash.  This is not the right place to take
-     care of that.  */
-
-  if (*bp == '(') {
-    struct arglist *arg_ptrs = NULL;
-    int argno = 0;
-
-    bp++;                      /* skip '(' */
-    SKIP_WHITE_SPACE (bp);
-
-    /* Loop over macro argument names.  */
-    while (*bp != ')')
-      {
-       struct arglist *temp = (struct arglist *) dmalloc (sizeof (*temp));
-       temp->name = bp;
-       temp->next = arg_ptrs;
-       temp->argno = argno++;
-       temp->rest_args = 0;
-
-       arg_ptrs = temp;
-
-       if (rest_args != 0)
-         {
-           cppReader_pedwarn (pfile,
-                        message ("another parameter follows `%s'",
-                                 cstring_fromChars (rest_extension)));
-         }
-
-       if (!is_idstart[(int) *bp])
-         {
-           cppReader_pedwarnLit (pfile,
-                           cstring_makeLiteralTemp ("invalid character in macro parameter name"));
-         }
-
-       /* Find the end of the arg name.  */
-       while (is_idchar[(int) *bp])
-         {
-           bp++;
-           /* do we have a "special" rest-args extension here? */
-           if (limit - bp > size_toInt (REST_EXTENSION_LENGTH)
-               && strncmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0)
-             {
-               rest_args = 1;
-               temp->rest_args = 1;
-               /*@innerbreak@*/ break;
-             }
-         }
-
-       temp->length = bp - temp->name;
-
-       if (rest_args != 0)
-         {
-           bp += REST_EXTENSION_LENGTH;
-         }
-
-       arglengths += temp->length + 2;
-       SKIP_WHITE_SPACE (bp);
-
-       if (temp->length == 0 || (*bp != ',' && *bp != ')')) {
-         cppReader_errorLit (pfile,
-                       cstring_makeLiteralTemp ("Parameter list for #define is not parseable"));
-         goto nope;
-       }
-
-       if (*bp == ',') {
-         bp++;
-         SKIP_WHITE_SPACE (bp);
-       }
-       if (bp >= limit) {
-         cppReader_errorLit (pfile,
-                       cstring_makeLiteralTemp ("unterminated parameter list in `#define'"));
-         goto nope;
-       }
-       {
-         struct arglist *otemp;
-
-         for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
-           {
-             if (temp->length == otemp->length &&
-                 strncmp (temp->name, otemp->name, size_fromInt (temp->length)) == 0) {
-               cstring name = cstring_copyLength (temp->name, temp->length);
-               cppReader_error (pfile,
-                          message ("duplicate argument name `%x' in `#define'", name));
-               goto nope;
-             }
-           }
-       }
-      }
-
-    ++bp;                      /* skip paren */
-    SKIP_WHITE_SPACE (bp);
-    /* now everything from bp before limit is the definition.  */
-    defn = collect_expansion (pfile, bp, limit, argno, arg_ptrs);
-    defn->rest_args = rest_args;
-    
-    /* Now set defn->args.argnames to the result of concatenating
-       the argument names in reverse order
-       with comma-space between them.  */
-    defn->args.argnames = (char *) dmalloc (size_fromInt (arglengths + 1));
-
-    {
-      struct arglist *temp;
-      int i = 0;
-      for (temp = arg_ptrs; temp != NULL; temp = temp->next) {
-       memcpy (&defn->args.argnames[i], temp->name, size_fromInt (temp->length));
-       i += temp->length;
-       if (temp->next != 0) {
-         defn->args.argnames[i++] = ',';
-         defn->args.argnames[i++] = ' ';
-       }
-      }
-
-      defn->args.argnames[i] = '\0';
-    }
-
-    sfree (arg_ptrs);
-  } else {
-    /* Simple expansion or empty definition.  */
-
-    if (bp < limit)
-      {
-       if (is_hor_space[(int) *bp]) {
-         bp++;
-         SKIP_WHITE_SPACE (bp);
-       } else {
-         switch (*bp) {
-         case '!':  case '"':  case '#':  case '%':  case '&':  case '\'':
-         case ')':  case '*':  case '+':  case ',':  case '-':  case '.':
-         case '/':  case ':':  case ';':  case '<':  case '=':  case '>':
-         case '?':  case '[':  case '\\': case ']':  case '^':  case '{':
-         case '|':  case '}':  case '~':
-           cppReader_warning (pfile,
-                        message ("Missing white space after #define %x",
-                                 cstring_prefix (cstring_fromChars (symname),
-                                                 sym_length)));
-           break;
-
-         default:
-           cppReader_pedwarn (pfile,
-                        message ("Missing white space after #define %x",
-                                 cstring_prefix (cstring_fromChars (symname),
-                                                 sym_length)));
-           break;
-         }
-       }
-      }
-    /* now everything from bp before limit is the definition.  */
-    defn = collect_expansion (pfile, bp, limit, -1, NULL);
-    defn->args.argnames = mstring_createEmpty ();
-  }
-
-  defn->noExpand = noExpand;
-  DPRINTF (("No expand: %d", noExpand));
-
-  defn->line = line;
-
-  /* not: llassert (cstring_isUndefined (defn->file)); */
-  defn->file = file;
-
-  /* OP is null if this is a predefinition */
-  defn->predefined = predefinition;
-  mdef.defn = defn;
-  mdef.symnam = symname;
-  mdef.symlen = sym_length;
-
-  return mdef;
-
-nope:
-  mdef.defn = NULL;
-  mdef.symnam = NULL;
-  return mdef;
-}
-
-/* Check a purported macro name SYMNAME, and yield its length.
-   USAGE is the kind of name this is intended for.  */
-
-int cppReader_checkMacroName (cppReader *pfile,
-                     char *symname,
-                     cstring usage)
-{
-  char *p;
-  size_t sym_length;
-
-  for (p = symname; is_idchar[(int) *p]; p++)
-    {
-      ;
-    }
-
-  sym_length = size_fromInt (p - symname);
-
-  if (sym_length == 0
-      || (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))
-    cppReader_error (pfile, message ("invalid %s name", usage));
-  else if (!is_idstart[(int) *symname])
-    {
-      char *msg = (char *) dmalloc (sym_length + 1);
-      memcpy (msg, symname, sym_length);
-      msg[sym_length] = '\0';
-      cppReader_error (pfile, message ("invalid %s name `%s'", usage,
-                                      cstring_fromChars (msg)));
-      sfree (msg);
-    }
-  else
-    {
-      if ((strncmp (symname, "defined", 7) == 0) && sym_length == 7)
-       {
-         cppReader_error (pfile, message ("invalid %s name `defined'", usage));
-       }
-    }
-
-  return size_toInt (sym_length);
-}
-
-/* Return zero if two DEFINITIONs are isomorphic.  */
-
-static bool
-compare_defs (DEFINITION *d1, DEFINITION *d2)
-{
-  register struct reflist *a1, *a2;
-  register char *p1 = d1->expansion;
-  register char *p2 = d2->expansion;
-  bool first = TRUE;
-
-  if (d1->nargs != d2->nargs)
-    {
-      return TRUE;
-    }
-
-  llassert (d1->args.argnames != NULL);
-  llassert (d2->args.argnames != NULL);
-
-  if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames) != 0)
-    {
-      return TRUE;
-    }
-
-  for (a1 = d1->pattern, a2 = d2->pattern;
-       (a1 != NULL) && (a2 != NULL);
-       a1 = a1->next, a2 = a2->next) {
-    if (!((a1->nchars == a2->nchars
-          && (strncmp (p1, p2, size_fromInt (a1->nchars)) == 0))
-         || ! comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
-       || a1->argno != a2->argno
-       || a1->stringify != a2->stringify
-       || a1->raw_before != a2->raw_before
-       || a1->raw_after != a2->raw_after)
-      return TRUE;
-    first = 0;
-    p1 += a1->nchars;
-    p2 += a2->nchars;
-  }
-  if (a1 != a2)
-    return TRUE;
-
-  if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
-                    p2, d2->length - (p2 - d2->expansion), 1))
-    return TRUE;
-
-  return FALSE;
-}
-
-/* Return TRUE if two parts of two macro definitions are effectively different.
-   One of the parts starts at BEG1 and has LEN1 chars;
-   the other has LEN2 chars at BEG2.
-   Any sequence of whitespace matches any other sequence of whitespace.
-   FIRST means these parts are the first of a macro definition;
-   so ignore leading whitespace entirely.
-   LAST means these parts are the last of a macro definition;
-   so ignore trailing whitespace entirely.  */
-
-static bool
-comp_def_part (bool first, char *beg1, int len1, char *beg2, int len2, bool last)
-{
-  char *end1 = beg1 + len1;
-  char *end2 = beg2 + len2;
-
-  if (first) {
-    while (beg1 != end1 && is_space[(int) *beg1]) { beg1++; }
-    while (beg2 != end2 && is_space[(int) *beg2]) { beg2++; }
-  }
-  if (last) {
-    while (beg1 != end1 && is_space[(int) end1[-1]]) { end1--; }
-    while (beg2 != end2 && is_space[(int) end2[-1]]) { end2--; }
-  }
-  while (beg1 != end1 && beg2 != end2) {
-    if (is_space[(int) *beg1] && is_space[(int) *beg2]) {
-      while (beg1 != end1 && is_space[(int) *beg1]) { beg1++; }
-      while (beg2 != end2 && is_space[(int) *beg2]) { beg2++; }
-    } else if (*beg1 == *beg2) {
-      beg1++; beg2++;
-    } else break;
-  }
-  return (beg1 != end1) || (beg2 != end2);
-}
-
-/* Process a #define command.
-   BUF points to the contents of the #define command, as a contiguous string.
-   LIMIT points to the first character past the end of the definition.
-   KEYWORD is the keyword-table entry for #define,
-   or NULL for a "predefined" macro.  */
-
-static int
-do_defineAux (cppReader *pfile, struct directive *keyword,
-             char *buf, char *limit, bool noExpand)
-{
-  int hashcode;
-  MACRODEF mdef;
-  hashNode hp;
-  
-  DPRINTF (("Define aux: %d", noExpand));
-
-  mdef = create_definition (buf, limit, pfile, keyword == NULL, noExpand);
-
-  if (mdef.defn == 0)
-    goto nope;
-
-  hashcode = hashf (mdef.symnam, mdef.symlen, CPP_HASHSIZE);
-
-  DPRINTF (("Macro: %s / %s", 
-           cstring_copyLength (mdef.symnam, mdef.symlen),
-           bool_unparse (noExpand)));
-
-  if ((hp = cppReader_lookup (mdef.symnam, mdef.symlen, hashcode)) != NULL)
-    {
-      bool ok = FALSE;
-
-      /* Redefining a precompiled key is ok.  */
-      if (hp->type == T_PCSTRING)
-       ok = TRUE;
-      /* Redefining a macro is ok if the definitions are the same.  */
-      else if (hp->type == T_MACRO)
-       ok = !compare_defs (mdef.defn, hp->value.defn);
-      /* Redefining a constant is ok with -D.  */
-      else if (hp->type == T_CONST)
-       ok = !CPPOPTIONS (pfile)->done_initializing;
-      else {
-       BADBRANCH;
-      }
-
-      /* Print the warning if it's not ok.  */
-      if (!ok)
-       {
-         /*
-         ** If we are passing through #define and #undef directives, do
-         ** that for this re-definition now.
-         */
-
-         if (CPPOPTIONS (pfile)->debug_output && (keyword != NULL))
-           {
-             /* llassert (keyword != NULL); */
-             pass_thru_directive (buf, limit, pfile, keyword);
-           }
-
-         cpp_setLocation (pfile);
-
-         if (hp->type == T_MACRO)
-           {
-             if (hp->value.defn->noExpand)
-               {
-                 ; /* error will be reported checking macros */
-               }
-             else
-               {
-                 genppllerrorhint
-                   (FLG_MACROREDEF,
-                    message ("Macro %q already defined",
-                             cstring_copyLength (mdef.symnam, mdef.symlen)),
-                    message ("%q: Previous definition of %q",
-                             fileloc_unparseRaw (hp->value.defn->file,
-                                                (int) hp->value.defn->line),
-                             cstring_copyLength (mdef.symnam, mdef.symlen)));
-               }
-           }
-         else
-           {
-             genppllerror (FLG_MACROREDEF,
-                           message ("Macro %q already defined",
-                                    cstring_copyLength (mdef.symnam,
-                                                        mdef.symlen)));
-
-           }
-       }
-
-      /* Replace the old definition.  */
-      hp->type = T_MACRO;
-      hp->value.defn = mdef.defn;
-    }
-  else
-    {
-      /*
-      ** If we are passing through #define and #undef directives, do
-      ** that for this new definition now.
-      */
-
-      hashNode hn;
-
-      if (CPPOPTIONS (pfile)->debug_output && (keyword != NULL))
-       {
-         pass_thru_directive (buf, limit, pfile, keyword);
-       }
-
-      DPRINTF (("Define macro: %s / %d", 
-               mdef.symnam, mdef.defn->noExpand));
-      
-      hn = cppReader_installMacro (mdef.symnam, mdef.symlen, mdef.defn, hashcode);
-      /*@-branchstate@*/
-    } /*@=branchstate@*/
-
-  return 0;
-
-nope:
-
-  return 1;
-}
-
-static int
-do_define (cppReader *pfile, struct directive *keyword,
-          char *buf, char *limit)
-{
-  DPRINTF (("Regular do define"));
-  return do_defineAux (pfile, keyword, buf, limit, FALSE);
-}
-
-/* This structure represents one parsed argument in a macro call.
-   `raw' points to the argument text as written (`raw_length' is its length).
-   `expanded' points to the argument's macro-expansion
-   (its length is `expand_length').
-   `stringified_length' is the length the argument would have
-   if stringified.
-   `use_count' is the number of times this macro arg is substituted
-   into the macro.  If the actual use count exceeds 10,
-   the value stored is 10.  */
-
-/* raw and expanded are relative to ARG_BASE */
-/*@notfunction@*/
-#define ARG_BASE ((pfile)->token_buffer)
-
-struct argdata {
-  /* Strings relative to pfile->token_buffer */
-  long raw;
-  size_t expanded;
-  size_t stringified;
-  int raw_length;
-  int expand_length;
-  int stringified_length;
-  bool newlines;
-  int use_count;
-};
-
-/* Allocate a new cppBuffer for PFILE, and push it on the input buffer stack.
-   If BUFFER != NULL, then use the LENGTH characters in BUFFER
-   as the new input buffer.
-   Return the new buffer, or NULL on failure.  */
-
-/*@null@*/ /*@exposed@*/ cppBuffer *
-cppReader_pushBuffer (cppReader *pfile, char *buffer, size_t length)
-{
-  cppBuffer *buf = cppReader_getBuffer (pfile);
-
-  if (buf == pfile->buffer_stack)
-    {
-      cppReader_fatalError
-       (pfile,
-        message ("%s: macro or `#include' recursion too deep",
-                 (buf->fname != NULL)
-                 ? buf->fname
-                 : cstring_makeLiteral ("<no name>")));
-      sfreeEventually (buffer);
-      return NULL;
-    }
-
-  llassert (buf != NULL);
-
-  buf--;
-  memset ((char *) buf, 0, sizeof (*buf));
-  CPPBUFFER (pfile) = buf;
-
-  buf->if_stack = pfile->if_stack;
-  buf->cleanup = cppReader_nullCleanup;
-  buf->underflow = cppReader_nullUnderflow;
-  buf->buf = buffer;
-  buf->cur = buf->buf;
-
-  if (buffer != NULL)
-    {
-      buf->alimit = buf->rlimit = buffer + length;
-    }
-  else
-    {
-      buf->alimit = buf->rlimit = NULL;
-    }
-
-  return buf;
-}
-
-cppBuffer *
-cppReader_popBuffer (cppReader *pfile)
-{
-  cppBuffer *buf = CPPBUFFER (pfile);
-
-  llassert (buf != NULL);
-
-  (void) (*buf->cleanup) (buf, pfile);
-  return ++CPPBUFFER (pfile);
-}
-
-/* Scan until CPPBUFFER (PFILE) is exhausted into PFILE->token_buffer.
-   Pop the buffer when done.  */
-
-void
-cppReader_scanBuffer (cppReader *pfile)
-{
-  cppBuffer *buffer = CPPBUFFER (pfile);
-  for (;;)
-    {
-      enum cpp_token token;
-      
-      token = cppGetToken (pfile);
-
-      if (token == CPP_EOF) /* Should not happen ...  */
-       {
-         break;
-       }
-
-      if (token == CPP_POP && CPPBUFFER (pfile) == buffer)
-       {
-         (void) cppReader_popBuffer (pfile);
-         break;
-       }
-    }
-}
-
-/*
- * Rescan a string (which may have escape marks) into pfile's buffer.
- * Place the result in pfile->token_buffer.
- *
- * The input is copied before it is scanned, so it is safe to pass
- * it something from the token_buffer that will get overwritten
- * (because it follows cppReader_getWritten).  This is used by do_include.
- */
-
-static void
-cpp_expand_to_buffer (cppReader *pfile, char *buf, size_t length)
-{
-  register cppBuffer *ip;
-  char *limit = buf + length;
-  char *buf1, *p1, *p2;
-
-  /* evans - 2001-08-26
-  ** length is unsigned - this doesn't make sense
-  if (length < 0)
-    abort ();
-  **
-  */
-
-  /* Set up the input on the input stack.  */
-
-  buf1 = (char *) dmalloc (length + 1);
-
-  p1 = buf;
-  p2 = buf1;
-
-  while (p1 != limit)
-    {
-      *p2++ = *p1++;
-    }
-
-  buf1[length] = '\0';
-
-  ip = cppReader_pushBuffer (pfile, buf1, length);
-
-  if (ip == NULL)
-    return;
-
-  ip->has_escapes = TRUE;
-
-  /* Scan the input, create the output.  */
-  cppReader_scanBuffer (pfile);
-
-  cppReader_nullTerminate (pfile);
-}
-
-static void
-adjust_position (char *buf, char *limit, int *linep, int *colp)
-{
-  while (buf < limit)
-    {
-      char ch = *buf++;
-      if (ch == '\n')
-       (*linep)++, (*colp) = 1;
-      else
-       (*colp)++;
-    }
-}
-
-/* Move line_base forward, updating lineno and colno.  */
-
-static void
-update_position (cppBuffer *pbuf)
-{
-  char *old_pos;
-  char *new_pos = pbuf->cur;
-  register struct parse_marker *mark;
-
-  llassert (pbuf->buf != NULL);
-  old_pos = pbuf->buf + pbuf->line_base;
-
-  for (mark = pbuf->marks;  mark != NULL; mark = mark->next)
-    {
-      if (pbuf->buf + mark->position < new_pos)
-       new_pos = pbuf->buf + mark->position;
-    }
-  pbuf->line_base += new_pos - old_pos;
-
-  llassert (old_pos != NULL);
-  llassert (new_pos != NULL);
-
-  adjust_position (old_pos, new_pos, &pbuf->lineno, &pbuf->colno);
-}
-
-void
-cppBuffer_lineAndColumn (/*@null@*/ cppBuffer *pbuf, /*@out@*/ int *linep,
-                        /*@null@*/ /*@out@*/ int *colp)
-{
-  int dummy;
-
-  if (colp == NULL)
-    {
-      colp = &dummy;
-      /*@-branchstate@*/
-    } /*@=branchstate@*/
-
-  if (pbuf != NULL)
-    {
-      *linep = pbuf->lineno;
-      *colp = pbuf->colno;
-
-      llassert (pbuf->buf != NULL);
-      llassert (pbuf->cur != NULL);
-
-      adjust_position (pbuf->buf + pbuf->line_base, pbuf->cur, linep, colp);
-    }
-  else
-    {
-      *linep = 0;
-      *colp = 0;
-    }
-}
-
-/* Return the cppBuffer that corresponds to a file (not a macro).  */
-
-/*@exposed@*/ /*@null@*/ cppBuffer *cppReader_fileBuffer (cppReader *pfile)
-{
-  cppBuffer *ip = cppReader_getBuffer (pfile);
-
-  for ( ;
-       ip != NULL && ip != cppReader_nullBuffer (pfile); 
-       ip = cppBuffer_prevBuffer (ip))
-    {
-      if (ip->fname != NULL)
-       {
-         return ip;
-       }
-    }
-  
-  return NULL;
-}
-
-static long
-count_newlines (char *buf, char *limit)
-{
-  register long count = 0;
-
-  while (buf < limit)
-    {
-      char ch = *buf++;
-      if (ch == '\n')
-       count++;
-    }
-  return count;
-}
-
-/*
- * write out a #line command, for instance, after an #include file.
- * If CONDITIONAL is nonzero, we can omit the #line if it would
- * appear to be a no-op, and we can output a few newlines instead
- * if we want to increase the line number by a small amount.
- * FILE_CHANGE says whether we are entering a file, leaving, or neither.
- */
-
-static void
-output_line_command (cppReader *pfile, bool conditional,
-                    enum file_change_code file_change)
-{
-  int line, col;
-  cppBuffer *ip = CPPBUFFER (pfile);
-  cppBuffer *buf;
-
-  llassert (ip != NULL);
-
-  if (ip->fname == NULL)
-    return;
-
-  update_position (ip);
-
-  if (CPPOPTIONS (pfile)->no_line_commands
-      || CPPOPTIONS (pfile)->no_output)
-    return;
-
-  buf = CPPBUFFER (pfile);
-
-  llassert (buf != NULL);
-
-  line = buf->lineno;
-  col = buf->colno;
-
-  llassert (ip->cur != NULL);
-
-  adjust_position (cppLineBase (ip), ip->cur, &line, &col);
-
-  if (CPPOPTIONS (pfile)->no_line_commands)
-    return;
-
-  if (conditional) {
-    if (line == pfile->lineno)
-      return;
-
-    /* If the inherited line number is a little too small,
-       output some newlines instead of a #line command.  */
-
-    if (line > pfile->lineno && line < pfile->lineno + 8)
-      {
-       cppReader_reserve (pfile, 20);
-       while (line > pfile->lineno)
-         {
-           cppReader_putCharQ (pfile, '\n');
-           pfile->lineno++;
-         }
-
-       return;
-      }
-  }
-
-  cppReader_reserve (pfile,
-                    size_fromInt (4 * cstring_length (ip->nominal_fname) + 50));
-
-  {
-#ifdef OUTPUT_LINE_COMMANDS
-    static char sharp_line[] = "#line ";
-#else
-    static char sharp_line[] = "# ";
-#endif
-    cppReader_putStrN (pfile, sharp_line, sizeof(sharp_line)-1);
-  }
-
-  sprintf (cppReader_getPWritten (pfile), "%d ", line);
-  cppReader_adjustWritten (pfile, strlen (cppReader_getPWritten (pfile)));
-
-  quote_string (pfile, cstring_toCharsSafe (ip->nominal_fname));
-
-  if (file_change != same_file) {
-    cppReader_putCharQ (pfile, ' ');
-    cppReader_putCharQ (pfile, file_change == enter_file ? '1' : '2');
-  }
-  /* Tell cc1 if following text comes from a system header file.  */
-  if (ip->system_header_p != '\0') {
-    cppReader_putCharQ (pfile, ' ');
-    cppReader_putCharQ (pfile, '3');
-  }
-#ifndef NO_IMPLICIT_EXTERN_C
-  /* Tell cc1plus if following text should be treated as C.  */
-  if (ip->system_header_p == (char) 2 && CPPOPTIONS (pfile)->cplusplus) {
-    cppReader_putCharQ (pfile, ' ');
-    cppReader_putCharQ (pfile, '4');
-  }
-#endif
-  cppReader_putCharQ (pfile, '\n');
-  pfile->lineno = line;
-}
-
-
-/*
- * Parse a macro argument and append the info on PFILE's token_buffer.
- * REST_ARGS means to absorb the rest of the args.
- * Return nonzero to indicate a syntax error.
- */
-
-static enum cpp_token
-macarg (cppReader *pfile, int rest_args)
-{
-  int paren = 0;
-  enum cpp_token token;
-  char save_put_out_comments = CPPOPTIONS (pfile)->put_out_comments;
-  bool oldexpand = pfile->no_macro_expand;
-  CPPOPTIONS (pfile)->put_out_comments = 1;
-
-  /* Try to parse as much of the argument as exists at this
-     input stack level.  */
-
-  pfile->no_macro_expand = TRUE;
-
-  for (;;)
-    {
-      token = cppGetToken (pfile);
-
-      switch (token)
-       {
-       case CPP_EOF:
-         goto done;
-       case CPP_POP:
-         /* If we've hit end of file, it's an error (reported by caller).
-            Ditto if it's the end of cpp_expand_to_buffer text.
-            If we've hit end of macro, just continue.  */
-         if (!cppBuffer_isMacro (CPPBUFFER (pfile)))
-           goto done;
-         /*@switchbreak@*/ break;
-       case CPP_LPAREN:
-         paren++;
-         /*@switchbreak@*/ break;
-       case CPP_RPAREN:
-         if (--paren < 0)
-           goto found;
-         /*@switchbreak@*/ break;
-       case CPP_COMMA:
-         /* if we've returned to lowest level and
-            we aren't absorbing all args */
-         if (paren == 0 && rest_args == 0)
-           goto found;
-         /*@switchbreak@*/ break;
-       found:
-         /* Remove ',' or ')' from argument buffer.  */
-         cppReader_adjustWritten (pfile, -1);
-         goto done;
-       default:
-         ;
-       }
-    }
-
-done:
-  CPPOPTIONS (pfile)->put_out_comments = save_put_out_comments;
-  pfile->no_macro_expand = oldexpand;
-
-  return token;
-}
-
-
-/* Turn newlines to spaces in the string of length LENGTH at START,
-   except inside of string constants.
-   The string is copied into itself with its beginning staying fixed.  */
-
-static int
-change_newlines (char *start, int length)
-{
-  register char *ibp;
-  register char *obp;
-  register char *limit;
-  char c;
-
-  ibp = start;
-  limit = start + length;
-  obp = start;
-
-  while (ibp < limit) {
-    *obp++ = c = *ibp++;
-    switch (c) {
-
-    case '\'':
-    case '\"':
-      /* Notice and skip strings, so that we don't delete newlines in them.  */
-      {
-       char quotec = c;
-       while (ibp < limit) {
-         *obp++ = c = *ibp++;
-         if (c == quotec)
-           /*@innerbreak@*/ break;
-         if (c == '\n' && quotec == '\'')
-           /*@innerbreak@*/ break;
-       }
-      }
-    /*@switchbreak@*/ break;
-    }
-  }
-
-  return obp - start;
-}
-
-static /*@observer@*/ struct tm *
-timestamp (/*@returned@*/ cppReader *pfile)
-{
-  if (pfile->timebuf == NULL)
-    {
-      time_t t = time ((time_t *) 0);
-      pfile->timebuf = localtime (&t);
-    }
-
-  llassert (pfile->timebuf != NULL);
-
-  return pfile->timebuf;
-}
-
-static ob_mstring monthnames[] = {
-  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
-} ;
-
-/*
- * expand things like __FILE__.  Place the expansion into the output
- * buffer *without* rescanning.
- */
-
-static void
-special_symbol (hashNode hp, cppReader *pfile)
-{
-  cstring buf = cstring_undefined;
-  size_t len;
-  int true_indepth;
-  cppBuffer *ip;
-  struct tm *timebuf;
-
-  int paren = 0;               /* For special `defined' keyword */
-
-  for (ip = cppReader_getBuffer (pfile); ip != NULL; ip = cppBuffer_prevBuffer (ip))
-    {
-      if (ip == cppReader_nullBuffer (pfile))
-       {
-         cppReader_errorLit (pfile,
-                       cstring_makeLiteralTemp ("cccp error: not in any file?!"));
-         return;                       /* the show must go on */
-       }
-
-      if (ip != NULL && ip->fname != NULL)
-       {
-         break;
-       }
-    }
-
-  switch (hp->type)
-    {
-    case T_FILE:
-    case T_BASE_FILE:
-      {
-       char *string;
-       if (hp->type == T_BASE_FILE)
-         {
-           while (cppBuffer_prevBuffer (ip) != cppReader_nullBuffer (pfile))
-             {
-               ip = cppBuffer_prevBuffer (ip);
-             }
-         }
-
-       llassert (ip != NULL);
-       string = cstring_toCharsSafe (ip->nominal_fname);
-
-       if (string == NULL)
-         {
-           string = "";
-         }
-
-       cppReader_reserve (pfile, 3 + 4 * strlen (string));
-       quote_string (pfile, string);
-       return;
-      }
-
-    case T_INCLUDE_LEVEL:
-      true_indepth = 0;
-      ip = cppReader_getBuffer (pfile);
-
-      for (;  ip != cppReader_nullBuffer (pfile) && ip != NULL;
-          ip = cppBuffer_prevBuffer (ip))
-       {
-         if (ip != NULL && ip->fname != NULL)
-           {
-             true_indepth++;
-           }
-       }
-
-      buf = message ("%d", true_indepth - 1);
-      break;
-
-    case T_VERSION:
-      buf = message ("\"%s\"", cstring_makeLiteralTemp (CPP_VERSION));
-      break;
-
-#ifndef NO_BUILTIN_SIZE_TYPE
-    case T_SIZE_TYPE:
-      buf = cstring_makeLiteral (SIZE_TYPE);
-      break;
-#endif
-
-#ifndef NO_BUILTIN_PTRDIFF_TYPE
-    case T_PTRDIFF_TYPE:
-      buf = cstring_makeLiteral (PTRDIFF_TYPE);
-      break;
-#endif
-
-    case T_WCHAR_TYPE:
-      buf = cstring_makeLiteral (cppReader_wcharType (pfile));
-      break;
-
-    case T_USER_LABEL_PREFIX_TYPE:
-      buf = cstring_makeLiteral (USER_LABEL_PREFIX);
-      break;
-
-    case T_REGISTER_PREFIX_TYPE:
-      buf = cstring_makeLiteral (REGISTER_PREFIX);
-      break;
-
-    case T_CONST:
-      buf = message ("%d", hp->value.ival);
-      break;
-
-    case T_SPECLINE:
-      {
-       if (ip != NULL)
-         {
-           int line = ip->lineno;
-           int col = ip->colno;
-
-           llassert (ip->cur != NULL);
-           adjust_position (cppLineBase (ip), ip->cur, &line, &col);
-
-           buf = message ("%d", (int) line);
-         }
-       else
-         {
-           BADBRANCH;
-         }
-      }
-    break;
-
-    case T_DATE:
-    case T_TIME:
-      {
-       char *sbuf = (char *) dmalloc (20);
-       timebuf = timestamp (pfile);
-       if (hp->type == T_DATE)
-         {
-           sprintf (sbuf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon],
-                    timebuf->tm_mday, timebuf->tm_year + 1900);
-         }
-       else
-         {
-           sprintf (sbuf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min,
-                    timebuf->tm_sec);
-         }
-
-       buf = cstring_fromCharsNew (sbuf);
-       sfree (sbuf);
-       break;
-      }
-
-    case T_SPEC_DEFINED:
-      buf = cstring_makeLiteral (" 0 ");     /* Assume symbol is not defined */
-      ip = cppReader_getBuffer (pfile);
-
-      llassert (ip->cur != NULL);
-      SKIP_WHITE_SPACE (ip->cur);
-
-      if (*ip->cur == '(')
-       {
-         paren++;
-         ip->cur++;                    /* Skip over the paren */
-         SKIP_WHITE_SPACE (ip->cur);
-       }
-
-      if (!is_idstart[(int) *ip->cur])
-       goto oops;
-      if (ip->cur[0] == 'L' && (ip->cur[1] == '\'' || ip->cur[1] == '"'))
-       goto oops;
-
-      if ((hp = cppReader_lookup (ip->cur, -1, -1)) != 0)
-       {
-         cstring_free (buf);
-         buf = cstring_makeLiteral (" 1 ");
-       }
-
-      while (is_idchar[(int) *ip->cur])
-       {
-         ++ip->cur;
-       }
-
-      SKIP_WHITE_SPACE (ip->cur);
-
-      if (paren != 0)
-       {
-         if (*ip->cur != ')')
-           goto oops;
-         ++ip->cur;
-       }
-      break;
-
-    oops:
-
-      cppReader_errorLit (pfile,
-                   cstring_makeLiteralTemp ("`defined' without an identifier"));
-      break;
-
-    default:
-      cpp_setLocation (pfile);
-      llfatalerror (message ("Pre-processing error: invalid special hash type"));
-    }
-
-  len = size_fromInt (cstring_length (buf));
-
-  cppReader_reserve (pfile, len + 1);
-  cppReader_putStrN (pfile, cstring_toCharsSafe (buf), len);
-  cppReader_nullTerminateQ (pfile);
-
-  cstring_free (buf);
-  return;
-}
-
-/* Write out a #define command for the special named MACRO_NAME
-   to PFILE's token_buffer.  */
-
-static void
-dump_special_to_buffer (cppReader *pfile, char *macro_name)
-{
-  static char define_directive[] = "#define ";
-  size_t macro_name_length = strlen (macro_name);
-  output_line_command (pfile, 0, same_file);
-  cppReader_reserve (pfile, sizeof(define_directive) + macro_name_length);
-  cppReader_putStrN (pfile, define_directive, sizeof(define_directive)-1);
-  cppReader_putStrN (pfile, macro_name, macro_name_length);
-  cppReader_putCharQ (pfile, ' ');
-  cpp_expand_to_buffer (pfile, macro_name, macro_name_length);
-  cppReader_putChar (pfile, '\n');
-}
-
-/* Initialize the built-in macros.  */
-
-static void
-cppReader_installBuiltin (/*@observer@*/ char *name, ctype ctyp,
-                         int len, enum node_type type,
-                         int ivalue, /*@null@*/ /*@only@*/ char *value,
-                         int hash)
-{
-  cstring sname = cstring_fromCharsNew (name);
-
-  llassert (usymtab_inGlobalScope ());
-
-  /*
-  ** Be careful here: this is done before the ctype table has
-  ** been initialized.
-  */
-
-  if (!usymtab_exists (sname))
-    {
-      uentry ue = uentry_makeConstant (sname, ctyp, fileloc_createBuiltin ());
-
-      if (ctype_equal (ctyp, ctype_string))
-       {
-         qualList ql = qualList_new ();
-         ql = qualList_add (ql, qual_createObserver ());
-         uentry_reflectQualifiers (ue, ql);
-         qualList_free (ql);
-       }
-      
-      usymtab_addGlobalEntry (ue);
-    }
-  else
-    {
-      ;
-    }
-
-  (void) cppReader_install (name, len, type, ivalue, value, hash);
-  cstring_free (sname);
-}
-
-static void
-cppReader_installBuiltinType (/*@observer@*/ char *name, ctype ctyp,
-                             int len, enum node_type type,
-                             int ivalue,
-                             /*@only@*/ /*@null@*/ char *value, int hash)
-{
-  cstring sname = cstring_fromChars (name);
-  /* evs 2000 07 10 - removed a memory leak, detected by lclint */
-
-  llassert (usymtab_inGlobalScope ());
-
-  if (!usymtab_existsTypeEither (sname))
-    {
-      uentry ue = uentry_makeDatatype (sname, ctyp,
-                                      NO, NO,
-                                      fileloc_createBuiltin ());
-      llassert (!usymtab_existsEither (sname));
-      usymtab_addGlobalEntry (ue);
-    }
-
-  (void) cppReader_install (name, len, type, ivalue, value, hash);
-}
-
-static void
-initialize_builtins (cppReader *pfile)
-{
-  cppReader_installBuiltin ("__LINE__", ctype_int, -1, T_SPECLINE, 0, NULL, -1);
-  cppReader_installBuiltin ("__DATE__", ctype_string, -1, T_DATE, 0, NULL, -1);
-  cppReader_installBuiltin ("__FILE__", ctype_string, -1, T_FILE, 0, NULL, -1);
-  cppReader_installBuiltin ("__BASE_FILE__", ctype_string, -1, T_BASE_FILE, 0, NULL, -1);
-  cppReader_installBuiltin ("__INCLUDE_LEVEL__", ctype_int, -1, T_INCLUDE_LEVEL, 0, NULL, -1);
-  cppReader_installBuiltin ("__VERSION__", ctype_string, -1, T_VERSION, 0, NULL, -1);
-#ifndef NO_BUILTIN_SIZE_TYPE
-  cppReader_installBuiltinType ("__SIZE_TYPE__", ctype_anyintegral, -1, T_SIZE_TYPE, 0, NULL, -1);
-#endif
-#ifndef NO_BUILTIN_PTRDIFF_TYPE
-  cppReader_installBuiltinType ("__PTRDIFF_TYPE__", ctype_anyintegral, -1, T_PTRDIFF_TYPE, 0, NULL, -1);
-#endif
-  cppReader_installBuiltinType ("__WCHAR_TYPE__", ctype_anyintegral, -1, T_WCHAR_TYPE, 0, NULL, -1);
-  cppReader_installBuiltin ("__USER_LABEL_PREFIX__", ctype_string, -1, T_USER_LABEL_PREFIX_TYPE, 0, NULL, -1);
-  cppReader_installBuiltin ("__REGISTER_PREFIX__", ctype_string, -1, T_REGISTER_PREFIX_TYPE, 0, NULL, -1);
-  cppReader_installBuiltin ("__TIME__", ctype_string, -1, T_TIME, 0, NULL, -1);
-
-  /*
-  ** No, don't define __STDC__
-  **
-
-  if (!cppReader_isTraditional (pfile))
-    {
-      cppReader_installBuiltin ("__STDC__", ctype_int, -1, T_CONST, STDC_VALUE, NULL, -1);
-    }
-
-  **
-  */
-
-# ifdef WIN32
-    cppReader_installBuiltin ("_WIN32", ctype_int, -1, T_CONST, STDC_VALUE, NULL, -1);
-# endif
-
-  /*
-  ** This is supplied using a -D by the compiler driver
-  ** so that it is present only when truly compiling with GNU C.
-  */
-
-  /*  cppReader_install ("__GNUC__", -1, T_CONST, 2, 0, -1);  */
-
-  cppReader_installBuiltin ("__LCLINT__", ctype_int, -1, T_CONST, 2, NULL, -1);
-
-  if (CPPOPTIONS (pfile)->debug_output)
-    {
-      dump_special_to_buffer (pfile, "__BASE_FILE__");
-      dump_special_to_buffer (pfile, "__VERSION__");
-#ifndef NO_BUILTIN_SIZE_TYPE
-      dump_special_to_buffer (pfile, "__SIZE_TYPE__");
-#endif
-#ifndef NO_BUILTIN_PTRDIFF_TYPE
-      dump_special_to_buffer (pfile, "__PTRDIFF_TYPE__");
-#endif
-      dump_special_to_buffer (pfile, "__WCHAR_TYPE__");
-      dump_special_to_buffer (pfile, "__DATE__");
-      dump_special_to_buffer (pfile, "__TIME__");
-      if (!cppReader_isTraditional (pfile))
-       dump_special_to_buffer (pfile, "__STDC__");
-    }
-}
-
-
-/* Return 1 iff a token ending in C1 followed directly by a token C2
-   could cause mis-tokenization.  */
-
-static bool
-unsafe_chars (char c1, char c2)
-{
-  switch (c1)
-    {
-    case '+': case '-':
-      if (c2 == c1 || c2 == '=')
-       return 1;
-      goto letter;
-    case '.':
-    case '0': case '1': case '2': case '3': case '4':
-    case '5': case '6': case '7': case '8': case '9':
-    case 'e': case 'E': case 'p': case 'P':
-      if (c2 == '-' || c2 == '+')
-       return 1; /* could extend a pre-processing number */
-      goto letter;
-    case 'L':
-      if (c2 == '\'' || c2 == '\"')
-       return 1;   /* Could turn into L"xxx" or L'xxx'.  */
-      goto letter;
-    letter:
-    case '_':
-    case 'a': case 'b': case 'c': case 'd':           case 'f':
-    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
-    case 'm': case 'n': case 'o':           case 'q': case 'r':
-    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
-    case 'y': case 'z':
-    case 'A': case 'B': case 'C': case 'D':           case 'F':
-    case 'G': case 'H': case 'I': case 'J': case 'K':
-    case 'M': case 'N': case 'O':           case 'Q': case 'R':
-    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
-    case 'Y': case 'Z':
-      /* We're in the middle of either a name or a pre-processing number.  */
-      return (is_idchar[(int) c2] || c2 == '.');
-    case '<': case '>': case '!': case '%': case '#': case ':':
-    case '^': case '&': case '|': case '*': case '/': case '=':
-      return (c2 == c1 || c2 == '=');
-    }
-  return 0;
-}
-
-/* Expand a macro call.
-   HP points to the symbol that is the macro being called.
-   Put the result of expansion onto the input stack
-   so that subsequent input by our caller will use it.
-
-   If macro wants arguments, caller has already verified that
-   an argument list follows; arguments come from the input stack.  */
-
-static void
-macroexpand (cppReader *pfile, /*@dependent@*/ hashNode hp)
-{
-  int nargs;
-  DEFINITION *defn = hp->value.defn;
-  char *xbuf;
-  char *oxbuf = NULL;
-  int start_line;
-  int start_column;
-  size_t xbuf_len;
-  size_t old_written = cppReader_getWritten (pfile);
-  int rest_args;
-  int rest_zero = 0;
-  int i;
-  struct argdata *args = NULL;
-
-  pfile->output_escapes++;
-
-  cppBuffer_lineAndColumn (cppReader_fileBuffer (pfile), &start_line, &start_column);
-
-  nargs = defn->nargs;
-
-  if (nargs >= 0)
-    {
-      enum cpp_token token = CPP_EOF;
-
-      args = (struct argdata *) dmalloc ((nargs + 1) * sizeof (*args));
-
-      for (i = 0; i < nargs; i++)
-       {
-         args[i].expanded = 0;
-         args[i].raw = 0;
-         args[i].raw_length = 0;
-         args[i].expand_length = args[i].stringified_length = -1;
-         args[i].use_count = 0;
-       }
-
-      /*
-      ** Parse all the macro args that are supplied.  I counts them.
-      ** The first NARGS args are stored in ARGS.
-      ** The rest are discarded.  If rest_args is set then we assume
-      ** macarg absorbed the rest of the args.
-      */
-
-      i = 0;
-      rest_args = 0;
-
-      cppReader_forward (pfile, 1); /* Discard the open-parenthesis before the first arg.  */
-      do
-       {
-         if (rest_args != 0)
-           {
-             continue;
-           }
-
-         if (i < nargs || (nargs == 0 && i == 0))
-           {
-             /* if we are working on last arg which absorbs rest of args... */
-             if (i == nargs - 1 && defn->rest_args)
-               {
-                 rest_args = 1;
-               }
-
-             args[i].raw = size_toLong (cppReader_getWritten (pfile));
-             token = macarg (pfile, rest_args);
-             args[i].raw_length = cppReader_getWritten (pfile) - args[i].raw;
-             args[i].newlines = FALSE; /* FIXME */
-           }
-         else
-           {
-             token = macarg (pfile, 0);
-           }
-
-         if (token == CPP_EOF || token == CPP_POP)
-           {
-             cppReader_errorWithLine (pfile, start_line, start_column,
-                                  cstring_fromCharsNew ("unterminated macro call"));
-             sfree (args);
-             return;
-           }
-         i++;
-       } while (token == CPP_COMMA);
-
-      /* If we got one arg but it was just whitespace, call that 0 args.  */
-      if (i == 1)
-       {
-         char *bp;
-         char *lim;
-
-         assertSet (args);
-
-         bp = ARG_BASE + args[0].raw;
-         lim = bp + args[0].raw_length;
-
-         /* cpp.texi says for foo ( ) we provide one argument.
-            However, if foo wants just 0 arguments, treat this as 0.  */
-
-         if (nargs == 0)
-           {
-             while (bp != lim && is_space[(int) *bp])
-               {
-                 bp++;
-               }
-           }
-
-         if (bp == lim)
-           i = 0;
-       }
-
-      /* Don't output an error message if we have already output one for
-        a parse error above.  */
-      rest_zero = 0;
-
-      if (nargs == 0 && i > 0)
-       {
-         cppReader_error (pfile,
-                    message ("arguments given to macro `%s'", hp->name));
-       }
-      else if (i < nargs)
-       {
-         /* traditional C allows foo() if foo wants one argument.  */
-         if (nargs == 1 && i == 0 && cppReader_isTraditional (pfile))
-           {
-             ;
-           }
-         /* the rest args token is allowed to absorb 0 tokens */
-         else if (i == nargs - 1 && defn->rest_args)
-           rest_zero = 1;
-         else if (i == 0)
-           cppReader_error (pfile,
-                      message ("macro `%s' used without args", hp->name));
-         else if (i == 1)
-           cppReader_error (pfile,
-                      message ("macro `%s' used with just one arg", hp->name));
-         else
-           {
-             cppReader_error (pfile,
-                        message ("macro `%s' used with only %d args",
-                                 hp->name, i));
-           }
-       }
-      else if (i > nargs)
-       {
-         cppReader_error (pfile,
-                    message ("macro `%s' used with too many (%d) args", hp->name, i));
-       }
-      else
-       {
-         ;
-       }
-    }
-
-  /* If macro wants zero args, we parsed the arglist for checking only.
-     Read directly from the macro definition.  */
-
-  if (nargs <= 0)
-    {
-      xbuf = defn->expansion;
-      xbuf_len = defn->length;
-    }
-  else
-    {
-      char *exp = defn->expansion;
-      int offset;      /* offset in expansion,
-                                  copied a piece at a time */
-      size_t totlen;   /* total amount of exp buffer filled so far */
-
-      register struct reflist *ap, *last_ap;
-      
-      assertSet (args); /* args is defined since the nargs > 0 path was taken */
-
-      /* Macro really takes args.  Compute the expansion of this call.  */
-
-      /* Compute length in characters of the macro's expansion.
-        Also count number of times each arg is used.  */
-      xbuf_len = defn->length;
-
-      llassert (args != NULL);
-
-      for (ap = defn->pattern; ap != NULL; ap = ap->next)
-       {
-         if (ap->stringify)
-           {
-             struct argdata *arg = &args[ap->argno];
-
-             /* Stringify it it hasn't already been */
-             assertSet (arg);
-
-             if (arg->stringified_length < 0)
-               {
-                 int arglen = arg->raw_length;
-                 bool escaped = FALSE;
-                 char in_string = '\0';
-                 char c;
-
-                 /* Initially need_space is -1.  Otherwise, 1 means the
-                    previous character was a space, but we suppressed it;
-                    0 means the previous character was a non-space.  */
-                 int need_space = -1;
-
-                 i = 0;
-                 arg->stringified = cppReader_getWritten (pfile);
-                 if (!cppReader_isTraditional (pfile))
-                   cppReader_putChar (pfile, '\"'); /* insert beginning quote */
-                 for (; i < arglen; i++)
-                   {
-                     c = (ARG_BASE + arg->raw)[i];
-
-                     if (in_string == '\0')
-                       {
-                         /* Internal sequences of whitespace are replaced by
-                            one space except within an string or char token.*/
-                         if (is_space[(int) c])
-                           {
-                             if (cppReader_getWritten (pfile) > arg->stringified
-                                 && (cppReader_getPWritten (pfile))[-1] == '@')
-                               {
-                                 /* "@ " escape markers are removed */
-                                 cppReader_adjustWritten (pfile, -1);
-                                 /*@innercontinue@*/ continue;
-                               }
-                             if (need_space == 0)
-                               need_space = 1;
-                             /*@innercontinue@*/ continue;
-                           }
-                         else if (need_space > 0)
-                           cppReader_putChar (pfile, ' ');
-                         else
-                           {
-                             ;
-                           }
-
-                         need_space = 0;
-                       }
-
-                     if (escaped)
-                       escaped = 0;
-                     else
-                       {
-                         if (c == '\\')
-                           escaped = 1;
-
-                         if (in_string != '\0')
-                           {
-                             if (c == in_string)
-                               in_string = '\0';
-                           }
-                         else if (c == '\"' || c == '\'')
-                           {
-                             in_string = c;
-                           }
-                         else
-                           {
-                             ;
-                           }
-                       }
-
-                     /* Escape these chars */
-                     if (c == '\"' || (in_string != '\0' && c == '\\'))
-                       cppReader_putChar (pfile, '\\');
-                     if (isprint (c))
-                       cppReader_putChar (pfile, c);
-                     else
-                       {
-                         cppReader_reserve (pfile, 4);
-                         sprintf (cppReader_getPWritten (pfile), "\\%03o",
-                                  (unsigned int) c);
-                         cppReader_adjustWritten (pfile, 4);
-                       }
-                   }
-                 if (!cppReader_isTraditional (pfile))
-                   cppReader_putChar (pfile, '\"'); /* insert ending quote */
-                 arg->stringified_length
-                   = size_toInt (cppReader_getWritten (pfile) - arg->stringified);
-               }
-
-             xbuf_len += args[ap->argno].stringified_length;
-           }
-         else if (ap->raw_before || ap->raw_after || cppReader_isTraditional (pfile))
-           {
-             /* Add 4 for two newline-space markers to prevent
-                token concatenation.  */
-             assertSet (args); /*@i534 shouldn't need this */
-             xbuf_len += args[ap->argno].raw_length + 4;
-           }
-         else
-           {
-             /* We have an ordinary (expanded) occurrence of the arg.
-                So compute its expansion, if we have not already.  */
-
-             assertSet (args); /*@i534 shouldn't need this */
-
-             if (args[ap->argno].expand_length < 0)
-               {
-                 args[ap->argno].expanded = cppReader_getWritten (pfile);
-                 cpp_expand_to_buffer (pfile,
-                                       ARG_BASE + args[ap->argno].raw,
-                                       size_fromInt (args[ap->argno].raw_length));
-
-                 args[ap->argno].expand_length
-                   = size_toInt (cppReader_getWritten (pfile) - args[ap->argno].expanded);
-               }
-
-             /* Add 4 for two newline-space markers to prevent
-                token concatenation.  */
-             xbuf_len += args[ap->argno].expand_length + 4;
-          }
-         if (args[ap->argno].use_count < 10)
-           args[ap->argno].use_count++;
-       }
-
-      xbuf = (char *) dmalloc (xbuf_len + 1);
-      oxbuf = xbuf;
-
-      /*
-      ** Generate in XBUF the complete expansion
-      ** with arguments substituted in.
-      ** TOTLEN is the total size generated so far.
-      ** OFFSET is the index in the definition
-      ** of where we are copying from.
-      */
-
-      offset = 0;
-      totlen = 0;
-
-      for (last_ap = NULL, ap = defn->pattern; ap != NULL;
-          last_ap = ap, ap = ap->next)
-       {
-         register struct argdata *arg = &args[ap->argno];
-         size_t count_before = totlen;
-
-         /* Add chars to XBUF.  */
-         for (i = 0; i < ap->nchars; i++, offset++)
-           {
-             xbuf[totlen++] = exp[offset];
-           }
-
-         /* If followed by an empty rest arg with concatenation,
-            delete the last run of nonwhite chars.  */
-         if (rest_zero && totlen > count_before
-             && ((ap->rest_args && ap->raw_before)
-                 || (last_ap != NULL && last_ap->rest_args
-                     && last_ap->raw_after)))
-           {
-             /* Delete final whitespace.  */
-             while (totlen > count_before && is_space[(int) xbuf[totlen - 1]])
-               {
-                 totlen--;
-               }
-
-             /* Delete the nonwhites before them.  */
-             while (totlen > count_before && ! is_space[(int) xbuf[totlen - 1]])
-               {
-                 totlen--;
-               }
-           }
-
-         if (ap->stringify != 0)
-           {
-             assertSet(arg);
-             memcpy (xbuf + totlen,
-                     ARG_BASE + arg->stringified,
-                     size_fromInt (arg->stringified_length));
-             totlen += arg->stringified_length;
-           }
-         else if (ap->raw_before || ap->raw_after || cppReader_isTraditional (pfile))
-           {
-             char *p1;
-             char *l1;
-
-             assertSet (arg);
-
-             p1 = ARG_BASE + arg->raw;
-             l1 = p1 + arg->raw_length;
-
-             if (ap->raw_before)
-               {
-                 while (p1 != l1 && is_space[(int) *p1])
-                   {
-                     p1++;
-                   }
-
-                 while (p1 != l1 && is_idchar[(int) *p1])
-                   {
-                     xbuf[totlen++] = *p1++;
-                   }
-
-                 /* Delete any no-reexpansion marker that follows
-                    an identifier at the beginning of the argument
-                    if the argument is concatenated with what precedes it.  */
-                 if (p1[0] == '@' && p1[1] == '-')
-                   p1 += 2;
-               }
-             if (ap->raw_after)
-               {
-                 /* Arg is concatenated after: delete trailing whitespace,
-                    whitespace markers, and no-reexpansion markers.  */
-                 while (p1 != l1)
-                   {
-                     if (is_space[(int) l1[-1]]) l1--;
-                     else if (l1[-1] == '-')
-                       {
-                         char *p2 = l1 - 1;
-                         /* If a `-' is preceded by an odd number of newlines then it
-                            and the last newline are a no-reexpansion marker.  */
-                         while (p2 != p1 && p2[-1] == '\n')
-                           {
-                             p2--;
-                           }
-
-                         if (((l1 - 1 - p2) & 1) != 0)
-                           {
-                             l1 -= 2;
-                           }
-                         else
-                           {
-                             /*@innerbreak@*/ break;
-                           }
-                       }
-                     else
-                       {
-                         /*@innerbreak@*/ break;
-                       }
-                   }
-               }
-
-             memcpy (xbuf + totlen, p1, size_fromInt (l1 - p1));
-             totlen += l1 - p1;
-           }
-         else
-           {
-             char *expanded;
-
-             assertSet (arg);
-             expanded = ARG_BASE + arg->expanded;
-
-             if (!ap->raw_before && totlen > 0
-                 && (arg->expand_length != 0)
-                 && !cppReader_isTraditional(pfile)
-                 && unsafe_chars (xbuf[totlen-1], expanded[0]))
-               {
-                 xbuf[totlen++] = '@';
-                 xbuf[totlen++] = ' ';
-               }
-
-             memcpy (xbuf + totlen, expanded,
-                     size_fromInt (arg->expand_length));
-             totlen += arg->expand_length;
-
-             if (!ap->raw_after && totlen > 0
-                 && offset < size_toInt (defn->length)
-                 && !cppReader_isTraditional(pfile)
-                 && unsafe_chars (xbuf[totlen-1], exp[offset]))
-               {
-                 xbuf[totlen++] = '@';
-                 xbuf[totlen++] = ' ';
-               }
-
-             /* If a macro argument with newlines is used multiple times,
-                then only expand the newlines once.  This avoids creating
-                output lines which don't correspond to any input line,
-                which confuses gdb and gcov.  */
-             if (arg->use_count > 1 && arg->newlines > 0)
-               {
-                 /* Don't bother doing change_newlines for subsequent
-                    uses of arg.  */
-                 arg->use_count = 1;
-                 arg->expand_length
-                   = change_newlines (expanded, arg->expand_length);
-               }
-           }
-
-         if (totlen > xbuf_len)
-           abort ();
-       }
-
-      /* if there is anything left of the definition
-        after handling the arg list, copy that in too.  */
-
-      for (i = offset; i < size_toInt (defn->length); i++)
-       {
-         /* if we've reached the end of the macro */
-         if (exp[i] == ')')
-           rest_zero = 0;
-         if (! (rest_zero && last_ap != NULL && last_ap->rest_args
-                && last_ap->raw_after))
-           xbuf[totlen++] = exp[i];
-       }
-
-      xbuf[totlen] = '\0';
-      xbuf_len = totlen;
-    }
-
-  pfile->output_escapes--;
-
-  /* Now put the expansion on the input stack
-     so our caller will commence reading from it.  */
-  push_macro_expansion (pfile, xbuf, xbuf_len, hp);
-  cppReader_getBuffer (pfile)->has_escapes = 1;
-
-  /* Pop the space we've used in the token_buffer for argument expansion.  */
-  cppReader_setWritten (pfile, old_written);
-
-  /* Recursive macro use sometimes works traditionally.
-     #define foo(x,y) bar (x (y,0), y)
-     foo (foo, baz)  */
-
-  if (!cppReader_isTraditional (pfile))
-    hp->type = T_DISABLED;
-
-  sfree (args);
-}
-
-static void
-push_macro_expansion (cppReader *pfile, char *xbuf, size_t xbuf_len,
-                     /*@dependent@*/ hashNode hp)
-{
-  cppBuffer *mbuf = cppReader_pushBuffer (pfile, xbuf, xbuf_len);
-
-  if (mbuf == NULL)
-    {
-      return;
-    }
-
-  mbuf->cleanup = cppReader_macroCleanup;
-
-  llassert (mbuf->hnode == NULL);
-  mbuf->hnode = hp;
-
-  /* The first chars of the expansion should be a "@ " added by
-     collect_expansion.  This is to prevent accidental token-pasting
-     between the text preceding the macro invocation, and the macro
-     expansion text.
-
-     We would like to avoid adding unneeded spaces (for the sake of
-     tools that use cpp, such as imake).  In some common cases we can
-     tell that it is safe to omit the space.
-
-     The character before the macro invocation cannot have been an
-     idchar (or else it would have been pasted with the idchars of
-     the macro name).  Therefore, if the first non-space character
-     of the expansion is an idchar, we do not need the extra space
-     to prevent token pasting.
-
-     Also, we don't need the extra space if the first char is '(',
-     or some other (less common) characters.  */
-
-  if (xbuf[0] == '@' && xbuf[1] == ' '
-      && (is_idchar[(int) xbuf[2]] || xbuf[2] == '(' || xbuf[2] == '\''
-         || xbuf[2] == '\"'))
-  {
-    llassert (mbuf->cur != NULL);
-    mbuf->cur += 2;
-  }
-}
-
-
-/* Like cppGetToken, except that it does not read past end-of-line.
-   Also, horizontal space is skipped, and macros are popped.  */
-
-static enum cpp_token
-get_directive_token (cppReader *pfile)
-{
-  for (;;)
-    {
-      size_t old_written = cppReader_getWritten (pfile);
-      enum cpp_token token;
-      cppSkipHspace (pfile);
-      if (cppReader_peekC (pfile) == '\n')
-       {
-         return CPP_VSPACE;
-       }
-
-      token = cppGetToken (pfile);
-
-      switch (token)
-       {
-       case CPP_POP:
-         if (!cppBuffer_isMacro (cppReader_getBuffer (pfile)))
-           return token;
-         /*@fallthrough@*/
-       case CPP_HSPACE:
-       case CPP_COMMENT:
-         cppReader_setWritten (pfile, old_written);
-         /*@switchbreak@*/ break;
-       default:
-         return token;
-       }
-    }
-}
-
-
-/* Handle #include and #import.
-   This function expects to see "fname" or <fname> on the input.
-
-   The input is normally in part of the output_buffer following
-   cppReader_getWritten, and will get overwritten by output_line_command.
-   I.e. in input file specification has been popped by cppReader_handleDirective.
-   This is safe.  */
-
-static int
-do_include (cppReader *pfile, struct directive *keyword,
-           /*@unused@*/ char *unused1, /*@unused@*/ char *unused2)
-{
-  bool skip_dirs = (keyword->type == T_INCLUDE_NEXT);
-  cstring fname;
-  char *fbeg, *fend;           /* Beginning and end of fname */
-  enum cpp_token token;
-
-  /* Chain of dirs to search */
-  struct file_name_list *search_start = CPPOPTIONS (pfile)->include;
-  struct file_name_list dsp[1];        /* First in chain, if #include "..." */
-  struct file_name_list *searchptr = NULL;
-  size_t old_written = cppReader_getWritten (pfile);
-
-  int flen;
-
-  int f;                       /* file number */
-  int angle_brackets = 0;      /* 0 for "...", 1 for <...> */
-  f= -1;                       /* JF we iz paranoid! */
-
-  pfile->parsing_include_directive++;
-  token = get_directive_token (pfile);
-  pfile->parsing_include_directive--;
-
-  if (token == CPP_STRING)
-    {
-      /* FIXME - check no trailing garbage */
-      fbeg = pfile->token_buffer + old_written + 1;
-      fend = cppReader_getPWritten (pfile) - 1;
-      if (fbeg[-1] == '<')
-       {
-         angle_brackets = 1;
-         /* If -I-, start with the first -I dir after the -I-.  */
-         if (CPPOPTIONS (pfile)->first_bracket_include != NULL)
-           search_start = CPPOPTIONS (pfile)->first_bracket_include;
-       }
-      /* If -I- was specified, don't search current dir, only spec'd ones.  */
-      else if (!CPPOPTIONS (pfile)->ignore_srcdir)
-       {
-         cppBuffer *fp = CPPBUFFER (pfile);
-         /* We have "filename".  Figure out directory this source
-            file is coming from and put it on the front of the list.  */
-
-         for ( ; fp != cppReader_nullBuffer (pfile); fp = cppBuffer_prevBuffer (fp))
-           {
-             int n;
-             char *ep,*nam;
-
-             llassert (fp != NULL);
-
-             nam = NULL;
-
-             if (cstring_isDefined (fp->nominal_fname))
-               {
-                 nam = cstring_toCharsSafe (fp->nominal_fname);
-
-                 /* 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;
-
-#ifndef VMS
-                 ep = strrchr (nam, CONNECTCHAR);
-#else                          /* VMS */
-                 ep = strrchr (nam, ']');
-                 if (ep == NULL) ep = strrchr (nam, '>');
-                 if (ep == NULL) ep = strrchr (nam, ':');
-                 if (ep != NULL) ep++;
-#endif                         /* VMS */
-                 if (ep != NULL)
-                   {
-                     char save;
-
-                     n = ep - nam;
-                     save = nam[n];
-                     nam[n] = '\0';
-
-                     /*@-onlytrans@*/ /* This looks like a memory leak... */ 
-                     dsp[0].fname = cstring_fromCharsNew (nam); /* evs 2000-07-20: was fromChars */
-                     /*@=onlytrans@*/
-                     nam[n] = save;
-
-                     if (n + INCLUDE_LEN_FUDGE > pfile->max_include_len)
-                       pfile->max_include_len = n + INCLUDE_LEN_FUDGE;
-                   }
-                 else
-                   {
-                     dsp[0].fname = cstring_undefined; /* Current directory */
-                   }
-
-                 dsp[0].got_name_map = 0;
-                 break;
-               }
-           }
-       }
-      else
-       {
-         ;
-       }
-    }
-#ifdef VMS
-  else if (token == CPP_NAME)
-    {
-      /*
-       * Support '#include xyz' like VAX-C to allow for easy use of all the
-       * decwindow include files. It defaults to '#include <xyz.h>' (so the
-       * code from case '<' is repeated here) and generates a warning.
-       */
-      cppReader_warning (pfile,
-                  "VAX-C-style include specification found, use '#include <filename.h>' !");
-      angle_brackets = 1;
-      /* If -I-, start with the first -I dir after the -I-.  */
-      if (CPPOPTIONS (pfile)->first_bracket_include)
-       search_start = CPPOPTIONS (pfile)->first_bracket_include;
-      fbeg = pfile->token_buffer + old_written;
-      fend = cppReader_getPWritten (pfile);
-    }
-#endif
-  else
-    {
-      cppReader_error (pfile,
-                message ("Preprocessor command #%s expects \"FILENAME\" or <FILENAME>",
-                         keyword->name));
-
-      cppReader_setWritten (pfile, old_written);
-      cppReader_skipRestOfLine (pfile);
-      return 0;
-    }
-
-  *fend = 0;
-
-  token = get_directive_token (pfile);
-  if (token != CPP_VSPACE)
-    {
-      cppReader_errorLit (pfile,
-                   cstring_makeLiteralTemp ("Junk at end of #include"));
-
-      while (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP)
-       {
-         token = get_directive_token (pfile);
-       }
-    }
-
-  /*
-  ** For #include_next, skip in the search path
-  ** past the dir in which the containing file was found.
-  */
-
-  if (skip_dirs)
-    {
-      cppBuffer *fp = CPPBUFFER (pfile);
-
-      for (; fp != cppReader_nullBuffer (pfile); fp = cppBuffer_prevBuffer (fp))
-       {
-         llassert (fp != NULL);
-
-         if (fp->fname != NULL)
-           {
-             /* fp->dir is null if the containing file was specified with
-                an absolute file name.  In that case, don't skip anything.  */
-             if (fp->dir == SELF_DIR_DUMMY)
-               {
-                 search_start = CPPOPTIONS (pfile)->include;
-               }
-             else if (fp->dir != NULL)
-               {
-                 search_start = fp->dir->next;
-               }
-             else
-               {
-                 ;
-               }
-
-             break;
-           }
-       }
-    }
-
-  cppReader_setWritten (pfile, old_written);
-
-  flen = fend - fbeg;
-
-  DPRINTF (("fbeg: %s", fbeg));
-
-  if (flen == 0)
-    {
-      cppReader_error (pfile,
-                message ("Empty file name in #%s", keyword->name));
-      return 0;
-    }
-
-  /*
-  ** Allocate this permanently, because it gets stored in the definitions
-  ** of macros.
-  */
-
-  fname = cstring_undefined;
-
-  /* + 2 above for slash and terminating null.  */
-  /* + 2 added for '.h' on VMS (to support '#include filename') */
-
-  /* If specified file name is absolute, just open it.  */
-
-  if (osd_isConnectChar (*fbeg)
-# if defined (WIN32) || defined (OS2)
-      || (*(fbeg + 1) == ':')
-# endif
-      )
-    {
-      fname = cstring_copyLength (fbeg, flen);
-      
-      if (redundant_include_p (pfile, fname))
-       {
-         cstring_free (fname);
-         return 0;
-       }
-      
-      f = open_include_file (pfile, fname, NULL);
-      
-      if (f == IMPORT_FOUND)
-       {
-         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 != NULL;
-          searchptr = searchptr->next)
-       {
-         if (!cstring_isEmpty (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 (cstring_isEmpty (searchptr->fname))
-               continue;
-             
-             fname = cstring_copy (searchptr->fname);
-             fname = cstring_appendChar (fname, CONNECTCHAR);
-             DPRINTF (("Here: %s", fname));
-           }
-         else
-           {
-             ;
-           }
-         
-         fname = cstring_concatLength (fname, fbeg, flen);
-
-         DPRINTF (("fname: %s", fname));
-         
-         /* Win32 directory fix from Kay Buschner. */
-#if defined (WIN32) || defined (OS2)
-         /* Fix all unixdir slashes to win dir slashes */
-         if (searchptr->fname && (searchptr->fname[0] != 0)) 
-           {
-             cstring_replaceAll (fname, '/', '\\');
-           }
-#endif /* WIN32 */
-
-#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 (strchr (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))
-           {
-             cstring_free (fname);
-             return 0;
-           }
-
-         DPRINTF (("Trying: %s", fname));
-
-         f = open_include_file (pfile, fname, searchptr);
-         
-         if (f == IMPORT_FOUND)
-           {
-             return 0;                 /* Already included this file */
-           }
-#ifdef EACCES
-         else if (f == IMPORT_NOT_FOUND && errno == EACCES)
-           {
-             cppReader_warning (pfile,
-                                message ("Header file %s exists, but is not readable", fname));
-           }
-#endif
-         
-         if (f >= 0)
-           {
-             break;
-           }
-       }
-    }
-  
-  if (f < 0)
-    {
-      /* A file that was not found.  */
-      fname = cstring_copyLength (fbeg, flen);
-
-      if (search_start != NULL)
-       {
-         cppReader_error (pfile,
-                          message ("Cannot find include file %s on search path: %x", 
-                                   fname,
-                                   searchPath_unparse (search_start)));
-       }
-      else
-       {
-         cppReader_error (pfile,
-                          message ("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->all_include_files; ptr != NULL; ptr = ptr->next)
-      {
-       if (cstring_equal (ptr->fname, fname))
-         {
-           /* This file was included before.  */
-           break;
-         }
-      }
-
-    if (ptr == NULL)
-      {
-       /* This is the first time for this file.  */
-       /* Add it to list of files included.  */
-
-       ptr = (struct file_name_list *) dmalloc (sizeof (*ptr));
-       ptr->control_macro = NULL;
-       ptr->c_system_include_path = NULL;
-       ptr->next = pfile->all_include_files;
-       ptr->fname = fname;
-       ptr->got_name_map = NULL;
-
-       DPRINTF (("Including file: %s", fname));
-       pfile->all_include_files = ptr;
-       assertSet (pfile->all_include_files);
-      }
-
-    if (angle_brackets != 0)
-      {
-       pfile->system_include_depth++;
-      }
-
-    /* Actually process the file */
-    if (cppReader_pushBuffer (pfile, NULL, 0) == NULL)
-      {
-       cstring_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--;
-      }
-    /*@-branchstate@*/
-  } /*@=branchstate@*/ 
-
-  return 0;
-}
-
-/* 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 bool
-redundant_include_p (cppReader *pfile, cstring name)
-{
-  struct file_name_list *l = pfile->all_include_files;
-
-  for (; l != NULL; l = l->next)
-    {
-      if (cstring_equal (name, l->fname)
-         && (l->control_macro != NULL)
-         && (cppReader_lookup (l->control_macro, -1, -1) != NULL))
-       {
-         return TRUE;
-       }
-    }
-
-  return FALSE;
-}
-
-/* Return nonzero if the given FILENAME is an absolute pathname which
-   designates a file within one of the known "system" include file
-   directories.  We assume here that if the given FILENAME looks like
-   it is the name of a file which resides either directly in a "system"
-   include file directory, or within any subdirectory thereof, then the
-   given file must be a "system" include file.  This function tells us
-   if we should suppress pedantic errors/warnings for the given FILENAME.
-
-   The value is 2 if the file is a C-language system header file
-   for which C++ should (on most systems) assume `extern "C"'.  */
-
-static bool
-is_system_include (cppReader *pfile, cstring filename)
-{
-  struct file_name_list *searchptr;
-
-  for (searchptr = CPPOPTIONS (pfile)->first_system_include;
-       searchptr != NULL;
-       searchptr = searchptr->next)
-    {
-      if (!cstring_isEmpty (searchptr->fname)) {
-       cstring sys_dir = searchptr->fname;
-       int length = cstring_length (sys_dir);
-
-       if (cstring_equalLen (sys_dir, filename, length)
-           && osd_isConnectChar (cstring_getChar (filename, length)))
-         {
-           if (searchptr->c_system_include_path)
-             return 2;
-           else
-             return 1;
-         }
-      }
-    }
-
-  return 0;
-}
-
-/* Convert a character string literal into a nul-terminated string.
-   The input string is [IN ... LIMIT).
-   The result is placed in RESULT.  RESULT can be the same as IN.
-   The value returned in the end of the string written to RESULT,
-   or NULL on error.  */
-
-static /*@null@*/ char *
-convert_string (cppReader *pfile, /*@returned@*/ char *result,
-               char *in, char *limit, int handle_escapes)
-{
-  char c;
-  c = *in++;
-
-  if (c != '\"')
-    {
-      return NULL;
-    }
-
-  while (in < limit)
-    {
-      c = *in++;
-
-      switch (c)
-       {
-       case '\0':
-         return NULL;
-       case '\"':
-         limit = in;
-         /*@switchbreak@*/ break;
-       case '\\':
-         if (handle_escapes)
-           {
-             char *bpc = (char *) in;
-             int i = (char) cppReader_parseEscape (pfile, &bpc);
-             in = (char *) bpc;
-             if (i >= 0)
-               *result++ = (char) c;
-             /*@switchbreak@*/ break;
-           }
-
-         /*@fallthrough@*/
-       default:
-         *result++ = c;
-       }
-    }
-
-  *result = 0;
-  return result;
-}
-
-/*
- * interpret #line command.  Remembers previously seen fnames
- * in its very own hash table.
- */
-
-/*@constant int FNAME_HASHSIZE@*/
-#define FNAME_HASHSIZE 37
-
-static int
-do_line (cppReader *pfile, /*@unused@*/ struct directive *keyword)
-{
-  cppBuffer *ip = cppReader_getBuffer (pfile);
-  int new_lineno;
-  size_t old_written = cppReader_getWritten (pfile);
-  enum file_change_code file_change = same_file;
-  enum cpp_token token;
-
-  token = get_directive_token (pfile);
-
-  if (token != CPP_NUMBER
-      || !isdigit(pfile->token_buffer[old_written]))
-    {
-      cppReader_errorLit (pfile,
-                   cstring_makeLiteralTemp ("invalid format `#line' command"));
-
-      goto bad_line_directive;
-    }
-
-  /* The Newline at the end of this line remains to be processed.
-     To put the next line at the specified line number,
-     we must store a line number now that is one less.  */
-  new_lineno = atoi (pfile->token_buffer + old_written) - 1;
-  cppReader_setWritten (pfile, old_written);
-
-  /* NEW_LINENO is one less than the actual line number here.  */
-  if (cppReader_isPedantic (pfile) && new_lineno < 0)
-    cppReader_pedwarnLit (pfile,
-                   cstring_makeLiteralTemp ("line number out of range in `#line' command"));
-
-  token = get_directive_token (pfile);
-
-  if (token == CPP_STRING) {
-    char *fname = pfile->token_buffer + old_written;
-    char *end_name;
-    static hashNode fname_table[FNAME_HASHSIZE];
-    hashNode hp; 
-    hashNode *hash_bucket;
-    char *p;
-    size_t num_start;
-    int fname_length;
-
-    /* Turn the file name, which is a character string literal,
-       into a null-terminated string.  Do this in place.  */
-    end_name = convert_string (pfile, fname, fname, cppReader_getPWritten (pfile), 1);
-    if (end_name == NULL)
-      {
-       cppReader_errorLit (pfile,
-                     cstring_makeLiteralTemp ("invalid format `#line' command"));
-       goto bad_line_directive;
-      }
-
-    fname_length = end_name - fname;
-    num_start = cppReader_getWritten (pfile);
-
-    token = get_directive_token (pfile);
-    if (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP) {
-      p = pfile->token_buffer + num_start;
-      if (cppReader_isPedantic (pfile))
-       cppReader_pedwarnLit (pfile,
-                       cstring_makeLiteralTemp ("garbage at end of `#line' command"));
-
-      if (token != CPP_NUMBER || *p < '0' || *p > '4' || p[1] != '\0')
-       {
-         cppReader_errorLit (pfile,
-                       cstring_makeLiteralTemp ("invalid format `#line' command"));
-         goto bad_line_directive;
-       }
-      if (*p == '1')
-       file_change = enter_file;
-      else if (*p == 2)
-       file_change = leave_file;
-      else if (*p == 3)
-       ip->system_header_p = 1;
-      else /* if (*p == 4) */
-       ip->system_header_p = 2;
-
-      cppReader_setWritten (pfile, num_start);
-      token = get_directive_token (pfile);
-      p = pfile->token_buffer + num_start;
-      if (token == CPP_NUMBER && p[1] == '\0' && (*p == '3' || *p== '4')) {
-       ip->system_header_p = *p == 3 ? 1 : 2;
-       token = get_directive_token (pfile);
-      }
-      if (token != CPP_VSPACE) {
-       cppReader_errorLit (pfile,
-                     cstring_makeLiteralTemp ("invalid format `#line' command"));
-
-       goto bad_line_directive;
-      }
-    }
-
-    hash_bucket =
-      &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
-    for (hp = *hash_bucket; hp != NULL; hp = hp->next)
-      {
-       if (hp->length == fname_length &&
-           strncmp (hp->value.cpval, fname, size_fromInt (fname_length)) == 0) {
-         ip->nominal_fname = cstring_fromChars (hp->value.cpval);
-         break;
-       }
-      }
-
-    if (hp == 0) {
-      /* Didn't find it; cons up a new one.  */
-      hp = (hashNode) dmalloc (sizeof (*hp));
-
-      hp->prev = NULL;
-      hp->bucket_hdr = NULL;
-      hp->type = T_NONE;
-      hp->name = cstring_undefined;
-      hp->next = *hash_bucket;
-
-      *hash_bucket = hp;
-
-      hp->length = fname_length;
-      hp->value.cpval = dmalloc (sizeof (*hp->value.cpval) * (fname_length + 1));
-      memcpy (hp->value.cpval, fname, size_fromInt (fname_length));
-      hp->value.cpval[fname_length] = '\0';
-      ip->nominal_fname = cstring_fromChars (hp->value.cpval);
-    }
-  }
-  else if (token != CPP_VSPACE && token != CPP_EOF)
-    {
-      cppReader_errorLit (pfile,
-                   cstring_makeLiteralTemp ("invalid format `#line' command"));
-      goto bad_line_directive;
-    }
-  else
-    {
-      ;
-    }
-
-  ip->lineno = new_lineno;
-bad_line_directive:
-  cppReader_skipRestOfLine (pfile);
-  cppReader_setWritten (pfile, old_written);
-  output_line_command (pfile, 0, file_change);
-  return 0;
-}
-
-/*
- * remove the definition of a symbol from the symbol table.
- * according to un*x /lib/cpp, it is not an error to undef
- * something that has no definitions, so it isn't one here either.
- */
-
-static int
-do_undef (cppReader *pfile, struct directive *keyword, char *buf, char *limit)
-{
-
-  int sym_length;
-  hashNode hp;
-  char *orig_buf = buf;
-
-  SKIP_WHITE_SPACE (buf);
-
-  sym_length = cppReader_checkMacroName (pfile, buf, cstring_makeLiteralTemp ("macro"));
-
-  while ((hp = cppReader_lookup (buf, sym_length, -1)) != NULL)
-    {
-      /* If we are generating additional info for debugging (with -g) we
-        need to pass through all effective #undef commands.  */
-      if (CPPOPTIONS (pfile)->debug_output && (keyword != NULL))
-       {
-         pass_thru_directive (orig_buf, limit, pfile, keyword);
-       }
-
-      if (hp->type != T_MACRO)
-       {
-         cppReader_warning (pfile,
-                      message ("Undefining preprocessor builtin: %s",
-                               hp->name));
-       }
-
-      cppReader_deleteMacro (hp);
-    }
-
-  if (cppReader_isPedantic (pfile)) {
-    buf += sym_length;
-    SKIP_WHITE_SPACE (buf);
-    if (buf != limit)
-      {
-       cppReader_pedwarnLit (pfile,
-                       cstring_makeLiteralTemp ("garbage after `#undef' directive"));
-      }
-  }
-
-  return 0;
-}
-
-
-/*
- * Report an error detected by the program we are processing.
- * Use the text of the line in the error message.
- * (We use error because it prints the filename & line#.)
- */
-
-static int
-do_error (cppReader *pfile, /*@unused@*/ struct directive *keyword,
-         char *buf, char *limit)
-{
-  int length = limit - buf;
-  cstring copy = cstring_copyLength (buf, length);
-  cstring adv = cstring_advanceWhiteSpace (copy);
-
-  cppReader_error (pfile, message ("#error %s", adv));
-  cstring_free (copy);
-  return 0;
-}
-
-/*
- * Report a warning detected by the program we are processing.
- * Use the text of the line in the warning message, then continue.
- * (We use error because it prints the filename & line#.)
- */
-
-static int
-do_warning (cppReader *pfile, /*@unused@*/ struct directive *keyword,
-           char *buf, char *limit)
-{
-  int length = limit - buf;
-  cstring copy = cstring_copyLength (buf, length);
-  cstring adv = cstring_advanceWhiteSpace (copy);
-  cppReader_warning (pfile, message ("#warning %s", adv));
-  cstring_free (copy);
-  return 0;
-}
-
-
-/* #ident has already been copied to the output file, so just ignore it.  */
-
-static int
-do_ident (cppReader *pfile, /*@unused@*/ struct directive *keyword,
-         /*@unused@*/ char *buf, /*@unused@*/ char *limit)
-{
-  /* Allow #ident in system headers, since that's not user's fault.  */
-  if (cppReader_isPedantic (pfile) && !cppReader_getBuffer (pfile)->system_header_p)
-    cppReader_pedwarnLit (pfile,
-                   cstring_makeLiteralTemp ("ANSI C does not allow `#ident'"));
-
-  /* Leave rest of line to be read by later calls to cppGetToken.  */
-
-  return 0;
-}
-
-/* #pragma and its argument line have already been copied to the output file.
-   Just check for some recognized pragmas that need validation here.  */
-
-static int
-do_pragma (cppReader *pfile, /*@unused@*/ struct directive *keyword,
-          /*@unused@*/ char *buf, /*@unused@*/ char *limit)
-{
-  while (*buf == ' ' || *buf == '\t')
-    {
-      buf++;
-    }
-
-  if (!strncmp (buf, "implementation", 14)) {
-    /* Be quiet about `#pragma implementation' for a file only if it hasn't
-       been included yet.  */
-    struct file_name_list *ptr;
-    char *p = buf + 14, *fname, *inc_fname;
-    int fname_len;
-    SKIP_WHITE_SPACE (p);
-    if (*p == '\n' || *p != '\"')
-      return 0;
-
-    fname = p + 1;
-    p = (char *) strchr (fname, '\"');
-    fname_len = p != NULL ? p - fname : mstring_length (fname);
-
-    for (ptr = pfile->all_include_files; ptr != NULL; ptr = ptr->next)
-      {
-       inc_fname = (char *) strrchr (cstring_toCharsSafe (ptr->fname), CONNECTCHAR);
-       inc_fname = (inc_fname != NULL)
-         ? inc_fname + 1 : cstring_toCharsSafe (ptr->fname);
-
-       if ((inc_fname != NULL)
-           && (strncmp (inc_fname, fname, size_fromInt (fname_len)) == 0))
-         {
-           cpp_setLocation (pfile);
-
-           ppllerror (message ("`#pragma implementation' for `%s' appears "
-                               "after file is included",
-                               cstring_fromChars (fname)));
-         }
-      }
-  }
-
-  return 0;
-}
-
-/*
- * handle #if command by
- *   1) inserting special `defined' keyword into the hash table
- *     that gets turned into 0 or 1 by special_symbol (thus,
- *     if the luser has a symbol called `defined' already, it won't
- *      work inside the #if command)
- *   2) rescan the input into a temporary output buffer
- *   3) pass the output buffer to the yacc parser and collect a value
- *   4) clean up the mess left from steps 1 and 2.
- *   5) call conditional_skip to skip til the next #endif (etc.),
- *      or not, depending on the value from step 3.
- */
-
-static int
-do_if (cppReader *pfile, /*@unused@*/ struct directive *keyword,
-       char *buf, char *limit)
-{
-  HOST_WIDE_INT value = eval_if_expression (pfile, buf, limit - buf);
-  conditional_skip (pfile, value == 0, T_IF, NULL);
-  return 0;
-}
-
-/*
- * handle a #elif directive by not changing  if_stack  either.
- * see the comment above do_else.
- */
-
-static int do_elif (cppReader *pfile, /*@unused@*/ struct directive *keyword,
-                   char *buf, char *limit)
-{
-  if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack)
-    {
-      cppReader_errorLit (pfile,
-                   cstring_makeLiteralTemp ("Preprocessor command #elif is not within a conditional"));
-      return 0;
-    }
-  else
-    {
-      llassert (pfile->if_stack != NULL);
-
-      if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF)
-       {
-         cppReader_errorLit (pfile,
-                       cstring_makeLiteralTemp ("`#elif' after `#else'"));
-
-         if (pfile->if_stack->fname != NULL
-             && cppReader_getBuffer (pfile)->fname != NULL
-             && !cstring_equal (pfile->if_stack->fname,
-                                cppReader_getBuffer (pfile)->nominal_fname))
-           fprintf (stderr, ", file %s", cstring_toCharsSafe (pfile->if_stack->fname));
-         fprintf (stderr, ")\n");
-       }
-      pfile->if_stack->type = T_ELIF;
-    }
-
-  if (pfile->if_stack->if_succeeded)
-    {
-      skip_if_group (pfile, 0);
-    }
-  else
-    {
-      HOST_WIDE_INT value = eval_if_expression (pfile, buf, limit - buf);
-      if (value == 0)
-       skip_if_group (pfile, 0);
-      else
-       {
-         ++pfile->if_stack->if_succeeded;      /* continue processing input */
-         output_line_command (pfile, 1, same_file);
-       }
-    }
-
-  return 0;
-}
-
-/*
- * evaluate a #if expression in BUF, of length LENGTH,
- * then parse the result as a C expression and return the value as an int.
- */
-
-static HOST_WIDE_INT
-eval_if_expression (cppReader *pfile,
-                   /*@unused@*/ char *buf,
-                   /*@unused@*/ int length)
-{
-  hashNode save_defined;
-  HOST_WIDE_INT value;
-  size_t old_written = cppReader_getWritten (pfile);
-
-  save_defined = cppReader_install ("defined", -1, T_SPEC_DEFINED, 0, 0, -1);
-  pfile->pcp_inside_if = 1;
-
-  value = cppReader_parseExpression (pfile);
-  pfile->pcp_inside_if = 0;
-
-  /* Clean up special symbol */
-  cppReader_deleteMacro (save_defined);
-
-  cppReader_setWritten (pfile, old_written); /* Pop */
-
-  return value;
-}
-
-/*
- * routine to handle ifdef/ifndef.  Try to look up the symbol,
- * then do or don't skip to the #endif/#else/#elif depending
- * on what directive is actually being processed.
- */
-
-static int
-do_xifdef (cppReader *pfile, struct directive *keyword,
-          /*@unused@*/ char *unused1, /*@unused@*/ char *unused2)
-{
-  int skip;
-  cppBuffer *ip = cppReader_getBuffer (pfile);
-  char *ident;
-  int ident_length;
-  enum cpp_token token;
-  int start_of_file = 0;
-  char *control_macro = 0;
-  size_t old_written = cppReader_getWritten (pfile);
-
-  DPRINTF (("do xifdef: %d",
-           keyword->type == T_IFNDEF));
-
-  /* Detect a #ifndef at start of file (not counting comments).  */
-  if (cstring_isDefined (ip->fname) && keyword->type == T_IFNDEF)
-    {
-      start_of_file = pfile->only_seen_white == 2;
-    }
-
-  pfile->no_macro_expand++;
-  token = get_directive_token (pfile);
-  pfile->no_macro_expand--;
-
-  ident = pfile->token_buffer + old_written;
-  ident_length = size_toInt (cppReader_getWritten (pfile) - old_written);
-  cppReader_setWritten (pfile, old_written); /* Pop */
-
-  if (token == CPP_VSPACE || token == CPP_POP || token == CPP_EOF)
-    {
-      skip = (keyword->type == T_IFDEF);
-      if (! cppReader_isTraditional (pfile))
-       {
-         cppReader_pedwarn (pfile,
-                      message ("`#%s' with no argument", keyword->name));
-       }
-    }
-  else if (token == CPP_NAME)
-    {
-      hashNode hp = cppReader_lookup (ident, ident_length, -1);
-      skip = (keyword->type == T_IFDEF) 
-       ? (hp == NULL) : (hp != NULL);
-
-      DPRINTF (("hp null: %d / %d / %d",
-               (hp == NULL),
-               (keyword->type == T_IFNDEF),
-               skip));
-               
-      if (start_of_file && !skip)
-       {
-         DPRINTF (("Not skipping!"));
-         control_macro = (char *) dmalloc (size_fromInt (ident_length + 1));
-         memcpy (control_macro, ident, size_fromInt (ident_length + 1));
-       }
-    }
-  else
-    {
-      skip = (keyword->type == T_IFDEF);
-      if (! cppReader_isTraditional (pfile))
-       {
-         cppReader_error (pfile,
-                    message ("`#%s' with invalid argument", keyword->name));
-       }
-    }
-
-  if (!cppReader_isTraditional (pfile))
-    {
-      int c;
-      cppSkipHspace (pfile);
-      c = cppReader_peekC (pfile);
-      if (c != EOF && c != '\n')
-       {
-         cppReader_pedwarn (pfile,
-                            message ("garbage at end of `#%s' argument", keyword->name));
-       }
-    }
-
-  cppReader_skipRestOfLine (pfile);
-
-  DPRINTF (("Conditional skip: %d", skip));
-  conditional_skip (pfile, skip, T_IF, control_macro);
-  return 0;
-}
-
-/* Push TYPE on stack; then, if SKIP is nonzero, skip ahead.
-   If this is a #ifndef starting at the beginning of a file,
-   CONTROL_MACRO is the macro name tested by the #ifndef.
-   Otherwise, CONTROL_MACRO is 0.  */
-
-static void
-conditional_skip (cppReader *pfile, int skip,
-                 enum node_type type,
-                 /*@dependent@*/ char *control_macro)
-{
-  cppIfStackFrame *temp = (cppIfStackFrame *) dmalloc (sizeof (*temp));
-
-  temp->fname = cppReader_getBuffer (pfile)->nominal_fname;
-  temp->next = pfile->if_stack;
-  temp->control_macro = control_macro;
-  temp->lineno = 0;
-  temp->if_succeeded = 0;
-
-  pfile->if_stack = temp;
-  pfile->if_stack->type = type;
-
-  if (skip != 0)
-    {
-      skip_if_group (pfile, 0);
-      return;
-    }
-  else
-    {
-      ++pfile->if_stack->if_succeeded;
-      output_line_command (pfile, 1, same_file);
-    }
-}
-
-/*
- * skip to #endif, #else, or #elif.  adjust line numbers, etc.
- * leaves input ptr at the sharp sign found.
- * If ANY is nonzero, return at next directive of any sort.
- */
-
-static void
-skip_if_group (cppReader *pfile, int any)
-{
-  int c;
-  struct directive *kt;
-  cppIfStackFrame *save_if_stack = pfile->if_stack; /* don't pop past here */
-  register int ident_length;
-  char *ident;
-  struct parse_marker line_start_mark;
-
-  parseSetMark (&line_start_mark, pfile);
-
-  if (CPPOPTIONS (pfile)->output_conditionals) {
-    static char failed[] = "#failed\n";
-    cppReader_puts (pfile, failed, sizeof(failed)-1);
-    pfile->lineno++;
-    output_line_command (pfile, 1, same_file);
-  }
-
-beg_of_line:
-  if (CPPOPTIONS (pfile)->output_conditionals)
-    {
-      cppBuffer *pbuf = cppReader_getBuffer (pfile);
-      char *start_line;
-
-      llassert (pbuf->buf != NULL);
-
-      start_line = pbuf->buf + line_start_mark.position;
-      cppReader_puts (pfile, start_line, size_fromInt (pbuf->cur - start_line));
-    }
-
-  parseMoveMark (&line_start_mark, pfile);
-
-  if (!cppReader_isTraditional (pfile))
-    {
-      cppSkipHspace (pfile);
-    }
-
-  c  = cppReader_getC (pfile);
-  if (c == '#')
-    {
-      size_t old_written = cppReader_getWritten (pfile);
-      cppSkipHspace (pfile);
-
-      parse_name (pfile, cppReader_getC (pfile));
-      ident_length = size_toInt (cppReader_getWritten (pfile) - old_written);
-      ident = pfile->token_buffer + old_written;
-      pfile->limit = ident;
-
-      for (kt = directive_table; kt->length >= 0; kt++)
-       {
-         cppIfStackFrame *temp;
-         if (ident_length == kt->length
-             && cstring_equalPrefix (kt->name, cstring_fromChars (ident)))
-           {
-             /* If we are asked to return on next directive, do so now.  */
-             if (any)
-               {
-                 goto done;
-               }
-
-             switch (kt->type)
-               {
-               case T_IF:
-               case T_IFDEF:
-               case T_IFNDEF:
-                 temp = (cppIfStackFrame *) dmalloc (sizeof (*temp));
-                 temp->next = pfile->if_stack;
-                 temp->fname = cppReader_getBuffer (pfile)->nominal_fname;
-                 temp->type = kt->type;
-                 temp->lineno = 0;
-                 temp->if_succeeded = 0;
-                 temp->control_macro = NULL;
-
-                 pfile->if_stack = temp;
-                 /*@switchbreak@*/ break;
-               case T_ELSE:
-               case T_ENDIF:
-                 if (cppReader_isPedantic (pfile) && pfile->if_stack != save_if_stack)
-                   validate_else (pfile,
-                                  cstring_makeLiteralTemp (kt->type == T_ELSE ? "#else" : "#endif"));
-                 /*@fallthrough@*/
-               case T_ELIF:
-                 if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack)
-                   {
-                     cppReader_error (pfile,
-                                message ("Preprocessor command #%s is not within a conditional", kt->name));
-                     /*@switchbreak@*/ break;
-                   }
-                 else if (pfile->if_stack == save_if_stack)
-                   {
-                     goto done;                /* found what we came for */
-                   }
-                 else
-                   {
-                     ;
-                   }
-
-                 if (kt->type != T_ENDIF)
-                   {
-                     llassert (pfile->if_stack != NULL);
-
-                     if (pfile->if_stack->type == T_ELSE)
-                       {
-                         cppReader_errorLit (pfile,
-                                       cstring_makeLiteralTemp ("`#else' or `#elif' after `#else'"));
-                       }
-
-                     pfile->if_stack->type = kt->type;
-                     /*@switchbreak@*/ break;
-                   }
-
-                 temp = pfile->if_stack;
-                 llassert (temp != NULL);
-                 pfile->if_stack = temp->next;
-                 sfree (temp);
-                 /*@switchbreak@*/ break;
-               default: ;
-                 /*@-branchstate@*/ 
-               }
-             /*@=branchstate@*/
-             break;
-           }
-         
-         /* Don't let erroneous code go by.  */
-         
-         if (kt->length < 0 && !CPPOPTIONS (pfile)->lang_asm
-             && cppReader_isPedantic (pfile))
-           {
-             cppReader_pedwarnLit (pfile,
-                                   cstring_makeLiteralTemp ("Invalid preprocessor directive name"));
-           }
-       }
-
-      c = cppReader_getC (pfile);
-    }
-  /* We're in the middle of a line.  Skip the rest of it.  */
-  for (;;) {
-    size_t old;
-
-    switch (c)
-      {
-      case EOF:
-       goto done;
-      case '/':                        /* possible comment */
-       c = skip_comment (pfile, NULL);
-       if (c == EOF)
-         goto done;
-       /*@switchbreak@*/ break;
-      case '\"':
-      case '\'':
-       cppReader_forward (pfile, -1);
-       old = cppReader_getWritten (pfile);
-       (void) cppGetToken (pfile);
-       cppReader_setWritten (pfile, old);
-       /*@switchbreak@*/ break;
-      case '\\':
-       /* Char after backslash loses its special meaning.  */
-       if (cppReader_peekC (pfile) == '\n')
-         {
-           cppReader_forward (pfile, 1);
-         }
-
-       /*@switchbreak@*/ break;
-      case '\n':
-       goto beg_of_line;
-      }
-    c = cppReader_getC (pfile);
-  }
-done:
-  if (CPPOPTIONS (pfile)->output_conditionals) {
-    static char end_failed[] = "#endfailed\n";
-    cppReader_puts (pfile, end_failed, sizeof(end_failed)-1);
-    pfile->lineno++;
-  }
-  pfile->only_seen_white = 1;
-
-  parseGotoMark (&line_start_mark, pfile);
-  parseClearMark (&line_start_mark);
-}
-
-/*
- * handle a #else directive.  Do this by just continuing processing
- * without changing  if_stack ;  this is so that the error message
- * for missing #endif's etc. will point to the original #if.  It
- * is possible that something different would be better.
- */
-
-static int
-do_else (cppReader *pfile, /*@unused@*/ struct directive *keyword,
-       /*@unused@*/ char *buf, /*@unused@*/ char *limit)
-{
-  if (cppReader_isPedantic (pfile))
-    {
-      validate_else (pfile, cstring_makeLiteralTemp ("#else"));
-    }
-
-  cppReader_skipRestOfLine (pfile);
-
-  if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack) {
-    cppReader_errorLit (pfile,
-                 cstring_makeLiteralTemp ("Preprocessor command #else is not within a conditional"));
-    return 0;
-  } else {
-    /* #ifndef can't have its special treatment for containing the whole file
-       if it has a #else clause.  */
-
-    llassert (pfile->if_stack != NULL);
-
-    pfile->if_stack->control_macro = 0;
-
-    if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF)
-      {
-       cpp_setLocation (pfile);
-       genppllerrorhint (FLG_PREPROC,
-                         message ("Pre-processor directive #else after #else"),
-                         message ("%q: Location of match",
-                                  fileloc_unparseRaw (pfile->if_stack->fname,
-                                                      pfile->if_stack->lineno)));
-      }
-
-    pfile->if_stack->type = T_ELSE;
-  }
-
-  if (pfile->if_stack->if_succeeded)
-    skip_if_group (pfile, 0);
-  else {
-    ++pfile->if_stack->if_succeeded;   /* continue processing input */
-    output_line_command (pfile, 1, same_file);
-  }
-
-  return 0;
-}
-
-/*
- * unstack after #endif command
- */
-
-static int
-do_endif (cppReader *pfile, /*@unused@*/ struct directive *keyword,
-         /*@unused@*/ char *buf, /*@unused@*/ char *limit)
-{
-  if (cppReader_isPedantic (pfile))
-    {
-      validate_else (pfile, cstring_makeLiteralTemp ("#endif"));
-    }
-
-  cppReader_skipRestOfLine (pfile);
-
-  if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack)
-    {
-      cppReader_errorLit (pfile, cstring_makeLiteralTemp ("Unbalanced #endif"));
-    }
-  else
-    {
-      cppIfStackFrame *temp = pfile->if_stack;
-
-      llassert (temp != NULL);
-
-      pfile->if_stack = temp->next;
-      if (temp->control_macro != 0)
-       {
-         /* This #endif matched a #ifndef at the start of the file.
-            See if it is at the end of the file.  */
-         struct parse_marker start_mark;
-         int c;
-
-         parseSetMark (&start_mark, pfile);
-
-         for (;;)
-           {
-             cppSkipHspace (pfile);
-             c = cppReader_getC (pfile);
-
-             if (c != '\n')
-               break;
-           }
-
-         parseGotoMark (&start_mark, pfile);
-         parseClearMark (&start_mark);
-
-         if (c == EOF)
-           {
-             /* If we get here, this #endif ends a #ifndef
-                that contains all of the file (aside from whitespace).
-                Arrange not to include the file again
-                if the macro that was tested is defined.
-
-                Do not do this for the top-level file in a -include or any
-                file in a -imacros.  */
-             struct file_name_list *ifile = pfile->all_include_files;
-
-             for ( ; ifile != NULL; ifile = ifile->next)
-               {
-                 if (cstring_equal (ifile->fname, cppReader_getBuffer (pfile)->fname))
-                   {
-                     ifile->control_macro = temp->control_macro;
-                     break;
-                   }
-               }
-           }
-       }
-
-      sfree (temp);
-      output_line_command (pfile, 1, same_file);
-    }
-  return 0;
-}
-
-/* When an #else or #endif is found while skipping failed conditional,
-   if -pedantic was specified, this is called to warn about text after
-   the command name.  P points to the first char after the command name.  */
-
-static void
-validate_else (cppReader *pfile, cstring directive)
-{
-  int c;
-  cppSkipHspace (pfile);
-  c = cppReader_peekC (pfile);
-  if (c != EOF && c != '\n')
-    {
-      cppReader_pedwarn (pfile,
-                  message ("text following `%s' violates ANSI standard", directive));
-    }
-}
-
-/*
-** Get the next token, and add it to the text in pfile->token_buffer.
-** Return the kind of token we got.
-*/
-
-enum cpp_token
-cppGetToken (cppReader *pfile)
-{
-  int c, c2, c3;
-  size_t old_written = 0;
-  int start_line, start_column;
-  enum cpp_token token;
-  struct cppOptions *opts = CPPOPTIONS (pfile);
-  cppReader_getBuffer (pfile)->prev = cppReader_getBuffer (pfile)->cur;
-
-get_next:
-  c = cppReader_getC (pfile);
-
-  if (c == EOF)
-    {
-    handle_eof:
-      if (cppReader_getBuffer (pfile)->seen_eof)
-       {
-         cppBuffer *buf = cppReader_popBuffer (pfile);
-
-         if (buf != cppReader_nullBuffer (pfile))
-           {
-             goto get_next;
-           }
-         else
-           {
-             return CPP_EOF;
-           }
-       }
-      else
-       {
-         cppBuffer *next_buf = cppBuffer_prevBuffer (cppReader_getBuffer (pfile));
-         cppReader_getBuffer (pfile)->seen_eof = 1;
-
-         if (cstring_isDefined (cppReader_getBuffer (pfile)->nominal_fname)
-             && next_buf != cppReader_nullBuffer (pfile))
-           {
-             /* We're about to return from an #include file.
-                Emit #line information now (as part of the CPP_POP) result.
-                But the #line refers to the file we will pop to.  */
-             cppBuffer *cur_buffer = CPPBUFFER (pfile);
-             CPPBUFFER (pfile) = next_buf;
-             pfile->input_stack_listing_current = 0;
-             output_line_command (pfile, 0, leave_file);
-             CPPBUFFER (pfile) = cur_buffer;
-           }
-         return CPP_POP;
-       }
-    }
-  else
-    {
-      long newlines;
-      struct parse_marker start_mark;
-
-      switch (c)
-       {
-       case '/':
-         if (cppReader_peekC (pfile) == '=')
-           {
-             goto op2;
-           }
-
-         if (opts->put_out_comments)
-           {
-             parseSetMark (&start_mark, pfile);
-           }
-
-         newlines = 0;
-         cppBuffer_lineAndColumn (cppReader_fileBuffer (pfile),
-                                  &start_line, &start_column);
-         c = skip_comment (pfile, &newlines);
-
-         if (opts->put_out_comments && (c == '/' || c == EOF))
-           {
-             assertSet (&start_mark);
-             parseClearMark (&start_mark);
-           }
-
-         if (c == '/')
-           goto randomchar;
-         if (c == EOF)
-           {
-             cppReader_errorWithLine (pfile, start_line, start_column,
-                                      cstring_makeLiteral ("Unterminated comment"));
-             goto handle_eof;
-           }
-         c = '/';  /* Initial letter of comment.  */
-       return_comment:
-         /* Comments are equivalent to spaces.
-            For -traditional, a comment is equivalent to nothing.  */
-
-         if (opts->put_out_comments)
-           {
-             enum cpp_token res;
-
-             assertSet (&start_mark);
-             res = cpp_handleComment (pfile, &start_mark);
-             pfile->lineno += newlines;
-             return res;
-           }
-         else if (cppReader_isTraditional (pfile))
-           {
-             return CPP_COMMENT;
-           }
-         else
-           {
-             cppReader_reserve(pfile, 1);
-             cppReader_putCharQ (pfile, ' ');
-             return CPP_HSPACE;
-           }
-
-       case '#':
-         if (!pfile->only_seen_white)
-           {
-             goto randomchar;
-           }
-
-         if (cppReader_handleDirective (pfile))
-           {
-             return CPP_DIRECTIVE;
-           }
-
-         pfile->only_seen_white = 0;
-         return CPP_OTHER;
-
-       case '\"':
-       case '\'':
-         /* A single quoted string is treated like a double -- some
-            programs (e.g., troff) are perverse this way */
-         cppBuffer_lineAndColumn (cppReader_fileBuffer (pfile),
-                                  &start_line, &start_column);
-         old_written = cppReader_getWritten (pfile);
-       string:
-         cppReader_putChar (pfile, c);
-         while (TRUE)
-           {
-             int cc = cppReader_getC (pfile);
-             if (cc == EOF)
-               {
-                 if (cppBuffer_isMacro (CPPBUFFER (pfile)))
-                   {
-                     /* try harder: this string crosses a macro expansion
-                        boundary.  This can happen naturally if -traditional.
-                        Otherwise, only -D can make a macro with an unmatched
-                        quote.  */
-                     cppBuffer *next_buf
-                       = cppBuffer_prevBuffer (cppReader_getBuffer (pfile));
-                     (*cppReader_getBuffer (pfile)->cleanup)
-                       (cppReader_getBuffer (pfile), pfile);
-                     CPPBUFFER (pfile) = next_buf;
-                     continue;
-                   }
-                 if (!cppReader_isTraditional (pfile))
-                   {
-                     cpp_setLocation (pfile);
-
-                     setLine (long_toInt (start_line));
-                     setColumn (long_toInt (start_column));
-
-                     if (pfile->multiline_string_line != long_toInt (start_line)
-                         && pfile->multiline_string_line != 0)
-                       {
-                         genppllerrorhint
-                           (FLG_PREPROC,
-                            message ("Unterminated string or character constant"),
-                            message ("%q: Possible real start of unterminated constant",
-                                     fileloc_unparseRaw 
-                                     (fileloc_filename (g_currentloc),
-                                      pfile->multiline_string_line)));
-                         pfile->multiline_string_line = 0;
-                       }
-                     else
-                       {
-                         genppllerror
-                           (FLG_PREPROC,
-                            message ("Unterminated string or character constant"));
-                       }
-                   }
-                 /*@loopbreak@*/ break;
-               }
-             cppReader_putChar (pfile, cc);
-             switch (cc)
-               {
-               case '\n':
-                 /* Traditionally, end of line ends a string constant with
-                    no error.  So exit the loop and record the new line.  */
-                 if (cppReader_isTraditional (pfile))
-                   goto while2end;
-                 if (c == '\'')
-                   {
-                     goto while2end;
-                   }
-                 if (cppReader_isPedantic (pfile)
-                     && pfile->multiline_string_line == 0)
-                   {
-                     cppReader_pedwarnWithLine
-                       (pfile, long_toInt (start_line),
-                        long_toInt (start_column),
-                        cstring_makeLiteral ("String constant runs past end of line"));
-                   }
-                 if (pfile->multiline_string_line == 0)
-                   {
-                     pfile->multiline_string_line = start_line;
-                   }
-
-                 /*@switchbreak@*/ break;
-
-               case '\\':
-                 cc = cppReader_getC (pfile);
-                 if (cc == '\n')
-                   {
-                     /* Backslash newline is replaced by nothing at all.  */
-                     cppReader_adjustWritten (pfile, -1);
-                     pfile->lineno++;
-                   }
-                 else
-                   {
-                     /* ANSI stupidly requires that in \\ the second \
-                        is *not* prevented from combining with a newline.  */
-                     NEWLINE_FIX1(cc);
-                     if (cc != EOF)
-                       cppReader_putChar (pfile, cc);
-                   }
-                 /*@switchbreak@*/ break;
-
-               case '\"':
-               case '\'':
-                 if (cc == c)
-                   goto while2end;
-                 /*@switchbreak@*/ break;
-               }
-           }
-       while2end:
-         pfile->lineno += count_newlines (pfile->token_buffer + old_written,
-                                          cppReader_getPWritten (pfile));
-         pfile->only_seen_white = 0;
-         return c == '\'' ? CPP_CHAR : CPP_STRING;
-
-       case '$':
-         if (!opts->dollars_in_ident)
-           goto randomchar;
-         goto letter;
-
-       case ':':
-         if (opts->cplusplus && cppReader_peekC (pfile) == ':')
-           goto op2;
-         goto randomchar;
-
-       case '&':
-       case '+':
-       case '|':
-         NEWLINE_FIX;
-         c2 = cppReader_peekC (pfile);
-         if (c2 == c || c2 == '=')
-           goto op2;
-         goto randomchar;
-
-       case '*':
-       case '!':
-       case '%':
-       case '=':
-       case '^':
-         NEWLINE_FIX;
-         if (cppReader_peekC (pfile) == '=')
-           goto op2;
-         goto randomchar;
-
-       case '-':
-         NEWLINE_FIX;
-         c2 = cppReader_peekC (pfile);
-         if (c2 == '-' && opts->chill)
-           {
-             /* Chill style comment */
-             if (opts->put_out_comments)
-               {
-                 parseSetMark (&start_mark, pfile);
-               }
-
-             cppReader_forward (pfile, 1);  /* Skip second '-'.  */
-
-             for (;;)
-               {
-                 c = cppReader_getC (pfile);
-                 if (c == EOF)
-                   /*@loopbreak@*/ break;
-                 if (c == '\n')
-                   {
-                     /* Don't consider final '\n' to be part of comment.  */
-                     cppReader_forward (pfile, -1);
-                     /*@loopbreak@*/ break;
-                   }
-               }
-             c = '-';
-             goto return_comment;
-           }
-         if (c2 == '-' || c2 == '=' || c2 == '>')
-           goto op2;
-         goto randomchar;
-
-       case '<':
-         if (pfile->parsing_include_directive)
-           {
-             for (;;)
-               {
-                 cppReader_putChar (pfile, c);
-                 if (c == '>')
-                   /*@loopbreak@*/ break;
-                 c = cppReader_getC (pfile);
-                 NEWLINE_FIX1 (c);
-                 if (c == '\n' || c == EOF)
-                   {
-                     cppReader_errorLit (pfile,
-                                   cstring_makeLiteralTemp ("Missing '>' in \"#include <FILENAME>\""));
-                     /*@loopbreak@*/ break;
-                   }
-               }
-             return CPP_STRING;
-           }
-         /*@fallthrough@*/
-       case '>':
-         NEWLINE_FIX;
-         c2 = cppReader_peekC (pfile);
-         if (c2 == '=')
-           goto op2;
-         if (c2 != c)
-           goto randomchar;
-         cppReader_forward (pfile, 1);
-         cppReader_reserve (pfile, 4);
-         cppReader_putChar (pfile, c);
-         cppReader_putChar (pfile, c2);
-         NEWLINE_FIX;
-         c3 = cppReader_peekC (pfile);
-         if (c3 == '=')
-           cppReader_putCharQ (pfile, cppReader_getC (pfile));
-         cppReader_nullTerminateQ (pfile);
-         pfile->only_seen_white = 0;
-         return CPP_OTHER;
-
-       case '@':
-         if (cppReader_getBuffer (pfile)->has_escapes)
-           {
-             c = cppReader_getC (pfile);
-             if (c == '-')
-               {
-                 if (pfile->output_escapes)
-                   cppReader_puts (pfile, "@-", 2);
-                 parse_name (pfile, cppReader_getC (pfile));
-                 return CPP_NAME;
-               }
-             else if (is_space [c])
-               {
-                 cppReader_reserve (pfile, 2);
-                 if (pfile->output_escapes)
-                   cppReader_putCharQ (pfile, '@');
-                 cppReader_putCharQ (pfile, c);
-                 return CPP_HSPACE;
-               }
-             else
-               {
-                 ;
-               }
-           }
-         if (pfile->output_escapes)
-           {
-             cppReader_puts (pfile, "@@", 2);
-             return CPP_OTHER;
-           }
-         goto randomchar;
-       case '.':
-         NEWLINE_FIX;
-         c2 = cppReader_peekC (pfile);
-         if (isdigit(c2))
-           {
-             cppReader_reserve(pfile, 2);
-             cppReader_putCharQ (pfile, '.');
-             c = cppReader_getC (pfile);
-             goto number;
-           }
-
-         /* FIXME - misses the case "..\\\n." */
-         if (c2 == '.' && cpp_peekN (pfile, 1) == '.')
-           {
-             cppReader_reserve(pfile, 4);
-             cppReader_putCharQ (pfile, '.');
-             cppReader_putCharQ (pfile, '.');
-             cppReader_putCharQ (pfile, '.');
-             cppReader_forward (pfile, 2);
-             cppReader_nullTerminateQ (pfile);
-             pfile->only_seen_white = 0;
-             return CPP_3DOTS;
-           }
-         goto randomchar;
-       op2:
-         token = CPP_OTHER;
-         pfile->only_seen_white = 0;
-        op2any:
-         cppReader_reserve(pfile, 3);
-         cppReader_putCharQ (pfile, c);
-         cppReader_putCharQ (pfile, cppReader_getC (pfile));
-         cppReader_nullTerminateQ (pfile);
-         return token;
-
-       case 'L':
-         NEWLINE_FIX;
-         c2 = cppReader_peekC (pfile);
-         if ((c2 == '\'' || c2 == '\"') && !cppReader_isTraditional (pfile))
-           {
-             cppReader_putChar (pfile, c);
-             c = cppReader_getC (pfile);
-             goto string;
-           }
-         goto letter;
-
-       case '0': case '1': case '2': case '3': case '4':
-       case '5': case '6': case '7': case '8': case '9':
-       number:
-         c2  = '.';
-         for (;;)
-           {
-             cppReader_reserve (pfile, 2);
-             cppReader_putCharQ (pfile, c);
-             NEWLINE_FIX;
-             c = cppReader_peekC (pfile);
-             if (c == EOF)
-               /*@loopbreak@*/ break;
-             if (!is_idchar[c] && c != '.'
-                 && ((c2 != 'e' && c2 != 'E'
-                      && ((c2 != 'p' && c2 != 'P') || cppReader_isC89 (pfile)))
-                     || (c != '+' && c != '-')))
-               /*@loopbreak@*/ break;
-             cppReader_forward (pfile, 1);
-             c2= c;
-           }
-
-         cppReader_nullTerminateQ (pfile);
-         pfile->only_seen_white = 0;
-         return CPP_NUMBER;
-
-       case 'b': case 'c': case 'd': case 'h': case 'o':
-       case 'B': case 'C': case 'D': case 'H': case 'O':
-         if (opts->chill && cppReader_peekC (pfile) == '\'')
-           {
-             pfile->only_seen_white = 0;
-             cppReader_reserve (pfile, 2);
-             cppReader_putCharQ (pfile, c);
-             cppReader_putCharQ (pfile, '\'');
-             cppReader_forward (pfile, 1);
-             for (;;)
-               {
-                 c = cppReader_getC (pfile);
-                 if (c == EOF)
-                   goto chill_number_eof;
-                 if (!is_idchar[c])
-                   {
-                     if (c == '\\' && cppReader_peekC (pfile) == '\n')
-                       {
-                         cppReader_forward (pfile, 2);
-                         continue;
-                       }
-                     /*@loopbreak@*/ break;
-                   }
-                 cppReader_putChar (pfile, c);
-               }
-             if (c == '\'')
-               {
-                 cppReader_reserve (pfile, 2);
-                 cppReader_putCharQ (pfile, c);
-                 cppReader_nullTerminateQ (pfile);
-                 return CPP_STRING;
-               }
-             else
-               {
-                 cppReader_forward (pfile, -1);
-               chill_number_eof:
-                 cppReader_nullTerminate (pfile);
-                 return CPP_NUMBER;
-               }
-           }
-         else
-           goto letter;
-       case '_':
-       case 'a': case 'e': case 'f': case 'g': case 'i': case 'j':
-       case 'k': case 'l': case 'm': case 'n': case 'p': case 'q':
-       case 'r': case 's': case 't': case 'u': case 'v': case 'w':
-       case 'x': case 'y': case 'z':
-       case 'A': case 'E': case 'F': case 'G': case 'I': case 'J':
-       case 'K': case 'M': case 'N': case 'P': case 'Q': case 'R':
-       case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
-       case 'Y': case 'Z':
-        letter:
-          {
-           hashNode hp;
-           char *ident;
-           size_t before_name_written = cppReader_getWritten (pfile);
-           int ident_len;
-           parse_name (pfile, c);
-           pfile->only_seen_white = 0;
-           if (pfile->no_macro_expand)
-             {
-               return CPP_NAME;
-             }
-
-           ident = pfile->token_buffer + before_name_written;
-           ident_len = (cppReader_getPWritten (pfile)) - ident;
-
-           hp = cppReader_lookupExpand (ident, ident_len, -1);
-
-           if (hp == NULL)
-             {
-               return CPP_NAME;
-             }
-
-           if (hp->type == T_DISABLED)
-             {
-               if (pfile->output_escapes)
-                 { /* Return "@-IDENT", followed by '\0'.  */
-                   int i;
-                   cppReader_reserve (pfile, 3);
-                   ident = pfile->token_buffer + before_name_written;
-                   cppReader_adjustWritten (pfile, 2);
-
-                   for (i = ident_len; i >= 0; i--)
-                     {
-                       ident[i+2] = ident[i];
-                     }
-
-                   ident[0] = '@';
-                   ident[1] = '-';
-                 }
-               return CPP_NAME;
-             }
-
-           /* If macro wants an arglist, verify that a '(' follows.
-              first skip all whitespace, copying it to the output
-              after the macro name.  Then, if there is no '(',
-              decide this is not a macro call and leave things that way.  */
-
-           if (hp->type == T_MACRO && hp->value.defn->nargs >= 0)
-             {
-               struct parse_marker macro_mark;
-               int is_macro_call;
-
-               while (cppBuffer_isMacro (CPPBUFFER (pfile)))
-                 {
-                   cppBuffer *next_buf;
-                   cppSkipHspace (pfile);
-                   if (cppReader_peekC (pfile) != EOF)
-                     {
-                       /*@loopbreak@*/ break;
-                     }
-
-                 next_buf = cppBuffer_prevBuffer (cppReader_getBuffer (pfile));
-                 (*cppReader_getBuffer (pfile)->cleanup) (cppReader_getBuffer (pfile), pfile);
-                 CPPBUFFER (pfile) = next_buf;
-                 }
-
-               parseSetMark (&macro_mark, pfile);
-
-               for (;;)
-                 {
-                   cppSkipHspace (pfile);
-                   c = cppReader_peekC (pfile);
-                   is_macro_call = c == '(';
-                   if (c != '\n')
-                     /*@loopbreak@*/ break;
-                   cppReader_forward (pfile, 1);
-                 }
-
-               if (!is_macro_call)
-                 {
-                   parseGotoMark (&macro_mark, pfile);
-                 }
-
-               parseClearMark (&macro_mark);
-
-               if (!is_macro_call)
-                 {
-                   return CPP_NAME;
-                 }
-             }
-           /* This is now known to be a macro call.  */
-
-           /* it might not actually be a macro.  */
-           if (hp->type != T_MACRO)
-             {
-               size_t xbuf_len;
-               char *xbuf;
-
-               cppReader_setWritten (pfile, before_name_written);
-               special_symbol (hp, pfile);
-               xbuf_len = cppReader_getWritten (pfile) - before_name_written;
-               xbuf = (char *) dmalloc (xbuf_len + 1);
-               cppReader_setWritten (pfile, before_name_written);
-               memcpy (xbuf, cppReader_getPWritten (pfile), xbuf_len + 1);
-               push_macro_expansion (pfile, xbuf, xbuf_len, hp);
-             }
-           else
-             {
-               /* Expand the macro, reading arguments as needed,
-                  and push the expansion on the input stack.  */
-                               macroexpand (pfile, hp);
-               cppReader_setWritten (pfile, before_name_written);
-             }
-
-           /* An extra "@ " is added to the end of a macro expansion
-              to prevent accidental token pasting.  We prefer to avoid
-              unneeded extra spaces (for the sake of cpp-using tools like
-              imake).  Here we remove the space if it is safe to do so.  */
-
-           llassert (pfile->buffer->rlimit != NULL);
-
-           if (pfile->buffer->rlimit - pfile->buffer->cur >= 3
-               && pfile->buffer->rlimit[-2] == '@'
-               && pfile->buffer->rlimit[-1] == ' ')
-             {
-               int c1 = pfile->buffer->rlimit[-3];
-               int cl2 = cppBufPeek (cppBuffer_prevBuffer (CPPBUFFER (pfile)));
-
-               if (cl2 == EOF || !unsafe_chars ((char) c1, (char) cl2))
-                 pfile->buffer->rlimit -= 2;
-             }
-         }
-         goto get_next;
-
-
-       case ' ':  case '\t':  case '\v':  case '\r':
-         for (;;)
-           {
-             cppReader_putChar (pfile, c);
-             c = cppReader_peekC (pfile);
-             if (c == EOF || !is_hor_space[c])
-               /*@loopbreak@*/ break;
-             cppReader_forward (pfile, 1);
-           }
-         return CPP_HSPACE;
-
-        case '\\':
-         c2 = cppReader_peekC (pfile);
-         if (c2 != '\n')
-           goto randomchar;
-         token = CPP_HSPACE;
-         goto op2any;
-
-       case '\n':
-         cppReader_putChar (pfile, c);
-         if (pfile->only_seen_white == 0)
-           pfile->only_seen_white = 1;
-         pfile->lineno++;
-         output_line_command (pfile, 1, same_file);
-         return CPP_VSPACE;
-
-       case '(': token = CPP_LPAREN;    goto char1;
-       case ')': token = CPP_RPAREN;    goto char1;
-       case '{': token = CPP_LBRACE;    goto char1;
-       case '}': token = CPP_RBRACE;    goto char1;
-       case ',': token = CPP_COMMA;     goto char1;
-       case ';': token = CPP_SEMICOLON; goto char1;
-
-       randomchar:
-       default:
-         token = CPP_OTHER;
-       char1:
-         pfile->only_seen_white = 0;
-         cppReader_putChar (pfile, c);
-         return token;
-       }
-    }
-
-  BADBRANCH;
-  /*@notreached@*/
-}
-
-/* Parse an identifier starting with C.  */
-
-void
-parse_name (cppReader *pfile, int c)
-{
-  for (;;)
-    {
-      if (!is_idchar[c])
-       {
-         if (c == '\\' && cppReader_peekC (pfile) == '\n')
-           {
-             cppReader_forward (pfile, 2);
-             continue;
-           }
-
-         cppReader_forward (pfile, -1);
-         break;
-       }
-
-      if (c == '$' && cppReader_isPedantic (pfile))
-       {
-         cppReader_pedwarnLit (pfile,
-                         cstring_makeLiteralTemp ("`$' in identifier"));
-       }
-
-      cppReader_reserve(pfile, 2); /* One more for final NUL.  */
-      cppReader_putCharQ (pfile, c);
-      c = cppReader_getC (pfile);
-
-      if (c == EOF)
-       break;
-    }
-
-  cppReader_nullTerminateQ (pfile);
-}
-
-/* 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;
-  cstring map_from;
-  cstring map_to;
-};
-
-/*@constant observer char *FILE_NAME_MAP_FILE*/
-#define FILE_NAME_MAP_FILE "header.gcc"
-
-/* Read a space delimited string of unlimited length from a stdio
-   file.  */
-
-static cstring read_filename_string (int ch, /*:open:*/ FILE *f)
-{
-  char *alloc, *set;
-  size_t len;
-
-  len = 20;
-  set = alloc = dmalloc (len + 1);
-
-  if (!is_space[ch])
-    {
-      *set++ = ch;
-      while ((ch = getc (f)) != EOF && ! is_space[ch])
-       {
-         if (set - alloc == size_toInt (len))
-           {
-             len *= 2;
-             alloc = drealloc (alloc, len + 1);
-             set = alloc + len / 2;
-             /*@-branchstate@*/ }
-
-         *set++ = ch;
-       } /*@=branchstate@*/
-    }
-  *set = '\0';
-  check (ungetc (ch, f) != EOF);
-
-  return cstring_fromChars (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;
-  cstring 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 (cppReader *pfile, cstring dirname)
-{
-  struct file_name_map_list *map_list_ptr;
-  cstring name;
-  FILE *f;
-
-  for (map_list_ptr = CPPOPTIONS (pfile)->map_list;
-       map_list_ptr != NULL;
-       map_list_ptr = map_list_ptr->map_list_next)
-    {
-      if (cstring_equal (map_list_ptr->map_list_name, dirname))
-       {
-         return map_list_ptr->map_list_map;
-       }
-    }
-
-  map_list_ptr = (struct file_name_map_list *) dmalloc (sizeof (*map_list_ptr));
-  map_list_ptr->map_list_name = cstring_copy (dirname);
-  map_list_ptr->map_list_map = NULL;
-
-  name = cstring_copy (dirname);
-
-  if (cstring_length (dirname) > 0)
-    {
-      name = cstring_appendChar (name, CONNECTCHAR);
-    }
-
-  name = cstring_concatFree1 (name, cstring_makeLiteralTemp (FILE_NAME_MAP_FILE));
-
-  f = fileTable_openFile (context_fileTable (), name, "r");
-  cstring_free (name);
-
-  if (f == NULL)
-    {
-      map_list_ptr->map_list_map = NULL;
-    }
-  else
-    {
-      int ch;
-
-      while ((ch = getc (f)) != EOF)
-       {
-         cstring 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 *) dmalloc (sizeof (*ptr));
-         ptr->map_from = from;
-
-         /* Make the real filename absolute.  */
-         if (cstring_length (to) > 1 
-             && osd_isConnectChar (cstring_firstChar (to)))
-           {
-             ptr->map_to = to;
-           }
-         else
-           {
-             ptr->map_to = cstring_copy (dirname);
-             ptr->map_to = cstring_appendChar (ptr->map_to, CONNECTCHAR);
-             ptr->map_to = cstring_concatFree (ptr->map_to, 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)
-               {
-                 /*@innerbreak@*/ break;
-               }
-           }
-       }
-
-      assertSet (map_list_ptr->map_list_map);
-      check (fileTable_closeFile (context_fileTable (),f) == 0);
-    }
-
-  map_list_ptr->map_list_next = pfile->opts->map_list;
-  pfile->opts->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 (cppReader *pfile,
-                  cstring fname,
-                  struct file_name_list *searchptr)
-{
-  char *filename = cstring_toCharsSafe (fname);
-  struct file_name_map *map;
-  char *from;
-  char *p, *dir;
-
-  cstring_markOwned (fname);
-
-  cpp_setLocation (pfile);
-
-  if (context_getFlag (FLG_NEVERINCLUDE))
-    {
-      if (isHeaderFile (fname))
-       {
-         return SKIP_INCLUDE;
-       }
-    }
-
-  if ((searchptr != NULL) && ! searchptr->got_name_map)
-    {
-      searchptr->name_map = read_name_map (pfile,
-                                          !cstring_isEmpty (searchptr->fname)
-                                          ? searchptr->fname :
-                                          cstring_makeLiteralTemp ("."));
-      searchptr->got_name_map = 1;
-    }
-
-  /* First check the mapping for the directory we are using.  */
-
-  if ((searchptr != NULL)
-      && (searchptr->name_map != NULL))
-    {
-      from = filename;
-
-      if (!cstring_isEmpty (searchptr->fname))
-       {
-         from += cstring_length (searchptr->fname) + 1;
-       }
-
-      for (map = searchptr->name_map;
-          map != NULL;
-          map = map->map_next)
-       {
-         if (cstring_equal (map->map_from, cstring_fromChars (from)))
-           {
-             /*
-             ** Found a match.  Check if the file should be skipped
-             */
-             
-             if (cpp_skipIncludeFile (map->map_to))
-               {
-                 return SKIP_INCLUDE;
-               }
-             else
-               {
-                 return cpp_openIncludeFile (cstring_toCharsSafe (map->map_to));
-               }
-           }
-       }
-    }
-
-  /*
-  ** 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 = strrchr (filename, CONNECTCHAR);
-
-  if (p == NULL)
-    {
-      p = filename;
-    }
-
-  if ((searchptr != NULL)
-      && (cstring_isDefined (searchptr->fname))
-      && (cstring_length (searchptr->fname) == p - filename)
-      && !strncmp (cstring_toCharsSafe (searchptr->fname),
-                  filename,
-                  size_fromInt (p - filename)))
-    {
-      /* filename is in SEARCHPTR, which we've already checked.  */
-
-      if (cpp_skipIncludeFile (cstring_fromChars (filename)))
-       {
-         return SKIP_INCLUDE;
-       }
-      else
-       {
-         return cpp_openIncludeFile (filename);
-       }
-    }
-
-  if (p == filename)
-    {
-      dir = mstring_copy (".");
-      from = filename;
-    }
-  else
-    {
-      dir = (char *) dmalloc (size_fromInt (p - filename + 1));
-      memcpy (dir, filename, size_fromInt (p - filename));
-      dir[p - filename] = '\0';
-      from = p + 1;
-    }
-
-  for (map = read_name_map (pfile, cstring_fromChars (dir));
-       map != NULL;
-       map = map->map_next)
-    {
-      if (cstring_equal (map->map_from, cstring_fromChars (from)))
-       {
-         sfree (dir);
-
-         if (cpp_skipIncludeFile (map->map_to))
-           {
-             return SKIP_INCLUDE;
-           }
-         else
-           {
-             return cpp_openIncludeFile (cstring_toCharsSafe (map->map_to));
-           }
-       }
-    }
-
-  sfree (dir);
-
-  if (cpp_skipIncludeFile (cstring_fromChars (filename)))
-    {
-      return SKIP_INCLUDE;
-    }
-  else
-    {
-      return cpp_openIncludeFile (filename);
-    }
-}
-
-/* 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 cppReader_pushBuffer.  */
-
-static int
-finclude (cppReader *pfile, int f,
-         cstring fname,
-         bool system_header_p,
-         /*@dependent@*/ struct file_name_list *dirptr)
-{
-  mode_t st_mode;
-  size_t st_size;
-  long i;
-  int length = 0;
-  cppBuffer *fp;                       /* For input stack frame */
-
-  if (file_size_and_mode (f, &st_mode, &st_size) < 0)
-    {
-      cppReader_perrorWithName (pfile, fname);
-      check (close (f) == 0);
-      (void) cppReader_popBuffer (pfile);
-      /*@-mustfree@*/
-      return 0;
-      /*@=mustfree@*/
-    }
-
-  fp = cppReader_getBuffer (pfile);
-
-  /*@-temptrans@*/ /* fname shouldn't really be temp */
-  fp->nominal_fname = fp->fname = fname;
-  /*@=temptrans@*/
-
-  fp->dir = dirptr;
-  fp->system_header_p = system_header_p;
-  fp->lineno = 1;
-  fp->colno = 1;
-  fp->cleanup = cppReader_fileCleanup;
-
-  if (S_ISREG (st_mode))
-    {
-      sfree (fp->buf);
-      fp->buf = (char *) dmalloc (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, size_toInt (st_size));
-      fp->rlimit = fp->buf + length;
-      if (length < 0) goto nope;
-    }
-  else if (S_ISDIR (st_mode))
-    {
-      cppReader_error (pfile,
-                      message ("Directory specified in #include: %s", fname));
-      check (close (f) == 0);
-      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;
-
-      sfree (fp->buf);
-      fp->buf = (char *) dmalloc (bsize + 2);
-
-      for (;;) {
-       i = safe_read (f, fp->buf + st_size, size_toInt (bsize - st_size));
-
-       if (i < 0)
-         goto nope;      /* error! */
-       st_size += i;
-
-       if (st_size != bsize)
-         {
-           break;      /* End of file */
-         }
-
-       bsize *= 2;
-       fp->buf = (char *) drealloc (fp->buf, bsize + 2);
-      }
-
-      fp->cur = fp->buf;
-      length = size_toInt (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';
-  }
-
-  fp->buf[length] = '\0';
-  fp->rlimit = fp->buf + length;
-
-  /* Close descriptor now, so nesting does not use lots of descriptors.  */
-  check (close (f) == 0);
-
-  /* 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;
-  return 1;
-
- nope:
-
-  cppReader_perrorWithName (pfile, fname);
-  check (close (f) == 0);
-  sfree (fp->buf);
-  return 1;
-}
-
-void
-cppReader_init (cppReader *pfile)
-{
-  memset ((char *) pfile, 0, sizeof (*pfile));
-
-  pfile->get_token = cppGetToken;
-  pfile->token_buffer_size = 200;
-  pfile->token_buffer = (char *) dmalloc (pfile->token_buffer_size);
-  pfile->all_include_files = NULL;
-
-  assertSet (pfile);
-
-  cppReader_setWritten (pfile, 0);
-
-  pfile->system_include_depth = 0;
-  pfile->max_include_len = 0;
-  pfile->timebuf = NULL;
-  pfile->only_seen_white = 1;
-
-  pfile->buffer = cppReader_nullBuffer (pfile);
-}
-
-void
-cppReader_finish (/*@unused@*/ cppReader *pfile)
-{
-  ;
-}
-
-/* Free resources used by PFILE.
-   This is the cppReader 'finalizer' or 'destructor' (in C++ terminology).  */
-
-void
-cppCleanup (cppReader *pfile)
-{
-  while (CPPBUFFER (pfile) != cppReader_nullBuffer (pfile))
-    {
-      (void) cppReader_popBuffer (pfile);
-    }
-
-  if (pfile->token_buffer != NULL)
-    {
-      sfree (pfile->token_buffer);
-      pfile->token_buffer = NULL;
-    }
-
-  while (pfile->if_stack != NULL)
-    {
-      cppIfStackFrame *temp = pfile->if_stack;
-      pfile->if_stack = temp->next;
-      sfree (temp);
-    }
-
-  while (pfile->all_include_files != NULL)
-    {
-      struct file_name_list *temp = pfile->all_include_files;
-      pfile->all_include_files = temp->next;
-      /*@-dependenttrans@*/
-      cstring_free (temp->fname);
-      /*@=dependenttrans@*/
-      sfree (temp);
-    }
-
-  cppReader_hashCleanup ();
-}
-
-/*
-** Get the file-mode and data size of the file open on FD
-** and store them in *MODE_POINTER and *SIZE_POINTER.
-*/
-
-static int
-file_size_and_mode (int fd, mode_t *mode_pointer, size_t *size_pointer)
-{
-  struct stat sbuf;
-
-  if (fstat (fd, &sbuf) < 0) {
-    return (-1);
-  }
-
-  if (mode_pointer != NULL)
-    {
-      *mode_pointer = sbuf.st_mode;
-    }
-
-  if (size_pointer != NULL)
-    {
-      *size_pointer = (size_t) sbuf.st_size;
-    }
-
-  return 0;
-}
-
-/* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
-   retrying if necessary.  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 (int desc, char *ptr, int len)
-{
-  int left = len;
-
-  while (left > 0)
-    {
-# if defined (WIN32) || defined (OS2) && defined (__IBMC__)
-         /*@-compdef@*/ /* ptr is an out parameter */
-      int nchars = _read (desc, ptr, (unsigned) left);
-         /*@=compdef@*/
-# else
-      ssize_t nchars = read (desc, ptr, size_fromInt (left));
-# endif
-
-      if (nchars < 0)
-       {
-#ifdef EINTR
-         if (errno == EINTR)
-           continue;
-#endif
-         return (int) nchars;
-       }
-
-      if (nchars == 0) {
-       break;
-      }
-
-      ptr += nchars;
-      left -= nchars;
-    }
-
-  return len - left;
-}
-
-/* Initialize PMARK to remember the current position of PFILE.  */
-
-void
-parseSetMark (struct parse_marker *pmark, cppReader *pfile)
-{
-  cppBuffer *pbuf = cppReader_getBuffer (pfile);
-
-  pmark->next = pbuf->marks;
-  /*@-temptrans@*/
-  pbuf->marks = pmark;
-  /*@=temptrans@*/
-
-  pmark->buf = pbuf;
-  pmark->position = pbuf->cur - pbuf->buf;
-}
-
-/* Cleanup PMARK - we no longer need it.  */
-
-void parseClearMark (struct parse_marker *pmark)
-{
-  struct parse_marker **pp = &pmark->buf->marks;
-
-  for (; ; pp = &(*pp)->next)
-    {
-      llassert (*pp != NULL);
-      if (*pp == pmark) break;
-    }
-
-  *pp = pmark->next;
-}
-
-/* Backup the current position of PFILE to that saved in PMARK.  */
-
-void
-parseGotoMark (struct parse_marker *pmark, cppReader *pfile)
-{
-  cppBuffer *pbuf = cppReader_getBuffer (pfile);
-
-  if (pbuf != pmark->buf)
-    {
-      cpp_setLocation (pfile);
-      llfatalbug (cstring_makeLiteral ("Internal error parseGotoMark"));
-    }
-
-  llassert (pbuf->buf != NULL);
-  pbuf->cur = pbuf->buf + pmark->position;
-}
-
-/* Reset PMARK to point to the current position of PFILE.  (Same
-   as parseClearMark (PMARK), parseSetMark (PMARK, PFILE) but faster.  */
-
-void
-parseMoveMark (struct parse_marker *pmark, cppReader *pfile)
-{
-  cppBuffer *pbuf = cppReader_getBuffer (pfile);
-
-  if (pbuf != pmark->buf)
-    {
-      cpp_setLocation (pfile);
-      llfatalerror (cstring_makeLiteral ("Internal error parseMoveMark"));
-    }
-
-  pmark->position = pbuf->cur - pbuf->buf;
-}
-
-void cppReader_initializeReader (cppReader *pfile) /* Must be done after library is loaded. */
-{
-  struct cppOptions *opts = CPPOPTIONS (pfile);
-  cstring xp;
-
-  /* The code looks at the defaults through this pointer, rather than through
-     the constant structure above.  This pointer gets changed if an environment
-     variable specifies other defaults.  */
-
-  struct default_include *include_defaults = include_defaults_array;
-
-  /* Add dirs from INCLUDEPATH_VAR after dirs from -I.  */
-  /* There seems to be confusion about what CPATH should do,
-     so for the moment it is not documented.  */
-  /* Some people say that CPATH should replace the standard include dirs,
-     but that seems pointless: it comes before them, so it overrides them
-     anyway.  */
-
-  xp = osd_getEnvironmentVariable (INCLUDEPATH_VAR);
-
-  if (cstring_isDefined (xp) && !opts->no_standard_includes)
-    {
-      path_include (pfile, cstring_toCharsSafe (xp));
-    }
-
-  /* Now that dollars_in_ident is known, initialize is_idchar.  */
-  initialize_char_syntax (opts);
-
-  /* CppReader_Install __LINE__, etc.  Must follow initialize_char_syntax
-     and option processing.  */
-
-  initialize_builtins (pfile);
-
-  /* Do standard #defines and assertions
-     that identify system and machine type.  */
-
-  if (!opts->inhibit_predefs) {
-    char *p = (char *) dmalloc (strlen (predefs) + 1);
-    strcpy (p, predefs);
-
-    while (*p)
-      {
-       char *q;
-
-       while (*p == ' ' || *p == '\t')
-         {
-           p++;
-         }
-
-       /* Handle -D options.  */
-       if (p[0] == '-' && p[1] == 'D')
-         {
-           q = &p[2];
-
-           while (*p && *p != ' ' && *p != '\t')
-             {
-               p++;
-             }
-
-           if (*p != 0)
-             {
-               *p++= 0;
-             }
-
-           if (opts->debug_output)
-             {
-               output_line_command (pfile, 0, same_file);
-             }
-
-           cppReader_define (pfile, q);
-
-           while (*p == ' ' || *p == '\t')
-             {
-               p++;
-             }
-         }
-       else
-         {
-           abort ();
-         }
-      }
-
-    sfree (p);
-  }
-
-  opts->done_initializing = 1;
-
-  { /* Read the appropriate environment variable and if it exists
-       replace include_defaults with the listed path.  */
-    char *epath = 0;
-#ifdef __CYGWIN32__
-  char *win32epath;
-  int win32_buf_size = 0; /* memory we need to allocate */
-#endif
-
-  if (opts->cplusplus)
-    {
-      epath = getenv ("CPLUS_INCLUDE_PATH");
-    }
-  else
-    {
-      epath = getenv ("C_INCLUDE_PATH");
-    }
-
-  /*
-  ** If the environment var for this language is set,
-  ** add to the default list of include directories.
-  */
-
-    if (epath != NULL) {
-      char *nstore = (char *) dmalloc (strlen (epath) + 2);
-      int num_dirs;
-      char *startp, *endp;
-
-#ifdef __CYGWIN32__
-      /* if we have a posix path list, convert to win32 path list */
-      if (cygwin32_posix_path_list_p (epath))
-        {
-          win32_buf_size = cygwin32_posix_to_win32_path_list_buf_size (epath);
-          win32epath = (char *) dmalloc /*@i4@*/ (win32_buf_size);
-          cygwin32_posix_to_win32_path_list (epath, win32epath);
-          epath = win32epath;
-        }
-#endif
-      for (num_dirs = 1, startp = epath; *startp; startp++)
-       {
-         if (*startp == PATH_SEPARATOR)
-           num_dirs++;
-       }
-
-      /*@-sizeoftype@*/
-      include_defaults
-       = (struct default_include *) dmalloc ((num_dirs
-                                              * sizeof (struct default_include))
-                                             + sizeof (include_defaults_array));
-      /*@=sizeoftype@*/
-
-      startp = endp = epath;
-      num_dirs = 0;
-      while (1) {
-        /* Handle cases like c:/usr/lib:d:/gcc/lib */
-        if ((*endp == PATH_SEPARATOR) || *endp == 0)
-         {
-           strncpy (nstore, startp, size_fromInt (endp - startp));
-           if (endp == startp)
-             {
-               strcpy (nstore, ".");
-             }
-           else
-             {
-               nstore[endp-startp] = '\0';
-             }
-
-           include_defaults[num_dirs].fname = cstring_fromCharsNew (nstore);
-           include_defaults[num_dirs].cplusplus = opts->cplusplus;
-           include_defaults[num_dirs].cxx_aware = 1;
-           num_dirs++;
-
-           if (*endp == '\0')
-             {
-               break;
-             }
-           endp = startp = endp + 1;
-         }
-       else
-         {
-           endp++;
-         }
-      }
-      /* Put the usual defaults back in at the end.  */
-      memcpy ((char *) &include_defaults[num_dirs],
-             (char *) include_defaults_array,
-             sizeof (include_defaults_array));
-
-      sfree (nstore);
-      /*@-branchstate@*/ } /*@=branchstate@*/
-  }
-
-  cppReader_appendIncludeChain (pfile, opts->before_system,
-                               opts->last_before_system);
-  opts->first_system_include = opts->before_system;
-
-  /* Unless -fnostdinc,
-     tack on the standard include file dirs to the specified list */
-  if (!opts->no_standard_includes) {
-    struct default_include *p = include_defaults;
-    char *specd_prefix = opts->include_prefix;
-    char *default_prefix = mstring_copy (GCC_INCLUDE_DIR);
-    int default_len = 0;
-
-       /* Remove the `include' from /usr/local/lib/gcc.../include.  */
-       if (default_prefix != NULL) {
-    if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) {
-      default_len = strlen (default_prefix) - 7;
-      default_prefix[default_len] = 0;
-    }
-       }
-
-    /* Search "translated" versions of GNU directories.
-       These have /usr/local/lib/gcc... replaced by specd_prefix.  */
-    if (specd_prefix != 0 && default_len != 0)
-      for (p = include_defaults; p->fname != NULL; p++) {
-       /* Some standard dirs are only for C++.  */
-       if (!p->cplusplus
-           || (opts->cplusplus && !opts->no_standard_cplusplus_includes)) {
-         /* Does this dir start with the prefix?  */
-         if (!strncmp (cstring_toCharsSafe (p->fname), default_prefix,
-                       size_fromInt (default_len)))
-           {
-             /* Yes; change prefix and add to search list.  */
-             struct file_name_list *nlist
-               = (struct file_name_list *) dmalloc (sizeof (*nlist));
-             size_t this_len = strlen (specd_prefix) + cstring_length (p->fname) - default_len;
-             char *str = (char *) dmalloc (this_len + 1);
-             strcpy (str, specd_prefix);
-             strcat (str, cstring_toCharsSafe (p->fname) + default_len);
-
-             nlist->next = NULL;
-             nlist->fname = cstring_fromChars (str);
-             nlist->control_macro = 0;
-             nlist->c_system_include_path = !p->cxx_aware;
-             nlist->got_name_map = 0;
-
-             cppReader_addIncludeChain (pfile, nlist);
-             if (opts->first_system_include == 0)
-               {
-                 opts->first_system_include = nlist;
-               }
-           }
-       }
-      }
-
-    /* Search ordinary names for GNU include directories.  */
-
-    for (p = include_defaults; p->fname != NULL; p++)
-      {
-       /* Some standard dirs are only for C++.  */
-       if (!p->cplusplus
-           || (opts->cplusplus && !opts->no_standard_cplusplus_includes))
-         {
-           struct file_name_list *nlist
-             = (struct file_name_list *) dmalloc (sizeof (*nlist));
-           nlist->control_macro = 0;
-           nlist->c_system_include_path = !p->cxx_aware;
-           nlist->fname = p->fname;
-           nlist->got_name_map = 0;
-           nlist->next = NULL;
-
-           cppReader_addIncludeChain (pfile, nlist);
-
-           if (opts->first_system_include == 0)
-             {
-               opts->first_system_include = nlist;
-             }
-         }
-      }
-    sfree (default_prefix);
-  }
-
-  /* Tack the after_include chain at the end of the include chain.  */
-  cppReader_appendIncludeChain (pfile, opts->after_include,
-                               opts->last_after_include);
-
-  if (opts->first_system_include == 0)
-    {
-      opts->first_system_include = opts->after_include;
-    }
-
-  /* With -v, print the list of dirs to search.  */
-  if (opts->verbose) {
-    struct file_name_list *p;
-    fprintf (stderr, "#include \"...\" search starts here:\n");
-
-    for (p = opts->include; p != NULL; p = p->next) {
-      if (p == opts->first_bracket_include)
-       fprintf (stderr, "#include <...> search starts here:\n");
-
-      fprintf (stderr, " %s\n", cstring_toCharsSafe (p->fname));
-    }
-    fprintf (stderr, "End of search list.\n");
-  }
-}
-
-int cppReader_startProcess (cppReader *pfile, cstring fname)
-{
-  cppBuffer *fp;
-  int f;
-  struct cppOptions *opts = CPPOPTIONS (pfile);
-
-  fp = cppReader_pushBuffer (pfile, NULL, 0);
-
-  if (fp == NULL)
-    {
-      return 0;
-    }
-
-  if (opts->in_fname == NULL)
-    {
-      opts->in_fname = cstring_makeLiteralTemp ("");
-    }
-
-  fp->fname = opts->in_fname;
-  fp->nominal_fname = fp->fname;
-  fp->lineno = 0;
-
-  /* Copy the entire contents of the main input file into
-     the stacked input buffer previously allocated for it.  */
-
-  if (cstring_isEmpty (fname))
-    {
-      fname = cstring_makeLiteralTemp ("");
-      f = 0;
-    }
-  else if ((f = open (cstring_toCharsSafe (fname), O_RDONLY, 0666)) < 0)
-    {
-      cppReader_error (pfile,
-                      message ("Error opening %s for reading: %s",
-                               fname, lldecodeerror (errno)));
-
-      return 0;
-    }
-  else
-    {
-      ;
-    }
-
-  if (finclude (pfile, f, fname, 0, NULL))
-    {
-      output_line_command (pfile, 0, same_file);
-    }
-
-  return 1;
-}
-
-static /*@exposed@*/ /*@null@*/ cppBuffer *cppReader_getBuffer (cppReader *pfile)
-{
-  return pfile->buffer;
-}
-
-/*@exposed@*/ cppBuffer *cppReader_getBufferSafe (cppReader *pfile)
-{
-  llassert (pfile->buffer != NULL);
-  return pfile->buffer;
-}
-
-/*@exposed@*/ char *cppLineBase (cppBuffer *buf)
-{
-  llassert (buf->buf != NULL);
-  return (buf->buf + buf->line_base);
-}
-
-int cppBufPeek (cppBuffer *buf)
-{
-  if (buf->cur == NULL || buf->rlimit == NULL) {
-    return EOF;
-  }
-
-  if (buf->cur < buf->rlimit) {
-    return *(buf->cur);
-  }
-
-  return EOF;
-}
-
-bool cppBuffer_isMacro (cppBuffer *buf)
-{
-  if (buf != NULL)
-    {
-      return (buf->cleanup == cppReader_macroCleanup);
-    }
-
-  return FALSE;
-}
-
-/*
-** Returns true if the macro should be checked, false
-** if it should be expanded normally.
-*/
-
-static bool notparseable = FALSE;  /* preceeded by @notparseable@ */
-static bool notfunction = FALSE;   /* preceeded by @notfunction@ */
-static bool expectiter = FALSE;    /* preceeded by @iter@ */
-static bool expectenditer = FALSE; /* second after @iter@ */
-static bool expectfunction = FALSE;    /* preceeded by @function@ */
-static bool expectconstant = FALSE;   /* preceeded by @constant@ */
-static bool expectmacro = FALSE;   /* preceeded by notfunction or notparseable */
-
-static void cpp_setLocation (cppReader *pfile)
-{
-  fileId fid;
-  int line;
-
-  if (pfile->buffer != NULL)
-    {
-      if (cstring_isDefined (cppReader_getBuffer (pfile)->nominal_fname))
-       {
-         cstring fname = cppReader_getBuffer (pfile)->nominal_fname;
-         
-         DPRINTF (("Looking up: %s", fname));
-         
-         if (fileTable_exists (context_fileTable (), fname))
-           {
-             fid = fileTable_lookup (context_fileTable (), fname);
-           }
-         else
-           {
-             DPRINTF (("Trying %s", cppReader_getBuffer (pfile)->fname));
-
-             fid = fileTable_lookup (context_fileTable (),
-                                     cppReader_getBuffer (pfile)->fname);
-           }
-       }
-      else
-       {
-         fid = fileTable_lookup (context_fileTable (),
-                                 cppReader_getBuffer (pfile)->fname);
-       }
-      
-      line = cppReader_getBuffer (pfile)->lineno;
-      fileloc_free (g_currentloc);
-
-      if (fileId_isValid (fid))
-       {
-         g_currentloc = fileloc_create (fid, line, 1);
-       }
-      else
-       {
-         g_currentloc = fileloc_createBuiltin ();
-       }
-    }
-  else
-    {
-      fileloc_free (g_currentloc);
-      g_currentloc = fileloc_createBuiltin ();
-    }
-}
-
-static bool cpp_shouldCheckMacro (cppReader *pfile, char *p) /*@*/
-{
-  bool checkmacro = FALSE;
-  bool hasParams = FALSE;
-  bool noexpand = FALSE;
-  cstring sname;
-  char c;
-
-  cpp_setLocation (pfile);
-
-  DPRINTF (("Should check macro? %s", p));
-
-  if (expectiter || expectconstant || expectenditer)
-    {
-      if (expectiter)
-       {
-         expectiter = FALSE;
-         expectenditer = TRUE;
-       }
-      else
-       {
-         expectiter = FALSE;
-         expectconstant = FALSE;
-         expectenditer = FALSE;
-       }
-
-      if (notfunction || notparseable)
-       {
-         notfunction = FALSE;
-         notparseable = FALSE;
-         return FALSE;
-       }
-      else
-       {
-         return TRUE;
-       }
-    }
-
-  llassert (*p == '#');
-  p++;
-
-  while (*p == ' ' || *p == '\t')
-    {
-      p++;
-    }
-
-  llassert (*p == 'd'); /* define starts */
-
-  p += 6;
-
-  while (*p == ' ' || *p == '\t')
-    {
-      p++;
-    }
-
-  sname = cstring_fromChars (p);
-  DPRINTF (("Check macro: %s", sname));
-
-  while (((c = *p) != ' ')
-        && c != '\0' && c != '('
-        && c != '\t' && c != '\\' && c != '\n'
-        && !iscntrl (c))
-    {
-      p++;
-    }
-
-  hasParams = (c == '(');
-  *p = '\0';
-
-
-  if (notparseable)
-    {
-      notparseable = FALSE;
-    }
-  else if (notfunction || fileloc_isStandardLib (g_currentloc))
-    {
-      DPRINTF (("Clear notfunction"));
-      notfunction = FALSE;
-    }
-  else
-    {
-      if (noexpand)
-       {
-         checkmacro = TRUE;
-
-         if (!expectenditer)
-           {
-             noexpand = FALSE;
-           }
-       }
-      else
-       {
-         if (usymtab_existsReal (sname))
-           {
-             uentry ue = usymtab_lookup (sname);
-
-             DPRINTF (("Lookup macro: %s", uentry_unparse (ue)));
-
-             if (fileloc_isPreproc (uentry_whereLast (ue)))
-               {
-                 goto macroDne;
-               }
-             else
-               {
-                 if (uentry_isSpecified (ue))
-                   {
-                     checkmacro = context_getFlag (FLG_SPECMACROS);
-                   }
-                 else
-                   {
-                     if (hasParams)
-                       {
-                         checkmacro = context_getFlag (FLG_LIBMACROS)
-                           || context_getFlag (FLG_FCNMACROS);
-                       }
-                   }
-               }
-           }
-         else
-           {
-           macroDne:
-             DPRINTF (("Macro doesn't exist: %s", bool_unparse (checkmacro)));
-
-             if (fileloc_isSystemFile (g_currentloc)
-                 && context_getFlag (FLG_SYSTEMDIREXPAND))
-               {
-                 ; /* don't check this macro */
-                 DPRINTF (("Don't check 1"));
-               }
-             else
-               {
-                 uentry le;
-                 
-                 if (hasParams)
-                   {
-                     DPRINTF (("Has params..."));
-
-                     if (context_getFlag (FLG_FCNMACROS))
-                       {
-                         if (usymtab_exists (sname))
-                           {
-                              /*
-                             ** only get here is macro is redefined
-                             ** error reported elsewhere
-                             */
-
-                             DPRINTF (("It exists!"));
-                           }
-                         else
-                           {
-                             /*
-                             ** We make it a forward function, since it might be declared elsewhere.
-                             ** After all headers have been processed, we should check the forward
-                             ** functions.
-                             */
-
-                             fileloc loc = fileloc_makePreproc (g_currentloc);
-
-                             /* the line is off-by-one, since the newline was already read */
-                             decLine ();
-
-                             if (expectfunction)
-                               {
-                                 expectfunction = FALSE;
-                               }
-
-                             le = uentry_makeForwardFunction (sname,
-                                                              typeId_invalid, loc);
-
-                             fileloc_free (loc);
-
-                             incLine ();
-
-                             /* Do not define here! */
-
-                             (void) usymtab_addEntry (le);
-                           }
-
-                         checkmacro = TRUE;
-                         DPRINTF (("Check: TRUE"));
-                       }
-                     else 
-                       {
-                         DPRINTF (("Flag FCN_MACROS not set!"));
-                       }
-                   }
-                 else
-                   {
-                     DPRINTF (("No params"));
-
-                     if (context_getFlag (FLG_CONSTMACROS))
-                       {
-                         bool nocontent = FALSE;
-
-                         if (c == '\0')
-                           {
-                             nocontent = TRUE;
-                           }
-                         else
-                           {
-                             if (isspace (c))
-                               {
-                                 char *rest = p + 1;
-
-                                 /*
-                                 ** Check if there is nothing after the define.
-                                 */
-
-                                 while ((*rest) != '\0' && isspace (*rest))
-                                   {
-                                     rest++;
-                                   }
-
-                                 if (*rest == '\0')
-                                   {
-                                     nocontent = TRUE; /* empty macro, don't check */
-                                   }
-                               }
-                           }
-
-                         if (usymtab_exists (sname))
-                           {
-                             ;
-                           }
-                         else
-                           {
-                             fileloc loc = fileloc_makePreproc (g_currentloc);
-                             DPRINTF (("Make constant: %s", sname));
-                             le = uentry_makeConstant (sname,
-                                                       ctype_unknown, loc);
-                             (void) usymtab_addEntry (le);
-                           }
-
-                         checkmacro = !nocontent;
-                       }
-                   }
-               }
-
-             if (checkmacro && usymtab_existsType (sname))
-               {
-                 DPRINTF (("Making false..."));
-                 decLine ();
-                 ppllerror (message ("Specified type implemented as macro: %s", sname));
-                 checkmacro = FALSE;
-                 incLine ();
-               }
-           }
-       }
-    }
-
-  if (!checkmacro)
-    {
-      if (usymtab_exists (sname))
-       {
-         uentry ue = usymtab_lookupExpose (sname);
-         fileloc tloc = fileloc_makePreproc (g_currentloc);
-
-         uentry_setDefined (ue, tloc);
-         fileloc_free (tloc);
-         uentry_setUsed (ue, fileloc_undefined);
-       }
-      else
-       {
-         fileloc tloc = fileloc_makePreproc (g_currentloc);
-         uentry ue = uentry_makeExpandedMacro (sname, tloc);
-         DPRINTF (("Make expanded macro: %s", sname));
-         DPRINTF (("Not in symbol table: %s", sname));
-         
-         (void) usymtab_addGlobalEntry (ue);
-         fileloc_free (tloc);
-       }
-    }
-
-  *p = c;
-  DPRINTF (("Returning: %s", bool_unparse (checkmacro)));
-  return checkmacro;
-}
-
-static enum cpp_token
-cpp_handleComment (cppReader *pfile, struct parse_marker *smark)
-{
-  cppBuffer *pbuf = cppReader_getBuffer (pfile);
-  char *start;
-  int len;
-  bool eliminateComment = FALSE;
-
-  llassert (pbuf->buf != NULL);
-
-  start = pbuf->buf + smark->position;
-
-  llassert (pbuf->cur != NULL);
-  len = pbuf->cur - start;
-
-  if (start[0] == '*'
-      && start[1] == context_getCommentMarkerChar ())
-    {
-      int i;
-      char c = ' ';
-      char *scomment = start + 2;
-      char savec = start[len];
-
-      start[0] = BEFORE_COMMENT_MARKER[0];
-      start[1] = BEFORE_COMMENT_MARKER[1];
-
-      llassert (start[len - 2] == '*');
-      start[len - 2] = AFTER_COMMENT_MARKER[0];
-
-      llassert (start[len - 1] == '/');
-      start[len - 1] = AFTER_COMMENT_MARKER[1];
-
-      cppReader_reserve(pfile, size_fromInt (1 + len));
-      cppReader_putCharQ (pfile, c);
-
-      cpp_setLocation (pfile);
-
-      start[len] = '\0';
-
-      if (mstring_containsString (scomment, "/*"))
-       {
-         (void) cppoptgenerror 
-           (FLG_NESTCOMMENT,
-            message ("Comment starts inside syntactic comment: %s", 
-                     cstring_fromChars (scomment)),
-            pfile);
-       }
-
-      start[len] = savec;
-
-      if (mstring_equalPrefix (scomment, "ignore"))
-       {
-         if (!context_getFlag (FLG_NOCOMMENTS))
-           {
-             context_enterSuppressRegion ();
-           }
-       }
-      else if (mstring_equalPrefix (scomment, "end"))
-       {
-         if (!context_getFlag (FLG_NOCOMMENTS))
-           {
-             context_exitSuppressRegion ();
-           }
-       }
-      else if (mstring_equalPrefix (scomment, "notparseable"))
-       {
-         notparseable = TRUE;
-         expectmacro = TRUE;
-         eliminateComment = TRUE;
-       }
-      else if (mstring_equalPrefix (scomment, "notfunction"))
-       {
-         notfunction = TRUE;
-         expectmacro = TRUE;
-         eliminateComment = TRUE;
-       }
-      else if (mstring_equalPrefix (scomment, "iter"))
-       {
-         expectiter = TRUE;
-       }
-      else if (mstring_equalPrefix (scomment, "function"))
-       {
-         expectfunction = TRUE;
-       }
-      else if (mstring_equalPrefix (scomment, "constant"))
-       {
-         expectconstant = TRUE;
-       }
-      else
-       {
-         char sChar = *scomment;
-
-         if (sChar == '='
-             || sChar == '-'
-             || sChar == '+')
-           {
-             char *rest = scomment + 1;
-
-             if (mstring_equalPrefix (rest, "commentchar"))
-               {
-                 eliminateComment = TRUE;
-
-                 if (sChar == '=')
-                   {
-                     ppllerror (cstring_makeLiteral
-                                ("Cannot restore commentchar"));
-                   }
-                 else
-                   {
-                     char *next = scomment + 12; /* strlen commentchar = 12 */
-
-                     if (*next != ' ' && *next != '\t' && *next != '\n')
-                       {
-                         ppllerror
-                           (message
-                            ("Syntactic commentchar comment is not followed by a "
-                             "whitespace character: %c",
-                             *next));
-                       }
-                     else
-                       {
-                         char cchar = *(next + 1);
-
-                         if (cchar == '\0')
-                           {
-                             ppllerror
-                               (cstring_makeLiteral
-                                ("Cannot set commentchar to NUL"));
-                           }
-                         else
-                           {
-                             context_setCommentMarkerChar (cchar);
-                             /* setComment = TRUE; */
-                           }
-                       }
-                   }
-               }
-             else if (mstring_equalPrefix (scomment, "nestcomment"))
-               {
-                 /* fix from Mike Miller <MikeM@xata.com> */
-                 context_fileSetFlag (FLG_NESTCOMMENT,
-                                      ynm_fromCodeChar (sChar));
-               }
-             else if (mstring_equalPrefix (rest, "namechecks"))
-               {
-                 context_fileSetFlag (FLG_NAMECHECKS,
-                                      ynm_fromCodeChar (sChar));
-               }
-             else if (mstring_equalPrefix (rest, "macroredef"))
-               {
-                 context_fileSetFlag (FLG_MACROREDEF,
-                                      ynm_fromCodeChar (sChar));
-               }
-             else if (mstring_equalPrefix (rest, "usevarargs"))
-               {
-                 context_fileSetFlag (FLG_USEVARARGS,
-                                      ynm_fromCodeChar (sChar));
-               }
-             else if (mstring_equalPrefix (rest, "nextlinemacros"))
-               {
-                 context_fileSetFlag (FLG_MACRONEXTLINE,
-                                      ynm_fromCodeChar (sChar));
-               }
-             else if (mstring_equalPrefix (rest, "allmacros")
-                      || mstring_equalPrefix (rest, "fcnmacros")
-                      || mstring_equalPrefix (rest, "constmacros"))
-               {
-                 flagcode fl;
-
-                 if (mstring_equalPrefix (rest, "allmacros"))
-                   {
-                     fl = FLG_ALLMACROS;
-                   }
-                 else if (mstring_equalPrefix (rest, "fcnmacros"))
-                   {
-                     fl = FLG_FCNMACROS;
-                   }
-                 else
-                   {
-                     llassert (mstring_equalPrefix (rest, "constmacros"));
-                     fl = FLG_CONSTMACROS;
-                   }
-
-
-                 context_fileSetFlag (fl, ynm_fromCodeChar (sChar));
-                 notfunction = FALSE;
-               }
-             else
-               {
-                 ;
-               }
-           }
-         else
-           {
-             ;
-           }
-       }
-
-      if (eliminateComment)
-       {
-         goto removeComment;
-       }
-
-      /* Replaces comment char's in start with spaces */
-
-      for (i = 2; i < len - 2; i++)
-       {
-         if (start[i] == BEFORE_COMMENT_MARKER[0]
-             || start[i] == BEFORE_COMMENT_MARKER[1]
-             || start[i] == context_getCommentMarkerChar ())
-           {
-             start[i] = ' ';
-           }
-       }
-
-      cppReader_putStrN (pfile, start, size_fromInt (len));
-      parseClearMark (smark);
-      return CPP_COMMENT;
-    }
-  else
-    {
-    removeComment:
-      {
-       int i;
-
-       /*
-       ** Output the comment as all spaces so line/column
-       ** in output file is still correct.
-       */
-
-       char c = ' ';
-       cstring lintcomment = cstring_undefined;
-
-       if (context_getFlag (FLG_LINTCOMMENTS))
-         {
-           if (mstring_equalPrefix (start, "*NOTREACHED*/"))
-             {
-               lintcomment = cstring_makeLiteralTemp ("l_notreach");
-             }
-           else if (mstring_equalPrefix (start, "*PRINTFLIKE*/"))
-             {
-               lintcomment = cstring_makeLiteralTemp ("l_printfli");
-             }
-           else if (mstring_equalPrefix (start, "*FALLTHROUGH*/"))
-             {
-               lintcomment = cstring_makeLiteralTemp ("l_fallthrou");
-             }
-           else if (mstring_equalPrefix (start, "*ARGSUSED*/"))
-             {
-               lintcomment = cstring_makeLiteralTemp ("l_argsus");
-             }
-           else if (mstring_equalPrefix (start, "*FALLTHRU*/"))
-             {
-               lintcomment = cstring_makeLiteralTemp ("l_fallth");
-             }
-           else
-             {
-               lintcomment = cstring_undefined;
-             }
-         }
-       else
-         {
-           lintcomment = cstring_undefined;
-         }
-
-       if (cstring_isDefined (lintcomment))
-         {
-           c = BEFORE_COMMENT_MARKER[0];
-           start[0] = BEFORE_COMMENT_MARKER[1];
-
-           llassert (cstring_length (lintcomment) == len - 3);
-
-           for (i = 1; i < len - 2; i++)
-             {
-               start[i] = cstring_getChar (lintcomment, i);
-             }
-           
-           start[len - 2] = AFTER_COMMENT_MARKER[0];
-           start[len - 1] = AFTER_COMMENT_MARKER[1];
-         }
-       else
-         {
-           /* Replaces  char's in start with spaces */
-           for (i = 0; i < len; i++)
-             {
-               if (start[i] == '/'
-                   && i < len - 1
-                   && start[i + 1] == '*') {
-                 (void) cppoptgenerror (FLG_NESTCOMMENT,
-                                        message ("Comment starts inside comment"),
-                                        pfile);
-               }
-               
-               if (start[i] != '\n')
-                 {
-                   start[i] = ' ';
-                 }
-             }
-         }
-
-       cppReader_reserve (pfile, size_fromInt (1 + len));
-       cppReader_putCharQ (pfile, c);
-       cppReader_putStrN (pfile, start, size_fromInt (len));
-       parseClearMark (smark);
-       return CPP_COMMENT;
-      }
-    }
-}
-
-static int cpp_openIncludeFile (char *filename)
-{
-  int res = open (filename, O_RDONLY, 0666);
-
-  /* evans 2001-08-23: was (res) - open returns -1 on error! reported by Robin Watts */
-  if (res >= 0)
-    {
-      if (!fileTable_exists (context_fileTable (),
-                            cstring_fromChars (filename)))
-       {
-         (void) fileTable_addHeaderFile (context_fileTable (),
-                                         cstring_fromChars (filename));
-       }
-      else
-       {
-         DPRINTF (("File already exists: %s", filename));
-       }
-    }
-
-  return res;
-}
-
-static bool cpp_skipIncludeFile (cstring fname)
-{
-  if (context_isSystemDir (fname))
-    {
-      DPRINTF (("System dir: %s", fname));
-
-      if (lcllib_isSkipHeader (fname))
-       {
-         DPRINTF (("Skip include TRUE: %s", fname));
-         return TRUE;
-       }
-      
-      if (context_getFlag (FLG_SKIPSYSHEADERS))
-       {
-         DPRINTF (("Skip include TRUE: %s", fname));
-         return TRUE;
-       }
-    }
-
-  if (context_getFlag (FLG_SINGLEINCLUDE))
-    {
-      fname = removePreDirs (fname);
-
-# if defined (WIN32) || defined (OS2)
-      cstring_replaceAll (fname, '/', '\\');
-# endif
-
-      if (fileTable_exists (context_fileTable (), fname))
-       {
-         DPRINTF (("Skip include TRUE: %s", fname));
-         return TRUE;
-       }
-    }
-
-  DPRINTF (("Skip include FALSE: %s", fname));
-  return FALSE;
-}
-
-static int cpp_peekN (cppReader *pfile, int n)
-{
-  cppBuffer *buf = cppReader_getBuffer (pfile);
-
-  llassert (buf->cur != NULL);
-
-  return (buf->rlimit - buf->cur >= (n)
-         ? buf->cur[n]
-         : EOF);
-}
-
-cppBuffer *cppBuffer_prevBuffer (cppBuffer *buf)
-{
-  return buf + 1;
-}
-
-void cppBuffer_forward (cppBuffer *buf, int n)
-{
-  llassert (buf->cur != NULL);
-  buf->cur += n;
-}
+/*\r
+See\r
+http://src.openresources.com/debian/src/devel/HTML/S/altgcc_2.7.2.2.orig%20altgcc-2.7.2.2.orig%20protoize.c.html\r
+static char *\r
+abspath (cwd, rel_filename)\r
+\r
+*/\r
+\r
+/*!!!!\r
+*** cpplib.c.old Tue Nov 28 2000 09:04:09 AM\r
+--- cpplib.c Tue Nov 28 2000 08:55:18 AM\r
+***************\r
+*** 5715,5722 ****\r
+     c2 = cppReader_peekC (pfile)\r
+     if (c2 != '\n'\r
+       goto randomchar\r
+!    token = CPP_HSPACE\r
+!    goto op2any\r
+--- 5714,5723 ----\r
+          case '\\'\r
+     c2 = cppReader_peekC (pfile)\r
+     if (c2 != '\n'\r
+       goto randomchar\r
+!    cppReader_forward (pfile, 1)\r
+!    pfile->lineno++\r
+!    return CPP_HSPACE\r
+  \r
\r
+   case '\n'\r
+     cppReader_putChar (pfile, c)\r
+\r
+\r
+Carl J. Appellof ( mailto:cappello@legato.com <mailto:cappello@legato.com> )\r
+*/ /*@i8@*/\r
+\r
+/*\r
+** LCLint - annotation-assisted static program checker\r
+** Copyright (C) 1994-2001 University of Virginia,\r
+**         Massachusetts Institute of Technology\r
+**\r
+** This program is free software; you can redistribute it and/or modify it\r
+** under the terms of the GNU General Public License as published by the\r
+** Free Software Foundation; either version 2 of the License, or (at your\r
+** option) any later version.\r
+** \r
+** This program is distributed in the hope that it will be useful, but\r
+** WITHOUT ANY WARRANTY; without even the implied warranty of\r
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+** General Public License for more details.\r
+** \r
+** The GNU General Public License is available from http://www.gnu.org/ or\r
+** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,\r
+** MA 02111-1307, USA.\r
+**\r
+** For information on lclint: lclint-request@cs.virginia.edu\r
+** To report a bug: lclint-bug@cs.virginia.edu\r
+** For more information: http://lclint.cs.virginia.edu\r
+*/\r
+/*\r
+** cpplib.c\r
+*/\r
+/*\r
+   Copyright (C) 1986, 87, 89, 92-6, 1997 Free Software Foundation, Inc.\r
+   Contributed by Per Bothner, 1994-95.\r
+   Based on CCCP program by Paul Rubin, June 1986\r
+   Adapted to ANSI C, Richard Stallman, Jan 1987\r
+\r
+This program is free software; you can redistribute it and/or modify it\r
+under the terms of the GNU General Public License as published by the\r
+Free Software Foundation; either version 2, or (at your option) any\r
+later version.\r
+\r
+This program is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with this program; if not, write to the Free Software\r
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
+\r
+ In other words, you are welcome to use, share and improve this program.\r
+ You are forbidden to forbid anyone else to use, share and improve\r
+ what you give them.   Help stamp out software-hoarding!  */\r
+\r
+/*\r
+ * Herbert 06/12/2000:\r
+ * - OS2 drive specs like WIN32\r
+ * - Includes for IBMs OS/2 compiler\r
+ */\r
+\r
+# include <ctype.h>\r
+# include <stdio.h>\r
+# include <signal.h>\r
+# ifdef __STDC__\r
+# include <stdlib.h>\r
+# endif\r
+\r
+# include <string.h>\r
+\r
+# if !(defined (WIN32) || defined (OS2) && defined (__IBMC__))\r
+# include <unistd.h>\r
+# endif\r
+\r
+# include <sys/types.h>\r
+# include <sys/stat.h>\r
+# include <fcntl.h>\r
+\r
+# if defined (WIN32) || defined (OS2) && defined (__IBMC__)\r
+# include <io.h>\r
+# include <sys/utime.h>                /* for __DATE__ and __TIME__ */\r
+# include <time.h>\r
+# else\r
+# ifndef VMS\r
+# ifndef USG\r
+# include <time.h> /* Reported by Paul Smith */\r
+# include <sys/time.h>\r
+# include <sys/resource.h>\r
+# else\r
+# include <sys/times.h>\r
+# include <time.h>\r
+# include <fcntl.h>\r
+# endif /* USG */\r
+# endif /* not VMS */\r
+# endif /* not WIN32 */\r
+\r
+/* This defines "errno" properly for VMS, and gives us EACCES.  */\r
+# include <errno.h>\r
+\r
+# include "lclintMacros.nf"\r
+# include "llbasic.h"\r
+# include "lcllib.h"\r
+# include "cpplib.h"\r
+# include "cpperror.h"\r
+# include "cpphash.h"\r
+# include "cppexp.h"\r
+# include "version.h"\r
+# include "portab.h"\r
+# include "osd.h"\r
+\r
+/*\r
+** This is really kludgey code...\r
+*/\r
+\r
+/*@+boolint@*/\r
+/*@+charint@*/\r
+\r
+#define NO_SHORTNAMES\r
+\r
+# ifdef open\r
+# undef open\r
+# undef read\r
+# undef write\r
+# endif /* open */\r
+\r
+/*@constant int IMPORT_FOUND@*/\r
+# define IMPORT_FOUND -2\r
+\r
+/*@constant int SKIP_INCLUDE@*/\r
+# define SKIP_INCLUDE IMPORT_FOUND\r
+\r
+/*@constant unused int IMPORT_NOT_FOUND@*/\r
+# define IMPORT_NOT_FOUND -1\r
+\r
+#ifndef STDC_VALUE\r
+/*@constant unused int STDC_VALUE@*/\r
+#define STDC_VALUE 1\r
+#endif\r
+\r
+/* By default, colon separates directories in a path.  */\r
+#ifndef PATH_SEPARATOR\r
+/*@constant char PATH_SEPARATOR@*/\r
+#define PATH_SEPARATOR ':'\r
+#endif\r
+\r
+static void parse_name (cppReader *, int);\r
+\r
+static int cpp_openIncludeFile (char *p_filename)\r
+     /*@modifies fileSystem @*/ ;\r
+\r
+static void cpp_setLocation (cppReader *p_pfile)\r
+     /*@modifies g_currentloc@*/ ;\r
+\r
+static enum cpp_token cpp_handleComment (cppReader *p_pfile,\r
+                                        struct parse_marker *p_smark)\r
+     /*@modifies p_pfile, p_smark@*/;\r
+\r
+static bool cpp_shouldCheckMacro (cppReader *p_pfile, char *p_p) /*@*/ ;\r
+\r
+static bool cpp_skipIncludeFile (cstring p_fname) /*@*/ ;\r
+\r
+#ifndef O_RDONLY\r
+#define O_RDONLY 0\r
+#endif\r
+\r
+/* Symbols to predefine.  */\r
+\r
+#ifdef CPP_PREDEFINES\r
+static /*@observer@*/ char *predefs = CPP_PREDEFINES;\r
+#else\r
+static /*@observer@*/ char *predefs = "";\r
+#endif\r
+\r
+/* We let tm.h override the types used here, to handle trivial differences\r
+   such as the choice of unsigned int or long unsigned int for size_t.\r
+   When machines start needing nontrivial differences in the size type,\r
+   it would be best to do something here to figure out automatically\r
+   from other information what type to use.  */\r
+\r
+/* The string value for __SIZE_TYPE__.  */\r
+\r
+#ifndef SIZE_TYPE\r
+/*@constant observer char *SIZE_TYPE@*/\r
+#define SIZE_TYPE "long unsigned int"\r
+#endif\r
+\r
+/* The string value for __PTRDIFF_TYPE__.  */\r
+\r
+#ifndef PTRDIFF_TYPE\r
+/*@constant observer char *PTRDIFF_TYPE@*/\r
+#define PTRDIFF_TYPE "long int"\r
+#endif\r
+\r
+/* The string value for __WCHAR_TYPE__.  */\r
+\r
+#ifndef WCHAR_TYPE\r
+/*@constant observer char *WCHAR_TYPE@*/\r
+#define WCHAR_TYPE "int"\r
+#endif\r
+\r
+/* The string value for __USER_LABEL_PREFIX__ */\r
+\r
+#ifndef USER_LABEL_PREFIX\r
+/*@constant observer char *USER_LABEL_PREFIX@*/\r
+#define USER_LABEL_PREFIX ""\r
+#endif\r
+\r
+/* The string value for __REGISTER_PREFIX__ */\r
+\r
+#ifndef REGISTER_PREFIX\r
+/*@constant observer char *REGISTER_PREFIX@*/\r
+#define REGISTER_PREFIX ""\r
+#endif\r
+\r
+/* table to tell if char can be part of a C identifier.  */\r
+static bool is_idchar[256];\r
+/* table to tell if char can be first char of a c identifier.  */\r
+static bool is_idstart[256];\r
+/* table to tell if c is horizontal space.  */\r
+static bool is_hor_space[256];\r
+/* table to tell if c is horizontal or vertical space.  */\r
+static bool is_space[256];\r
+\r
+static /*@exposed@*/ /*@null@*/ cppBuffer *\r
+cppReader_getBuffer (/*@special@*/ cppReader *p_pfile)\r
+     /*@uses p_pfile->buffer@*/\r
+     /*@modifies nothing@*/ ;\r
+\r
+/*@notfunction@*/\r
+# define SKIP_WHITE_SPACE(p) do { /*@access cstring@*/ while (is_hor_space[(int) *(p)]) { (p)++; } } /*@noaccess cstring@*/ while (0)\r
+\r
+/*@notfunction@*/\r
+# define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*(p)]) { (p)++; } } while (0)\r
+\r
+static int cpp_peekN (cppReader *p_pfile, int p_n) /*@*/ ;\r
+\r
+/*@function static int cppBuffer_get (sef cppBuffer *p_b) modifies *p_b ; @*/\r
+# define cppBuffer_get(BUFFER) \\r
+  ((BUFFER)->cur < (BUFFER)->rlimit ? *(BUFFER)->cur++ : EOF)\r
+\r
+/* Append string STR (of length N) to PFILE's output buffer.  Make space. */\r
+/*@function static void cppReader_puts (sef cppReader *p_file, char *p_str, sef size_t p_n)\r
+                     modifies *p_file; @*/\r
+# define cppReader_puts(PFILE, STR, N) \\r
+  cppReader_reserve(PFILE, N), cppReader_putStrN (PFILE, STR,N)\r
+\r
+/* Append character CH to PFILE's output buffer.  Assume sufficient space. */\r
+\r
+/*@function static void cppReader_putCharQ (cppReader *p_file, char p_ch)\r
+                    modifies *p_file; @*/\r
+# define cppReader_putCharQ(PFILE, CH) (*(PFILE)->limit++ = (CH))\r
+\r
+/* Append character CH to PFILE's output buffer.  Make space if need be. */\r
+\r
+/*@function static void cppReader_putChar (sef cppReader *p_file, char p_ch)\r
+                    modifies *p_file; @*/\r
+#define cppReader_putChar(PFILE, CH) (cppReader_reserve (PFILE, (size_t) 1), cppReader_putCharQ (PFILE, CH))\r
+\r
+/* Make sure PFILE->limit is followed by '\0'. */\r
+/*@function static void cppReader_nullTerminateQ (cppReader *p_file)\r
+      modifies *p_file; @*/\r
+\r
+#define cppReader_nullTerminateQ(PFILE) (*(PFILE)->limit = 0)\r
+\r
+/*@function static void cppReader_nullTerminate (sef cppReader *p_file)\r
+                           modifies *p_file; @*/\r
+# define cppReader_nullTerminate(PFILE) \\r
+  (cppReader_reserve (PFILE, (size_t) 1), *(PFILE)->limit = 0)\r
+\r
+/*@function static void cppReader_adjustWritten (cppReader *p_file, size_t)\r
+                           modifies *p_file; @*/\r
+#define cppReader_adjustWritten(PFILE,DELTA) ((PFILE)->limit += (DELTA))\r
+\r
+/*@function static bool cppReader_isC89 (cppReader *) modifies nothing; @*/\r
+#define cppReader_isC89(PFILE) (CPPOPTIONS(PFILE)->c89)\r
+\r
+/*@function static observer char *cppReader_wcharType (cppReader *)\r
+     modifies nothing; @*/\r
+\r
+# define cppReader_wcharType(PFILE) \\r
+  (CPPOPTIONS (PFILE)->cplusplus ? "__wchar_t" : WCHAR_TYPE)\r
+\r
+static void cppBuffer_forward (cppBuffer *p_buf, int p_n) /*@modifies *p_buf@*/ ;\r
+\r
+/*@function static void cppReader_forward (cppReader *p_pfile, int) modifies *p_pfile; @*/\r
+# define cppReader_forward(pfile, N) \\r
+  (cppBuffer_forward (cppReader_getBufferSafe (pfile), (N)))\r
+\r
+/*@function static int cppReader_getC (cppReader *p_pfile) modifies *p_pfile; @*/\r
+# define cppReader_getC(pfile)   (cppBuffer_get (cppReader_getBufferSafe (pfile)))\r
+\r
+/*@function static int cppReader_peekC (cppReader *) modifies nothing;@*/\r
+# define cppReader_peekC(pfile)  (cppBufPeek (cppReader_getBufferSafe (pfile)))\r
+\r
+/* Move all backslash-newline pairs out of embarrassing places.\r
+   Exchange all such pairs following BP\r
+   with any potentially-embarrassing characters that follow them.\r
+   Potentially-embarrassing characters are / and *\r
+   (because a backslash-newline inside a comment delimiter\r
+   would cause it not to be recognized).  */\r
+\r
+/*@notfunction@*/\r
+# define NEWLINE_FIX \\r
+   do { while (cppReader_peekC (pfile) == '\\' && cpp_peekN (pfile, 1) == '\n') { cppReader_forward (pfile, 2); } } while(FALSE)\r
+\r
+     /* Same, but assume we've already read the potential '\\' into C.  */\r
+/*@notfunction@*/\r
+# define NEWLINE_FIX1(C) do { \\r
+     while ((C) == '\\' && cppReader_peekC (pfile) == '\n') { cppReader_forward (pfile, 1); (C) = cppReader_getC (pfile); }\\r
+                                                                          } while(0)\r
+\r
+static void parseSetMark (/*@out@*/ struct parse_marker *,\r
+                         cppReader *);\r
+static void parseClearMark (struct parse_marker *);\r
+static void parseGotoMark (struct parse_marker *, cppReader *);\r
+static void parseMoveMark (struct parse_marker *, cppReader *);\r
+\r
+/* If we have a huge buffer, may need to cache more recent counts */\r
+static /*@exposed@*/ char *cppLineBase (/*@sef@*/ cppBuffer *);\r
+\r
+static /*@exposed@*/ /*@null@*/ cppBuffer *\r
+   cppReader_pushBuffer (cppReader *p_pfile,\r
+                        /*@owned@*/ /*@null@*/ char *, size_t)\r
+     /*@modifies p_pfile@*/ ;\r
+\r
+static void cppReader_appendIncludeChain\r
+(cppReader *p_pfile,\r
+ /*@keep@*/ struct file_name_list *p_first,\r
+ /*@dependent@*/ struct file_name_list *p_last);\r
+\r
+static void cppReader_macroCleanup (cppBuffer *p_pbuf, cppReader *p_pfile);\r
+static enum cpp_token cppReader_nullUnderflow (/*@unused@*/ cppReader *p_pfile);\r
+\r
+static void cppReader_nullCleanup (/*@unused@*/ cppBuffer *p_pbuf,\r
+                                  /*@unused@*/ cppReader *p_pfile);\r
+\r
+static void cppReader_fileCleanup (cppBuffer *p_pbuf,\r
+                                  /*@unused@*/ cppReader *p_pfile);\r
+\r
+static int cppReader_handleDirective (cppReader *p_pfile);\r
+\r
+static void cppReader_scanBuffer (cppReader *p_pfile);\r
+\r
+# if defined (WIN32) || defined (OS2) && defined (__IBMC__)\r
+\r
+/*\r
+** WIN32 (at least the VC++ include files) does not define mode_t.\r
+*/\r
+\r
+/*@-incondefs@*/ /*@-czechtypes@*/\r
+typedef unsigned int mode_t;\r
+/*@=incondefs@*/ /*@=czechtypes@*/\r
+\r
+# endif\r
+\r
+static int file_size_and_mode (int p_fd, /*@out@*/ mode_t *p_mode_pointer,\r
+                              /*@out@*/ size_t *p_size_pointer);\r
+static int safe_read (int p_desc, /*@out@*/ char *p_ptr, int p_len);\r
+\r
+\r
+/*\r
+** cppBuffer_isMacro is true if the buffer contains macro expansion.\r
+** (Note that it is false while we're expanding marco *arguments*.)\r
+*/\r
+\r
+static bool cppBuffer_isMacro (/*@null@*/ cppBuffer *) /*@*/ ;\r
+\r
+static void path_include (cppReader *p_pfile, char *p_path)\r
+     /*@modifies p_pfile@*/ ;\r
+\r
+static void initialize_builtins (cppReader *p_pfile)\r
+     /*@modifies p_pfile@*/ ;\r
+\r
+static void initialize_char_syntax (struct cppOptions *p_opts) ;\r
+\r
+static int /*@alt void@*/ finclude (cppReader *p_pfile, int p_f,\r
+                                   cstring p_fname,\r
+                                   bool p_system_header_p,\r
+                                   /*@dependent@*/ /*@null@*/ struct file_name_list *p_dirptr);\r
+\r
+static void validate_else (cppReader *p_pfile, cstring p_directive);\r
+\r
+static void conditional_skip (cppReader *p_pfile, int p_skip,\r
+                             enum node_type p_type,\r
+                             /*@dependent@*/ /*@null@*/ char *p_control_macro);\r
+\r
+static HOST_WIDE_INT eval_if_expression (cppReader *p_pfile,\r
+                                        char *p_buf,\r
+                                        int p_length);\r
+\r
+static void skip_if_group (cppReader *p_pfile, int p_any);\r
+\r
+static bool comp_def_part (bool p_first, char *p_beg1, int p_len1,\r
+                          char *p_beg2, int p_len2, bool p_last);\r
+\r
+#ifdef abort\r
+extern void fancy_abort ();\r
+#endif\r
+\r
+static bool redundant_include_p (cppReader *p_pfile, /*@null@*/ cstring p_name);\r
+static bool is_system_include (cppReader *p_pfile, cstring p_filename);\r
+\r
+static /*@observer@*/ /*@null@*/ struct file_name_map *\r
+read_name_map (cppReader *p_pfile, cstring p_dirname);\r
+\r
+static cstring read_filename_string (int p_ch, /*:open:*/ FILE *p_f);\r
+\r
+static int open_include_file (cppReader *p_pfile,\r
+                             /*@owned@*/ cstring p_fname,\r
+                             /*@null@*/ struct file_name_list *p_searchptr);\r
+\r
+static void push_macro_expansion (cppReader *,\r
+                                 /*@owned@*/ char *, size_t,\r
+                                 /*@dependent@*/ hashNode);\r
+\r
+/* Last arg to output_line_command.  */\r
+enum file_change_code {\r
+  same_file, enter_file, leave_file\r
+};\r
+\r
+/* `struct directive' defines one #-directive, including how to handle it.  */\r
+\r
+struct directive {\r
+  int length;                  /* Length of name */\r
+  /*@null@*/ int (*func)();    /* Function to handle directive */\r
+  /*@observer@*/ cstring name; /* Name of directive */\r
+  enum node_type type;         /* Code which describes which directive.  */\r
+  bool command_reads_line;      /* One if rest of line is read by func.  */\r
+  bool traditional_comments;   /* Nonzero: keep comments if -traditional.  */\r
+  bool pass_thru;              /* Copy preprocessed directive to output file.*/\r
+};\r
+\r
+/* These functions are declared to return int instead of void since they\r
+   are going to be placed in a table and some old compilers have trouble with\r
+   pointers to functions returning void.  */\r
+\r
+static int do_define (cppReader *, /*@null@*/ struct directive *, \r
+                     char *, char *);\r
+static int do_defineAux (cppReader *, /*@null@*/ struct directive *,\r
+                        char *, char *, bool);\r
+     \r
+static int do_line (cppReader *, /*@null@*/ struct directive *);\r
+static int do_include (cppReader *, struct directive *, char *, char *);\r
+static int do_undef (cppReader *, struct directive *, char *, char *);\r
+static int do_error (cppReader *, struct directive *, char *, char *);\r
+static int do_pragma (cppReader *, struct directive *, char *, char *);\r
+static int do_ident (cppReader *, struct directive *, char *, char *);\r
+static int do_if (cppReader *, struct directive *, char *, char *);\r
+static int do_xifdef (cppReader *, struct directive *, char *, char *);\r
+static int do_else (cppReader *, struct directive *, char *, char *);\r
+static int do_elif (cppReader *, struct directive *, char *, char *);\r
+static int do_endif (cppReader *, struct directive *, char *, char *);\r
+static int do_warning (cppReader *, struct directive *, char *, char *);\r
+\r
+/* If a buffer's dir field is SELF_DIR_DUMMY, it means the file was found\r
+   via the same directory as the file that #included it.  */\r
+\r
+/*@constant observer struct file_name_list *SELF_DIR_DUMMY@*/\r
+#define SELF_DIR_DUMMY ((struct file_name_list *) (~0))\r
+\r
+/* #include "file" looks in source file dir, then stack.  */\r
+/* #include <file> just looks in the stack.  */\r
+/* -I directories are added to the end, then the defaults are added.  */\r
+\r
+/*@access cstring@*/\r
+\r
+static struct default_include {\r
+  /*@dependent@*/ /*@observer@*/ cstring fname;        /* The name of the directory.  */\r
+  int cplusplus;               /* Only look here if we're compiling C++.  */\r
+  int cxx_aware;               /* Includes in this directory don't need to\r
+                                  be wrapped in extern "C" when compiling\r
+                                  C++.  */\r
+} include_defaults_array[]\r
+= {\r
+  /* This is the dir for fixincludes.  Put it just before\r
+     the files that we fix.  */\r
+  { GCC_INCLUDE_DIR, 0, 0 },\r
+  { GCC_INCLUDE_DIR2, 0, 0 },\r
+  { cstring_undefined, 0, 0 }\r
+};\r
+\r
+/*@noaccess cstring@*/\r
+\r
+/* Here is the actual list of #-directives, most-often-used first.\r
+   The initialize_builtins function assumes #define is the very first.  */\r
+\r
+/*@access cstring@*/\r
+\r
+static struct directive directive_table[] = {\r
+  {  6, do_define, "define", T_DEFINE, FALSE, TRUE, FALSE },\r
+  {  5, do_xifdef, "ifdef", T_IFDEF, TRUE, FALSE, FALSE },\r
+  {  6, do_xifdef, "ifndef", T_IFNDEF, TRUE, FALSE, FALSE },\r
+  {  7, do_include, "include", T_INCLUDE, TRUE, FALSE, FALSE },\r
+  {  5, do_endif, "endif", T_ENDIF, TRUE, FALSE, FALSE },\r
+  {  4, do_else, "else", T_ELSE, TRUE, FALSE, FALSE },\r
+  {  2, do_if, "if", T_IF, TRUE, FALSE, FALSE },\r
+  {  4, do_elif, "elif", T_ELIF, TRUE, FALSE, FALSE },\r
+  {  5, do_undef, "undef", T_UNDEF, FALSE, FALSE, FALSE },\r
+  {  5, do_error, "error", T_ERROR, FALSE, FALSE, FALSE },\r
+  {  7, do_warning, "warning", T_WARNING, FALSE, FALSE, FALSE },\r
+  {  6, do_pragma, "pragma", T_PRAGMA, FALSE, FALSE, TRUE},\r
+  {  4, do_line, "line", T_LINE, TRUE, FALSE, FALSE },\r
+  {  5, do_ident, "ident", T_IDENT, TRUE, FALSE, TRUE },\r
+  /* {  8, do_unassert, "unassert", T_UNASSERT, TRUE, FALSE, FALSE }, */\r
+  {  -1, 0, "", T_UNUSED, FALSE, FALSE, FALSE },\r
+};\r
+/*@noaccess cstring@*/\r
+\r
+static cstring searchPath_unparse (struct file_name_list *search_start) \r
+{\r
+  cstring res = cstring_newEmpty ();\r
+  struct file_name_list *searchptr = NULL;\r
+\r
+  for (searchptr = search_start; searchptr != NULL;\r
+       searchptr = searchptr->next)\r
+    {\r
+      if (!cstring_isEmpty (searchptr->fname)) {\r
+       res = cstring_concatFree1 (res, searchptr->fname);\r
+       if (searchptr->next != NULL) {\r
+         res = cstring_appendChar (res, ';');\r
+       }\r
+      }\r
+    }\r
+\r
+  return res;\r
+}\r
+\r
+/*@+charint@*/\r
+static void\r
+initialize_char_syntax (struct cppOptions *opts)\r
+{\r
+  char i;\r
+\r
+  /*\r
+   * Set up is_idchar and is_idstart tables.  These should be\r
+   * faster than saying (is_alpha (c) || c == '_'), etc.\r
+   * Set up these things before calling any routines tthat\r
+   * refer to them.\r
+   */\r
+\r
+  for (i = 'a'; i <= 'z'; i++) {\r
+    is_idchar[i - 'a' + 'A'] = TRUE;\r
+    is_idchar[(int) i] = TRUE;\r
+    is_idstart[i - 'a' + 'A'] = TRUE;\r
+    is_idstart[(int) i] = TRUE;\r
+  }\r
+\r
+  for (i = '0'; i <= '9'; i++)\r
+    {\r
+      is_idchar[(int) i] = TRUE;\r
+    }\r
+\r
+  is_idchar['_'] = TRUE;\r
+  is_idstart['_'] = TRUE;\r
+  is_idchar['$'] = opts->dollars_in_ident;\r
+  is_idstart['$'] = opts->dollars_in_ident;\r
+\r
+  /* horizontal space table */\r
+  is_hor_space[' '] = TRUE;\r
+  is_hor_space['\t'] = TRUE;\r
+  is_hor_space['\v'] = TRUE;\r
+  is_hor_space['\f'] = TRUE;\r
+  is_hor_space['\r'] = TRUE;\r
+\r
+  is_space[' '] = TRUE;\r
+  is_space['\t'] = TRUE;\r
+  is_space['\v'] = TRUE;\r
+  is_space['\f'] = TRUE;\r
+  is_space['\n'] = TRUE;\r
+  is_space['\r'] = TRUE;\r
+}\r
+\r
+bool isIdentifierChar (char c)\r
+{\r
+  return is_idchar[(int) c];\r
+}\r
+\r
+/* Place into P_PFILE a quoted string representing the string SRC.\r
+   Caller must reserve enough space in pfile->token_buffer.  */\r
+\r
+static void\r
+quote_string (cppReader *pfile, char *src)\r
+{\r
+  char c;\r
+\r
+  cppReader_putCharQ (pfile, '\"');\r
+  for (;;)\r
+    {\r
+      switch ((c = *src++))\r
+       {\r
+       default:\r
+         if (isprint (c))\r
+           cppReader_putCharQ (pfile, c);\r
+         else\r
+           {\r
+             sprintf (cppReader_getPWritten (pfile), "\\%03o",\r
+                      (unsigned int) c);\r
+             cppReader_adjustWritten (pfile, (size_t) 4);\r
+           }\r
+         /*@switchbreak@*/ break;\r
+\r
+       case '\"':\r
+       case '\\':\r
+         cppReader_putCharQ (pfile, '\\');\r
+         cppReader_putCharQ (pfile, c);\r
+         /*@switchbreak@*/ break;\r
+\r
+       case '\0':\r
+         cppReader_putCharQ (pfile, '\"');\r
+         cppReader_nullTerminateQ (pfile);\r
+         return;\r
+       }\r
+    }\r
+}\r
+\r
+/* Re-allocates PFILE->token_buffer so it will hold at least N more chars.  */\r
+\r
+void\r
+cppReader_growBuffer (cppReader *pfile, size_t n)\r
+{\r
+  size_t old_written = cppReader_getWritten (pfile);\r
+  pfile->token_buffer_size = n + 2 * pfile->token_buffer_size;\r
+  pfile->token_buffer = (char *)\r
+    drealloc (pfile->token_buffer, pfile->token_buffer_size);\r
+  cppReader_setWritten (pfile, old_written);\r
+}\r
+\r
+/*\r
+ * process a given definition string, for initialization\r
+ * If STR is just an identifier, define it with value 1.\r
+ * If STR has anything after the identifier, then it should\r
+ * be identifier=definition.\r
+ */\r
+\r
+void\r
+cppReader_define (cppReader *pfile, char *str)\r
+{\r
+  char *buf = NULL;\r
+  char *p = str;\r
+\r
+  DPRINTF (("Cpp reader define: %s", str));\r
+\r
+  if (!is_idstart[(int) *p])\r
+    {\r
+      DPRINTF (("ERROR 1"));\r
+      cppReader_error (pfile,\r
+                      message ("Malformed option `-D%s'",\r
+                               cstring_fromChars (str)));\r
+      \r
+      return;\r
+    }\r
+\r
+  p++;\r
+\r
+  DPRINTF (("Here 2"));\r
+\r
+  while (is_idchar[(int) *p])\r
+    {\r
+      p++;\r
+    }\r
+\r
+  if (*p == '(') {\r
+    p++;\r
+    while (*p != ')' && *p != '\0') {\r
+      p++;\r
+    }\r
+\r
+    if (*p == ')') {\r
+      p++;\r
+    } else {\r
+      cppReader_error \r
+       (pfile,\r
+        message ("Malformed option: -D%s (no closing parenthesis)", \r
+                 cstring_fromChars (str)));\r
+    }\r
+  }\r
+\r
+  DPRINTF (("Here 2"));\r
+\r
+  if (*p == '\0')\r
+    {\r
+      buf = (char *) dmalloc (size_fromInt (p - str + 4));\r
+      strcpy ((char *) buf, str);\r
+      strcat ((char *) buf, " 1");\r
+    }\r
+  else if (*p != '=')\r
+    {\r
+      DPRINTF (("ERROR 2"));\r
+      cppReader_error (pfile,\r
+                      message ("Malformed option: -D%s (expected '=', found '%c')",\r
+                               cstring_fromChars (str),\r
+                               *p));\r
+      return;\r
+    }\r
+  else\r
+    {\r
+      char *q;\r
+      /* Copy the entire option so we can modify it.  */\r
+      DPRINTF (("Copying..."));\r
+      buf = (char *) dmalloc (2 * strlen (str) + 1);\r
+      strncpy (buf, str, size_fromInt (p - str));\r
+\r
+      /* Change the = to a space.  */\r
+      buf[p - str] = ' ';\r
+      /* Scan for any backslash-newline and remove it.  */\r
+      p++;\r
+      q = &buf[p - str];\r
+\r
+      while (*p != '\0')\r
+       {\r
+         if (*p == '\\' && p[1] == '\n')\r
+           p += 2;\r
+         else\r
+           *q++ = *p++;\r
+       }\r
+\r
+      DPRINTF (("Here we are..."));\r
+      *q = '\0';\r
+    }\r
+\r
+  llassert (buf != NULL);\r
+  DPRINTF (("Do define: %s / %ld", buf, size_toLong (strlen (buf))));\r
+  (void) do_define (pfile, NULL, buf, buf + strlen (buf));\r
+  sfree (buf);\r
+}\r
+\r
+/* Append a chain of `struct file_name_list's\r
+   to the end of the main include chain.\r
+   FIRST is gthe beginning of the chain to append, and LAST is the end.  */\r
+\r
+void\r
+cppReader_appendIncludeChain (cppReader *pfile,\r
+                     struct file_name_list *first,\r
+                     struct file_name_list *last)\r
+{\r
+  struct cppOptions *opts = CPPOPTIONS (pfile);\r
+  struct file_name_list *dir;\r
+\r
+  if (first == NULL || last == NULL)\r
+    {\r
+      return;\r
+    }\r
+\r
+  if (opts->include == 0)\r
+    {\r
+      opts->include = first;\r
+    }\r
+  else\r
+    {\r
+      llassert (opts->last_include->next == NULL);\r
+      opts->last_include->next = first;\r
+    }\r
+\r
+  if (opts->first_bracket_include == 0)\r
+    {\r
+      opts->first_bracket_include = first;\r
+\r
+      for (dir = first; ; dir = dir->next) {\r
+       int len = cstring_length (dir->fname) + INCLUDE_LEN_FUDGE;\r
+       if (len > pfile->max_include_len)\r
+         pfile->max_include_len = len;\r
+       if (dir == last)\r
+         break;\r
+      }\r
+    }\r
+\r
+  llassert (last->next == NULL);\r
+  /* last->next = NULL; */\r
+  opts->last_include = last;\r
+}\r
+\r
+# if 0\r
+static /*@unused@*/ void \r
+cppReader_showIncludeChain (cppReader *pfile)\r
+{\r
+  struct file_name_list *dirs = CPPOPTIONS (pfile)->include;\r
+\r
+  if (dirs != NULL)\r
+    {\r
+      while (dirs != NULL)\r
+       {\r
+         fprintf (stderr, "*%s*:", cstring_toCharsSafe (dirs->fname));\r
+         dirs = dirs->next;\r
+       }\r
+\r
+      fprintf (stderr, "\n");\r
+    }\r
+  else\r
+    {\r
+      fprintf (stderr, "No includes\n");\r
+    }\r
+}\r
+# endif\r
+\r
+cstring \r
+cppReader_getIncludePath ()\r
+{\r
+  cppReader *pfile = &g_cppState;\r
+  struct file_name_list *dirs = CPPOPTIONS (pfile)->include;\r
+  cstring res = cstring_undefined;\r
+\r
+  if (dirs != NULL)\r
+    {\r
+      while (dirs != NULL)\r
+       {\r
+         res = message ("%q%c%s", res, PATH_SEPARATOR, dirs->fname);\r
+         dirs = dirs->next;\r
+       }\r
+    }\r
+  else\r
+    {\r
+      res = cstring_makeLiteral ("<no include path>");\r
+    }\r
+\r
+  return res;\r
+}\r
+\r
+void\r
+cppReader_addIncludeChain (cppReader *pfile, struct file_name_list *dir)\r
+{\r
+  struct cppOptions *opts = CPPOPTIONS (pfile);\r
+\r
+  if (dir == 0)\r
+    {\r
+      return;\r
+    }\r
+\r
+  if (opts->include == 0)\r
+    {\r
+      opts->include = dir;\r
+    }\r
+  else\r
+    {\r
+      llassert (opts->last_include->next == NULL);\r
+      opts->last_include->next = dir;\r
+    }\r
+\r
+  if (opts->first_bracket_include == 0)\r
+    {\r
+      int len = cstring_length (dir->fname) + INCLUDE_LEN_FUDGE;\r
+      opts->first_bracket_include = dir;\r
+      if (len > pfile->max_include_len)\r
+       {\r
+         pfile->max_include_len = len;\r
+       }\r
+    }\r
+\r
+  dir->next = NULL;\r
+  opts->last_include = dir;\r
+  /* cppReader_showIncludeChain (pfile); */\r
+}\r
+\r
+/* Given a colon-separated list of file names PATH,\r
+   add all the names to the search path for include files.  */\r
+\r
+static void\r
+path_include (cppReader *pfile, char *path)\r
+{\r
+  char *p;\r
+\r
+#ifdef __CYGWIN32__\r
+  char *win32temp;\r
+\r
+  /* if we have a posix path list, convert to win32 path list */\r
+  win32temp = (char *) dmalloc /*@i4@*/\r
+    (cygwin32_posix_to_win32_path_list_buf_size (path));\r
+  cygwin32_posix_to_win32_path_list (path, win32temp);\r
+  path = win32temp;\r
+#endif\r
+\r
+  p = path;\r
+\r
+  if (*p != '\0')\r
+    while (1) {\r
+      char *q = p;\r
+      char *name;\r
+      struct file_name_list *dirtmp;\r
+\r
+      /* Find the end of this name.  */\r
+      while (*q != '\0' && *q != PATH_SEPARATOR)\r
+       {\r
+         q++;\r
+       }\r
+\r
+      if (p == q)\r
+       {\r
+         /* An empty name in the path stands for the current directory.  */\r
+         name = (char *) dmalloc ((size_t) 2);\r
+         name[0] = '.';\r
+         name[1] = '\0';\r
+       }\r
+      else\r
+       {\r
+         /* Otherwise use the directory that is named.  */\r
+         name = (char *) dmalloc (size_fromInt (q - p + 1));\r
+         memcpy (name, p, size_fromInt (q - p));\r
+         name[q - p] = '\0';\r
+       }\r
+\r
+      dirtmp = (struct file_name_list *) dmalloc (sizeof (*dirtmp));\r
+      dirtmp->next = 0;                /* New one goes on the end */\r
+      dirtmp->control_macro = 0;\r
+      dirtmp->c_system_include_path = 0;\r
+      dirtmp->fname = cstring_fromChars (name);\r
+      dirtmp->got_name_map = 0;\r
+      cppReader_addIncludeChain (pfile, dirtmp);\r
+\r
+      /* Advance past this name.  */\r
+      p = q;\r
+      if (*p == '\0')\r
+       break;\r
+      /* Skip the colon.  */\r
+      p++;\r
+    }\r
+}\r
+\r
+void\r
+cppOptions_init (cppOptions *opts)\r
+{\r
+  memset ((char *) opts, 0, sizeof *opts);\r
+  assertSet (opts);\r
+\r
+  opts->in_fname = NULL;\r
+  opts->out_fname = NULL;\r
+\r
+  /* Initialize is_idchar to allow $.  */\r
+  opts->dollars_in_ident = TRUE;\r
+\r
+  opts->no_line_commands = 0;\r
+  opts->no_trigraphs = TRUE;\r
+  opts->put_out_comments = 1;\r
+  opts->print_include_names = 0;\r
+  opts->dump_macros = DUMP_DEFINITIONS; /* DUMP_NONE; */\r
+  opts->no_output = 0;\r
+  opts->cplusplus = 0;\r
+\r
+  opts->cplusplus_comments = 1;\r
+  opts->verbose = 0;\r
+  opts->lang_asm = 0;\r
+  opts->for_lint = 0;\r
+  opts->chill = 0;\r
+  opts->pedantic_errors = 0;\r
+  opts->warn_comments = 0;\r
+  opts->warnings_are_errors = 0;\r
+\r
+  initialize_char_syntax (opts);\r
+}\r
+\r
+enum cpp_token\r
+cppReader_nullUnderflow (/*@unused@*/ cppReader *pfile)\r
+{\r
+  return CPP_EOF;\r
+}\r
+\r
+void\r
+cppReader_nullCleanup (/*@unused@*/ cppBuffer *pbuf,\r
+             /*@unused@*/ cppReader *pfile)\r
+{\r
+  ;\r
+}\r
+\r
+void\r
+cppReader_macroCleanup (cppBuffer *pbuf, /*@unused@*/ cppReader *pfile)\r
+{\r
+  hashNode macro = pbuf->hnode;\r
+\r
+  if (macro->type == T_DISABLED)\r
+    {\r
+      macro->type = T_MACRO;\r
+    }\r
+\r
+  if (macro->type != T_MACRO || pbuf->buf != macro->value.defn->expansion)\r
+    {\r
+      sfree (pbuf->buf);\r
+      pbuf->buf = NULL;\r
+    }\r
+}\r
+\r
+void\r
+cppReader_fileCleanup (cppBuffer *pbuf, /*@unused@*/ cppReader *pfile)\r
+{\r
+  if (pbuf->buf != NULL)\r
+    {\r
+      sfree (pbuf->buf);\r
+      pbuf->buf = NULL;\r
+    }\r
+}\r
+\r
+/* Assuming we have read '/'.\r
+   If this is the start of a comment (followed by '*' or '/'),\r
+   skip to the end of the comment, and return ' '.\r
+   Return EOF if we reached the end of file before the end of the comment.\r
+   If not the start of a comment, return '/'.  */\r
+\r
+static int\r
+skip_comment (cppReader *pfile, /*@null@*/ long *linep)\r
+{\r
+  int c = 0;\r
+\r
+  llassert (pfile->buffer != NULL);\r
+  llassert (pfile->buffer->cur != NULL);\r
+\r
+  while (cppReader_peekC (pfile) == '\\' && cpp_peekN (pfile, 1) == '\n')\r
+    {\r
+      if (linep != NULL)\r
+       {\r
+         (*linep)++;\r
+       }\r
+\r
+      cppReader_forward (pfile, 2);\r
+    }\r
+\r
+  if (cppReader_peekC (pfile) == '*')\r
+    {\r
+      cppReader_forward (pfile, 1);\r
+\r
+      for (;;)\r
+       {\r
+         int prev_c = c;\r
+         c = cppReader_getC (pfile);\r
+\r
+         if (c == EOF)\r
+           {\r
+             return EOF;\r
+           }\r
+\r
+         while (c == (int) '\\' && cppReader_peekC (pfile) == (int) '\n')\r
+           {\r
+             if (linep != NULL )\r
+               {\r
+                 (*linep)++;\r
+               }\r
+\r
+             cppReader_forward (pfile, 1), c = cppReader_getC (pfile);\r
+           }\r
+\r
+         if (prev_c == (int) '*' && c == (int) '/')\r
+           {\r
+             return (int) ' ';\r
+           }\r
+\r
+         if (c == (int) '\n' && (linep != NULL))\r
+           {\r
+             (*linep)++;\r
+           }\r
+       }\r
+    }\r
+  else if (cppReader_peekC (pfile) == '/' \r
+          && CPPOPTIONS (pfile)->cplusplus_comments)\r
+    {\r
+      cppReader_forward (pfile, 1);\r
+\r
+      for (;;)\r
+       {\r
+         c = cppReader_getC (pfile);\r
+\r
+         if (c == EOF)\r
+           {\r
+             /* Allow hash comment to be terminated by EOF.  */\r
+             return (int) ' '; \r
+           }\r
+\r
+         while (c == (int) '\\' && cppReader_peekC (pfile) == '\n')\r
+           {\r
+             cppReader_forward (pfile, 1);\r
+             c = cppReader_getC (pfile);\r
+\r
+             if (linep != NULL)\r
+               {\r
+                 (*linep)++;\r
+               }\r
+           }\r
+\r
+         if (c == (int) '\n')\r
+           {\r
+             /* Don't consider final '\n' to be part of comment.  */\r
+             cppReader_forward (pfile, -1);\r
+             return (int) ' ';\r
+           }\r
+       }\r
+    }\r
+  else\r
+    {\r
+      return (int) '/';\r
+    }\r
+}\r
+\r
+/* Skip whitespace \-newline and comments.  Does not macro-expand.  */\r
+int /*@alt void@*/\r
+cppSkipHspace (cppReader *pfile)\r
+{\r
+  int nspaces = 0;\r
+\r
+  while (TRUE)\r
+    {\r
+      int c;\r
+\r
+      llassert (pfile->buffer != NULL);\r
+\r
+      c = cppReader_peekC (pfile);\r
+\r
+      if (c == EOF)\r
+       {\r
+         return 0; /* FIXME */\r
+       }\r
+\r
+      if (is_hor_space[c])\r
+       {\r
+         if ((c == '\f' || c == '\v') && cppReader_isPedantic (pfile))\r
+           cppReader_pedwarn (pfile,\r
+                        message ("%s in preprocessing directive",\r
+                                 c == '\f'\r
+                                 ? cstring_makeLiteralTemp ("formfeed")\r
+                                 : cstring_makeLiteralTemp ("vertical tab")));\r
+\r
+         nspaces++;\r
+         cppReader_forward (pfile, 1);\r
+       }\r
+      else if (c == '/')\r
+       {\r
+         cppReader_forward (pfile, 1);\r
+         c = skip_comment (pfile, NULL);\r
+\r
+         if (c == '/')\r
+           {\r
+             cppReader_forward (pfile, -1);\r
+           }\r
+\r
+         if (c == EOF || c == '/')\r
+           {\r
+             return nspaces;\r
+           }\r
+       }\r
+      else if (c == '\\' && cpp_peekN (pfile, 1) == '\n')\r
+       {\r
+         cppReader_forward (pfile, 2);\r
+       }\r
+      else if (c == '@' && CPPBUFFER (pfile)->has_escapes\r
+              && is_hor_space [cpp_peekN (pfile, 1)])\r
+       {\r
+         cppReader_forward (pfile, 2);\r
+       }\r
+      else\r
+       {\r
+         return nspaces;\r
+       }\r
+    }\r
+}\r
+\r
+/* Read the rest of the current line.\r
+   The line is appended to PFILE's output buffer.  */\r
+\r
+static void\r
+copy_rest_of_line (cppReader *pfile)\r
+{\r
+  struct cppOptions *opts = CPPOPTIONS (pfile);\r
+\r
+  for (;;)\r
+    {\r
+      int c;\r
+      int nextc;\r
+\r
+      llassert (pfile->buffer != NULL);\r
+\r
+      c = cppReader_getC (pfile);\r
+      switch (c)\r
+       {\r
+       case EOF:\r
+         goto end_directive;\r
+       case '\\':\r
+         if (cppReader_peekC (pfile) == '\n')\r
+           {\r
+             cppReader_forward (pfile, 1);\r
+             continue;\r
+           }\r
+\r
+       /*@fallthrough@*/ case '\'': case '\"':\r
+         goto scan_directive_token;\r
+\r
+       case '/':\r
+         nextc = cppReader_peekC (pfile);\r
+\r
+         /*\r
+         ** was (opts->cplusplus_comments && nextc == '*')\r
+         ** yoikes!\r
+         */\r
+\r
+         if (nextc == '*'\r
+             || (opts->cplusplus_comments && nextc == '/'))\r
+           {\r
+             goto scan_directive_token;\r
+           }\r
+         /*@switchbreak@*/ break;\r
+       case '\f':\r
+       case '\v':\r
+         if (cppReader_isPedantic (pfile))\r
+           cppReader_pedwarn (pfile,\r
+                        message ("%s in preprocessing directive",\r
+                                 c == '\f'\r
+                                 ? cstring_makeLiteralTemp ("formfeed")\r
+                                 : cstring_makeLiteralTemp ("vertical tab")));\r
+         /*@switchbreak@*/ break;\r
+\r
+       case '\n':\r
+         cppReader_forward (pfile, -1);\r
+         goto end_directive;\r
+       scan_directive_token:\r
+         cppReader_forward (pfile, -1);\r
+         (void) cppGetToken (pfile);\r
+         continue;\r
+       }\r
+      cppReader_putChar (pfile, c);\r
+    }\r
+end_directive: ;\r
+  cppReader_nullTerminate (pfile);\r
+}\r
+\r
+void\r
+cppReader_skipRestOfLine (cppReader *pfile)\r
+{\r
+  size_t old = cppReader_getWritten (pfile);\r
+  copy_rest_of_line (pfile);\r
+  cppReader_setWritten (pfile, old);\r
+}\r
+\r
+/* Handle a possible # directive.\r
+   '#' has already been read.  */\r
+\r
+int\r
+cppReader_handleDirective (cppReader *pfile)\r
+{\r
+  int c;\r
+  struct directive *kt = NULL;\r
+  int ident_length;\r
+  size_t after_ident = 0;\r
+  char *ident = NULL;\r
+  char *line_end = NULL;\r
+  size_t old_written = cppReader_getWritten (pfile);\r
+  int nspaces = cppSkipHspace (pfile);\r
+\r
+  c = cppReader_peekC (pfile);\r
+\r
+  if (c >= '0' && c <= '9')\r
+    {\r
+      /* Handle # followed by a line number.  */\r
+      if (cppReader_isPedantic (pfile))\r
+       {\r
+         cppReader_pedwarnLit\r
+           (pfile,\r
+            cstring_makeLiteralTemp ("`#' followed by integer"));\r
+       }\r
+\r
+      (void) do_line (pfile, NULL);\r
+      goto done_a_directive;\r
+    }\r
+\r
+\r
+  /* Now find the directive name.  */\r
+\r
+  cppReader_putChar (pfile, '#');\r
+\r
+  parse_name (pfile, cppReader_getC (pfile));\r
+\r
+  llassert (pfile->token_buffer != NULL);\r
+  ident = pfile->token_buffer + old_written + 1;\r
+\r
+  ident_length = cppReader_getPWritten (pfile) - ident;\r
+\r
+  if (ident_length == 0 && cppReader_peekC (pfile) == '\n')\r
+    {\r
+      /* A line of just `#' becomes blank.  */\r
+      return 1; \r
+    }\r
+\r
+  for (kt = directive_table; ; kt++) \r
+    {\r
+      if (kt->length <= 0)\r
+       {\r
+         return 0; /* goto not_a_directive; */\r
+       }\r
+\r
+      if (kt->length == ident_length\r
+         && (cstring_equalPrefix (kt->name, cstring_fromChars (ident))))\r
+       {\r
+         break;\r
+       }\r
+    }\r
+\r
+  if (kt->command_reads_line)\r
+    {\r
+      after_ident = 0;\r
+    }\r
+  else\r
+    {\r
+      /* Nonzero means do not delete comments within the directive.\r
+        #define needs this when -traditional.  */\r
+      bool comments = 1; /*cppReader_isTraditional (pfile) && kt->traditional_comments;  */\r
+      int save_put_out_comments = CPPOPTIONS (pfile)->put_out_comments;\r
+      CPPOPTIONS (pfile)->put_out_comments = comments;\r
+      after_ident = cppReader_getWritten (pfile);\r
+      copy_rest_of_line (pfile);\r
+      CPPOPTIONS (pfile)->put_out_comments = save_put_out_comments;\r
+    }\r
+\r
+\r
+  /* For #pragma and #define, we may want to pass through the directive.\r
+     Other directives may create output, but we don't want the directive\r
+     itself out, so we pop it now.  For example #include may write a #line\r
+     command (see comment in do_include), and conditionals may emit\r
+     #failed ... #endfailed stuff.  But note that popping the buffer\r
+     means the parameters to kt->func may point after pfile->limit\r
+     so these parameters are invalid as soon as something gets appended\r
+     to the token_buffer.  */\r
+\r
+  line_end = cppReader_getPWritten (pfile);\r
+\r
+\r
+  if (!kt->pass_thru && kt->type != T_DEFINE)\r
+    {\r
+      cppReader_setWritten (pfile, old_written);\r
+    }\r
+\r
+  llassert (pfile->token_buffer != NULL);\r
+\r
+  /* was kt->pass_thru || */\r
+\r
+  if (kt->type == T_DEFINE\r
+      && cpp_shouldCheckMacro (pfile, pfile->token_buffer + old_written))\r
+    {\r
+      char *p = pfile->token_buffer + old_written;\r
+\r
+      /*\r
+      ** Still need to record value for preprocessing, so \r
+      ** #ifdef's, etc. using the value behave correctly.\r
+      */\r
+      \r
+      (void) do_defineAux (pfile, kt, \r
+                          pfile->token_buffer + after_ident,\r
+                          line_end,\r
+                          TRUE);\r
+      \r
+      if (*p == '#')\r
+       {\r
+         *p = ' ';\r
+       }\r
+\r
+      SKIP_WHITE_SPACE (p);\r
+\r
+      llassert (*p == 'd');\r
+      *p++ = LLMRCODE[0];\r
+\r
+      llassert (*p == 'e');\r
+      *p++ = LLMRCODE[1];\r
+\r
+      llassert (*p == 'f');\r
+      *p++ = LLMRCODE[2];\r
+\r
+      llassert (*p == 'i');\r
+      *p++ = LLMRCODE[3];\r
+\r
+      llassert (*p == 'n');\r
+      *p++ = LLMRCODE[4];\r
+\r
+      llassert (*p == 'e');\r
+\r
+      /*\r
+      ** This is way-bogus.  We use the last char to record the number of\r
+      ** spaces.  Its too hard to get them back into the input stream.\r
+      */\r
+\r
+      if (nspaces > 9) nspaces = 9;\r
+\r
+      *p++ = '0' + nspaces;\r
+\r
+      return 0; /* not_a_directive */\r
+    }\r
+  else if (kt->pass_thru)\r
+    {\r
+      /* Just leave the entire #define in the output stack.  */\r
+      return 0; /* not_a_directive */\r
+\r
+    }\r
+  else if (kt->type == T_DEFINE\r
+          && CPPOPTIONS (pfile)->dump_macros == DUMP_NAMES)\r
+    {\r
+      char *p = pfile->token_buffer + old_written + 7;  /* Skip "#define". */\r
+      SKIP_WHITE_SPACE (p);\r
+\r
+      while (is_idchar[(int) *p])\r
+       {\r
+         p++;\r
+       }\r
+\r
+      pfile->limit = p;\r
+      cppReader_putChar (pfile, '\n');\r
+    }\r
+  else if (kt->type == T_DEFINE)\r
+    {\r
+      cppReader_setWritten (pfile, old_written);\r
+    }\r
+  else\r
+    {\r
+      ;\r
+    }\r
+\r
+done_a_directive:\r
+  if (kt == NULL) {\r
+    return 1;\r
+  } else {\r
+    llassert (kt->func != NULL);\r
+    (void) (kt->func) (pfile, kt, pfile->token_buffer + after_ident, line_end);\r
+    return 1;\r
+  }\r
+}\r
+\r
+/* Pass a directive through to the output file.\r
+   BUF points to the contents of the directive, as a contiguous string.\r
+   LIMIT points to the first character past the end of the directive.\r
+   KEYWORD is the keyword-table entry for the directive.  */\r
+\r
+static void\r
+pass_thru_directive (char *buf, char *limit,\r
+                    cppReader *pfile,\r
+                    struct directive *keyword)\r
+{\r
+  int keyword_length = keyword->length;\r
+\r
+  cppReader_reserve (pfile,\r
+                    size_fromInt (2 + keyword_length + (limit - buf)));\r
+  cppReader_putCharQ (pfile, '#');\r
+  /*@-observertrans@*/\r
+  cppReader_putStrN (pfile, cstring_toCharsSafe (keyword->name),\r
+                    size_fromInt (keyword_length));\r
+  /*:=observertrans@*/\r
+\r
+  if (limit != buf && buf[0] != ' ')\r
+    {\r
+      /* Was a bug, since reserve only used 1 + ... */\r
+      cppReader_putCharQ (pfile, ' ');\r
+    }\r
+\r
+  cppReader_putStrN (pfile, buf, size_fromInt (limit - buf));\r
+}\r
+\r
+/* Read a replacement list for a macro with parameters.\r
+   Build the DEFINITION structure.\r
+   Reads characters of text starting at BUF until END.\r
+   ARGLIST specifies the formal parameters to look for\r
+   in the text of the definition; NARGS is the number of args\r
+   in that list, or -1 for a macro name that wants no argument list.\r
+   MACRONAME is the macro name itself (so we can avoid recursive expansion)\r
+   and NAMELEN is its length in characters.\r
+\r
+   Note that comments, backslash-newlines, and leading white space\r
+   have already been deleted from the argument.  */\r
+\r
+static DEFINITION *\r
+collect_expansion (cppReader *pfile, char *buf, char *limit,\r
+                  int nargs, /*@null@*/ struct arglist *arglist)\r
+{\r
+  DEFINITION *defn;\r
+  char *p, *lastp, *exp_p;\r
+  struct reflist *endpat = NULL;\r
+  /* Pointer to first nonspace after last ## seen.  */\r
+  char *concat = 0;\r
+  /* Pointer to first nonspace after last single-# seen.  */\r
+  char *stringify = 0;\r
+  size_t maxsize;\r
+  char expected_delimiter = '\0';\r
+\r
+\r
+  /* Scan thru the replacement list, ignoring comments and quoted\r
+     strings, picking up on the macro calls.  It does a linear search\r
+     thru the arg list on every potential symbol.  Profiling might say\r
+     that something smarter should happen.  */\r
+\r
+  if (limit < buf)\r
+    abort ();\r
+\r
+  /* Find the beginning of the trailing whitespace.  */\r
+  p = buf;\r
+\r
+  while (p < limit && is_space[(int) limit[-1]])\r
+    {\r
+      limit--;\r
+    }\r
+\r
+  /* Allocate space for the text in the macro definition.\r
+     Leading and trailing whitespace chars need 2 bytes each.\r
+     Each other input char may or may not need 1 byte,\r
+     so this is an upper bound.  The extra 5 are for invented\r
+     leading and trailing newline-marker and final null.  */\r
+  maxsize = (sizeof (*defn) + (limit - p) + 5);\r
+\r
+  /* Occurrences of '@' get doubled, so allocate extra space for them.  */\r
+  while (p < limit)\r
+    {\r
+      if (*p++ == '@')\r
+       {\r
+         maxsize++;\r
+       }\r
+    }\r
+\r
+  defn = (DEFINITION *) dmalloc (maxsize);\r
+  defn->noExpand = FALSE;\r
+  defn->file = NULL;\r
+  defn->pattern = NULL;\r
+  defn->nargs = nargs;\r
+  defn->predefined = NULL;\r
+\r
+  exp_p = defn->expansion = (char *) defn + sizeof (*defn);\r
+\r
+  defn->line = 0;\r
+  defn->rest_args = NULL;\r
+  defn->args.argnames = NULL;\r
+\r
+  lastp = exp_p;\r
+\r
+  p = buf;\r
+\r
+  /* Add one initial space escape-marker to prevent accidental\r
+     token-pasting (often removed by macroexpand).  */\r
+  *exp_p++ = '@';\r
+  *exp_p++ = ' ';\r
+\r
+  if (limit - p >= 2 && p[0] == '#' && p[1] == '#') {\r
+    cppReader_errorLit (pfile,\r
+                       cstring_makeLiteralTemp ("`##' at start of macro definition"));\r
+    p += 2;\r
+  }\r
+\r
+  /* Process the main body of the definition.  */\r
+  while (p < limit) {\r
+    int skipped_arg = 0;\r
+    register char c = *p++;\r
+\r
+    *exp_p++ = c;\r
+\r
+    if (!cppReader_isTraditional (pfile)) {\r
+      switch (c) {\r
+      case '\'':\r
+      case '\"':\r
+       if (expected_delimiter != '\0')\r
+         {\r
+           if (c == expected_delimiter)\r
+             expected_delimiter = '\0';\r
+         }\r
+       else\r
+         {\r
+           expected_delimiter = c;\r
+         }\r
+       /*@switchbreak@*/ break;\r
+\r
+      case '\\':\r
+       if (p < limit && (expected_delimiter != '\0'))\r
+         {\r
+           /* In a string, backslash goes through\r
+              and makes next char ordinary.  */\r
+           *exp_p++ = *p++;\r
+         }\r
+       /*@switchbreak@*/ break;\r
+\r
+      case '@':\r
+       /* An '@' in a string or character constant stands for itself,\r
+          and does not need to be escaped.  */\r
+       if (expected_delimiter == '\0')\r
+         {\r
+           *exp_p++ = c;\r
+         }\r
+\r
+       /*@switchbreak@*/ break;\r
+\r
+      case '#':\r
+       /* # is ordinary inside a string.  */\r
+       if (expected_delimiter != '\0')\r
+         {\r
+           /*@switchbreak@*/ break;\r
+         }\r
+\r
+       if (p < limit && *p == '#') {\r
+         /* ##: concatenate preceding and following tokens.  */\r
+         /* Take out the first #, discard preceding whitespace.  */\r
+         exp_p--;\r
+\r
+         /*@-usedef@*/\r
+         while (exp_p > lastp && is_hor_space[(int) exp_p[-1]])\r
+           {\r
+             --exp_p;\r
+           }\r
+         /*@=usedef@*/\r
+\r
+         /* Skip the second #.  */\r
+         p++;\r
+         /* Discard following whitespace.  */\r
+         SKIP_WHITE_SPACE (p);\r
+         concat = p;\r
+         if (p == limit)\r
+           {\r
+             cppReader_errorLit (pfile,\r
+                           cstring_makeLiteralTemp ("`##' at end of macro definition"));\r
+           }\r
+       } else if (nargs >= 0) {\r
+         /* Single #: stringify following argument ref.\r
+            Don't leave the # in the expansion.  */\r
+         exp_p--;\r
+         SKIP_WHITE_SPACE (p);\r
+         if (p == limit || ! is_idstart[(int) *p]\r
+             || (*p == 'L' && p + 1 < limit && (p[1] == '\'' || p[1] == '"')))\r
+           cppReader_errorLit (pfile,\r
+                         cstring_makeLiteralTemp ("`#' operator is not followed by a macro argument name"));\r
+         else\r
+           stringify = p;\r
+       } else {\r
+         ; /* BADBRANCH; */\r
+       }\r
+\r
+       /*@switchbreak@*/ break;\r
+      }\r
+    } else {\r
+      /* In -traditional mode, recognize arguments inside strings and\r
+        and character constants, and ignore special properties of #.\r
+        Arguments inside strings are considered "stringified", but no\r
+        extra quote marks are supplied.  */\r
+      switch (c) {\r
+      case '\'':\r
+      case '\"':\r
+       if (expected_delimiter != '\0') {\r
+         if (c == expected_delimiter)\r
+           expected_delimiter = '\0';\r
+       } else\r
+         expected_delimiter = c;\r
+       /*@switchbreak@*/ break;\r
+\r
+      case '\\':\r
+       /* Backslash quotes delimiters and itself, but not macro args.  */\r
+       if (expected_delimiter != '\0' && p < limit\r
+           && (*p == expected_delimiter || *p == '\\')) {\r
+         *exp_p++ = *p++;\r
+         continue;\r
+       }\r
+       /*@switchbreak@*/ break;\r
+\r
+      case '/':\r
+       if (expected_delimiter != '\0') /* No comments inside strings.  */\r
+         /*@switchbreak@*/ break;\r
+       if (*p == '*') {\r
+         /* If we find a comment that wasn't removed by cppReader_handleDirective,\r
+            this must be -traditional.  So replace the comment with\r
+            nothing at all.  */\r
+         exp_p--;\r
+         p += 1;\r
+         while (p < limit && !(p[-2] == '*' && p[-1] == '/'))\r
+           {\r
+             p++;\r
+           }\r
+       }\r
+       /*@switchbreak@*/ break;\r
+      }\r
+    }\r
+\r
+    /* Handle the start of a symbol.  */\r
+    if (is_idchar[(int) c] && nargs > 0) {\r
+      char *id_beg = p - 1;\r
+      int id_len;\r
+\r
+      --exp_p;\r
+      while (p != limit && is_idchar[(int) *p])\r
+       {\r
+         p++;\r
+       }\r
+\r
+      id_len = p - id_beg;\r
+\r
+      if (is_idstart[(int) c]\r
+         && ! (id_len == 1 && c == 'L' && (*p == '\'' || *p == '"'))) {\r
+       register struct arglist *arg;\r
+\r
+       for (arg = arglist; arg != NULL; arg = arg->next) {\r
+         struct reflist *tpat;\r
+\r
+         if (arg->name[0] == c\r
+             && arg->length == id_len\r
+             && strncmp (arg->name, id_beg, size_fromInt (id_len)) == 0) {\r
+           char *p1;\r
+\r
+           if (expected_delimiter && CPPOPTIONS (pfile)->warn_stringify) {\r
+             if (cppReader_isTraditional (pfile)) {\r
+               cppReader_warning (pfile,\r
+                                  message ("macro argument `%x' is stringified.",\r
+                                           cstring_prefix (cstring_fromChars (arg->name), id_len)));\r
+             } else {\r
+               cppReader_warning (pfile,\r
+                                  message ("macro arg `%x' would be stringified with -traditional.",\r
+                                           cstring_prefix (cstring_fromChars (arg->name), id_len)));\r
+             }\r
+           }\r
+           /* If ANSI, don't actually substitute inside a string.  */\r
+           if (!cppReader_isTraditional (pfile) && expected_delimiter)\r
+             /*@innerbreak@*/ break;\r
+           /* make a pat node for this arg and append it to the end of\r
+              the pat list */\r
+           tpat = (struct reflist *) dmalloc (sizeof (*tpat));\r
+           tpat->next = NULL;\r
+           tpat->raw_before = (concat == id_beg);\r
+           tpat->raw_after = 0;\r
+           tpat->rest_args = arg->rest_args;\r
+           tpat->stringify = (cppReader_isTraditional (pfile)\r
+                              ? expected_delimiter != '\0'\r
+                              : stringify == id_beg);\r
+\r
+           if (endpat == NULL)\r
+             {\r
+               defn->pattern = tpat;\r
+             }\r
+           else\r
+             {\r
+               endpat->next = tpat;\r
+               /*@-branchstate@*/\r
+             } /*@=branchstate@*/ /* evs 2000 was =branchstate */\r
+\r
+           endpat = tpat;\r
+\r
+           tpat->argno = arg->argno;\r
+           tpat->nchars = exp_p - lastp;\r
+\r
+           p1 = p;\r
+\r
+           SKIP_WHITE_SPACE (p1);\r
+\r
+           if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#')\r
+             {\r
+               tpat->raw_after = 1;\r
+             }\r
+\r
+           lastp = exp_p;      /* place to start copying from next time */\r
+           skipped_arg = 1;\r
+\r
+           /*@innerbreak@*/ break;\r
+         }\r
+       }\r
+      }\r
+\r
+      /* If this was not a macro arg, copy it into the expansion.  */\r
+      if (skipped_arg == 0) {\r
+       register char *lim1 = p;\r
+       p = id_beg;\r
+\r
+       while (p != lim1)\r
+         {\r
+           *exp_p++ = *p++;\r
+         }\r
+\r
+       if (stringify == id_beg)\r
+         cppReader_errorLit (pfile,\r
+                             cstring_makeLiteralTemp ("`#' operator should be followed by a macro argument name"));\r
+      }\r
+    }\r
+  }\r
+\r
+  if (!cppReader_isTraditional (pfile) && expected_delimiter == '\0')\r
+    {\r
+      /* If ANSI, put in a "@ " marker to prevent token pasting.\r
+        But not if "inside a string" (which in ANSI mode\r
+        happens only for -D option).  */\r
+      *exp_p++ = '@';\r
+      *exp_p++ = ' ';\r
+    }\r
+\r
+  *exp_p = '\0';\r
+\r
+  defn->length = size_fromInt (exp_p - defn->expansion);\r
+\r
+  /* Crash now if we overrun the allocated size.  */\r
+  if (defn->length + 1 > maxsize)\r
+    {\r
+      llfatalbug (cstring_makeLiteral ("Maximum definition size exceeded."));\r
+    }\r
+\r
+  return defn;\r
+}\r
+\r
+/*\r
+ * special extension string that can be added to the last macro argument to\r
+ * allow it to absorb the "rest" of the arguments when expanded.  Ex:\r
+ *             #define wow(a, b...)            process (b, a, b)\r
+ *             { wow (1, 2, 3); }      ->      { process (2, 3, 1, 2, 3); }\r
+ *             { wow (one, two); }     ->      { process (two, one, two); }\r
+ * if this "rest_arg" is used with the concat token '##' and if it is not\r
+ * supplied then the token attached to with ## will not be outputted.  Ex:\r
+ *             #define wow (a, b...)           process (b ## , a, ## b)\r
+ *             { wow (1, 2); }         ->      { process (2, 1, 2); }\r
+ *             { wow (one); }          ->      { process (one); {\r
+ */\r
+\r
+/*@-readonlytrans@*/\r
+static char rest_extension[] = "...";\r
+/*:=readonlytrans@*/\r
+\r
+/*@notfunction@*/\r
+#define REST_EXTENSION_LENGTH  (sizeof (rest_extension) - 1)\r
+\r
+/* Create a DEFINITION node from a #define directive.  Arguments are\r
+   as for do_define.  */\r
+\r
+static /*@null@*/ MACRODEF\r
+create_definition (char *buf, char *limit,\r
+                  cppReader *pfile, bool predefinition,\r
+                  bool noExpand)\r
+{\r
+  char *bp;                    /* temp ptr into input buffer */\r
+  char *symname;               /* remember where symbol name starts */\r
+  int sym_length;              /* and how long it is */\r
+  int rest_args = 0;   /* really int! */\r
+  int line;\r
+  int col;\r
+  cstring file = (CPPBUFFER (pfile) != NULL)\r
+    ? CPPBUFFER (pfile)->nominal_fname : cstring_makeLiteralTemp ("");\r
+  DEFINITION *defn;\r
+  int arglengths = 0;          /* Accumulate lengths of arg names\r
+                                  plus number of args.  */\r
+  MACRODEF mdef;\r
+\r
+  cppBuffer_lineAndColumn (CPPBUFFER (pfile), &line, &col);\r
+\r
+  bp = buf;\r
+\r
+  while (is_hor_space[(int) *bp])\r
+    {\r
+      bp++;\r
+    }\r
+\r
+  symname = bp;                        /* remember where it starts */\r
+\r
+  sym_length = cppReader_checkMacroName (pfile, bp, cstring_makeLiteralTemp ("macro"));\r
+\r
+  bp += sym_length;\r
+\r
+  /* Lossage will occur if identifiers or control keywords are broken\r
+     across lines using backslash.  This is not the right place to take\r
+     care of that.  */\r
+\r
+  if (*bp == '(') {\r
+    struct arglist *arg_ptrs = NULL;\r
+    int argno = 0;\r
+\r
+    bp++;                      /* skip '(' */\r
+    SKIP_WHITE_SPACE (bp);\r
+\r
+    /* Loop over macro argument names.  */\r
+    while (*bp != ')')\r
+      {\r
+       struct arglist *temp = (struct arglist *) dmalloc (sizeof (*temp));\r
+       temp->name = bp;\r
+       temp->next = arg_ptrs;\r
+       temp->argno = argno++;\r
+       temp->rest_args = 0;\r
+\r
+       arg_ptrs = temp;\r
+\r
+       if (rest_args != 0)\r
+         {\r
+           cppReader_pedwarn (pfile,\r
+                        message ("another parameter follows `%s'",\r
+                                 cstring_fromChars (rest_extension)));\r
+         }\r
+\r
+       if (!is_idstart[(int) *bp])\r
+         {\r
+           cppReader_pedwarnLit (pfile,\r
+                           cstring_makeLiteralTemp ("invalid character in macro parameter name"));\r
+         }\r
+\r
+       /* Find the end of the arg name.  */\r
+       while (is_idchar[(int) *bp])\r
+         {\r
+           bp++;\r
+           /* do we have a "special" rest-args extension here? */\r
+           if (limit - bp > size_toInt (REST_EXTENSION_LENGTH)\r
+               && strncmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0)\r
+             {\r
+               rest_args = 1;\r
+               temp->rest_args = 1;\r
+               /*@innerbreak@*/ break;\r
+             }\r
+         }\r
+\r
+       temp->length = bp - temp->name;\r
+\r
+       if (rest_args != 0)\r
+         {\r
+           bp += REST_EXTENSION_LENGTH;\r
+         }\r
+\r
+       arglengths += temp->length + 2;\r
+       SKIP_WHITE_SPACE (bp);\r
+\r
+       if (temp->length == 0 || (*bp != ',' && *bp != ')')) {\r
+         cppReader_errorLit (pfile,\r
+                       cstring_makeLiteralTemp ("Parameter list for #define is not parseable"));\r
+         goto nope;\r
+       }\r
+\r
+       if (*bp == ',') {\r
+         bp++;\r
+         SKIP_WHITE_SPACE (bp);\r
+       }\r
+       if (bp >= limit) {\r
+         cppReader_errorLit (pfile,\r
+                       cstring_makeLiteralTemp ("unterminated parameter list in `#define'"));\r
+         goto nope;\r
+       }\r
+       {\r
+         struct arglist *otemp;\r
+\r
+         for (otemp = temp->next; otemp != NULL; otemp = otemp->next)\r
+           {\r
+             if (temp->length == otemp->length &&\r
+                 strncmp (temp->name, otemp->name, size_fromInt (temp->length)) == 0) {\r
+               cstring name = cstring_copyLength (temp->name, temp->length);\r
+               cppReader_error (pfile,\r
+                          message ("duplicate argument name `%x' in `#define'", name));\r
+               goto nope;\r
+             }\r
+           }\r
+       }\r
+      }\r
+\r
+    ++bp;                      /* skip paren */\r
+    SKIP_WHITE_SPACE (bp);\r
+    /* now everything from bp before limit is the definition.  */\r
+    defn = collect_expansion (pfile, bp, limit, argno, arg_ptrs);\r
+    defn->rest_args = rest_args;\r
+    \r
+    /* Now set defn->args.argnames to the result of concatenating\r
+       the argument names in reverse order\r
+       with comma-space between them.  */\r
+    defn->args.argnames = (char *) dmalloc (size_fromInt (arglengths + 1));\r
+\r
+    {\r
+      struct arglist *temp;\r
+      int i = 0;\r
+      for (temp = arg_ptrs; temp != NULL; temp = temp->next) {\r
+       memcpy (&defn->args.argnames[i], temp->name, size_fromInt (temp->length));\r
+       i += temp->length;\r
+       if (temp->next != 0) {\r
+         defn->args.argnames[i++] = ',';\r
+         defn->args.argnames[i++] = ' ';\r
+       }\r
+      }\r
+\r
+      defn->args.argnames[i] = '\0';\r
+    }\r
+\r
+    sfree (arg_ptrs);\r
+  } else {\r
+    /* Simple expansion or empty definition.  */\r
+\r
+    if (bp < limit)\r
+      {\r
+       if (is_hor_space[(int) *bp]) {\r
+         bp++;\r
+         SKIP_WHITE_SPACE (bp);\r
+       } else {\r
+         switch (*bp) {\r
+         case '!':  case '"':  case '#':  case '%':  case '&':  case '\'':\r
+         case ')':  case '*':  case '+':  case ',':  case '-':  case '.':\r
+         case '/':  case ':':  case ';':  case '<':  case '=':  case '>':\r
+         case '?':  case '[':  case '\\': case ']':  case '^':  case '{':\r
+         case '|':  case '}':  case '~':\r
+           cppReader_warning (pfile,\r
+                        message ("Missing white space after #define %x",\r
+                                 cstring_prefix (cstring_fromChars (symname),\r
+                                                 sym_length)));\r
+           break;\r
+\r
+         default:\r
+           cppReader_pedwarn (pfile,\r
+                        message ("Missing white space after #define %x",\r
+                                 cstring_prefix (cstring_fromChars (symname),\r
+                                                 sym_length)));\r
+           break;\r
+         }\r
+       }\r
+      }\r
+    /* now everything from bp before limit is the definition.  */\r
+    defn = collect_expansion (pfile, bp, limit, -1, NULL);\r
+    defn->args.argnames = mstring_createEmpty ();\r
+  }\r
+\r
+  defn->noExpand = noExpand;\r
+  DPRINTF (("No expand: %d", noExpand));\r
+\r
+  defn->line = line;\r
+\r
+  /* not: llassert (cstring_isUndefined (defn->file)); */\r
+  defn->file = file;\r
+\r
+  /* OP is null if this is a predefinition */\r
+  defn->predefined = predefinition;\r
+  mdef.defn = defn;\r
+  mdef.symnam = symname;\r
+  mdef.symlen = sym_length;\r
+\r
+  return mdef;\r
+\r
+nope:\r
+  mdef.defn = NULL;\r
+  mdef.symnam = NULL;\r
+  return mdef;\r
+}\r
+\r
+/* Check a purported macro name SYMNAME, and yield its length.\r
+   USAGE is the kind of name this is intended for.  */\r
+\r
+int cppReader_checkMacroName (cppReader *pfile,\r
+                     char *symname,\r
+                     cstring usage)\r
+{\r
+  char *p;\r
+  size_t sym_length;\r
+\r
+  for (p = symname; is_idchar[(int) *p]; p++)\r
+    {\r
+      ;\r
+    }\r
+\r
+  sym_length = size_fromInt (p - symname);\r
+\r
+  if (sym_length == 0\r
+      || (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))\r
+    cppReader_error (pfile, message ("invalid %s name", usage));\r
+  else if (!is_idstart[(int) *symname])\r
+    {\r
+      char *msg = (char *) dmalloc (sym_length + 1);\r
+      memcpy (msg, symname, sym_length);\r
+      msg[sym_length] = '\0';\r
+      cppReader_error (pfile, message ("invalid %s name `%s'", usage,\r
+                                      cstring_fromChars (msg)));\r
+      sfree (msg);\r
+    }\r
+  else\r
+    {\r
+      if ((strncmp (symname, "defined", 7) == 0) && sym_length == 7)\r
+       {\r
+         cppReader_error (pfile, message ("invalid %s name `defined'", usage));\r
+       }\r
+    }\r
+\r
+  return size_toInt (sym_length);\r
+}\r
+\r
+/* Return zero if two DEFINITIONs are isomorphic.  */\r
+\r
+static bool\r
+compare_defs (DEFINITION *d1, DEFINITION *d2)\r
+{\r
+  register struct reflist *a1, *a2;\r
+  register char *p1 = d1->expansion;\r
+  register char *p2 = d2->expansion;\r
+  bool first = TRUE;\r
+\r
+  if (d1->nargs != d2->nargs)\r
+    {\r
+      return TRUE;\r
+    }\r
+\r
+  llassert (d1->args.argnames != NULL);\r
+  llassert (d2->args.argnames != NULL);\r
+\r
+  if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames) != 0)\r
+    {\r
+      return TRUE;\r
+    }\r
+\r
+  for (a1 = d1->pattern, a2 = d2->pattern;\r
+       (a1 != NULL) && (a2 != NULL);\r
+       a1 = a1->next, a2 = a2->next) {\r
+    if (!((a1->nchars == a2->nchars\r
+          && (strncmp (p1, p2, size_fromInt (a1->nchars)) == 0))\r
+         || ! comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))\r
+       || a1->argno != a2->argno\r
+       || a1->stringify != a2->stringify\r
+       || a1->raw_before != a2->raw_before\r
+       || a1->raw_after != a2->raw_after)\r
+      return TRUE;\r
+    first = 0;\r
+    p1 += a1->nchars;\r
+    p2 += a2->nchars;\r
+  }\r
+  if (a1 != a2)\r
+    return TRUE;\r
+\r
+  if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion),\r
+                    p2, d2->length - (p2 - d2->expansion), 1))\r
+    return TRUE;\r
+\r
+  return FALSE;\r
+}\r
+\r
+/* Return TRUE if two parts of two macro definitions are effectively different.\r
+   One of the parts starts at BEG1 and has LEN1 chars;\r
+   the other has LEN2 chars at BEG2.\r
+   Any sequence of whitespace matches any other sequence of whitespace.\r
+   FIRST means these parts are the first of a macro definition;\r
+   so ignore leading whitespace entirely.\r
+   LAST means these parts are the last of a macro definition;\r
+   so ignore trailing whitespace entirely.  */\r
+\r
+static bool\r
+comp_def_part (bool first, char *beg1, int len1, char *beg2, int len2, bool last)\r
+{\r
+  char *end1 = beg1 + len1;\r
+  char *end2 = beg2 + len2;\r
+\r
+  if (first) {\r
+    while (beg1 != end1 && is_space[(int) *beg1]) { beg1++; }\r
+    while (beg2 != end2 && is_space[(int) *beg2]) { beg2++; }\r
+  }\r
+  if (last) {\r
+    while (beg1 != end1 && is_space[(int) end1[-1]]) { end1--; }\r
+    while (beg2 != end2 && is_space[(int) end2[-1]]) { end2--; }\r
+  }\r
+  while (beg1 != end1 && beg2 != end2) {\r
+    if (is_space[(int) *beg1] && is_space[(int) *beg2]) {\r
+      while (beg1 != end1 && is_space[(int) *beg1]) { beg1++; }\r
+      while (beg2 != end2 && is_space[(int) *beg2]) { beg2++; }\r
+    } else if (*beg1 == *beg2) {\r
+      beg1++; beg2++;\r
+    } else break;\r
+  }\r
+  return (beg1 != end1) || (beg2 != end2);\r
+}\r
+\r
+/* Process a #define command.\r
+   BUF points to the contents of the #define command, as a contiguous string.\r
+   LIMIT points to the first character past the end of the definition.\r
+   KEYWORD is the keyword-table entry for #define,\r
+   or NULL for a "predefined" macro.  */\r
+\r
+static int\r
+do_defineAux (cppReader *pfile, struct directive *keyword,\r
+             char *buf, char *limit, bool noExpand)\r
+{\r
+  int hashcode;\r
+  MACRODEF mdef;\r
+  hashNode hp;\r
+  \r
+  DPRINTF (("Define aux: %d", noExpand));\r
+\r
+  mdef = create_definition (buf, limit, pfile, keyword == NULL, noExpand);\r
+\r
+  if (mdef.defn == 0)\r
+    goto nope;\r
+\r
+  hashcode = hashf (mdef.symnam, mdef.symlen, CPP_HASHSIZE);\r
+\r
+  DPRINTF (("Macro: %s / %s", \r
+           cstring_copyLength (mdef.symnam, mdef.symlen),\r
+           bool_unparse (noExpand)));\r
+\r
+  if ((hp = cppReader_lookup (mdef.symnam, mdef.symlen, hashcode)) != NULL)\r
+    {\r
+      bool ok = FALSE;\r
+\r
+      /* Redefining a precompiled key is ok.  */\r
+      if (hp->type == T_PCSTRING)\r
+       ok = TRUE;\r
+      /* Redefining a macro is ok if the definitions are the same.  */\r
+      else if (hp->type == T_MACRO)\r
+       ok = !compare_defs (mdef.defn, hp->value.defn);\r
+      /* Redefining a constant is ok with -D.  */\r
+      else if (hp->type == T_CONST)\r
+       ok = !CPPOPTIONS (pfile)->done_initializing;\r
+      else {\r
+       BADBRANCH;\r
+      }\r
+\r
+      /* Print the warning if it's not ok.  */\r
+      if (!ok)\r
+       {\r
+         /*\r
+         ** If we are passing through #define and #undef directives, do\r
+         ** that for this re-definition now.\r
+         */\r
+\r
+         if (CPPOPTIONS (pfile)->debug_output && (keyword != NULL))\r
+           {\r
+             /* llassert (keyword != NULL); */\r
+             pass_thru_directive (buf, limit, pfile, keyword);\r
+           }\r
+\r
+         cpp_setLocation (pfile);\r
+\r
+         if (hp->type == T_MACRO)\r
+           {\r
+             if (hp->value.defn->noExpand)\r
+               {\r
+                 ; /* error will be reported checking macros */\r
+               }\r
+             else\r
+               {\r
+                 genppllerrorhint\r
+                   (FLG_MACROREDEF,\r
+                    message ("Macro %q already defined",\r
+                             cstring_copyLength (mdef.symnam, mdef.symlen)),\r
+                    message ("%q: Previous definition of %q",\r
+                             fileloc_unparseRaw (hp->value.defn->file,\r
+                                                (int) hp->value.defn->line),\r
+                             cstring_copyLength (mdef.symnam, mdef.symlen)));\r
+               }\r
+           }\r
+         else\r
+           {\r
+             genppllerror (FLG_MACROREDEF,\r
+                           message ("Macro %q already defined",\r
+                                    cstring_copyLength (mdef.symnam,\r
+                                                        mdef.symlen)));\r
+\r
+           }\r
+       }\r
+\r
+      /* Replace the old definition.  */\r
+      hp->type = T_MACRO;\r
+      hp->value.defn = mdef.defn;\r
+    }\r
+  else\r
+    {\r
+      /*\r
+      ** If we are passing through #define and #undef directives, do\r
+      ** that for this new definition now.\r
+      */\r
+\r
+      hashNode hn;\r
+\r
+      if (CPPOPTIONS (pfile)->debug_output && (keyword != NULL))\r
+       {\r
+         pass_thru_directive (buf, limit, pfile, keyword);\r
+       }\r
+\r
+      DPRINTF (("Define macro: %s / %d", \r
+               mdef.symnam, mdef.defn->noExpand));\r
+      \r
+      hn = cppReader_installMacro (mdef.symnam, mdef.symlen, mdef.defn, hashcode);\r
+      /*@-branchstate@*/\r
+    } /*@=branchstate@*/\r
+\r
+  return 0;\r
+\r
+nope:\r
+\r
+  return 1;\r
+}\r
+\r
+static int\r
+do_define (cppReader *pfile, struct directive *keyword,\r
+          char *buf, char *limit)\r
+{\r
+  DPRINTF (("Regular do define"));\r
+  return do_defineAux (pfile, keyword, buf, limit, FALSE);\r
+}\r
+\r
+/* This structure represents one parsed argument in a macro call.\r
+   `raw' points to the argument text as written (`raw_length' is its length).\r
+   `expanded' points to the argument's macro-expansion\r
+   (its length is `expand_length').\r
+   `stringified_length' is the length the argument would have\r
+   if stringified.\r
+   `use_count' is the number of times this macro arg is substituted\r
+   into the macro.  If the actual use count exceeds 10,\r
+   the value stored is 10.  */\r
+\r
+/* raw and expanded are relative to ARG_BASE */\r
+/*@notfunction@*/\r
+#define ARG_BASE ((pfile)->token_buffer)\r
+\r
+struct argdata {\r
+  /* Strings relative to pfile->token_buffer */\r
+  long raw;\r
+  size_t expanded;\r
+  size_t stringified;\r
+  int raw_length;\r
+  int expand_length;\r
+  int stringified_length;\r
+  bool newlines;\r
+  int use_count;\r
+};\r
+\r
+/* Allocate a new cppBuffer for PFILE, and push it on the input buffer stack.\r
+   If BUFFER != NULL, then use the LENGTH characters in BUFFER\r
+   as the new input buffer.\r
+   Return the new buffer, or NULL on failure.  */\r
+\r
+/*@null@*/ /*@exposed@*/ cppBuffer *\r
+cppReader_pushBuffer (cppReader *pfile, char *buffer, size_t length)\r
+{\r
+  cppBuffer *buf = cppReader_getBuffer (pfile);\r
+\r
+  if (buf == pfile->buffer_stack)\r
+    {\r
+      cppReader_fatalError\r
+       (pfile,\r
+        message ("%s: macro or `#include' recursion too deep",\r
+                 (buf->fname != NULL)\r
+                 ? buf->fname\r
+                 : cstring_makeLiteral ("<no name>")));\r
+      sfreeEventually (buffer);\r
+      return NULL;\r
+    }\r
+\r
+  llassert (buf != NULL);\r
+\r
+  buf--;\r
+  memset ((char *) buf, 0, sizeof (*buf));\r
+  CPPBUFFER (pfile) = buf;\r
+\r
+  buf->if_stack = pfile->if_stack;\r
+  buf->cleanup = cppReader_nullCleanup;\r
+  buf->underflow = cppReader_nullUnderflow;\r
+  buf->buf = buffer;\r
+  buf->cur = buf->buf;\r
+\r
+  if (buffer != NULL)\r
+    {\r
+      buf->alimit = buf->rlimit = buffer + length;\r
+    }\r
+  else\r
+    {\r
+      buf->alimit = buf->rlimit = NULL;\r
+    }\r
+\r
+  return buf;\r
+}\r
+\r
+cppBuffer *\r
+cppReader_popBuffer (cppReader *pfile)\r
+{\r
+  cppBuffer *buf = CPPBUFFER (pfile);\r
+\r
+  llassert (buf != NULL);\r
+\r
+  (void) (*buf->cleanup) (buf, pfile);\r
+  return ++CPPBUFFER (pfile);\r
+}\r
+\r
+/* Scan until CPPBUFFER (PFILE) is exhausted into PFILE->token_buffer.\r
+   Pop the buffer when done.  */\r
+\r
+void\r
+cppReader_scanBuffer (cppReader *pfile)\r
+{\r
+  cppBuffer *buffer = CPPBUFFER (pfile);\r
+  for (;;)\r
+    {\r
+      enum cpp_token token;\r
+      \r
+      token = cppGetToken (pfile);\r
+\r
+      if (token == CPP_EOF) /* Should not happen ...  */\r
+       {\r
+         break;\r
+       }\r
+\r
+      if (token == CPP_POP && CPPBUFFER (pfile) == buffer)\r
+       {\r
+         (void) cppReader_popBuffer (pfile);\r
+         break;\r
+       }\r
+    }\r
+}\r
+\r
+/*\r
+ * Rescan a string (which may have escape marks) into pfile's buffer.\r
+ * Place the result in pfile->token_buffer.\r
+ *\r
+ * The input is copied before it is scanned, so it is safe to pass\r
+ * it something from the token_buffer that will get overwritten\r
+ * (because it follows cppReader_getWritten).  This is used by do_include.\r
+ */\r
+\r
+static void\r
+cpp_expand_to_buffer (cppReader *pfile, char *buf, size_t length)\r
+{\r
+  register cppBuffer *ip;\r
+  char *limit = buf + length;\r
+  char *buf1, *p1, *p2;\r
+\r
+  /* evans - 2001-08-26\r
+  ** length is unsigned - this doesn't make sense\r
+  if (length < 0)\r
+    abort ();\r
+  **\r
+  */\r
+\r
+  /* Set up the input on the input stack.  */\r
+\r
+  buf1 = (char *) dmalloc (length + 1);\r
+\r
+  p1 = buf;\r
+  p2 = buf1;\r
+\r
+  while (p1 != limit)\r
+    {\r
+      *p2++ = *p1++;\r
+    }\r
+\r
+  buf1[length] = '\0';\r
+\r
+  ip = cppReader_pushBuffer (pfile, buf1, length);\r
+\r
+  if (ip == NULL)\r
+    return;\r
+\r
+  ip->has_escapes = TRUE;\r
+\r
+  /* Scan the input, create the output.  */\r
+  cppReader_scanBuffer (pfile);\r
+\r
+  cppReader_nullTerminate (pfile);\r
+}\r
+\r
+static void\r
+adjust_position (char *buf, char *limit, int *linep, int *colp)\r
+{\r
+  while (buf < limit)\r
+    {\r
+      char ch = *buf++;\r
+      if (ch == '\n')\r
+       (*linep)++, (*colp) = 1;\r
+      else\r
+       (*colp)++;\r
+    }\r
+}\r
+\r
+/* Move line_base forward, updating lineno and colno.  */\r
+\r
+static void\r
+update_position (cppBuffer *pbuf)\r
+{\r
+  char *old_pos;\r
+  char *new_pos = pbuf->cur;\r
+  register struct parse_marker *mark;\r
+\r
+  llassert (pbuf->buf != NULL);\r
+  old_pos = pbuf->buf + pbuf->line_base;\r
+\r
+  for (mark = pbuf->marks;  mark != NULL; mark = mark->next)\r
+    {\r
+      if (pbuf->buf + mark->position < new_pos)\r
+       new_pos = pbuf->buf + mark->position;\r
+    }\r
+  pbuf->line_base += new_pos - old_pos;\r
+\r
+  llassert (old_pos != NULL);\r
+  llassert (new_pos != NULL);\r
+\r
+  adjust_position (old_pos, new_pos, &pbuf->lineno, &pbuf->colno);\r
+}\r
+\r
+void\r
+cppBuffer_lineAndColumn (/*@null@*/ cppBuffer *pbuf, /*@out@*/ int *linep,\r
+                        /*@null@*/ /*@out@*/ int *colp)\r
+{\r
+  int dummy;\r
+\r
+  if (colp == NULL)\r
+    {\r
+      colp = &dummy;\r
+      /*@-branchstate@*/\r
+    } /*@=branchstate@*/\r
+\r
+  if (pbuf != NULL)\r
+    {\r
+      *linep = pbuf->lineno;\r
+      *colp = pbuf->colno;\r
+\r
+      llassert (pbuf->buf != NULL);\r
+      llassert (pbuf->cur != NULL);\r
+\r
+      adjust_position (pbuf->buf + pbuf->line_base, pbuf->cur, linep, colp);\r
+    }\r
+  else\r
+    {\r
+      *linep = 0;\r
+      *colp = 0;\r
+    }\r
+}\r
+\r
+/* Return the cppBuffer that corresponds to a file (not a macro).  */\r
+\r
+/*@exposed@*/ /*@null@*/ cppBuffer *cppReader_fileBuffer (cppReader *pfile)\r
+{\r
+  cppBuffer *ip = cppReader_getBuffer (pfile);\r
+\r
+  for ( ;\r
+       ip != NULL && ip != cppReader_nullBuffer (pfile); \r
+       ip = cppBuffer_prevBuffer (ip))\r
+    {\r
+      if (ip->fname != NULL)\r
+       {\r
+         return ip;\r
+       }\r
+    }\r
+  \r
+  return NULL;\r
+}\r
+\r
+static long\r
+count_newlines (char *buf, char *limit)\r
+{\r
+  register long count = 0;\r
+\r
+  while (buf < limit)\r
+    {\r
+      char ch = *buf++;\r
+      if (ch == '\n')\r
+       count++;\r
+    }\r
+  return count;\r
+}\r
+\r
+/*\r
+ * write out a #line command, for instance, after an #include file.\r
+ * If CONDITIONAL is nonzero, we can omit the #line if it would\r
+ * appear to be a no-op, and we can output a few newlines instead\r
+ * if we want to increase the line number by a small amount.\r
+ * FILE_CHANGE says whether we are entering a file, leaving, or neither.\r
+ */\r
+\r
+static void\r
+output_line_command (cppReader *pfile, bool conditional,\r
+                    enum file_change_code file_change)\r
+{\r
+  int line, col;\r
+  cppBuffer *ip = CPPBUFFER (pfile);\r
+  cppBuffer *buf;\r
+\r
+  llassert (ip != NULL);\r
+\r
+  if (ip->fname == NULL)\r
+    return;\r
+\r
+  update_position (ip);\r
+\r
+  if (CPPOPTIONS (pfile)->no_line_commands\r
+      || CPPOPTIONS (pfile)->no_output)\r
+    return;\r
+\r
+  buf = CPPBUFFER (pfile);\r
+\r
+  llassert (buf != NULL);\r
+\r
+  line = buf->lineno;\r
+  col = buf->colno;\r
+\r
+  llassert (ip->cur != NULL);\r
+\r
+  adjust_position (cppLineBase (ip), ip->cur, &line, &col);\r
+\r
+  if (CPPOPTIONS (pfile)->no_line_commands)\r
+    return;\r
+\r
+  if (conditional) {\r
+    if (line == pfile->lineno)\r
+      return;\r
+\r
+    /* If the inherited line number is a little too small,\r
+       output some newlines instead of a #line command.  */\r
+\r
+    if (line > pfile->lineno && line < pfile->lineno + 8)\r
+      {\r
+       cppReader_reserve (pfile, 20);\r
+       while (line > pfile->lineno)\r
+         {\r
+           cppReader_putCharQ (pfile, '\n');\r
+           pfile->lineno++;\r
+         }\r
+\r
+       return;\r
+      }\r
+  }\r
+\r
+  cppReader_reserve (pfile,\r
+                    size_fromInt (4 * cstring_length (ip->nominal_fname) + 50));\r
+\r
+  {\r
+#ifdef OUTPUT_LINE_COMMANDS\r
+    static char sharp_line[] = "#line ";\r
+#else\r
+    static char sharp_line[] = "# ";\r
+#endif\r
+    cppReader_putStrN (pfile, sharp_line, sizeof(sharp_line)-1);\r
+  }\r
+\r
+  sprintf (cppReader_getPWritten (pfile), "%d ", line);\r
+  cppReader_adjustWritten (pfile, strlen (cppReader_getPWritten (pfile)));\r
+\r
+  quote_string (pfile, cstring_toCharsSafe (ip->nominal_fname));\r
+\r
+  if (file_change != same_file) {\r
+    cppReader_putCharQ (pfile, ' ');\r
+    cppReader_putCharQ (pfile, file_change == enter_file ? '1' : '2');\r
+  }\r
+  /* Tell cc1 if following text comes from a system header file.  */\r
+  if (ip->system_header_p != '\0') {\r
+    cppReader_putCharQ (pfile, ' ');\r
+    cppReader_putCharQ (pfile, '3');\r
+  }\r
+#ifndef NO_IMPLICIT_EXTERN_C\r
+  /* Tell cc1plus if following text should be treated as C.  */\r
+  if (ip->system_header_p == (char) 2 && CPPOPTIONS (pfile)->cplusplus) {\r
+    cppReader_putCharQ (pfile, ' ');\r
+    cppReader_putCharQ (pfile, '4');\r
+  }\r
+#endif\r
+  cppReader_putCharQ (pfile, '\n');\r
+  pfile->lineno = line;\r
+}\r
+\r
+\r
+/*\r
+ * Parse a macro argument and append the info on PFILE's token_buffer.\r
+ * REST_ARGS means to absorb the rest of the args.\r
+ * Return nonzero to indicate a syntax error.\r
+ */\r
+\r
+static enum cpp_token\r
+macarg (cppReader *pfile, int rest_args)\r
+{\r
+  int paren = 0;\r
+  enum cpp_token token;\r
+  char save_put_out_comments = CPPOPTIONS (pfile)->put_out_comments;\r
+  bool oldexpand = pfile->no_macro_expand;\r
+  CPPOPTIONS (pfile)->put_out_comments = 1;\r
+\r
+  /* Try to parse as much of the argument as exists at this\r
+     input stack level.  */\r
+\r
+  pfile->no_macro_expand = TRUE;\r
+\r
+  for (;;)\r
+    {\r
+      token = cppGetToken (pfile);\r
+\r
+      switch (token)\r
+       {\r
+       case CPP_EOF:\r
+         goto done;\r
+       case CPP_POP:\r
+         /* If we've hit end of file, it's an error (reported by caller).\r
+            Ditto if it's the end of cpp_expand_to_buffer text.\r
+            If we've hit end of macro, just continue.  */\r
+         if (!cppBuffer_isMacro (CPPBUFFER (pfile)))\r
+           goto done;\r
+         /*@switchbreak@*/ break;\r
+       case CPP_LPAREN:\r
+         paren++;\r
+         /*@switchbreak@*/ break;\r
+       case CPP_RPAREN:\r
+         if (--paren < 0)\r
+           goto found;\r
+         /*@switchbreak@*/ break;\r
+       case CPP_COMMA:\r
+         /* if we've returned to lowest level and\r
+            we aren't absorbing all args */\r
+         if (paren == 0 && rest_args == 0)\r
+           goto found;\r
+         /*@switchbreak@*/ break;\r
+       found:\r
+         /* Remove ',' or ')' from argument buffer.  */\r
+         cppReader_adjustWritten (pfile, -1);\r
+         goto done;\r
+       default:\r
+         ;\r
+       }\r
+    }\r
+\r
+done:\r
+  CPPOPTIONS (pfile)->put_out_comments = save_put_out_comments;\r
+  pfile->no_macro_expand = oldexpand;\r
+\r
+  return token;\r
+}\r
+\r
+\r
+/* Turn newlines to spaces in the string of length LENGTH at START,\r
+   except inside of string constants.\r
+   The string is copied into itself with its beginning staying fixed.  */\r
+\r
+static int\r
+change_newlines (char *start, int length)\r
+{\r
+  register char *ibp;\r
+  register char *obp;\r
+  register char *limit;\r
+  char c;\r
+\r
+  ibp = start;\r
+  limit = start + length;\r
+  obp = start;\r
+\r
+  while (ibp < limit) {\r
+    *obp++ = c = *ibp++;\r
+    switch (c) {\r
+\r
+    case '\'':\r
+    case '\"':\r
+      /* Notice and skip strings, so that we don't delete newlines in them.  */\r
+      {\r
+       char quotec = c;\r
+       while (ibp < limit) {\r
+         *obp++ = c = *ibp++;\r
+         if (c == quotec)\r
+           /*@innerbreak@*/ break;\r
+         if (c == '\n' && quotec == '\'')\r
+           /*@innerbreak@*/ break;\r
+       }\r
+      }\r
+    /*@switchbreak@*/ break;\r
+    }\r
+  }\r
+\r
+  return obp - start;\r
+}\r
+\r
+static /*@observer@*/ struct tm *\r
+timestamp (/*@returned@*/ cppReader *pfile)\r
+{\r
+  if (pfile->timebuf == NULL)\r
+    {\r
+      time_t t = time ((time_t *) 0);\r
+      pfile->timebuf = localtime (&t);\r
+    }\r
+\r
+  llassert (pfile->timebuf != NULL);\r
+\r
+  return pfile->timebuf;\r
+}\r
+\r
+static ob_mstring monthnames[] = {\r
+  "Jan", "Feb", "Mar", "Apr", "May", "Jun",\r
+  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",\r
+} ;\r
+\r
+/*\r
+ * expand things like __FILE__.  Place the expansion into the output\r
+ * buffer *without* rescanning.\r
+ */\r
+\r
+static void\r
+special_symbol (hashNode hp, cppReader *pfile)\r
+{\r
+  cstring buf = cstring_undefined;\r
+  size_t len;\r
+  int true_indepth;\r
+  cppBuffer *ip;\r
+  struct tm *timebuf;\r
+\r
+  int paren = 0;               /* For special `defined' keyword */\r
+\r
+  for (ip = cppReader_getBuffer (pfile); ip != NULL; ip = cppBuffer_prevBuffer (ip))\r
+    {\r
+      if (ip == cppReader_nullBuffer (pfile))\r
+       {\r
+         cppReader_errorLit (pfile,\r
+                       cstring_makeLiteralTemp ("cccp error: not in any file?!"));\r
+         return;                       /* the show must go on */\r
+       }\r
+\r
+      if (ip != NULL && ip->fname != NULL)\r
+       {\r
+         break;\r
+       }\r
+    }\r
+\r
+  switch (hp->type)\r
+    {\r
+    case T_FILE:\r
+    case T_BASE_FILE:\r
+      {\r
+       char *string;\r
+       if (hp->type == T_BASE_FILE)\r
+         {\r
+           while (cppBuffer_prevBuffer (ip) != cppReader_nullBuffer (pfile))\r
+             {\r
+               ip = cppBuffer_prevBuffer (ip);\r
+             }\r
+         }\r
+\r
+       llassert (ip != NULL);\r
+       string = cstring_toCharsSafe (ip->nominal_fname);\r
+\r
+       if (string == NULL)\r
+         {\r
+           string = "";\r
+         }\r
+\r
+       cppReader_reserve (pfile, 3 + 4 * strlen (string));\r
+       quote_string (pfile, string);\r
+       return;\r
+      }\r
+\r
+    case T_INCLUDE_LEVEL:\r
+      true_indepth = 0;\r
+      ip = cppReader_getBuffer (pfile);\r
+\r
+      for (;  ip != cppReader_nullBuffer (pfile) && ip != NULL;\r
+          ip = cppBuffer_prevBuffer (ip))\r
+       {\r
+         if (ip != NULL && ip->fname != NULL)\r
+           {\r
+             true_indepth++;\r
+           }\r
+       }\r
+\r
+      buf = message ("%d", true_indepth - 1);\r
+      break;\r
+\r
+    case T_VERSION:\r
+      buf = message ("\"%s\"", cstring_makeLiteralTemp (CPP_VERSION));\r
+      break;\r
+\r
+#ifndef NO_BUILTIN_SIZE_TYPE\r
+    case T_SIZE_TYPE:\r
+      buf = cstring_makeLiteral (SIZE_TYPE);\r
+      break;\r
+#endif\r
+\r
+#ifndef NO_BUILTIN_PTRDIFF_TYPE\r
+    case T_PTRDIFF_TYPE:\r
+      buf = cstring_makeLiteral (PTRDIFF_TYPE);\r
+      break;\r
+#endif\r
+\r
+    case T_WCHAR_TYPE:\r
+      buf = cstring_makeLiteral (cppReader_wcharType (pfile));\r
+      break;\r
+\r
+    case T_USER_LABEL_PREFIX_TYPE:\r
+      buf = cstring_makeLiteral (USER_LABEL_PREFIX);\r
+      break;\r
+\r
+    case T_REGISTER_PREFIX_TYPE:\r
+      buf = cstring_makeLiteral (REGISTER_PREFIX);\r
+      break;\r
+\r
+    case T_CONST:\r
+      buf = message ("%d", hp->value.ival);\r
+      break;\r
+\r
+    case T_SPECLINE:\r
+      {\r
+       if (ip != NULL)\r
+         {\r
+           int line = ip->lineno;\r
+           int col = ip->colno;\r
+\r
+           llassert (ip->cur != NULL);\r
+           adjust_position (cppLineBase (ip), ip->cur, &line, &col);\r
+\r
+           buf = message ("%d", (int) line);\r
+         }\r
+       else\r
+         {\r
+           BADBRANCH;\r
+         }\r
+      }\r
+    break;\r
+\r
+    case T_DATE:\r
+    case T_TIME:\r
+      {\r
+       char *sbuf = (char *) dmalloc (20);\r
+       timebuf = timestamp (pfile);\r
+       if (hp->type == T_DATE)\r
+         {\r
+           sprintf (sbuf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon],\r
+                    timebuf->tm_mday, timebuf->tm_year + 1900);\r
+         }\r
+       else\r
+         {\r
+           sprintf (sbuf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min,\r
+                    timebuf->tm_sec);\r
+         }\r
+\r
+       buf = cstring_fromCharsNew (sbuf);\r
+       sfree (sbuf);\r
+       break;\r
+      }\r
+\r
+    case T_SPEC_DEFINED:\r
+      buf = cstring_makeLiteral (" 0 ");     /* Assume symbol is not defined */\r
+      ip = cppReader_getBuffer (pfile);\r
+\r
+      llassert (ip->cur != NULL);\r
+      SKIP_WHITE_SPACE (ip->cur);\r
+\r
+      if (*ip->cur == '(')\r
+       {\r
+         paren++;\r
+         ip->cur++;                    /* Skip over the paren */\r
+         SKIP_WHITE_SPACE (ip->cur);\r
+       }\r
+\r
+      if (!is_idstart[(int) *ip->cur])\r
+       goto oops;\r
+      if (ip->cur[0] == 'L' && (ip->cur[1] == '\'' || ip->cur[1] == '"'))\r
+       goto oops;\r
+\r
+      if ((hp = cppReader_lookup (ip->cur, -1, -1)) != 0)\r
+       {\r
+         cstring_free (buf);\r
+         buf = cstring_makeLiteral (" 1 ");\r
+       }\r
+\r
+      while (is_idchar[(int) *ip->cur])\r
+       {\r
+         ++ip->cur;\r
+       }\r
+\r
+      SKIP_WHITE_SPACE (ip->cur);\r
+\r
+      if (paren != 0)\r
+       {\r
+         if (*ip->cur != ')')\r
+           goto oops;\r
+         ++ip->cur;\r
+       }\r
+      break;\r
+\r
+    oops:\r
+\r
+      cppReader_errorLit (pfile,\r
+                   cstring_makeLiteralTemp ("`defined' without an identifier"));\r
+      break;\r
+\r
+    default:\r
+      cpp_setLocation (pfile);\r
+      llfatalerror (message ("Pre-processing error: invalid special hash type"));\r
+    }\r
+\r
+  len = size_fromInt (cstring_length (buf));\r
+\r
+  cppReader_reserve (pfile, len + 1);\r
+  cppReader_putStrN (pfile, cstring_toCharsSafe (buf), len);\r
+  cppReader_nullTerminateQ (pfile);\r
+\r
+  cstring_free (buf);\r
+  return;\r
+}\r
+\r
+/* Write out a #define command for the special named MACRO_NAME\r
+   to PFILE's token_buffer.  */\r
+\r
+static void\r
+dump_special_to_buffer (cppReader *pfile, char *macro_name)\r
+{\r
+  static char define_directive[] = "#define ";\r
+  size_t macro_name_length = strlen (macro_name);\r
+  output_line_command (pfile, 0, same_file);\r
+  cppReader_reserve (pfile, sizeof(define_directive) + macro_name_length);\r
+  cppReader_putStrN (pfile, define_directive, sizeof(define_directive)-1);\r
+  cppReader_putStrN (pfile, macro_name, macro_name_length);\r
+  cppReader_putCharQ (pfile, ' ');\r
+  cpp_expand_to_buffer (pfile, macro_name, macro_name_length);\r
+  cppReader_putChar (pfile, '\n');\r
+}\r
+\r
+/* Initialize the built-in macros.  */\r
+\r
+static void\r
+cppReader_installBuiltin (/*@observer@*/ char *name, ctype ctyp,\r
+                         int len, enum node_type type,\r
+                         int ivalue, /*@null@*/ /*@only@*/ char *value,\r
+                         int hash)\r
+{\r
+  cstring sname = cstring_fromCharsNew (name);\r
+\r
+  llassert (usymtab_inGlobalScope ());\r
+\r
+  /*\r
+  ** Be careful here: this is done before the ctype table has\r
+  ** been initialized.\r
+  */\r
+\r
+  if (!usymtab_exists (sname))\r
+    {\r
+      uentry ue = uentry_makeConstant (sname, ctyp, fileloc_createBuiltin ());\r
+\r
+      if (ctype_equal (ctyp, ctype_string))\r
+       {\r
+         qualList ql = qualList_new ();\r
+         ql = qualList_add (ql, qual_createObserver ());\r
+         uentry_reflectQualifiers (ue, ql);\r
+         qualList_free (ql);\r
+       }\r
+      \r
+      usymtab_addGlobalEntry (ue);\r
+    }\r
+  else\r
+    {\r
+      ;\r
+    }\r
+\r
+  (void) cppReader_install (name, len, type, ivalue, value, hash);\r
+  cstring_free (sname);\r
+}\r
+\r
+static void\r
+cppReader_installBuiltinType (/*@observer@*/ char *name, ctype ctyp,\r
+                             int len, enum node_type type,\r
+                             int ivalue,\r
+                             /*@only@*/ /*@null@*/ char *value, int hash)\r
+{\r
+  cstring sname = cstring_fromChars (name);\r
+  /* evs 2000 07 10 - removed a memory leak, detected by lclint */\r
+\r
+  llassert (usymtab_inGlobalScope ());\r
+\r
+  if (!usymtab_existsTypeEither (sname))\r
+    {\r
+      uentry ue = uentry_makeDatatype (sname, ctyp,\r
+                                      NO, NO,\r
+                                      fileloc_createBuiltin ());\r
+      llassert (!usymtab_existsEither (sname));\r
+      usymtab_addGlobalEntry (ue);\r
+    }\r
+\r
+  (void) cppReader_install (name, len, type, ivalue, value, hash);\r
+}\r
+\r
+static void\r
+initialize_builtins (cppReader *pfile)\r
+{\r
+  cppReader_installBuiltin ("__LINE__", ctype_int, -1, T_SPECLINE, 0, NULL, -1);\r
+  cppReader_installBuiltin ("__DATE__", ctype_string, -1, T_DATE, 0, NULL, -1);\r
+  cppReader_installBuiltin ("__FILE__", ctype_string, -1, T_FILE, 0, NULL, -1);\r
+  cppReader_installBuiltin ("__BASE_FILE__", ctype_string, -1, T_BASE_FILE, 0, NULL, -1);\r
+  cppReader_installBuiltin ("__INCLUDE_LEVEL__", ctype_int, -1, T_INCLUDE_LEVEL, 0, NULL, -1);\r
+  cppReader_installBuiltin ("__VERSION__", ctype_string, -1, T_VERSION, 0, NULL, -1);\r
+#ifndef NO_BUILTIN_SIZE_TYPE\r
+  cppReader_installBuiltinType ("__SIZE_TYPE__", ctype_anyintegral, -1, T_SIZE_TYPE, 0, NULL, -1);\r
+#endif\r
+#ifndef NO_BUILTIN_PTRDIFF_TYPE\r
+  cppReader_installBuiltinType ("__PTRDIFF_TYPE__", ctype_anyintegral, -1, T_PTRDIFF_TYPE, 0, NULL, -1);\r
+#endif\r
+  cppReader_installBuiltinType ("__WCHAR_TYPE__", ctype_anyintegral, -1, T_WCHAR_TYPE, 0, NULL, -1);\r
+  cppReader_installBuiltin ("__USER_LABEL_PREFIX__", ctype_string, -1, T_USER_LABEL_PREFIX_TYPE, 0, NULL, -1);\r
+  cppReader_installBuiltin ("__REGISTER_PREFIX__", ctype_string, -1, T_REGISTER_PREFIX_TYPE, 0, NULL, -1);\r
+  cppReader_installBuiltin ("__TIME__", ctype_string, -1, T_TIME, 0, NULL, -1);\r
+\r
+  /*\r
+  ** No, don't define __STDC__\r
+  **\r
+\r
+  if (!cppReader_isTraditional (pfile))\r
+    {\r
+      cppReader_installBuiltin ("__STDC__", ctype_int, -1, T_CONST, STDC_VALUE, NULL, -1);\r
+    }\r
+\r
+  **\r
+  */\r
+\r
+# ifdef WIN32\r
+    cppReader_installBuiltin ("_WIN32", ctype_int, -1, T_CONST, STDC_VALUE, NULL, -1);\r
+# endif\r
+\r
+  /*\r
+  ** This is supplied using a -D by the compiler driver\r
+  ** so that it is present only when truly compiling with GNU C.\r
+  */\r
+\r
+  /*  cppReader_install ("__GNUC__", -1, T_CONST, 2, 0, -1);  */\r
+\r
+  cppReader_installBuiltin ("__LCLINT__", ctype_int, -1, T_CONST, 2, NULL, -1);\r
+\r
+  if (CPPOPTIONS (pfile)->debug_output)\r
+    {\r
+      dump_special_to_buffer (pfile, "__BASE_FILE__");\r
+      dump_special_to_buffer (pfile, "__VERSION__");\r
+#ifndef NO_BUILTIN_SIZE_TYPE\r
+      dump_special_to_buffer (pfile, "__SIZE_TYPE__");\r
+#endif\r
+#ifndef NO_BUILTIN_PTRDIFF_TYPE\r
+      dump_special_to_buffer (pfile, "__PTRDIFF_TYPE__");\r
+#endif\r
+      dump_special_to_buffer (pfile, "__WCHAR_TYPE__");\r
+      dump_special_to_buffer (pfile, "__DATE__");\r
+      dump_special_to_buffer (pfile, "__TIME__");\r
+      if (!cppReader_isTraditional (pfile))\r
+       dump_special_to_buffer (pfile, "__STDC__");\r
+    }\r
+}\r
+\r
+\r
+/* Return 1 iff a token ending in C1 followed directly by a token C2\r
+   could cause mis-tokenization.  */\r
+\r
+static bool\r
+unsafe_chars (char c1, char c2)\r
+{\r
+  switch (c1)\r
+    {\r
+    case '+': case '-':\r
+      if (c2 == c1 || c2 == '=')\r
+       return 1;\r
+      goto letter;\r
+    case '.':\r
+    case '0': case '1': case '2': case '3': case '4':\r
+    case '5': case '6': case '7': case '8': case '9':\r
+    case 'e': case 'E': case 'p': case 'P':\r
+      if (c2 == '-' || c2 == '+')\r
+       return 1; /* could extend a pre-processing number */\r
+      goto letter;\r
+    case 'L':\r
+      if (c2 == '\'' || c2 == '\"')\r
+       return 1;   /* Could turn into L"xxx" or L'xxx'.  */\r
+      goto letter;\r
+    letter:\r
+    case '_':\r
+    case 'a': case 'b': case 'c': case 'd':           case 'f':\r
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':\r
+    case 'm': case 'n': case 'o':           case 'q': case 'r':\r
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':\r
+    case 'y': case 'z':\r
+    case 'A': case 'B': case 'C': case 'D':           case 'F':\r
+    case 'G': case 'H': case 'I': case 'J': case 'K':\r
+    case 'M': case 'N': case 'O':           case 'Q': case 'R':\r
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':\r
+    case 'Y': case 'Z':\r
+      /* We're in the middle of either a name or a pre-processing number.  */\r
+      return (is_idchar[(int) c2] || c2 == '.');\r
+    case '<': case '>': case '!': case '%': case '#': case ':':\r
+    case '^': case '&': case '|': case '*': case '/': case '=':\r
+      return (c2 == c1 || c2 == '=');\r
+    }\r
+  return 0;\r
+}\r
+\r
+/* Expand a macro call.\r
+   HP points to the symbol that is the macro being called.\r
+   Put the result of expansion onto the input stack\r
+   so that subsequent input by our caller will use it.\r
+\r
+   If macro wants arguments, caller has already verified that\r
+   an argument list follows; arguments come from the input stack.  */\r
+\r
+static void\r
+macroexpand (cppReader *pfile, /*@dependent@*/ hashNode hp)\r
+{\r
+  int nargs;\r
+  DEFINITION *defn = hp->value.defn;\r
+  char *xbuf;\r
+  char *oxbuf = NULL;\r
+  int start_line;\r
+  int start_column;\r
+  size_t xbuf_len;\r
+  size_t old_written = cppReader_getWritten (pfile);\r
+  int rest_args;\r
+  int rest_zero = 0;\r
+  int i;\r
+  struct argdata *args = NULL;\r
+\r
+  pfile->output_escapes++;\r
+\r
+  cppBuffer_lineAndColumn (cppReader_fileBuffer (pfile), &start_line, &start_column);\r
+\r
+  nargs = defn->nargs;\r
+\r
+  if (nargs >= 0)\r
+    {\r
+      enum cpp_token token = CPP_EOF;\r
+\r
+      args = (struct argdata *) dmalloc ((nargs + 1) * sizeof (*args));\r
+\r
+      for (i = 0; i < nargs; i++)\r
+       {\r
+         args[i].expanded = 0;\r
+         args[i].raw = 0;\r
+         args[i].raw_length = 0;\r
+         args[i].expand_length = args[i].stringified_length = -1;\r
+         args[i].use_count = 0;\r
+       }\r
+\r
+      /*\r
+      ** Parse all the macro args that are supplied.  I counts them.\r
+      ** The first NARGS args are stored in ARGS.\r
+      ** The rest are discarded.  If rest_args is set then we assume\r
+      ** macarg absorbed the rest of the args.\r
+      */\r
+\r
+      i = 0;\r
+      rest_args = 0;\r
+\r
+      cppReader_forward (pfile, 1); /* Discard the open-parenthesis before the first arg.  */\r
+      do\r
+       {\r
+         if (rest_args != 0)\r
+           {\r
+             continue;\r
+           }\r
+\r
+         if (i < nargs || (nargs == 0 && i == 0))\r
+           {\r
+             /* if we are working on last arg which absorbs rest of args... */\r
+             if (i == nargs - 1 && defn->rest_args)\r
+               {\r
+                 rest_args = 1;\r
+               }\r
+\r
+             args[i].raw = size_toLong (cppReader_getWritten (pfile));\r
+             token = macarg (pfile, rest_args);\r
+             args[i].raw_length = cppReader_getWritten (pfile) - args[i].raw;\r
+             args[i].newlines = FALSE; /* FIXME */\r
+           }\r
+         else\r
+           {\r
+             token = macarg (pfile, 0);\r
+           }\r
+\r
+         if (token == CPP_EOF || token == CPP_POP)\r
+           {\r
+             cppReader_errorWithLine (pfile, start_line, start_column,\r
+                                  cstring_fromCharsNew ("unterminated macro call"));\r
+             sfree (args);\r
+             return;\r
+           }\r
+         i++;\r
+       } while (token == CPP_COMMA);\r
+\r
+      /* If we got one arg but it was just whitespace, call that 0 args.  */\r
+      if (i == 1)\r
+       {\r
+         char *bp;\r
+         char *lim;\r
+\r
+         assertSet (args);\r
+\r
+         bp = ARG_BASE + args[0].raw;\r
+         lim = bp + args[0].raw_length;\r
+\r
+         /* cpp.texi says for foo ( ) we provide one argument.\r
+            However, if foo wants just 0 arguments, treat this as 0.  */\r
+\r
+         if (nargs == 0)\r
+           {\r
+             while (bp != lim && is_space[(int) *bp])\r
+               {\r
+                 bp++;\r
+               }\r
+           }\r
+\r
+         if (bp == lim)\r
+           i = 0;\r
+       }\r
+\r
+      /* Don't output an error message if we have already output one for\r
+        a parse error above.  */\r
+      rest_zero = 0;\r
+\r
+      if (nargs == 0 && i > 0)\r
+       {\r
+         cppReader_error (pfile,\r
+                    message ("arguments given to macro `%s'", hp->name));\r
+       }\r
+      else if (i < nargs)\r
+       {\r
+         /* traditional C allows foo() if foo wants one argument.  */\r
+         if (nargs == 1 && i == 0 && cppReader_isTraditional (pfile))\r
+           {\r
+             ;\r
+           }\r
+         /* the rest args token is allowed to absorb 0 tokens */\r
+         else if (i == nargs - 1 && defn->rest_args)\r
+           rest_zero = 1;\r
+         else if (i == 0)\r
+           cppReader_error (pfile,\r
+                      message ("macro `%s' used without args", hp->name));\r
+         else if (i == 1)\r
+           cppReader_error (pfile,\r
+                      message ("macro `%s' used with just one arg", hp->name));\r
+         else\r
+           {\r
+             cppReader_error (pfile,\r
+                        message ("macro `%s' used with only %d args",\r
+                                 hp->name, i));\r
+           }\r
+       }\r
+      else if (i > nargs)\r
+       {\r
+         cppReader_error (pfile,\r
+                    message ("macro `%s' used with too many (%d) args", hp->name, i));\r
+       }\r
+      else\r
+       {\r
+         ;\r
+       }\r
+    }\r
+\r
+  /* If macro wants zero args, we parsed the arglist for checking only.\r
+     Read directly from the macro definition.  */\r
+\r
+  if (nargs <= 0)\r
+    {\r
+      xbuf = defn->expansion;\r
+      xbuf_len = defn->length;\r
+    }\r
+  else\r
+    {\r
+      char *exp = defn->expansion;\r
+      int offset;      /* offset in expansion,\r
+                                  copied a piece at a time */\r
+      size_t totlen;   /* total amount of exp buffer filled so far */\r
+\r
+      register struct reflist *ap, *last_ap;\r
+      \r
+      assertSet (args); /* args is defined since the nargs > 0 path was taken */\r
+\r
+      /* Macro really takes args.  Compute the expansion of this call.  */\r
+\r
+      /* Compute length in characters of the macro's expansion.\r
+        Also count number of times each arg is used.  */\r
+      xbuf_len = defn->length;\r
+\r
+      llassert (args != NULL);\r
+\r
+      for (ap = defn->pattern; ap != NULL; ap = ap->next)\r
+       {\r
+         if (ap->stringify)\r
+           {\r
+             struct argdata *arg = &args[ap->argno];\r
+\r
+             /* Stringify it it hasn't already been */\r
+             assertSet (arg);\r
+\r
+             if (arg->stringified_length < 0)\r
+               {\r
+                 int arglen = arg->raw_length;\r
+                 bool escaped = FALSE;\r
+                 char in_string = '\0';\r
+                 char c;\r
+\r
+                 /* Initially need_space is -1.  Otherwise, 1 means the\r
+                    previous character was a space, but we suppressed it;\r
+                    0 means the previous character was a non-space.  */\r
+                 int need_space = -1;\r
+\r
+                 i = 0;\r
+                 arg->stringified = cppReader_getWritten (pfile);\r
+                 if (!cppReader_isTraditional (pfile))\r
+                   cppReader_putChar (pfile, '\"'); /* insert beginning quote */\r
+                 for (; i < arglen; i++)\r
+                   {\r
+                     c = (ARG_BASE + arg->raw)[i];\r
+\r
+                     if (in_string == '\0')\r
+                       {\r
+                         /* Internal sequences of whitespace are replaced by\r
+                            one space except within an string or char token.*/\r
+                         if (is_space[(int) c])\r
+                           {\r
+                             if (cppReader_getWritten (pfile) > arg->stringified\r
+                                 && (cppReader_getPWritten (pfile))[-1] == '@')\r
+                               {\r
+                                 /* "@ " escape markers are removed */\r
+                                 cppReader_adjustWritten (pfile, -1);\r
+                                 /*@innercontinue@*/ continue;\r
+                               }\r
+                             if (need_space == 0)\r
+                               need_space = 1;\r
+                             /*@innercontinue@*/ continue;\r
+                           }\r
+                         else if (need_space > 0)\r
+                           cppReader_putChar (pfile, ' ');\r
+                         else\r
+                           {\r
+                             ;\r
+                           }\r
+\r
+                         need_space = 0;\r
+                       }\r
+\r
+                     if (escaped)\r
+                       escaped = 0;\r
+                     else\r
+                       {\r
+                         if (c == '\\')\r
+                           escaped = 1;\r
+\r
+                         if (in_string != '\0')\r
+                           {\r
+                             if (c == in_string)\r
+                               in_string = '\0';\r
+                           }\r
+                         else if (c == '\"' || c == '\'')\r
+                           {\r
+                             in_string = c;\r
+                           }\r
+                         else\r
+                           {\r
+                             ;\r
+                           }\r
+                       }\r
+\r
+                     /* Escape these chars */\r
+                     if (c == '\"' || (in_string != '\0' && c == '\\'))\r
+                       cppReader_putChar (pfile, '\\');\r
+                     if (isprint (c))\r
+                       cppReader_putChar (pfile, c);\r
+                     else\r
+                       {\r
+                         cppReader_reserve (pfile, 4);\r
+                         sprintf (cppReader_getPWritten (pfile), "\\%03o",\r
+                                  (unsigned int) c);\r
+                         cppReader_adjustWritten (pfile, 4);\r
+                       }\r
+                   }\r
+                 if (!cppReader_isTraditional (pfile))\r
+                   cppReader_putChar (pfile, '\"'); /* insert ending quote */\r
+                 arg->stringified_length\r
+                   = size_toInt (cppReader_getWritten (pfile) - arg->stringified);\r
+               }\r
+\r
+             xbuf_len += args[ap->argno].stringified_length;\r
+           }\r
+         else if (ap->raw_before || ap->raw_after || cppReader_isTraditional (pfile))\r
+           {\r
+             /* Add 4 for two newline-space markers to prevent\r
+                token concatenation.  */\r
+             assertSet (args); /*@i534 shouldn't need this */\r
+             xbuf_len += args[ap->argno].raw_length + 4;\r
+           }\r
+         else\r
+           {\r
+             /* We have an ordinary (expanded) occurrence of the arg.\r
+                So compute its expansion, if we have not already.  */\r
+\r
+             assertSet (args); /*@i534 shouldn't need this */\r
+\r
+             if (args[ap->argno].expand_length < 0)\r
+               {\r
+                 args[ap->argno].expanded = cppReader_getWritten (pfile);\r
+                 cpp_expand_to_buffer (pfile,\r
+                                       ARG_BASE + args[ap->argno].raw,\r
+                                       size_fromInt (args[ap->argno].raw_length));\r
+\r
+                 args[ap->argno].expand_length\r
+                   = size_toInt (cppReader_getWritten (pfile) - args[ap->argno].expanded);\r
+               }\r
+\r
+             /* Add 4 for two newline-space markers to prevent\r
+                token concatenation.  */\r
+             xbuf_len += args[ap->argno].expand_length + 4;\r
+          }\r
+         if (args[ap->argno].use_count < 10)\r
+           args[ap->argno].use_count++;\r
+       }\r
+\r
+      xbuf = (char *) dmalloc (xbuf_len + 1);\r
+      oxbuf = xbuf;\r
+\r
+      /*\r
+      ** Generate in XBUF the complete expansion\r
+      ** with arguments substituted in.\r
+      ** TOTLEN is the total size generated so far.\r
+      ** OFFSET is the index in the definition\r
+      ** of where we are copying from.\r
+      */\r
+\r
+      offset = 0;\r
+      totlen = 0;\r
+\r
+      for (last_ap = NULL, ap = defn->pattern; ap != NULL;\r
+          last_ap = ap, ap = ap->next)\r
+       {\r
+         register struct argdata *arg = &args[ap->argno];\r
+         size_t count_before = totlen;\r
+\r
+         /* Add chars to XBUF.  */\r
+         for (i = 0; i < ap->nchars; i++, offset++)\r
+           {\r
+             xbuf[totlen++] = exp[offset];\r
+           }\r
+\r
+         /* If followed by an empty rest arg with concatenation,\r
+            delete the last run of nonwhite chars.  */\r
+         if (rest_zero && totlen > count_before\r
+             && ((ap->rest_args && ap->raw_before)\r
+                 || (last_ap != NULL && last_ap->rest_args\r
+                     && last_ap->raw_after)))\r
+           {\r
+             /* Delete final whitespace.  */\r
+             while (totlen > count_before && is_space[(int) xbuf[totlen - 1]])\r
+               {\r
+                 totlen--;\r
+               }\r
+\r
+             /* Delete the nonwhites before them.  */\r
+             while (totlen > count_before && ! is_space[(int) xbuf[totlen - 1]])\r
+               {\r
+                 totlen--;\r
+               }\r
+           }\r
+\r
+         if (ap->stringify != 0)\r
+           {\r
+             assertSet(arg);\r
+             memcpy (xbuf + totlen,\r
+                     ARG_BASE + arg->stringified,\r
+                     size_fromInt (arg->stringified_length));\r
+             totlen += arg->stringified_length;\r
+           }\r
+         else if (ap->raw_before || ap->raw_after || cppReader_isTraditional (pfile))\r
+           {\r
+             char *p1;\r
+             char *l1;\r
+\r
+             assertSet (arg);\r
+\r
+             p1 = ARG_BASE + arg->raw;\r
+             l1 = p1 + arg->raw_length;\r
+\r
+             if (ap->raw_before)\r
+               {\r
+                 while (p1 != l1 && is_space[(int) *p1])\r
+                   {\r
+                     p1++;\r
+                   }\r
+\r
+                 while (p1 != l1 && is_idchar[(int) *p1])\r
+                   {\r
+                     xbuf[totlen++] = *p1++;\r
+                   }\r
+\r
+                 /* Delete any no-reexpansion marker that follows\r
+                    an identifier at the beginning of the argument\r
+                    if the argument is concatenated with what precedes it.  */\r
+                 if (p1[0] == '@' && p1[1] == '-')\r
+                   p1 += 2;\r
+               }\r
+             if (ap->raw_after)\r
+               {\r
+                 /* Arg is concatenated after: delete trailing whitespace,\r
+                    whitespace markers, and no-reexpansion markers.  */\r
+                 while (p1 != l1)\r
+                   {\r
+                     if (is_space[(int) l1[-1]]) l1--;\r
+                     else if (l1[-1] == '-')\r
+                       {\r
+                         char *p2 = l1 - 1;\r
+                         /* If a `-' is preceded by an odd number of newlines then it\r
+                            and the last newline are a no-reexpansion marker.  */\r
+                         while (p2 != p1 && p2[-1] == '\n')\r
+                           {\r
+                             p2--;\r
+                           }\r
+\r
+                         if (((l1 - 1 - p2) & 1) != 0)\r
+                           {\r
+                             l1 -= 2;\r
+                           }\r
+                         else\r
+                           {\r
+                             /*@innerbreak@*/ break;\r
+                           }\r
+                       }\r
+                     else\r
+                       {\r
+                         /*@innerbreak@*/ break;\r
+                       }\r
+                   }\r
+               }\r
+\r
+             memcpy (xbuf + totlen, p1, size_fromInt (l1 - p1));\r
+             totlen += l1 - p1;\r
+           }\r
+         else\r
+           {\r
+             char *expanded;\r
+\r
+             assertSet (arg);\r
+             expanded = ARG_BASE + arg->expanded;\r
+\r
+             if (!ap->raw_before && totlen > 0\r
+                 && (arg->expand_length != 0)\r
+                 && !cppReader_isTraditional(pfile)\r
+                 && unsafe_chars (xbuf[totlen-1], expanded[0]))\r
+               {\r
+                 xbuf[totlen++] = '@';\r
+                 xbuf[totlen++] = ' ';\r
+               }\r
+\r
+             memcpy (xbuf + totlen, expanded,\r
+                     size_fromInt (arg->expand_length));\r
+             totlen += arg->expand_length;\r
+\r
+             if (!ap->raw_after && totlen > 0\r
+                 && offset < size_toInt (defn->length)\r
+                 && !cppReader_isTraditional(pfile)\r
+                 && unsafe_chars (xbuf[totlen-1], exp[offset]))\r
+               {\r
+                 xbuf[totlen++] = '@';\r
+                 xbuf[totlen++] = ' ';\r
+               }\r
+\r
+             /* If a macro argument with newlines is used multiple times,\r
+                then only expand the newlines once.  This avoids creating\r
+                output lines which don't correspond to any input line,\r
+                which confuses gdb and gcov.  */\r
+             if (arg->use_count > 1 && arg->newlines > 0)\r
+               {\r
+                 /* Don't bother doing change_newlines for subsequent\r
+                    uses of arg.  */\r
+                 arg->use_count = 1;\r
+                 arg->expand_length\r
+                   = change_newlines (expanded, arg->expand_length);\r
+               }\r
+           }\r
+\r
+         if (totlen > xbuf_len)\r
+           abort ();\r
+       }\r
+\r
+      /* if there is anything left of the definition\r
+        after handling the arg list, copy that in too.  */\r
+\r
+      for (i = offset; i < size_toInt (defn->length); i++)\r
+       {\r
+         /* if we've reached the end of the macro */\r
+         if (exp[i] == ')')\r
+           rest_zero = 0;\r
+         if (! (rest_zero && last_ap != NULL && last_ap->rest_args\r
+                && last_ap->raw_after))\r
+           xbuf[totlen++] = exp[i];\r
+       }\r
+\r
+      xbuf[totlen] = '\0';\r
+      xbuf_len = totlen;\r
+    }\r
+\r
+  pfile->output_escapes--;\r
+\r
+  /* Now put the expansion on the input stack\r
+     so our caller will commence reading from it.  */\r
+  push_macro_expansion (pfile, xbuf, xbuf_len, hp);\r
+  cppReader_getBuffer (pfile)->has_escapes = 1;\r
+\r
+  /* Pop the space we've used in the token_buffer for argument expansion.  */\r
+  cppReader_setWritten (pfile, old_written);\r
+\r
+  /* Recursive macro use sometimes works traditionally.\r
+     #define foo(x,y) bar (x (y,0), y)\r
+     foo (foo, baz)  */\r
+\r
+  if (!cppReader_isTraditional (pfile))\r
+    hp->type = T_DISABLED;\r
+\r
+  sfree (args);\r
+}\r
+\r
+static void\r
+push_macro_expansion (cppReader *pfile, char *xbuf, size_t xbuf_len,\r
+                     /*@dependent@*/ hashNode hp)\r
+{\r
+  cppBuffer *mbuf = cppReader_pushBuffer (pfile, xbuf, xbuf_len);\r
+\r
+  if (mbuf == NULL)\r
+    {\r
+      return;\r
+    }\r
+\r
+  mbuf->cleanup = cppReader_macroCleanup;\r
+\r
+  llassert (mbuf->hnode == NULL);\r
+  mbuf->hnode = hp;\r
+\r
+  /* The first chars of the expansion should be a "@ " added by\r
+     collect_expansion.  This is to prevent accidental token-pasting\r
+     between the text preceding the macro invocation, and the macro\r
+     expansion text.\r
+\r
+     We would like to avoid adding unneeded spaces (for the sake of\r
+     tools that use cpp, such as imake).  In some common cases we can\r
+     tell that it is safe to omit the space.\r
+\r
+     The character before the macro invocation cannot have been an\r
+     idchar (or else it would have been pasted with the idchars of\r
+     the macro name).  Therefore, if the first non-space character\r
+     of the expansion is an idchar, we do not need the extra space\r
+     to prevent token pasting.\r
+\r
+     Also, we don't need the extra space if the first char is '(',\r
+     or some other (less common) characters.  */\r
+\r
+  if (xbuf[0] == '@' && xbuf[1] == ' '\r
+      && (is_idchar[(int) xbuf[2]] || xbuf[2] == '(' || xbuf[2] == '\''\r
+         || xbuf[2] == '\"'))\r
+  {\r
+    llassert (mbuf->cur != NULL);\r
+    mbuf->cur += 2;\r
+  }\r
+}\r
+\r
+\r
+/* Like cppGetToken, except that it does not read past end-of-line.\r
+   Also, horizontal space is skipped, and macros are popped.  */\r
+\r
+static enum cpp_token\r
+get_directive_token (cppReader *pfile)\r
+{\r
+  for (;;)\r
+    {\r
+      size_t old_written = cppReader_getWritten (pfile);\r
+      enum cpp_token token;\r
+      cppSkipHspace (pfile);\r
+      if (cppReader_peekC (pfile) == '\n')\r
+       {\r
+         return CPP_VSPACE;\r
+       }\r
+\r
+      token = cppGetToken (pfile);\r
+\r
+      switch (token)\r
+       {\r
+       case CPP_POP:\r
+         if (!cppBuffer_isMacro (cppReader_getBuffer (pfile)))\r
+           return token;\r
+         /*@fallthrough@*/\r
+       case CPP_HSPACE:\r
+       case CPP_COMMENT:\r
+         cppReader_setWritten (pfile, old_written);\r
+         /*@switchbreak@*/ break;\r
+       default:\r
+         return token;\r
+       }\r
+    }\r
+}\r
+\r
+\r
+/* Handle #include and #import.\r
+   This function expects to see "fname" or <fname> on the input.\r
+\r
+   The input is normally in part of the output_buffer following\r
+   cppReader_getWritten, and will get overwritten by output_line_command.\r
+   I.e. in input file specification has been popped by cppReader_handleDirective.\r
+   This is safe.  */\r
+\r
+static int\r
+do_include (cppReader *pfile, struct directive *keyword,\r
+           /*@unused@*/ char *unused1, /*@unused@*/ char *unused2)\r
+{\r
+  bool skip_dirs = (keyword->type == T_INCLUDE_NEXT);\r
+  cstring fname;\r
+  char *fbeg, *fend;           /* Beginning and end of fname */\r
+  enum cpp_token token;\r
+\r
+  /* Chain of dirs to search */\r
+  struct file_name_list *search_start = CPPOPTIONS (pfile)->include;\r
+  struct file_name_list dsp[1];        /* First in chain, if #include "..." */\r
+  struct file_name_list *searchptr = NULL;\r
+  size_t old_written = cppReader_getWritten (pfile);\r
+\r
+  int flen;\r
+\r
+  int f;                       /* file number */\r
+  int angle_brackets = 0;      /* 0 for "...", 1 for <...> */\r
+  f= -1;                       /* JF we iz paranoid! */\r
+\r
+  pfile->parsing_include_directive++;\r
+  token = get_directive_token (pfile);\r
+  pfile->parsing_include_directive--;\r
+\r
+  if (token == CPP_STRING)\r
+    {\r
+      /* FIXME - check no trailing garbage */\r
+      fbeg = pfile->token_buffer + old_written + 1;\r
+      fend = cppReader_getPWritten (pfile) - 1;\r
+      if (fbeg[-1] == '<')\r
+       {\r
+         angle_brackets = 1;\r
+         /* If -I-, start with the first -I dir after the -I-.  */\r
+         if (CPPOPTIONS (pfile)->first_bracket_include != NULL)\r
+           search_start = CPPOPTIONS (pfile)->first_bracket_include;\r
+       }\r
+      /* If -I- was specified, don't search current dir, only spec'd ones.  */\r
+      else if (!CPPOPTIONS (pfile)->ignore_srcdir)\r
+       {\r
+         cppBuffer *fp = CPPBUFFER (pfile);\r
+         /* We have "filename".  Figure out directory this source\r
+            file is coming from and put it on the front of the list.  */\r
+\r
+         for ( ; fp != cppReader_nullBuffer (pfile); fp = cppBuffer_prevBuffer (fp))\r
+           {\r
+             int n;\r
+             char *ep,*nam;\r
+\r
+             llassert (fp != NULL);\r
+\r
+             nam = NULL;\r
+\r
+             if (cstring_isDefined (fp->nominal_fname))\r
+               {\r
+                 nam = cstring_toCharsSafe (fp->nominal_fname);\r
+\r
+                 /* Found a named file.  Figure out dir of the file,\r
+                    and put it in front of the search list.  */\r
+                 dsp[0].next = search_start;\r
+                 search_start = dsp;\r
+\r
+#ifndef VMS\r
+                 ep = strrchr (nam, CONNECTCHAR);\r
+#else                          /* VMS */\r
+                 ep = strrchr (nam, ']');\r
+                 if (ep == NULL) ep = strrchr (nam, '>');\r
+                 if (ep == NULL) ep = strrchr (nam, ':');\r
+                 if (ep != NULL) ep++;\r
+#endif                         /* VMS */\r
+                 if (ep != NULL)\r
+                   {\r
+                     char save;\r
+\r
+                     n = ep - nam;\r
+                     save = nam[n];\r
+                     nam[n] = '\0';\r
+\r
+                     /*@-onlytrans@*/ /* This looks like a memory leak... */ \r
+                     dsp[0].fname = cstring_fromCharsNew (nam); /* evs 2000-07-20: was fromChars */\r
+                     /*@=onlytrans@*/\r
+                     nam[n] = save;\r
+\r
+                     if (n + INCLUDE_LEN_FUDGE > pfile->max_include_len)\r
+                       pfile->max_include_len = n + INCLUDE_LEN_FUDGE;\r
+                   }\r
+                 else\r
+                   {\r
+                     dsp[0].fname = cstring_undefined; /* Current directory */\r
+                   }\r
+\r
+                 dsp[0].got_name_map = 0;\r
+                 break;\r
+               }\r
+           }\r
+       }\r
+      else\r
+       {\r
+         ;\r
+       }\r
+    }\r
+#ifdef VMS\r
+  else if (token == CPP_NAME)\r
+    {\r
+      /*\r
+       * Support '#include xyz' like VAX-C to allow for easy use of all the\r
+       * decwindow include files. It defaults to '#include <xyz.h>' (so the\r
+       * code from case '<' is repeated here) and generates a warning.\r
+       */\r
+      cppReader_warning (pfile,\r
+                  "VAX-C-style include specification found, use '#include <filename.h>' !");\r
+      angle_brackets = 1;\r
+      /* If -I-, start with the first -I dir after the -I-.  */\r
+      if (CPPOPTIONS (pfile)->first_bracket_include)\r
+       search_start = CPPOPTIONS (pfile)->first_bracket_include;\r
+      fbeg = pfile->token_buffer + old_written;\r
+      fend = cppReader_getPWritten (pfile);\r
+    }\r
+#endif\r
+  else\r
+    {\r
+      cppReader_error (pfile,\r
+                message ("Preprocessor command #%s expects \"FILENAME\" or <FILENAME>",\r
+                         keyword->name));\r
+\r
+      cppReader_setWritten (pfile, old_written);\r
+      cppReader_skipRestOfLine (pfile);\r
+      return 0;\r
+    }\r
+\r
+  *fend = 0;\r
+\r
+  token = get_directive_token (pfile);\r
+  if (token != CPP_VSPACE)\r
+    {\r
+      cppReader_errorLit (pfile,\r
+                   cstring_makeLiteralTemp ("Junk at end of #include"));\r
+\r
+      while (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP)\r
+       {\r
+         token = get_directive_token (pfile);\r
+       }\r
+    }\r
+\r
+  /*\r
+  ** For #include_next, skip in the search path\r
+  ** past the dir in which the containing file was found.\r
+  */\r
+\r
+  if (skip_dirs)\r
+    {\r
+      cppBuffer *fp = CPPBUFFER (pfile);\r
+\r
+      for (; fp != cppReader_nullBuffer (pfile); fp = cppBuffer_prevBuffer (fp))\r
+       {\r
+         llassert (fp != NULL);\r
+\r
+         if (fp->fname != NULL)\r
+           {\r
+             /* fp->dir is null if the containing file was specified with\r
+                an absolute file name.  In that case, don't skip anything.  */\r
+             if (fp->dir == SELF_DIR_DUMMY)\r
+               {\r
+                 search_start = CPPOPTIONS (pfile)->include;\r
+               }\r
+             else if (fp->dir != NULL)\r
+               {\r
+                 search_start = fp->dir->next;\r
+               }\r
+             else\r
+               {\r
+                 ;\r
+               }\r
+\r
+             break;\r
+           }\r
+       }\r
+    }\r
+\r
+  cppReader_setWritten (pfile, old_written);\r
+\r
+  flen = fend - fbeg;\r
+\r
+  DPRINTF (("fbeg: %s", fbeg));\r
+\r
+  if (flen == 0)\r
+    {\r
+      cppReader_error (pfile,\r
+                message ("Empty file name in #%s", keyword->name));\r
+      return 0;\r
+    }\r
+\r
+  /*\r
+  ** Allocate this permanently, because it gets stored in the definitions\r
+  ** of macros.\r
+  */\r
+\r
+  fname = cstring_undefined;\r
+\r
+  /* + 2 above for slash and terminating null.  */\r
+  /* + 2 added for '.h' on VMS (to support '#include filename') */\r
+\r
+  /* If specified file name is absolute, just open it.  */\r
+\r
+  if (osd_isConnectChar (*fbeg)\r
+# if defined (WIN32) || defined (OS2)\r
+      || (*(fbeg + 1) == ':')\r
+# endif\r
+      )\r
+    {\r
+      fname = cstring_copyLength (fbeg, flen);\r
+      \r
+      if (redundant_include_p (pfile, fname))\r
+       {\r
+         cstring_free (fname);\r
+         return 0;\r
+       }\r
+      \r
+      f = open_include_file (pfile, fname, NULL);\r
+      \r
+      if (f == IMPORT_FOUND)\r
+       {\r
+         return 0;             /* Already included this file */\r
+       }\r
+    } \r
+  else \r
+    {\r
+      /* Search directory path, trying to open the file.\r
+        Copy each filename tried into FNAME.  */\r
+\r
+      for (searchptr = search_start; searchptr != NULL;\r
+          searchptr = searchptr->next)\r
+       {\r
+         if (!cstring_isEmpty (searchptr->fname))\r
+           {\r
+             /* The empty string in a search path is ignored.\r
+                This makes it possible to turn off entirely\r
+                a standard piece of the list.  */\r
+             if (cstring_isEmpty (searchptr->fname))\r
+               continue;\r
+             \r
+             fname = cstring_copy (searchptr->fname);\r
+             fname = cstring_appendChar (fname, CONNECTCHAR);\r
+             DPRINTF (("Here: %s", fname));\r
+           }\r
+         else\r
+           {\r
+             ;\r
+           }\r
+         \r
+         fname = cstring_concatLength (fname, fbeg, flen);\r
+\r
+         DPRINTF (("fname: %s", fname));\r
+         \r
+         /* Win32 directory fix from Kay Buschner. */\r
+#if defined (WIN32) || defined (OS2)\r
+         /* Fix all unixdir slashes to win dir slashes */\r
+         if (searchptr->fname && (searchptr->fname[0] != 0)) \r
+           {\r
+             cstring_replaceAll (fname, '/', '\\');\r
+           }\r
+#endif /* WIN32 */\r
+\r
+#ifdef VMS\r
+         /* Change this 1/2 Unix 1/2 VMS file specification into a\r
+            full VMS file specification */\r
+         if (searchptr->fname && (searchptr->fname[0] != 0)) {\r
+           /* Fix up the filename */\r
+           hack_vms_include_specification (fname);\r
+         } else {\r
+           /* This is a normal VMS filespec, so use it unchanged.  */\r
+           strncpy (fname, fbeg, flen);\r
+           fname[flen] = 0;\r
+           /* if it's '#include filename', add the missing .h */\r
+           if (strchr (fname,'.') == NULL) {\r
+             strcat (fname, ".h");\r
+           }\r
+         }\r
+#endif /* VMS */\r
+         /* ??? There are currently 3 separate mechanisms for avoiding processing\r
+            of redundant include files: #import, #pragma once, and\r
+            redundant_include_p.  It would be nice if they were unified.  */\r
+         \r
+         if (redundant_include_p (pfile, fname))\r
+           {\r
+             cstring_free (fname);\r
+             return 0;\r
+           }\r
+\r
+         DPRINTF (("Trying: %s", fname));\r
+\r
+         f = open_include_file (pfile, fname, searchptr);\r
+         \r
+         if (f == IMPORT_FOUND)\r
+           {\r
+             return 0;                 /* Already included this file */\r
+           }\r
+#ifdef EACCES\r
+         else if (f == IMPORT_NOT_FOUND && errno == EACCES)\r
+           {\r
+             cppReader_warning (pfile,\r
+                                message ("Header file %s exists, but is not readable", fname));\r
+           }\r
+#endif\r
+         \r
+         if (f >= 0)\r
+           {\r
+             break;\r
+           }\r
+       }\r
+    }\r
+  \r
+  if (f < 0)\r
+    {\r
+      /* A file that was not found.  */\r
+      fname = cstring_copyLength (fbeg, flen);\r
+\r
+      if (search_start != NULL)\r
+       {\r
+         cppReader_error (pfile,\r
+                          message ("Cannot find include file %s on search path: %x", \r
+                                   fname,\r
+                                   searchPath_unparse (search_start)));\r
+       }\r
+      else\r
+       {\r
+         cppReader_error (pfile,\r
+                          message ("No include path in which to find %s", fname));\r
+       }\r
+    }\r
+  else {\r
+    /*\r
+    ** Check to see if this include file is a once-only include file.\r
+    ** If so, give up.\r
+    */\r
+\r
+    struct file_name_list *ptr;\r
+\r
+    for (ptr = pfile->all_include_files; ptr != NULL; ptr = ptr->next)\r
+      {\r
+       if (cstring_equal (ptr->fname, fname))\r
+         {\r
+           /* This file was included before.  */\r
+           break;\r
+         }\r
+      }\r
+\r
+    if (ptr == NULL)\r
+      {\r
+       /* This is the first time for this file.  */\r
+       /* Add it to list of files included.  */\r
+\r
+       ptr = (struct file_name_list *) dmalloc (sizeof (*ptr));\r
+       ptr->control_macro = NULL;\r
+       ptr->c_system_include_path = NULL;\r
+       ptr->next = pfile->all_include_files;\r
+       ptr->fname = fname;\r
+       ptr->got_name_map = NULL;\r
+\r
+       DPRINTF (("Including file: %s", fname));\r
+       pfile->all_include_files = ptr;\r
+       assertSet (pfile->all_include_files);\r
+      }\r
+\r
+    if (angle_brackets != 0)\r
+      {\r
+       pfile->system_include_depth++;\r
+      }\r
+\r
+    /* Actually process the file */\r
+    if (cppReader_pushBuffer (pfile, NULL, 0) == NULL)\r
+      {\r
+       cstring_free (fname);\r
+       return 0;\r
+      }\r
+\r
+    if (finclude (pfile, f, fname, is_system_include (pfile, fname),\r
+                 searchptr != dsp ? searchptr : SELF_DIR_DUMMY))\r
+      {\r
+       output_line_command (pfile, 0, enter_file);\r
+       pfile->only_seen_white = 2;\r
+      }\r
+\r
+    if (angle_brackets)\r
+      {\r
+       pfile->system_include_depth--;\r
+      }\r
+    /*@-branchstate@*/\r
+  } /*@=branchstate@*/ \r
+\r
+  return 0;\r
+}\r
+\r
+/* Return nonzero if there is no need to include file NAME\r
+   because it has already been included and it contains a conditional\r
+   to make a repeated include do nothing.  */\r
+\r
+static bool\r
+redundant_include_p (cppReader *pfile, cstring name)\r
+{\r
+  struct file_name_list *l = pfile->all_include_files;\r
+\r
+  for (; l != NULL; l = l->next)\r
+    {\r
+      if (cstring_equal (name, l->fname)\r
+         && (l->control_macro != NULL)\r
+         && (cppReader_lookup (l->control_macro, -1, -1) != NULL))\r
+       {\r
+         return TRUE;\r
+       }\r
+    }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/* Return nonzero if the given FILENAME is an absolute pathname which\r
+   designates a file within one of the known "system" include file\r
+   directories.  We assume here that if the given FILENAME looks like\r
+   it is the name of a file which resides either directly in a "system"\r
+   include file directory, or within any subdirectory thereof, then the\r
+   given file must be a "system" include file.  This function tells us\r
+   if we should suppress pedantic errors/warnings for the given FILENAME.\r
+\r
+   The value is 2 if the file is a C-language system header file\r
+   for which C++ should (on most systems) assume `extern "C"'.  */\r
+\r
+static bool\r
+is_system_include (cppReader *pfile, cstring filename)\r
+{\r
+  struct file_name_list *searchptr;\r
+\r
+  for (searchptr = CPPOPTIONS (pfile)->first_system_include;\r
+       searchptr != NULL;\r
+       searchptr = searchptr->next)\r
+    {\r
+      if (!cstring_isEmpty (searchptr->fname)) {\r
+       cstring sys_dir = searchptr->fname;\r
+       int length = cstring_length (sys_dir);\r
+\r
+       if (cstring_equalLen (sys_dir, filename, length)\r
+           && osd_isConnectChar (cstring_getChar (filename, length)))\r
+         {\r
+           if (searchptr->c_system_include_path)\r
+             return 2;\r
+           else\r
+             return 1;\r
+         }\r
+      }\r
+    }\r
+\r
+  return 0;\r
+}\r
+\r
+/* Convert a character string literal into a nul-terminated string.\r
+   The input string is [IN ... LIMIT).\r
+   The result is placed in RESULT.  RESULT can be the same as IN.\r
+   The value returned in the end of the string written to RESULT,\r
+   or NULL on error.  */\r
+\r
+static /*@null@*/ char *\r
+convert_string (cppReader *pfile, /*@returned@*/ char *result,\r
+               char *in, char *limit, int handle_escapes)\r
+{\r
+  char c;\r
+  c = *in++;\r
+\r
+  if (c != '\"')\r
+    {\r
+      return NULL;\r
+    }\r
+\r
+  while (in < limit)\r
+    {\r
+      c = *in++;\r
+\r
+      switch (c)\r
+       {\r
+       case '\0':\r
+         return NULL;\r
+       case '\"':\r
+         limit = in;\r
+         /*@switchbreak@*/ break;\r
+       case '\\':\r
+         if (handle_escapes)\r
+           {\r
+             char *bpc = (char *) in;\r
+             int i = (char) cppReader_parseEscape (pfile, &bpc);\r
+             in = (char *) bpc;\r
+             if (i >= 0)\r
+               *result++ = (char) c;\r
+             /*@switchbreak@*/ break;\r
+           }\r
+\r
+         /*@fallthrough@*/\r
+       default:\r
+         *result++ = c;\r
+       }\r
+    }\r
+\r
+  *result = 0;\r
+  return result;\r
+}\r
+\r
+/*\r
+ * interpret #line command.  Remembers previously seen fnames\r
+ * in its very own hash table.\r
+ */\r
+\r
+/*@constant int FNAME_HASHSIZE@*/\r
+#define FNAME_HASHSIZE 37\r
+\r
+static int\r
+do_line (cppReader *pfile, /*@unused@*/ struct directive *keyword)\r
+{\r
+  cppBuffer *ip = cppReader_getBuffer (pfile);\r
+  int new_lineno;\r
+  size_t old_written = cppReader_getWritten (pfile);\r
+  enum file_change_code file_change = same_file;\r
+  enum cpp_token token;\r
+\r
+  token = get_directive_token (pfile);\r
+\r
+  if (token != CPP_NUMBER\r
+      || !isdigit(pfile->token_buffer[old_written]))\r
+    {\r
+      cppReader_errorLit (pfile,\r
+                   cstring_makeLiteralTemp ("invalid format `#line' command"));\r
+\r
+      goto bad_line_directive;\r
+    }\r
+\r
+  /* The Newline at the end of this line remains to be processed.\r
+     To put the next line at the specified line number,\r
+     we must store a line number now that is one less.  */\r
+  new_lineno = atoi (pfile->token_buffer + old_written) - 1;\r
+  cppReader_setWritten (pfile, old_written);\r
+\r
+  /* NEW_LINENO is one less than the actual line number here.  */\r
+  if (cppReader_isPedantic (pfile) && new_lineno < 0)\r
+    cppReader_pedwarnLit (pfile,\r
+                   cstring_makeLiteralTemp ("line number out of range in `#line' command"));\r
+\r
+  token = get_directive_token (pfile);\r
+\r
+  if (token == CPP_STRING) {\r
+    char *fname = pfile->token_buffer + old_written;\r
+    char *end_name;\r
+    static hashNode fname_table[FNAME_HASHSIZE];\r
+    hashNode hp; \r
+    hashNode *hash_bucket;\r
+    char *p;\r
+    size_t num_start;\r
+    int fname_length;\r
+\r
+    /* Turn the file name, which is a character string literal,\r
+       into a null-terminated string.  Do this in place.  */\r
+    end_name = convert_string (pfile, fname, fname, cppReader_getPWritten (pfile), 1);\r
+    if (end_name == NULL)\r
+      {\r
+       cppReader_errorLit (pfile,\r
+                     cstring_makeLiteralTemp ("invalid format `#line' command"));\r
+       goto bad_line_directive;\r
+      }\r
+\r
+    fname_length = end_name - fname;\r
+    num_start = cppReader_getWritten (pfile);\r
+\r
+    token = get_directive_token (pfile);\r
+    if (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP) {\r
+      p = pfile->token_buffer + num_start;\r
+      if (cppReader_isPedantic (pfile))\r
+       cppReader_pedwarnLit (pfile,\r
+                       cstring_makeLiteralTemp ("garbage at end of `#line' command"));\r
+\r
+      if (token != CPP_NUMBER || *p < '0' || *p > '4' || p[1] != '\0')\r
+       {\r
+         cppReader_errorLit (pfile,\r
+                       cstring_makeLiteralTemp ("invalid format `#line' command"));\r
+         goto bad_line_directive;\r
+       }\r
+      if (*p == '1')\r
+       file_change = enter_file;\r
+      else if (*p == 2)\r
+       file_change = leave_file;\r
+      else if (*p == 3)\r
+       ip->system_header_p = 1;\r
+      else /* if (*p == 4) */\r
+       ip->system_header_p = 2;\r
+\r
+      cppReader_setWritten (pfile, num_start);\r
+      token = get_directive_token (pfile);\r
+      p = pfile->token_buffer + num_start;\r
+      if (token == CPP_NUMBER && p[1] == '\0' && (*p == '3' || *p== '4')) {\r
+       ip->system_header_p = *p == 3 ? 1 : 2;\r
+       token = get_directive_token (pfile);\r
+      }\r
+      if (token != CPP_VSPACE) {\r
+       cppReader_errorLit (pfile,\r
+                     cstring_makeLiteralTemp ("invalid format `#line' command"));\r
+\r
+       goto bad_line_directive;\r
+      }\r
+    }\r
+\r
+    hash_bucket =\r
+      &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];\r
+    for (hp = *hash_bucket; hp != NULL; hp = hp->next)\r
+      {\r
+       if (hp->length == fname_length &&\r
+           strncmp (hp->value.cpval, fname, size_fromInt (fname_length)) == 0) {\r
+         ip->nominal_fname = cstring_fromChars (hp->value.cpval);\r
+         break;\r
+       }\r
+      }\r
+\r
+    if (hp == 0) {\r
+      /* Didn't find it; cons up a new one.  */\r
+      hp = (hashNode) dmalloc (sizeof (*hp));\r
+\r
+      hp->prev = NULL;\r
+      hp->bucket_hdr = NULL;\r
+      hp->type = T_NONE;\r
+      hp->name = cstring_undefined;\r
+      hp->next = *hash_bucket;\r
+\r
+      *hash_bucket = hp;\r
+\r
+      hp->length = fname_length;\r
+      hp->value.cpval = dmalloc (sizeof (*hp->value.cpval) * (fname_length + 1));\r
+      memcpy (hp->value.cpval, fname, size_fromInt (fname_length));\r
+      hp->value.cpval[fname_length] = '\0';\r
+      ip->nominal_fname = cstring_fromChars (hp->value.cpval);\r
+    }\r
+  }\r
+  else if (token != CPP_VSPACE && token != CPP_EOF)\r
+    {\r
+      cppReader_errorLit (pfile,\r
+                   cstring_makeLiteralTemp ("invalid format `#line' command"));\r
+      goto bad_line_directive;\r
+    }\r
+  else\r
+    {\r
+      ;\r
+    }\r
+\r
+  ip->lineno = new_lineno;\r
+bad_line_directive:\r
+  cppReader_skipRestOfLine (pfile);\r
+  cppReader_setWritten (pfile, old_written);\r
+  output_line_command (pfile, 0, file_change);\r
+  return 0;\r
+}\r
+\r
+/*\r
+ * remove the definition of a symbol from the symbol table.\r
+ * according to un*x /lib/cpp, it is not an error to undef\r
+ * something that has no definitions, so it isn't one here either.\r
+ */\r
+\r
+static int\r
+do_undef (cppReader *pfile, struct directive *keyword, char *buf, char *limit)\r
+{\r
+\r
+  int sym_length;\r
+  hashNode hp;\r
+  char *orig_buf = buf;\r
+\r
+  SKIP_WHITE_SPACE (buf);\r
+\r
+  sym_length = cppReader_checkMacroName (pfile, buf, cstring_makeLiteralTemp ("macro"));\r
+\r
+  while ((hp = cppReader_lookup (buf, sym_length, -1)) != NULL)\r
+    {\r
+      /* If we are generating additional info for debugging (with -g) we\r
+        need to pass through all effective #undef commands.  */\r
+      if (CPPOPTIONS (pfile)->debug_output && (keyword != NULL))\r
+       {\r
+         pass_thru_directive (orig_buf, limit, pfile, keyword);\r
+       }\r
+\r
+      if (hp->type != T_MACRO)\r
+       {\r
+         cppReader_warning (pfile,\r
+                      message ("Undefining preprocessor builtin: %s",\r
+                               hp->name));\r
+       }\r
+\r
+      cppReader_deleteMacro (hp);\r
+    }\r
+\r
+  if (cppReader_isPedantic (pfile)) {\r
+    buf += sym_length;\r
+    SKIP_WHITE_SPACE (buf);\r
+    if (buf != limit)\r
+      {\r
+       cppReader_pedwarnLit (pfile,\r
+                       cstring_makeLiteralTemp ("garbage after `#undef' directive"));\r
+      }\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+\r
+/*\r
+ * Report an error detected by the program we are processing.\r
+ * Use the text of the line in the error message.\r
+ * (We use error because it prints the filename & line#.)\r
+ */\r
+\r
+static int\r
+do_error (cppReader *pfile, /*@unused@*/ struct directive *keyword,\r
+         char *buf, char *limit)\r
+{\r
+  int length = limit - buf;\r
+  cstring copy = cstring_copyLength (buf, length);\r
+  cstring adv = cstring_advanceWhiteSpace (copy);\r
+\r
+  cppReader_error (pfile, message ("#error %s", adv));\r
+  cstring_free (copy);\r
+  return 0;\r
+}\r
+\r
+/*\r
+ * Report a warning detected by the program we are processing.\r
+ * Use the text of the line in the warning message, then continue.\r
+ * (We use error because it prints the filename & line#.)\r
+ */\r
+\r
+static int\r
+do_warning (cppReader *pfile, /*@unused@*/ struct directive *keyword,\r
+           char *buf, char *limit)\r
+{\r
+  int length = limit - buf;\r
+  cstring copy = cstring_copyLength (buf, length);\r
+  cstring adv = cstring_advanceWhiteSpace (copy);\r
+  cppReader_warning (pfile, message ("#warning %s", adv));\r
+  cstring_free (copy);\r
+  return 0;\r
+}\r
+\r
+\r
+/* #ident has already been copied to the output file, so just ignore it.  */\r
+\r
+static int\r
+do_ident (cppReader *pfile, /*@unused@*/ struct directive *keyword,\r
+         /*@unused@*/ char *buf, /*@unused@*/ char *limit)\r
+{\r
+  /* Allow #ident in system headers, since that's not user's fault.  */\r
+  if (cppReader_isPedantic (pfile) && !cppReader_getBuffer (pfile)->system_header_p)\r
+    cppReader_pedwarnLit (pfile,\r
+                   cstring_makeLiteralTemp ("ANSI C does not allow `#ident'"));\r
+\r
+  /* Leave rest of line to be read by later calls to cppGetToken.  */\r
+\r
+  return 0;\r
+}\r
+\r
+/* #pragma and its argument line have already been copied to the output file.\r
+   Just check for some recognized pragmas that need validation here.  */\r
+\r
+static int\r
+do_pragma (cppReader *pfile, /*@unused@*/ struct directive *keyword,\r
+          /*@unused@*/ char *buf, /*@unused@*/ char *limit)\r
+{\r
+  while (*buf == ' ' || *buf == '\t')\r
+    {\r
+      buf++;\r
+    }\r
+\r
+  if (!strncmp (buf, "implementation", 14)) {\r
+    /* Be quiet about `#pragma implementation' for a file only if it hasn't\r
+       been included yet.  */\r
+    struct file_name_list *ptr;\r
+    char *p = buf + 14, *fname, *inc_fname;\r
+    int fname_len;\r
+    SKIP_WHITE_SPACE (p);\r
+    if (*p == '\n' || *p != '\"')\r
+      return 0;\r
+\r
+    fname = p + 1;\r
+    p = (char *) strchr (fname, '\"');\r
+    fname_len = p != NULL ? p - fname : mstring_length (fname);\r
+\r
+    for (ptr = pfile->all_include_files; ptr != NULL; ptr = ptr->next)\r
+      {\r
+       inc_fname = (char *) strrchr (cstring_toCharsSafe (ptr->fname), CONNECTCHAR);\r
+       inc_fname = (inc_fname != NULL)\r
+         ? inc_fname + 1 : cstring_toCharsSafe (ptr->fname);\r
+\r
+       if ((inc_fname != NULL)\r
+           && (strncmp (inc_fname, fname, size_fromInt (fname_len)) == 0))\r
+         {\r
+           cpp_setLocation (pfile);\r
+\r
+           ppllerror (message ("`#pragma implementation' for `%s' appears "\r
+                               "after file is included",\r
+                               cstring_fromChars (fname)));\r
+         }\r
+      }\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/*\r
+ * handle #if command by\r
+ *   1) inserting special `defined' keyword into the hash table\r
+ *     that gets turned into 0 or 1 by special_symbol (thus,\r
+ *     if the luser has a symbol called `defined' already, it won't\r
+ *      work inside the #if command)\r
+ *   2) rescan the input into a temporary output buffer\r
+ *   3) pass the output buffer to the yacc parser and collect a value\r
+ *   4) clean up the mess left from steps 1 and 2.\r
+ *   5) call conditional_skip to skip til the next #endif (etc.),\r
+ *      or not, depending on the value from step 3.\r
+ */\r
+\r
+static int\r
+do_if (cppReader *pfile, /*@unused@*/ struct directive *keyword,\r
+       char *buf, char *limit)\r
+{\r
+  HOST_WIDE_INT value = eval_if_expression (pfile, buf, limit - buf);\r
+  conditional_skip (pfile, value == 0, T_IF, NULL);\r
+  return 0;\r
+}\r
+\r
+/*\r
+ * handle a #elif directive by not changing  if_stack  either.\r
+ * see the comment above do_else.\r
+ */\r
+\r
+static int do_elif (cppReader *pfile, /*@unused@*/ struct directive *keyword,\r
+                   char *buf, char *limit)\r
+{\r
+  if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack)\r
+    {\r
+      cppReader_errorLit (pfile,\r
+                   cstring_makeLiteralTemp ("Preprocessor command #elif is not within a conditional"));\r
+      return 0;\r
+    }\r
+  else\r
+    {\r
+      llassert (pfile->if_stack != NULL);\r
+\r
+      if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF)\r
+       {\r
+         cppReader_errorLit (pfile,\r
+                       cstring_makeLiteralTemp ("`#elif' after `#else'"));\r
+\r
+         if (pfile->if_stack->fname != NULL\r
+             && cppReader_getBuffer (pfile)->fname != NULL\r
+             && !cstring_equal (pfile->if_stack->fname,\r
+                                cppReader_getBuffer (pfile)->nominal_fname))\r
+           fprintf (stderr, ", file %s", cstring_toCharsSafe (pfile->if_stack->fname));\r
+         fprintf (stderr, ")\n");\r
+       }\r
+      pfile->if_stack->type = T_ELIF;\r
+    }\r
+\r
+  if (pfile->if_stack->if_succeeded)\r
+    {\r
+      skip_if_group (pfile, 0);\r
+    }\r
+  else\r
+    {\r
+      HOST_WIDE_INT value = eval_if_expression (pfile, buf, limit - buf);\r
+      if (value == 0)\r
+       skip_if_group (pfile, 0);\r
+      else\r
+       {\r
+         ++pfile->if_stack->if_succeeded;      /* continue processing input */\r
+         output_line_command (pfile, 1, same_file);\r
+       }\r
+    }\r
+\r
+  return 0;\r
+}\r
+\r
+/*\r
+ * evaluate a #if expression in BUF, of length LENGTH,\r
+ * then parse the result as a C expression and return the value as an int.\r
+ */\r
+\r
+static HOST_WIDE_INT\r
+eval_if_expression (cppReader *pfile,\r
+                   /*@unused@*/ char *buf,\r
+                   /*@unused@*/ int length)\r
+{\r
+  hashNode save_defined;\r
+  HOST_WIDE_INT value;\r
+  size_t old_written = cppReader_getWritten (pfile);\r
+\r
+  save_defined = cppReader_install ("defined", -1, T_SPEC_DEFINED, 0, 0, -1);\r
+  pfile->pcp_inside_if = 1;\r
+\r
+  value = cppReader_parseExpression (pfile);\r
+  pfile->pcp_inside_if = 0;\r
+\r
+  /* Clean up special symbol */\r
+  cppReader_deleteMacro (save_defined);\r
+\r
+  cppReader_setWritten (pfile, old_written); /* Pop */\r
+\r
+  return value;\r
+}\r
+\r
+/*\r
+ * routine to handle ifdef/ifndef.  Try to look up the symbol,\r
+ * then do or don't skip to the #endif/#else/#elif depending\r
+ * on what directive is actually being processed.\r
+ */\r
+\r
+static int\r
+do_xifdef (cppReader *pfile, struct directive *keyword,\r
+          /*@unused@*/ char *unused1, /*@unused@*/ char *unused2)\r
+{\r
+  int skip;\r
+  cppBuffer *ip = cppReader_getBuffer (pfile);\r
+  char *ident;\r
+  int ident_length;\r
+  enum cpp_token token;\r
+  int start_of_file = 0;\r
+  char *control_macro = 0;\r
+  size_t old_written = cppReader_getWritten (pfile);\r
+\r
+  DPRINTF (("do xifdef: %d",\r
+           keyword->type == T_IFNDEF));\r
+\r
+  /* Detect a #ifndef at start of file (not counting comments).  */\r
+  if (cstring_isDefined (ip->fname) && keyword->type == T_IFNDEF)\r
+    {\r
+      start_of_file = pfile->only_seen_white == 2;\r
+    }\r
+\r
+  pfile->no_macro_expand++;\r
+  token = get_directive_token (pfile);\r
+  pfile->no_macro_expand--;\r
+\r
+  ident = pfile->token_buffer + old_written;\r
+  ident_length = size_toInt (cppReader_getWritten (pfile) - old_written);\r
+  cppReader_setWritten (pfile, old_written); /* Pop */\r
+\r
+  if (token == CPP_VSPACE || token == CPP_POP || token == CPP_EOF)\r
+    {\r
+      skip = (keyword->type == T_IFDEF);\r
+      if (! cppReader_isTraditional (pfile))\r
+       {\r
+         cppReader_pedwarn (pfile,\r
+                      message ("`#%s' with no argument", keyword->name));\r
+       }\r
+    }\r
+  else if (token == CPP_NAME)\r
+    {\r
+      hashNode hp = cppReader_lookup (ident, ident_length, -1);\r
+      skip = (keyword->type == T_IFDEF) \r
+       ? (hp == NULL) : (hp != NULL);\r
+\r
+      DPRINTF (("hp null: %d / %d / %d",\r
+               (hp == NULL),\r
+               (keyword->type == T_IFNDEF),\r
+               skip));\r
+               \r
+      if (start_of_file && !skip)\r
+       {\r
+         DPRINTF (("Not skipping!"));\r
+         control_macro = (char *) dmalloc (size_fromInt (ident_length + 1));\r
+         memcpy (control_macro, ident, size_fromInt (ident_length + 1));\r
+       }\r
+    }\r
+  else\r
+    {\r
+      skip = (keyword->type == T_IFDEF);\r
+      if (! cppReader_isTraditional (pfile))\r
+       {\r
+         cppReader_error (pfile,\r
+                    message ("`#%s' with invalid argument", keyword->name));\r
+       }\r
+    }\r
+\r
+  if (!cppReader_isTraditional (pfile))\r
+    {\r
+      int c;\r
+      cppSkipHspace (pfile);\r
+      c = cppReader_peekC (pfile);\r
+      if (c != EOF && c != '\n')\r
+       {\r
+         cppReader_pedwarn (pfile,\r
+                            message ("garbage at end of `#%s' argument", keyword->name));\r
+       }\r
+    }\r
+\r
+  cppReader_skipRestOfLine (pfile);\r
+\r
+  DPRINTF (("Conditional skip: %d", skip));\r
+  conditional_skip (pfile, skip, T_IF, control_macro);\r
+  return 0;\r
+}\r
+\r
+/* Push TYPE on stack; then, if SKIP is nonzero, skip ahead.\r
+   If this is a #ifndef starting at the beginning of a file,\r
+   CONTROL_MACRO is the macro name tested by the #ifndef.\r
+   Otherwise, CONTROL_MACRO is 0.  */\r
+\r
+static void\r
+conditional_skip (cppReader *pfile, int skip,\r
+                 enum node_type type,\r
+                 /*@dependent@*/ char *control_macro)\r
+{\r
+  cppIfStackFrame *temp = (cppIfStackFrame *) dmalloc (sizeof (*temp));\r
+\r
+  temp->fname = cppReader_getBuffer (pfile)->nominal_fname;\r
+  temp->next = pfile->if_stack;\r
+  temp->control_macro = control_macro;\r
+  temp->lineno = 0;\r
+  temp->if_succeeded = 0;\r
+\r
+  pfile->if_stack = temp;\r
+  pfile->if_stack->type = type;\r
+\r
+  if (skip != 0)\r
+    {\r
+      skip_if_group (pfile, 0);\r
+      return;\r
+    }\r
+  else\r
+    {\r
+      ++pfile->if_stack->if_succeeded;\r
+      output_line_command (pfile, 1, same_file);\r
+    }\r
+}\r
+\r
+/*\r
+ * skip to #endif, #else, or #elif.  adjust line numbers, etc.\r
+ * leaves input ptr at the sharp sign found.\r
+ * If ANY is nonzero, return at next directive of any sort.\r
+ */\r
+\r
+static void\r
+skip_if_group (cppReader *pfile, int any)\r
+{\r
+  int c;\r
+  struct directive *kt;\r
+  cppIfStackFrame *save_if_stack = pfile->if_stack; /* don't pop past here */\r
+  register int ident_length;\r
+  char *ident;\r
+  struct parse_marker line_start_mark;\r
+\r
+  parseSetMark (&line_start_mark, pfile);\r
+\r
+  if (CPPOPTIONS (pfile)->output_conditionals) {\r
+    static char failed[] = "#failed\n";\r
+    cppReader_puts (pfile, failed, sizeof(failed)-1);\r
+    pfile->lineno++;\r
+    output_line_command (pfile, 1, same_file);\r
+  }\r
+\r
+beg_of_line:\r
+  if (CPPOPTIONS (pfile)->output_conditionals)\r
+    {\r
+      cppBuffer *pbuf = cppReader_getBuffer (pfile);\r
+      char *start_line;\r
+\r
+      llassert (pbuf->buf != NULL);\r
+\r
+      start_line = pbuf->buf + line_start_mark.position;\r
+      cppReader_puts (pfile, start_line, size_fromInt (pbuf->cur - start_line));\r
+    }\r
+\r
+  parseMoveMark (&line_start_mark, pfile);\r
+\r
+  if (!cppReader_isTraditional (pfile))\r
+    {\r
+      cppSkipHspace (pfile);\r
+    }\r
+\r
+  c  = cppReader_getC (pfile);\r
+  if (c == '#')\r
+    {\r
+      size_t old_written = cppReader_getWritten (pfile);\r
+      cppSkipHspace (pfile);\r
+\r
+      parse_name (pfile, cppReader_getC (pfile));\r
+      ident_length = size_toInt (cppReader_getWritten (pfile) - old_written);\r
+      ident = pfile->token_buffer + old_written;\r
+      pfile->limit = ident;\r
+\r
+      for (kt = directive_table; kt->length >= 0; kt++)\r
+       {\r
+         cppIfStackFrame *temp;\r
+         if (ident_length == kt->length\r
+             && cstring_equalPrefix (kt->name, cstring_fromChars (ident)))\r
+           {\r
+             /* If we are asked to return on next directive, do so now.  */\r
+             if (any)\r
+               {\r
+                 goto done;\r
+               }\r
+\r
+             switch (kt->type)\r
+               {\r
+               case T_IF:\r
+               case T_IFDEF:\r
+               case T_IFNDEF:\r
+                 temp = (cppIfStackFrame *) dmalloc (sizeof (*temp));\r
+                 temp->next = pfile->if_stack;\r
+                 temp->fname = cppReader_getBuffer (pfile)->nominal_fname;\r
+                 temp->type = kt->type;\r
+                 temp->lineno = 0;\r
+                 temp->if_succeeded = 0;\r
+                 temp->control_macro = NULL;\r
+\r
+                 pfile->if_stack = temp;\r
+                 /*@switchbreak@*/ break;\r
+               case T_ELSE:\r
+               case T_ENDIF:\r
+                 if (cppReader_isPedantic (pfile) && pfile->if_stack != save_if_stack)\r
+                   validate_else (pfile,\r
+                                  cstring_makeLiteralTemp (kt->type == T_ELSE ? "#else" : "#endif"));\r
+                 /*@fallthrough@*/\r
+               case T_ELIF:\r
+                 if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack)\r
+                   {\r
+                     cppReader_error (pfile,\r
+                                message ("Preprocessor command #%s is not within a conditional", kt->name));\r
+                     /*@switchbreak@*/ break;\r
+                   }\r
+                 else if (pfile->if_stack == save_if_stack)\r
+                   {\r
+                     goto done;                /* found what we came for */\r
+                   }\r
+                 else\r
+                   {\r
+                     ;\r
+                   }\r
+\r
+                 if (kt->type != T_ENDIF)\r
+                   {\r
+                     llassert (pfile->if_stack != NULL);\r
+\r
+                     if (pfile->if_stack->type == T_ELSE)\r
+                       {\r
+                         cppReader_errorLit (pfile,\r
+                                       cstring_makeLiteralTemp ("`#else' or `#elif' after `#else'"));\r
+                       }\r
+\r
+                     pfile->if_stack->type = kt->type;\r
+                     /*@switchbreak@*/ break;\r
+                   }\r
+\r
+                 temp = pfile->if_stack;\r
+                 llassert (temp != NULL);\r
+                 pfile->if_stack = temp->next;\r
+                 sfree (temp);\r
+                 /*@switchbreak@*/ break;\r
+               default: ;\r
+                 /*@-branchstate@*/ \r
+               }\r
+             /*@=branchstate@*/\r
+             break;\r
+           }\r
+         \r
+         /* Don't let erroneous code go by.  */\r
+         \r
+         if (kt->length < 0 && !CPPOPTIONS (pfile)->lang_asm\r
+             && cppReader_isPedantic (pfile))\r
+           {\r
+             cppReader_pedwarnLit (pfile,\r
+                                   cstring_makeLiteralTemp ("Invalid preprocessor directive name"));\r
+           }\r
+       }\r
+\r
+      c = cppReader_getC (pfile);\r
+    }\r
+  /* We're in the middle of a line.  Skip the rest of it.  */\r
+  for (;;) {\r
+    size_t old;\r
+\r
+    switch (c)\r
+      {\r
+      case EOF:\r
+       goto done;\r
+      case '/':                        /* possible comment */\r
+       c = skip_comment (pfile, NULL);\r
+       if (c == EOF)\r
+         goto done;\r
+       /*@switchbreak@*/ break;\r
+      case '\"':\r
+      case '\'':\r
+       cppReader_forward (pfile, -1);\r
+       old = cppReader_getWritten (pfile);\r
+       (void) cppGetToken (pfile);\r
+       cppReader_setWritten (pfile, old);\r
+       /*@switchbreak@*/ break;\r
+      case '\\':\r
+       /* Char after backslash loses its special meaning.  */\r
+       if (cppReader_peekC (pfile) == '\n')\r
+         {\r
+           cppReader_forward (pfile, 1);\r
+         }\r
+\r
+       /*@switchbreak@*/ break;\r
+      case '\n':\r
+       goto beg_of_line;\r
+      }\r
+    c = cppReader_getC (pfile);\r
+  }\r
+done:\r
+  if (CPPOPTIONS (pfile)->output_conditionals) {\r
+    static char end_failed[] = "#endfailed\n";\r
+    cppReader_puts (pfile, end_failed, sizeof(end_failed)-1);\r
+    pfile->lineno++;\r
+  }\r
+  pfile->only_seen_white = 1;\r
+\r
+  parseGotoMark (&line_start_mark, pfile);\r
+  parseClearMark (&line_start_mark);\r
+}\r
+\r
+/*\r
+ * handle a #else directive.  Do this by just continuing processing\r
+ * without changing  if_stack ;  this is so that the error message\r
+ * for missing #endif's etc. will point to the original #if.  It\r
+ * is possible that something different would be better.\r
+ */\r
+\r
+static int\r
+do_else (cppReader *pfile, /*@unused@*/ struct directive *keyword,\r
+       /*@unused@*/ char *buf, /*@unused@*/ char *limit)\r
+{\r
+  if (cppReader_isPedantic (pfile))\r
+    {\r
+      validate_else (pfile, cstring_makeLiteralTemp ("#else"));\r
+    }\r
+\r
+  cppReader_skipRestOfLine (pfile);\r
+\r
+  if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack) {\r
+    cppReader_errorLit (pfile,\r
+                 cstring_makeLiteralTemp ("Preprocessor command #else is not within a conditional"));\r
+    return 0;\r
+  } else {\r
+    /* #ifndef can't have its special treatment for containing the whole file\r
+       if it has a #else clause.  */\r
+\r
+    llassert (pfile->if_stack != NULL);\r
+\r
+    pfile->if_stack->control_macro = 0;\r
+\r
+    if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF)\r
+      {\r
+       cpp_setLocation (pfile);\r
+       genppllerrorhint (FLG_PREPROC,\r
+                         message ("Pre-processor directive #else after #else"),\r
+                         message ("%q: Location of match",\r
+                                  fileloc_unparseRaw (pfile->if_stack->fname,\r
+                                                      pfile->if_stack->lineno)));\r
+      }\r
+\r
+    pfile->if_stack->type = T_ELSE;\r
+  }\r
+\r
+  if (pfile->if_stack->if_succeeded)\r
+    skip_if_group (pfile, 0);\r
+  else {\r
+    ++pfile->if_stack->if_succeeded;   /* continue processing input */\r
+    output_line_command (pfile, 1, same_file);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/*\r
+ * unstack after #endif command\r
+ */\r
+\r
+static int\r
+do_endif (cppReader *pfile, /*@unused@*/ struct directive *keyword,\r
+         /*@unused@*/ char *buf, /*@unused@*/ char *limit)\r
+{\r
+  if (cppReader_isPedantic (pfile))\r
+    {\r
+      validate_else (pfile, cstring_makeLiteralTemp ("#endif"));\r
+    }\r
+\r
+  cppReader_skipRestOfLine (pfile);\r
+\r
+  if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack)\r
+    {\r
+      cppReader_errorLit (pfile, cstring_makeLiteralTemp ("Unbalanced #endif"));\r
+    }\r
+  else\r
+    {\r
+      cppIfStackFrame *temp = pfile->if_stack;\r
+\r
+      llassert (temp != NULL);\r
+\r
+      pfile->if_stack = temp->next;\r
+      if (temp->control_macro != 0)\r
+       {\r
+         /* This #endif matched a #ifndef at the start of the file.\r
+            See if it is at the end of the file.  */\r
+         struct parse_marker start_mark;\r
+         int c;\r
+\r
+         parseSetMark (&start_mark, pfile);\r
+\r
+         for (;;)\r
+           {\r
+             cppSkipHspace (pfile);\r
+             c = cppReader_getC (pfile);\r
+\r
+             if (c != '\n')\r
+               break;\r
+           }\r
+\r
+         parseGotoMark (&start_mark, pfile);\r
+         parseClearMark (&start_mark);\r
+\r
+         if (c == EOF)\r
+           {\r
+             /* If we get here, this #endif ends a #ifndef\r
+                that contains all of the file (aside from whitespace).\r
+                Arrange not to include the file again\r
+                if the macro that was tested is defined.\r
+\r
+                Do not do this for the top-level file in a -include or any\r
+                file in a -imacros.  */\r
+             struct file_name_list *ifile = pfile->all_include_files;\r
+\r
+             for ( ; ifile != NULL; ifile = ifile->next)\r
+               {\r
+                 if (cstring_equal (ifile->fname, cppReader_getBuffer (pfile)->fname))\r
+                   {\r
+                     ifile->control_macro = temp->control_macro;\r
+                     break;\r
+                   }\r
+               }\r
+           }\r
+       }\r
+\r
+      sfree (temp);\r
+      output_line_command (pfile, 1, same_file);\r
+    }\r
+  return 0;\r
+}\r
+\r
+/* When an #else or #endif is found while skipping failed conditional,\r
+   if -pedantic was specified, this is called to warn about text after\r
+   the command name.  P points to the first char after the command name.  */\r
+\r
+static void\r
+validate_else (cppReader *pfile, cstring directive)\r
+{\r
+  int c;\r
+  cppSkipHspace (pfile);\r
+  c = cppReader_peekC (pfile);\r
+  if (c != EOF && c != '\n')\r
+    {\r
+      cppReader_pedwarn (pfile,\r
+                  message ("text following `%s' violates ANSI standard", directive));\r
+    }\r
+}\r
+\r
+/*\r
+** Get the next token, and add it to the text in pfile->token_buffer.\r
+** Return the kind of token we got.\r
+*/\r
+\r
+enum cpp_token\r
+cppGetToken (cppReader *pfile)\r
+{\r
+  int c, c2, c3;\r
+  size_t old_written = 0;\r
+  int start_line, start_column;\r
+  enum cpp_token token;\r
+  struct cppOptions *opts = CPPOPTIONS (pfile);\r
+  cppReader_getBuffer (pfile)->prev = cppReader_getBuffer (pfile)->cur;\r
+\r
+get_next:\r
+  c = cppReader_getC (pfile);\r
+\r
+  if (c == EOF)\r
+    {\r
+    handle_eof:\r
+      if (cppReader_getBuffer (pfile)->seen_eof)\r
+       {\r
+         cppBuffer *buf = cppReader_popBuffer (pfile);\r
+\r
+         if (buf != cppReader_nullBuffer (pfile))\r
+           {\r
+             goto get_next;\r
+           }\r
+         else\r
+           {\r
+             return CPP_EOF;\r
+           }\r
+       }\r
+      else\r
+       {\r
+         cppBuffer *next_buf = cppBuffer_prevBuffer (cppReader_getBuffer (pfile));\r
+         cppReader_getBuffer (pfile)->seen_eof = 1;\r
+\r
+         if (cstring_isDefined (cppReader_getBuffer (pfile)->nominal_fname)\r
+             && next_buf != cppReader_nullBuffer (pfile))\r
+           {\r
+             /* We're about to return from an #include file.\r
+                Emit #line information now (as part of the CPP_POP) result.\r
+                But the #line refers to the file we will pop to.  */\r
+             cppBuffer *cur_buffer = CPPBUFFER (pfile);\r
+             CPPBUFFER (pfile) = next_buf;\r
+             pfile->input_stack_listing_current = 0;\r
+             output_line_command (pfile, 0, leave_file);\r
+             CPPBUFFER (pfile) = cur_buffer;\r
+           }\r
+         return CPP_POP;\r
+       }\r
+    }\r
+  else\r
+    {\r
+      long newlines;\r
+      struct parse_marker start_mark;\r
+\r
+      switch (c)\r
+       {\r
+       case '/':\r
+         if (cppReader_peekC (pfile) == '=')\r
+           {\r
+             goto op2;\r
+           }\r
+\r
+         if (opts->put_out_comments)\r
+           {\r
+             parseSetMark (&start_mark, pfile);\r
+           }\r
+\r
+         newlines = 0;\r
+         cppBuffer_lineAndColumn (cppReader_fileBuffer (pfile),\r
+                                  &start_line, &start_column);\r
+         c = skip_comment (pfile, &newlines);\r
+\r
+         if (opts->put_out_comments && (c == '/' || c == EOF))\r
+           {\r
+             assertSet (&start_mark);\r
+             parseClearMark (&start_mark);\r
+           }\r
+\r
+         if (c == '/')\r
+           goto randomchar;\r
+         if (c == EOF)\r
+           {\r
+             cppReader_errorWithLine (pfile, start_line, start_column,\r
+                                      cstring_makeLiteral ("Unterminated comment"));\r
+             goto handle_eof;\r
+           }\r
+         c = '/';  /* Initial letter of comment.  */\r
+       return_comment:\r
+         /* Comments are equivalent to spaces.\r
+            For -traditional, a comment is equivalent to nothing.  */\r
+\r
+         if (opts->put_out_comments)\r
+           {\r
+             enum cpp_token res;\r
+\r
+             assertSet (&start_mark);\r
+             res = cpp_handleComment (pfile, &start_mark);\r
+             pfile->lineno += newlines;\r
+             return res;\r
+           }\r
+         else if (cppReader_isTraditional (pfile))\r
+           {\r
+             return CPP_COMMENT;\r
+           }\r
+         else\r
+           {\r
+             cppReader_reserve(pfile, 1);\r
+             cppReader_putCharQ (pfile, ' ');\r
+             return CPP_HSPACE;\r
+           }\r
+\r
+       case '#':\r
+         if (!pfile->only_seen_white)\r
+           {\r
+             goto randomchar;\r
+           }\r
+\r
+         if (cppReader_handleDirective (pfile))\r
+           {\r
+             return CPP_DIRECTIVE;\r
+           }\r
+\r
+         pfile->only_seen_white = 0;\r
+         return CPP_OTHER;\r
+\r
+       case '\"':\r
+       case '\'':\r
+         /* A single quoted string is treated like a double -- some\r
+            programs (e.g., troff) are perverse this way */\r
+         cppBuffer_lineAndColumn (cppReader_fileBuffer (pfile),\r
+                                  &start_line, &start_column);\r
+         old_written = cppReader_getWritten (pfile);\r
+       string:\r
+         cppReader_putChar (pfile, c);\r
+         while (TRUE)\r
+           {\r
+             int cc = cppReader_getC (pfile);\r
+             if (cc == EOF)\r
+               {\r
+                 if (cppBuffer_isMacro (CPPBUFFER (pfile)))\r
+                   {\r
+                     /* try harder: this string crosses a macro expansion\r
+                        boundary.  This can happen naturally if -traditional.\r
+                        Otherwise, only -D can make a macro with an unmatched\r
+                        quote.  */\r
+                     cppBuffer *next_buf\r
+                       = cppBuffer_prevBuffer (cppReader_getBuffer (pfile));\r
+                     (*cppReader_getBuffer (pfile)->cleanup)\r
+                       (cppReader_getBuffer (pfile), pfile);\r
+                     CPPBUFFER (pfile) = next_buf;\r
+                     continue;\r
+                   }\r
+                 if (!cppReader_isTraditional (pfile))\r
+                   {\r
+                     cpp_setLocation (pfile);\r
+\r
+                     setLine (long_toInt (start_line));\r
+                     setColumn (long_toInt (start_column));\r
+\r
+                     if (pfile->multiline_string_line != long_toInt (start_line)\r
+                         && pfile->multiline_string_line != 0)\r
+                       {\r
+                         genppllerrorhint\r
+                           (FLG_PREPROC,\r
+                            message ("Unterminated string or character constant"),\r
+                            message ("%q: Possible real start of unterminated constant",\r
+                                     fileloc_unparseRaw \r
+                                     (fileloc_filename (g_currentloc),\r
+                                      pfile->multiline_string_line)));\r
+                         pfile->multiline_string_line = 0;\r
+                       }\r
+                     else\r
+                       {\r
+                         genppllerror\r
+                           (FLG_PREPROC,\r
+                            message ("Unterminated string or character constant"));\r
+                       }\r
+                   }\r
+                 /*@loopbreak@*/ break;\r
+               }\r
+             cppReader_putChar (pfile, cc);\r
+             switch (cc)\r
+               {\r
+               case '\n':\r
+                 /* Traditionally, end of line ends a string constant with\r
+                    no error.  So exit the loop and record the new line.  */\r
+                 if (cppReader_isTraditional (pfile))\r
+                   goto while2end;\r
+                 if (c == '\'')\r
+                   {\r
+                     goto while2end;\r
+                   }\r
+                 if (cppReader_isPedantic (pfile)\r
+                     && pfile->multiline_string_line == 0)\r
+                   {\r
+                     cppReader_pedwarnWithLine\r
+                       (pfile, long_toInt (start_line),\r
+                        long_toInt (start_column),\r
+                        cstring_makeLiteral ("String constant runs past end of line"));\r
+                   }\r
+                 if (pfile->multiline_string_line == 0)\r
+                   {\r
+                     pfile->multiline_string_line = start_line;\r
+                   }\r
+\r
+                 /*@switchbreak@*/ break;\r
+\r
+               case '\\':\r
+                 cc = cppReader_getC (pfile);\r
+                 if (cc == '\n')\r
+                   {\r
+                     /* Backslash newline is replaced by nothing at all.  */\r
+                     cppReader_adjustWritten (pfile, -1);\r
+                     pfile->lineno++;\r
+                   }\r
+                 else\r
+                   {\r
+                     /* ANSI stupidly requires that in \\ the second \\r
+                        is *not* prevented from combining with a newline.  */\r
+                     NEWLINE_FIX1(cc);\r
+                     if (cc != EOF)\r
+                       cppReader_putChar (pfile, cc);\r
+                   }\r
+                 /*@switchbreak@*/ break;\r
+\r
+               case '\"':\r
+               case '\'':\r
+                 if (cc == c)\r
+                   goto while2end;\r
+                 /*@switchbreak@*/ break;\r
+               }\r
+           }\r
+       while2end:\r
+         pfile->lineno += count_newlines (pfile->token_buffer + old_written,\r
+                                          cppReader_getPWritten (pfile));\r
+         pfile->only_seen_white = 0;\r
+         return c == '\'' ? CPP_CHAR : CPP_STRING;\r
+\r
+       case '$':\r
+         if (!opts->dollars_in_ident)\r
+           goto randomchar;\r
+         goto letter;\r
+\r
+       case ':':\r
+         if (opts->cplusplus && cppReader_peekC (pfile) == ':')\r
+           goto op2;\r
+         goto randomchar;\r
+\r
+       case '&':\r
+       case '+':\r
+       case '|':\r
+         NEWLINE_FIX;\r
+         c2 = cppReader_peekC (pfile);\r
+         if (c2 == c || c2 == '=')\r
+           goto op2;\r
+         goto randomchar;\r
+\r
+       case '*':\r
+       case '!':\r
+       case '%':\r
+       case '=':\r
+       case '^':\r
+         NEWLINE_FIX;\r
+         if (cppReader_peekC (pfile) == '=')\r
+           goto op2;\r
+         goto randomchar;\r
+\r
+       case '-':\r
+         NEWLINE_FIX;\r
+         c2 = cppReader_peekC (pfile);\r
+         if (c2 == '-' && opts->chill)\r
+           {\r
+             /* Chill style comment */\r
+             if (opts->put_out_comments)\r
+               {\r
+                 parseSetMark (&start_mark, pfile);\r
+               }\r
+\r
+             cppReader_forward (pfile, 1);  /* Skip second '-'.  */\r
+\r
+             for (;;)\r
+               {\r
+                 c = cppReader_getC (pfile);\r
+                 if (c == EOF)\r
+                   /*@loopbreak@*/ break;\r
+                 if (c == '\n')\r
+                   {\r
+                     /* Don't consider final '\n' to be part of comment.  */\r
+                     cppReader_forward (pfile, -1);\r
+                     /*@loopbreak@*/ break;\r
+                   }\r
+               }\r
+             c = '-';\r
+             goto return_comment;\r
+           }\r
+         if (c2 == '-' || c2 == '=' || c2 == '>')\r
+           goto op2;\r
+         goto randomchar;\r
+\r
+       case '<':\r
+         if (pfile->parsing_include_directive)\r
+           {\r
+             for (;;)\r
+               {\r
+                 cppReader_putChar (pfile, c);\r
+                 if (c == '>')\r
+                   /*@loopbreak@*/ break;\r
+                 c = cppReader_getC (pfile);\r
+                 NEWLINE_FIX1 (c);\r
+                 if (c == '\n' || c == EOF)\r
+                   {\r
+                     cppReader_errorLit (pfile,\r
+                                   cstring_makeLiteralTemp ("Missing '>' in \"#include <FILENAME>\""));\r
+                     /*@loopbreak@*/ break;\r
+                   }\r
+               }\r
+             return CPP_STRING;\r
+           }\r
+         /*@fallthrough@*/\r
+       case '>':\r
+         NEWLINE_FIX;\r
+         c2 = cppReader_peekC (pfile);\r
+         if (c2 == '=')\r
+           goto op2;\r
+         if (c2 != c)\r
+           goto randomchar;\r
+         cppReader_forward (pfile, 1);\r
+         cppReader_reserve (pfile, 4);\r
+         cppReader_putChar (pfile, c);\r
+         cppReader_putChar (pfile, c2);\r
+         NEWLINE_FIX;\r
+         c3 = cppReader_peekC (pfile);\r
+         if (c3 == '=')\r
+           cppReader_putCharQ (pfile, cppReader_getC (pfile));\r
+         cppReader_nullTerminateQ (pfile);\r
+         pfile->only_seen_white = 0;\r
+         return CPP_OTHER;\r
+\r
+       case '@':\r
+         if (cppReader_getBuffer (pfile)->has_escapes)\r
+           {\r
+             c = cppReader_getC (pfile);\r
+             if (c == '-')\r
+               {\r
+                 if (pfile->output_escapes)\r
+                   cppReader_puts (pfile, "@-", 2);\r
+                 parse_name (pfile, cppReader_getC (pfile));\r
+                 return CPP_NAME;\r
+               }\r
+             else if (is_space [c])\r
+               {\r
+                 cppReader_reserve (pfile, 2);\r
+                 if (pfile->output_escapes)\r
+                   cppReader_putCharQ (pfile, '@');\r
+                 cppReader_putCharQ (pfile, c);\r
+                 return CPP_HSPACE;\r
+               }\r
+             else\r
+               {\r
+                 ;\r
+               }\r
+           }\r
+         if (pfile->output_escapes)\r
+           {\r
+             cppReader_puts (pfile, "@@", 2);\r
+             return CPP_OTHER;\r
+           }\r
+         goto randomchar;\r
+       case '.':\r
+         NEWLINE_FIX;\r
+         c2 = cppReader_peekC (pfile);\r
+         if (isdigit(c2))\r
+           {\r
+             cppReader_reserve(pfile, 2);\r
+             cppReader_putCharQ (pfile, '.');\r
+             c = cppReader_getC (pfile);\r
+             goto number;\r
+           }\r
+\r
+         /* FIXME - misses the case "..\\\n." */\r
+         if (c2 == '.' && cpp_peekN (pfile, 1) == '.')\r
+           {\r
+             cppReader_reserve(pfile, 4);\r
+             cppReader_putCharQ (pfile, '.');\r
+             cppReader_putCharQ (pfile, '.');\r
+             cppReader_putCharQ (pfile, '.');\r
+             cppReader_forward (pfile, 2);\r
+             cppReader_nullTerminateQ (pfile);\r
+             pfile->only_seen_white = 0;\r
+             return CPP_3DOTS;\r
+           }\r
+         goto randomchar;\r
+       op2:\r
+         token = CPP_OTHER;\r
+         pfile->only_seen_white = 0;\r
+        op2any:\r
+         cppReader_reserve(pfile, 3);\r
+         cppReader_putCharQ (pfile, c);\r
+         cppReader_putCharQ (pfile, cppReader_getC (pfile));\r
+         cppReader_nullTerminateQ (pfile);\r
+         return token;\r
+\r
+       case 'L':\r
+         NEWLINE_FIX;\r
+         c2 = cppReader_peekC (pfile);\r
+         if ((c2 == '\'' || c2 == '\"') && !cppReader_isTraditional (pfile))\r
+           {\r
+             cppReader_putChar (pfile, c);\r
+             c = cppReader_getC (pfile);\r
+             goto string;\r
+           }\r
+         goto letter;\r
+\r
+       case '0': case '1': case '2': case '3': case '4':\r
+       case '5': case '6': case '7': case '8': case '9':\r
+       number:\r
+         c2  = '.';\r
+         for (;;)\r
+           {\r
+             cppReader_reserve (pfile, 2);\r
+             cppReader_putCharQ (pfile, c);\r
+             NEWLINE_FIX;\r
+             c = cppReader_peekC (pfile);\r
+             if (c == EOF)\r
+               /*@loopbreak@*/ break;\r
+             if (!is_idchar[c] && c != '.'\r
+                 && ((c2 != 'e' && c2 != 'E'\r
+                      && ((c2 != 'p' && c2 != 'P') || cppReader_isC89 (pfile)))\r
+                     || (c != '+' && c != '-')))\r
+               /*@loopbreak@*/ break;\r
+             cppReader_forward (pfile, 1);\r
+             c2= c;\r
+           }\r
+\r
+         cppReader_nullTerminateQ (pfile);\r
+         pfile->only_seen_white = 0;\r
+         return CPP_NUMBER;\r
+\r
+       case 'b': case 'c': case 'd': case 'h': case 'o':\r
+       case 'B': case 'C': case 'D': case 'H': case 'O':\r
+         if (opts->chill && cppReader_peekC (pfile) == '\'')\r
+           {\r
+             pfile->only_seen_white = 0;\r
+             cppReader_reserve (pfile, 2);\r
+             cppReader_putCharQ (pfile, c);\r
+             cppReader_putCharQ (pfile, '\'');\r
+             cppReader_forward (pfile, 1);\r
+             for (;;)\r
+               {\r
+                 c = cppReader_getC (pfile);\r
+                 if (c == EOF)\r
+                   goto chill_number_eof;\r
+                 if (!is_idchar[c])\r
+                   {\r
+                     if (c == '\\' && cppReader_peekC (pfile) == '\n')\r
+                       {\r
+                         cppReader_forward (pfile, 2);\r
+                         continue;\r
+                       }\r
+                     /*@loopbreak@*/ break;\r
+                   }\r
+                 cppReader_putChar (pfile, c);\r
+               }\r
+             if (c == '\'')\r
+               {\r
+                 cppReader_reserve (pfile, 2);\r
+                 cppReader_putCharQ (pfile, c);\r
+                 cppReader_nullTerminateQ (pfile);\r
+                 return CPP_STRING;\r
+               }\r
+             else\r
+               {\r
+                 cppReader_forward (pfile, -1);\r
+               chill_number_eof:\r
+                 cppReader_nullTerminate (pfile);\r
+                 return CPP_NUMBER;\r
+               }\r
+           }\r
+         else\r
+           goto letter;\r
+       case '_':\r
+       case 'a': case 'e': case 'f': case 'g': case 'i': case 'j':\r
+       case 'k': case 'l': case 'm': case 'n': case 'p': case 'q':\r
+       case 'r': case 's': case 't': case 'u': case 'v': case 'w':\r
+       case 'x': case 'y': case 'z':\r
+       case 'A': case 'E': case 'F': case 'G': case 'I': case 'J':\r
+       case 'K': case 'M': case 'N': case 'P': case 'Q': case 'R':\r
+       case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':\r
+       case 'Y': case 'Z':\r
+        letter:\r
+          {\r
+           hashNode hp;\r
+           char *ident;\r
+           size_t before_name_written = cppReader_getWritten (pfile);\r
+           int ident_len;\r
+           parse_name (pfile, c);\r
+           pfile->only_seen_white = 0;\r
+           if (pfile->no_macro_expand)\r
+             {\r
+               return CPP_NAME;\r
+             }\r
+\r
+           ident = pfile->token_buffer + before_name_written;\r
+           ident_len = (cppReader_getPWritten (pfile)) - ident;\r
+\r
+           hp = cppReader_lookupExpand (ident, ident_len, -1);\r
+\r
+           if (hp == NULL)\r
+             {\r
+               return CPP_NAME;\r
+             }\r
+\r
+           if (hp->type == T_DISABLED)\r
+             {\r
+               if (pfile->output_escapes)\r
+                 { /* Return "@-IDENT", followed by '\0'.  */\r
+                   int i;\r
+                   cppReader_reserve (pfile, 3);\r
+                   ident = pfile->token_buffer + before_name_written;\r
+                   cppReader_adjustWritten (pfile, 2);\r
+\r
+                   for (i = ident_len; i >= 0; i--)\r
+                     {\r
+                       ident[i+2] = ident[i];\r
+                     }\r
+\r
+                   ident[0] = '@';\r
+                   ident[1] = '-';\r
+                 }\r
+               return CPP_NAME;\r
+             }\r
+\r
+           /* If macro wants an arglist, verify that a '(' follows.\r
+              first skip all whitespace, copying it to the output\r
+              after the macro name.  Then, if there is no '(',\r
+              decide this is not a macro call and leave things that way.  */\r
+\r
+           if (hp->type == T_MACRO && hp->value.defn->nargs >= 0)\r
+             {\r
+               struct parse_marker macro_mark;\r
+               int is_macro_call;\r
+\r
+               while (cppBuffer_isMacro (CPPBUFFER (pfile)))\r
+                 {\r
+                   cppBuffer *next_buf;\r
+                   cppSkipHspace (pfile);\r
+                   if (cppReader_peekC (pfile) != EOF)\r
+                     {\r
+                       /*@loopbreak@*/ break;\r
+                     }\r
+\r
+                 next_buf = cppBuffer_prevBuffer (cppReader_getBuffer (pfile));\r
+                 (*cppReader_getBuffer (pfile)->cleanup) (cppReader_getBuffer (pfile), pfile);\r
+                 CPPBUFFER (pfile) = next_buf;\r
+                 }\r
+\r
+               parseSetMark (&macro_mark, pfile);\r
+\r
+               for (;;)\r
+                 {\r
+                   cppSkipHspace (pfile);\r
+                   c = cppReader_peekC (pfile);\r
+                   is_macro_call = c == '(';\r
+                   if (c != '\n')\r
+                     /*@loopbreak@*/ break;\r
+                   cppReader_forward (pfile, 1);\r
+                 }\r
+\r
+               if (!is_macro_call)\r
+                 {\r
+                   parseGotoMark (&macro_mark, pfile);\r
+                 }\r
+\r
+               parseClearMark (&macro_mark);\r
+\r
+               if (!is_macro_call)\r
+                 {\r
+                   return CPP_NAME;\r
+                 }\r
+             }\r
+           /* This is now known to be a macro call.  */\r
+\r
+           /* it might not actually be a macro.  */\r
+           if (hp->type != T_MACRO)\r
+             {\r
+               size_t xbuf_len;\r
+               char *xbuf;\r
+\r
+               cppReader_setWritten (pfile, before_name_written);\r
+               special_symbol (hp, pfile);\r
+               xbuf_len = cppReader_getWritten (pfile) - before_name_written;\r
+               xbuf = (char *) dmalloc (xbuf_len + 1);\r
+               cppReader_setWritten (pfile, before_name_written);\r
+               memcpy (xbuf, cppReader_getPWritten (pfile), xbuf_len + 1);\r
+               push_macro_expansion (pfile, xbuf, xbuf_len, hp);\r
+             }\r
+           else\r
+             {\r
+               /* Expand the macro, reading arguments as needed,\r
+                  and push the expansion on the input stack.  */\r
+                               macroexpand (pfile, hp);\r
+               cppReader_setWritten (pfile, before_name_written);\r
+             }\r
+\r
+           /* An extra "@ " is added to the end of a macro expansion\r
+              to prevent accidental token pasting.  We prefer to avoid\r
+              unneeded extra spaces (for the sake of cpp-using tools like\r
+              imake).  Here we remove the space if it is safe to do so.  */\r
+\r
+           llassert (pfile->buffer->rlimit != NULL);\r
+\r
+           if (pfile->buffer->rlimit - pfile->buffer->cur >= 3\r
+               && pfile->buffer->rlimit[-2] == '@'\r
+               && pfile->buffer->rlimit[-1] == ' ')\r
+             {\r
+               int c1 = pfile->buffer->rlimit[-3];\r
+               int cl2 = cppBufPeek (cppBuffer_prevBuffer (CPPBUFFER (pfile)));\r
+\r
+               if (cl2 == EOF || !unsafe_chars ((char) c1, (char) cl2))\r
+                 pfile->buffer->rlimit -= 2;\r
+             }\r
+         }\r
+         goto get_next;\r
+\r
+\r
+       case ' ':  case '\t':  case '\v':  case '\r':\r
+         for (;;)\r
+           {\r
+             cppReader_putChar (pfile, c);\r
+             c = cppReader_peekC (pfile);\r
+             if (c == EOF || !is_hor_space[c])\r
+               /*@loopbreak@*/ break;\r
+             cppReader_forward (pfile, 1);\r
+           }\r
+         return CPP_HSPACE;\r
+\r
+        case '\\':\r
+         c2 = cppReader_peekC (pfile);\r
+         if (c2 != '\n')\r
+           goto randomchar;\r
+         token = CPP_HSPACE;\r
+         goto op2any;\r
+\r
+       case '\n':\r
+         cppReader_putChar (pfile, c);\r
+         if (pfile->only_seen_white == 0)\r
+           pfile->only_seen_white = 1;\r
+         pfile->lineno++;\r
+         output_line_command (pfile, 1, same_file);\r
+         return CPP_VSPACE;\r
+\r
+       case '(': token = CPP_LPAREN;    goto char1;\r
+       case ')': token = CPP_RPAREN;    goto char1;\r
+       case '{': token = CPP_LBRACE;    goto char1;\r
+       case '}': token = CPP_RBRACE;    goto char1;\r
+       case ',': token = CPP_COMMA;     goto char1;\r
+       case ';': token = CPP_SEMICOLON; goto char1;\r
+\r
+       randomchar:\r
+       default:\r
+         token = CPP_OTHER;\r
+       char1:\r
+         pfile->only_seen_white = 0;\r
+         cppReader_putChar (pfile, c);\r
+         return token;\r
+       }\r
+    }\r
+\r
+  BADBRANCH;\r
+  /*@notreached@*/\r
+}\r
+\r
+/* Parse an identifier starting with C.  */\r
+\r
+void\r
+parse_name (cppReader *pfile, int c)\r
+{\r
+  for (;;)\r
+    {\r
+      if (!is_idchar[c])\r
+       {\r
+         if (c == '\\' && cppReader_peekC (pfile) == '\n')\r
+           {\r
+             cppReader_forward (pfile, 2);\r
+             continue;\r
+           }\r
+\r
+         cppReader_forward (pfile, -1);\r
+         break;\r
+       }\r
+\r
+      if (c == '$' && cppReader_isPedantic (pfile))\r
+       {\r
+         cppReader_pedwarnLit (pfile,\r
+                         cstring_makeLiteralTemp ("`$' in identifier"));\r
+       }\r
+\r
+      cppReader_reserve(pfile, 2); /* One more for final NUL.  */\r
+      cppReader_putCharQ (pfile, c);\r
+      c = cppReader_getC (pfile);\r
+\r
+      if (c == EOF)\r
+       break;\r
+    }\r
+\r
+  cppReader_nullTerminateQ (pfile);\r
+}\r
+\r
+/* The file_name_map structure holds a mapping of file names for a\r
+   particular directory.  This mapping is read from the file named\r
+   FILE_NAME_MAP_FILE in that directory.  Such a file can be used to\r
+   map filenames on a file system with severe filename restrictions,\r
+   such as DOS.  The format of the file name map file is just a series\r
+   of lines with two tokens on each line.  The first token is the name\r
+   to map, and the second token is the actual name to use.  */\r
+\r
+struct file_name_map\r
+{\r
+  struct file_name_map *map_next;\r
+  cstring map_from;\r
+  cstring map_to;\r
+};\r
+\r
+/*@constant observer char *FILE_NAME_MAP_FILE*/\r
+#define FILE_NAME_MAP_FILE "header.gcc"\r
+\r
+/* Read a space delimited string of unlimited length from a stdio\r
+   file.  */\r
+\r
+static cstring read_filename_string (int ch, /*:open:*/ FILE *f)\r
+{\r
+  char *alloc, *set;\r
+  size_t len;\r
+\r
+  len = 20;\r
+  set = alloc = dmalloc (len + 1);\r
+\r
+  if (!is_space[ch])\r
+    {\r
+      *set++ = ch;\r
+      while ((ch = getc (f)) != EOF && ! is_space[ch])\r
+       {\r
+         if (set - alloc == size_toInt (len))\r
+           {\r
+             len *= 2;\r
+             alloc = drealloc (alloc, len + 1);\r
+             set = alloc + len / 2;\r
+             /*@-branchstate@*/ }\r
+\r
+         *set++ = ch;\r
+       } /*@=branchstate@*/\r
+    }\r
+  *set = '\0';\r
+  check (ungetc (ch, f) != EOF);\r
+\r
+  return cstring_fromChars (alloc);\r
+}\r
+\r
+/* This structure holds a linked list of file name maps, one per directory.  */\r
+\r
+struct file_name_map_list\r
+{\r
+  struct file_name_map_list *map_list_next;\r
+  cstring map_list_name;\r
+  struct file_name_map *map_list_map;\r
+};\r
+\r
+/* Read the file name map file for DIRNAME.  */\r
+\r
+static struct file_name_map *\r
+read_name_map (cppReader *pfile, cstring dirname)\r
+{\r
+  struct file_name_map_list *map_list_ptr;\r
+  cstring name;\r
+  FILE *f;\r
+\r
+  for (map_list_ptr = CPPOPTIONS (pfile)->map_list;\r
+       map_list_ptr != NULL;\r
+       map_list_ptr = map_list_ptr->map_list_next)\r
+    {\r
+      if (cstring_equal (map_list_ptr->map_list_name, dirname))\r
+       {\r
+         return map_list_ptr->map_list_map;\r
+       }\r
+    }\r
+\r
+  map_list_ptr = (struct file_name_map_list *) dmalloc (sizeof (*map_list_ptr));\r
+  map_list_ptr->map_list_name = cstring_copy (dirname);\r
+  map_list_ptr->map_list_map = NULL;\r
+\r
+  name = cstring_copy (dirname);\r
+\r
+  if (cstring_length (dirname) > 0)\r
+    {\r
+      name = cstring_appendChar (name, CONNECTCHAR);\r
+    }\r
+\r
+  name = cstring_concatFree1 (name, cstring_makeLiteralTemp (FILE_NAME_MAP_FILE));\r
+\r
+  f = fileTable_openFile (context_fileTable (), name, "r");\r
+  cstring_free (name);\r
+\r
+  if (f == NULL)\r
+    {\r
+      map_list_ptr->map_list_map = NULL;\r
+    }\r
+  else\r
+    {\r
+      int ch;\r
+\r
+      while ((ch = getc (f)) != EOF)\r
+       {\r
+         cstring from, to;\r
+         struct file_name_map *ptr;\r
+\r
+         if (is_space[ch])\r
+           {\r
+             continue;\r
+           }\r
+\r
+         from = read_filename_string (ch, f);\r
+         while ((ch = getc (f)) != EOF && is_hor_space[ch])\r
+           {\r
+             ;\r
+           }\r
+\r
+         to = read_filename_string (ch, f);\r
+\r
+         ptr = (struct file_name_map *) dmalloc (sizeof (*ptr));\r
+         ptr->map_from = from;\r
+\r
+         /* Make the real filename absolute.  */\r
+         if (cstring_length (to) > 1 \r
+             && osd_isConnectChar (cstring_firstChar (to)))\r
+           {\r
+             ptr->map_to = to;\r
+           }\r
+         else\r
+           {\r
+             ptr->map_to = cstring_copy (dirname);\r
+             ptr->map_to = cstring_appendChar (ptr->map_to, CONNECTCHAR);\r
+             ptr->map_to = cstring_concatFree (ptr->map_to, to);\r
+           }\r
+\r
+         ptr->map_next = map_list_ptr->map_list_map;\r
+         map_list_ptr->map_list_map = ptr;\r
+\r
+         while ((ch = getc (f)) != '\n')\r
+           {\r
+             if (ch == EOF)\r
+               {\r
+                 /*@innerbreak@*/ break;\r
+               }\r
+           }\r
+       }\r
+\r
+      assertSet (map_list_ptr->map_list_map);\r
+      check (fileTable_closeFile (context_fileTable (),f) == 0);\r
+    }\r
+\r
+  map_list_ptr->map_list_next = pfile->opts->map_list;\r
+  pfile->opts->map_list = map_list_ptr;\r
+\r
+  return map_list_ptr->map_list_map;\r
+}\r
+\r
+/* Try to open include file FILENAME.  SEARCHPTR is the directory\r
+   being tried from the include file search path.  This function maps\r
+   filenames on file systems based on information read by\r
+   read_name_map.  */\r
+\r
+static int\r
+open_include_file (cppReader *pfile,\r
+                  cstring fname,\r
+                  struct file_name_list *searchptr)\r
+{\r
+  char *filename = cstring_toCharsSafe (fname);\r
+  struct file_name_map *map;\r
+  char *from;\r
+  char *p, *dir;\r
+\r
+  cstring_markOwned (fname);\r
+\r
+  cpp_setLocation (pfile);\r
+\r
+  if (context_getFlag (FLG_NEVERINCLUDE))\r
+    {\r
+      if (isHeaderFile (fname))\r
+       {\r
+         return SKIP_INCLUDE;\r
+       }\r
+    }\r
+\r
+  if ((searchptr != NULL) && ! searchptr->got_name_map)\r
+    {\r
+      searchptr->name_map = read_name_map (pfile,\r
+                                          !cstring_isEmpty (searchptr->fname)\r
+                                          ? searchptr->fname :\r
+                                          cstring_makeLiteralTemp ("."));\r
+      searchptr->got_name_map = 1;\r
+    }\r
+\r
+  /* First check the mapping for the directory we are using.  */\r
+\r
+  if ((searchptr != NULL)\r
+      && (searchptr->name_map != NULL))\r
+    {\r
+      from = filename;\r
+\r
+      if (!cstring_isEmpty (searchptr->fname))\r
+       {\r
+         from += cstring_length (searchptr->fname) + 1;\r
+       }\r
+\r
+      for (map = searchptr->name_map;\r
+          map != NULL;\r
+          map = map->map_next)\r
+       {\r
+         if (cstring_equal (map->map_from, cstring_fromChars (from)))\r
+           {\r
+             /*\r
+             ** Found a match.  Check if the file should be skipped\r
+             */\r
+             \r
+             if (cpp_skipIncludeFile (map->map_to))\r
+               {\r
+                 return SKIP_INCLUDE;\r
+               }\r
+             else\r
+               {\r
+                 return cpp_openIncludeFile (cstring_toCharsSafe (map->map_to));\r
+               }\r
+           }\r
+       }\r
+    }\r
+\r
+  /*\r
+  ** Try to find a mapping file for the particular directory we are\r
+  ** looking in.  Thus #include <sys/types.h> will look up sys/types.h\r
+  ** in /usr/include/header.gcc and look up types.h in\r
+  ** /usr/include/sys/header.gcc.\r
+  */\r
+\r
+  p = strrchr (filename, CONNECTCHAR);\r
+\r
+  if (p == NULL)\r
+    {\r
+      p = filename;\r
+    }\r
+\r
+  if ((searchptr != NULL)\r
+      && (cstring_isDefined (searchptr->fname))\r
+      && (cstring_length (searchptr->fname) == p - filename)\r
+      && !strncmp (cstring_toCharsSafe (searchptr->fname),\r
+                  filename,\r
+                  size_fromInt (p - filename)))\r
+    {\r
+      /* filename is in SEARCHPTR, which we've already checked.  */\r
+\r
+      if (cpp_skipIncludeFile (cstring_fromChars (filename)))\r
+       {\r
+         return SKIP_INCLUDE;\r
+       }\r
+      else\r
+       {\r
+         return cpp_openIncludeFile (filename);\r
+       }\r
+    }\r
+\r
+  if (p == filename)\r
+    {\r
+      dir = mstring_copy (".");\r
+      from = filename;\r
+    }\r
+  else\r
+    {\r
+      dir = (char *) dmalloc (size_fromInt (p - filename + 1));\r
+      memcpy (dir, filename, size_fromInt (p - filename));\r
+      dir[p - filename] = '\0';\r
+      from = p + 1;\r
+    }\r
+\r
+  for (map = read_name_map (pfile, cstring_fromChars (dir));\r
+       map != NULL;\r
+       map = map->map_next)\r
+    {\r
+      if (cstring_equal (map->map_from, cstring_fromChars (from)))\r
+       {\r
+         sfree (dir);\r
+\r
+         if (cpp_skipIncludeFile (map->map_to))\r
+           {\r
+             return SKIP_INCLUDE;\r
+           }\r
+         else\r
+           {\r
+             return cpp_openIncludeFile (cstring_toCharsSafe (map->map_to));\r
+           }\r
+       }\r
+    }\r
+\r
+  sfree (dir);\r
+\r
+  if (cpp_skipIncludeFile (cstring_fromChars (filename)))\r
+    {\r
+      return SKIP_INCLUDE;\r
+    }\r
+  else\r
+    {\r
+      return cpp_openIncludeFile (filename);\r
+    }\r
+}\r
+\r
+/* Process the contents of include file FNAME, already open on descriptor F,\r
+   with output to OP.\r
+   SYSTEM_HEADER_P is 1 if this file resides in any one of the known\r
+   "system" include directories (as decided by the `is_system_include'\r
+   function above).\r
+   DIRPTR is the link in the dir path through which this file was found,\r
+   or 0 if the file name was absolute or via the current directory.\r
+   Return 1 on success, 0 on failure.\r
+\r
+   The caller is responsible for the cppReader_pushBuffer.  */\r
+\r
+static int\r
+finclude (cppReader *pfile, int f,\r
+         cstring fname,\r
+         bool system_header_p,\r
+         /*@dependent@*/ struct file_name_list *dirptr)\r
+{\r
+  mode_t st_mode;\r
+  size_t st_size;\r
+  long i;\r
+  int length = 0;\r
+  cppBuffer *fp;                       /* For input stack frame */\r
+\r
+  if (file_size_and_mode (f, &st_mode, &st_size) < 0)\r
+    {\r
+      cppReader_perrorWithName (pfile, fname);\r
+      check (close (f) == 0);\r
+      (void) cppReader_popBuffer (pfile);\r
+      /*@-mustfree@*/\r
+      return 0;\r
+      /*@=mustfree@*/\r
+    }\r
+\r
+  fp = cppReader_getBuffer (pfile);\r
+\r
+  /*@-temptrans@*/ /* fname shouldn't really be temp */\r
+  fp->nominal_fname = fp->fname = fname;\r
+  /*@=temptrans@*/\r
+\r
+  fp->dir = dirptr;\r
+  fp->system_header_p = system_header_p;\r
+  fp->lineno = 1;\r
+  fp->colno = 1;\r
+  fp->cleanup = cppReader_fileCleanup;\r
+\r
+  if (S_ISREG (st_mode))\r
+    {\r
+      sfree (fp->buf);\r
+      fp->buf = (char *) dmalloc (st_size + 2);\r
+      fp->alimit = fp->buf + st_size + 2;\r
+      fp->cur = fp->buf;\r
+\r
+      /* Read the file contents, knowing that st_size is an upper bound\r
+        on the number of bytes we can read.  */\r
+      length = safe_read (f, fp->buf, size_toInt (st_size));\r
+      fp->rlimit = fp->buf + length;\r
+      if (length < 0) goto nope;\r
+    }\r
+  else if (S_ISDIR (st_mode))\r
+    {\r
+      cppReader_error (pfile,\r
+                      message ("Directory specified in #include: %s", fname));\r
+      check (close (f) == 0);\r
+      return 0;\r
+    }\r
+  else\r
+    {\r
+      /*\r
+      ** Cannot count its file size before reading.\r
+      ** First read the entire file into heap and\r
+      ** copy them into buffer on stack.\r
+      */\r
+\r
+      size_t bsize = 2000;\r
+\r
+      st_size = 0;\r
+\r
+      sfree (fp->buf);\r
+      fp->buf = (char *) dmalloc (bsize + 2);\r
+\r
+      for (;;) {\r
+       i = safe_read (f, fp->buf + st_size, size_toInt (bsize - st_size));\r
+\r
+       if (i < 0)\r
+         goto nope;      /* error! */\r
+       st_size += i;\r
+\r
+       if (st_size != bsize)\r
+         {\r
+           break;      /* End of file */\r
+         }\r
+\r
+       bsize *= 2;\r
+       fp->buf = (char *) drealloc (fp->buf, bsize + 2);\r
+      }\r
+\r
+      fp->cur = fp->buf;\r
+      length = size_toInt (st_size);\r
+    }\r
+\r
+  if ((length > 0 && fp->buf[length - 1] != '\n')\r
+      /* Backslash-newline at end is not good enough.  */\r
+      || (length > 1 && fp->buf[length - 2] == '\\')) {\r
+    fp->buf[length++] = '\n';\r
+  }\r
+\r
+  fp->buf[length] = '\0';\r
+  fp->rlimit = fp->buf + length;\r
+\r
+  /* Close descriptor now, so nesting does not use lots of descriptors.  */\r
+  check (close (f) == 0);\r
+\r
+  /* Must do this before calling trigraph_pcp, so that the correct file name\r
+     will be printed in warning messages.  */\r
+\r
+  pfile->input_stack_listing_current = 0;\r
+  return 1;\r
+\r
+ nope:\r
+\r
+  cppReader_perrorWithName (pfile, fname);\r
+  check (close (f) == 0);\r
+  sfree (fp->buf);\r
+  return 1;\r
+}\r
+\r
+void\r
+cppReader_init (cppReader *pfile)\r
+{\r
+  memset ((char *) pfile, 0, sizeof (*pfile));\r
+\r
+  pfile->get_token = cppGetToken;\r
+  pfile->token_buffer_size = 200;\r
+  pfile->token_buffer = (char *) dmalloc (pfile->token_buffer_size);\r
+  pfile->all_include_files = NULL;\r
+\r
+  assertSet (pfile);\r
+\r
+  cppReader_setWritten (pfile, 0);\r
+\r
+  pfile->system_include_depth = 0;\r
+  pfile->max_include_len = 0;\r
+  pfile->timebuf = NULL;\r
+  pfile->only_seen_white = 1;\r
+\r
+  pfile->buffer = cppReader_nullBuffer (pfile);\r
+}\r
+\r
+void\r
+cppReader_finish (/*@unused@*/ cppReader *pfile)\r
+{\r
+  ;\r
+}\r
+\r
+/* Free resources used by PFILE.\r
+   This is the cppReader 'finalizer' or 'destructor' (in C++ terminology).  */\r
+\r
+void\r
+cppCleanup (cppReader *pfile)\r
+{\r
+  while (CPPBUFFER (pfile) != cppReader_nullBuffer (pfile))\r
+    {\r
+      (void) cppReader_popBuffer (pfile);\r
+    }\r
+\r
+  if (pfile->token_buffer != NULL)\r
+    {\r
+      sfree (pfile->token_buffer);\r
+      pfile->token_buffer = NULL;\r
+    }\r
+\r
+  while (pfile->if_stack != NULL)\r
+    {\r
+      cppIfStackFrame *temp = pfile->if_stack;\r
+      pfile->if_stack = temp->next;\r
+      sfree (temp);\r
+    }\r
+\r
+  while (pfile->all_include_files != NULL)\r
+    {\r
+      struct file_name_list *temp = pfile->all_include_files;\r
+      pfile->all_include_files = temp->next;\r
+      /*@-dependenttrans@*/\r
+      cstring_free (temp->fname);\r
+      /*@=dependenttrans@*/\r
+      sfree (temp);\r
+    }\r
+\r
+  cppReader_hashCleanup ();\r
+}\r
+\r
+/*\r
+** Get the file-mode and data size of the file open on FD\r
+** and store them in *MODE_POINTER and *SIZE_POINTER.\r
+*/\r
+\r
+static int\r
+file_size_and_mode (int fd, mode_t *mode_pointer, size_t *size_pointer)\r
+{\r
+  struct stat sbuf;\r
+\r
+  if (fstat (fd, &sbuf) < 0) {\r
+    return (-1);\r
+  }\r
+\r
+  if (mode_pointer != NULL)\r
+    {\r
+      *mode_pointer = sbuf.st_mode;\r
+    }\r
+\r
+  if (size_pointer != NULL)\r
+    {\r
+      *size_pointer = (size_t) sbuf.st_size;\r
+    }\r
+\r
+  return 0;\r
+}\r
+\r
+/* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,\r
+   retrying if necessary.  Return a negative value if an error occurs,\r
+   otherwise return the actual number of bytes read,\r
+   which must be LEN unless end-of-file was reached.  */\r
+\r
+static int safe_read (int desc, char *ptr, int len)\r
+{\r
+  int left = len;\r
+\r
+  while (left > 0)\r
+    {\r
+# if defined (WIN32) || defined (OS2) && defined (__IBMC__)\r
+         /*@-compdef@*/ /* ptr is an out parameter */\r
+      int nchars = _read (desc, ptr, (unsigned) left);\r
+         /*@=compdef@*/\r
+# else\r
+      ssize_t nchars = read (desc, ptr, size_fromInt (left));\r
+# endif\r
+\r
+      if (nchars < 0)\r
+       {\r
+#ifdef EINTR\r
+         if (errno == EINTR)\r
+           continue;\r
+#endif\r
+         return (int) nchars;\r
+       }\r
+\r
+      if (nchars == 0) {\r
+       break;\r
+      }\r
+\r
+      ptr += nchars;\r
+      left -= nchars;\r
+    }\r
+\r
+  return len - left;\r
+}\r
+\r
+/* Initialize PMARK to remember the current position of PFILE.  */\r
+\r
+void\r
+parseSetMark (struct parse_marker *pmark, cppReader *pfile)\r
+{\r
+  cppBuffer *pbuf = cppReader_getBuffer (pfile);\r
+\r
+  pmark->next = pbuf->marks;\r
+  /*@-temptrans@*/\r
+  pbuf->marks = pmark;\r
+  /*@=temptrans@*/\r
+\r
+  pmark->buf = pbuf;\r
+  pmark->position = pbuf->cur - pbuf->buf;\r
+}\r
+\r
+/* Cleanup PMARK - we no longer need it.  */\r
+\r
+void parseClearMark (struct parse_marker *pmark)\r
+{\r
+  struct parse_marker **pp = &pmark->buf->marks;\r
+\r
+  for (; ; pp = &(*pp)->next)\r
+    {\r
+      llassert (*pp != NULL);\r
+      if (*pp == pmark) break;\r
+    }\r
+\r
+  *pp = pmark->next;\r
+}\r
+\r
+/* Backup the current position of PFILE to that saved in PMARK.  */\r
+\r
+void\r
+parseGotoMark (struct parse_marker *pmark, cppReader *pfile)\r
+{\r
+  cppBuffer *pbuf = cppReader_getBuffer (pfile);\r
+\r
+  if (pbuf != pmark->buf)\r
+    {\r
+      cpp_setLocation (pfile);\r
+      llfatalbug (cstring_makeLiteral ("Internal error parseGotoMark"));\r
+    }\r
+\r
+  llassert (pbuf->buf != NULL);\r
+  pbuf->cur = pbuf->buf + pmark->position;\r
+}\r
+\r
+/* Reset PMARK to point to the current position of PFILE.  (Same\r
+   as parseClearMark (PMARK), parseSetMark (PMARK, PFILE) but faster.  */\r
+\r
+void\r
+parseMoveMark (struct parse_marker *pmark, cppReader *pfile)\r
+{\r
+  cppBuffer *pbuf = cppReader_getBuffer (pfile);\r
+\r
+  if (pbuf != pmark->buf)\r
+    {\r
+      cpp_setLocation (pfile);\r
+      llfatalerror (cstring_makeLiteral ("Internal error parseMoveMark"));\r
+    }\r
+\r
+  pmark->position = pbuf->cur - pbuf->buf;\r
+}\r
+\r
+void cppReader_initializeReader (cppReader *pfile) /* Must be done after library is loaded. */\r
+{\r
+  struct cppOptions *opts = CPPOPTIONS (pfile);\r
+  cstring xp;\r
+\r
+  /* The code looks at the defaults through this pointer, rather than through\r
+     the constant structure above.  This pointer gets changed if an environment\r
+     variable specifies other defaults.  */\r
+\r
+  struct default_include *include_defaults = include_defaults_array;\r
+\r
+  /* Add dirs from INCLUDEPATH_VAR after dirs from -I.  */\r
+  /* There seems to be confusion about what CPATH should do,\r
+     so for the moment it is not documented.  */\r
+  /* Some people say that CPATH should replace the standard include dirs,\r
+     but that seems pointless: it comes before them, so it overrides them\r
+     anyway.  */\r
+\r
+  xp = osd_getEnvironmentVariable (INCLUDEPATH_VAR);\r
+\r
+  if (cstring_isDefined (xp) && !opts->no_standard_includes)\r
+    {\r
+      path_include (pfile, cstring_toCharsSafe (xp));\r
+    }\r
+\r
+  /* Now that dollars_in_ident is known, initialize is_idchar.  */\r
+  initialize_char_syntax (opts);\r
+\r
+  /* CppReader_Install __LINE__, etc.  Must follow initialize_char_syntax\r
+     and option processing.  */\r
+\r
+  initialize_builtins (pfile);\r
+\r
+  /* Do standard #defines and assertions\r
+     that identify system and machine type.  */\r
+\r
+  if (!opts->inhibit_predefs) {\r
+    char *p = (char *) dmalloc (strlen (predefs) + 1);\r
+    strcpy (p, predefs);\r
+\r
+    while (*p)\r
+      {\r
+       char *q;\r
+\r
+       while (*p == ' ' || *p == '\t')\r
+         {\r
+           p++;\r
+         }\r
+\r
+       /* Handle -D options.  */\r
+       if (p[0] == '-' && p[1] == 'D')\r
+         {\r
+           q = &p[2];\r
+\r
+           while (*p && *p != ' ' && *p != '\t')\r
+             {\r
+               p++;\r
+             }\r
+\r
+           if (*p != 0)\r
+             {\r
+               *p++= 0;\r
+             }\r
+\r
+           if (opts->debug_output)\r
+             {\r
+               output_line_command (pfile, 0, same_file);\r
+             }\r
+\r
+           cppReader_define (pfile, q);\r
+\r
+           while (*p == ' ' || *p == '\t')\r
+             {\r
+               p++;\r
+             }\r
+         }\r
+       else\r
+         {\r
+           abort ();\r
+         }\r
+      }\r
+\r
+    sfree (p);\r
+  }\r
+\r
+  opts->done_initializing = 1;\r
+\r
+  { /* Read the appropriate environment variable and if it exists\r
+       replace include_defaults with the listed path.  */\r
+    char *epath = 0;\r
+#ifdef __CYGWIN32__\r
+  char *win32epath;\r
+  int win32_buf_size = 0; /* memory we need to allocate */\r
+#endif\r
+\r
+  if (opts->cplusplus)\r
+    {\r
+      epath = getenv ("CPLUS_INCLUDE_PATH");\r
+    }\r
+  else\r
+    {\r
+      epath = getenv ("C_INCLUDE_PATH");\r
+    }\r
+\r
+  /*\r
+  ** If the environment var for this language is set,\r
+  ** add to the default list of include directories.\r
+  */\r
+\r
+    if (epath != NULL) {\r
+      char *nstore = (char *) dmalloc (strlen (epath) + 2);\r
+      int num_dirs;\r
+      char *startp, *endp;\r
+\r
+#ifdef __CYGWIN32__\r
+      /* if we have a posix path list, convert to win32 path list */\r
+      if (cygwin32_posix_path_list_p (epath))\r
+        {\r
+          win32_buf_size = cygwin32_posix_to_win32_path_list_buf_size (epath);\r
+          win32epath = (char *) dmalloc /*@i4@*/ (win32_buf_size);\r
+          cygwin32_posix_to_win32_path_list (epath, win32epath);\r
+          epath = win32epath;\r
+        }\r
+#endif\r
+      for (num_dirs = 1, startp = epath; *startp; startp++)\r
+       {\r
+         if (*startp == PATH_SEPARATOR)\r
+           num_dirs++;\r
+       }\r
+\r
+      /*@-sizeoftype@*/\r
+      include_defaults\r
+       = (struct default_include *) dmalloc ((num_dirs\r
+                                              * sizeof (struct default_include))\r
+                                             + sizeof (include_defaults_array));\r
+      /*@=sizeoftype@*/\r
+\r
+      startp = endp = epath;\r
+      num_dirs = 0;\r
+      while (1) {\r
+        /* Handle cases like c:/usr/lib:d:/gcc/lib */\r
+        if ((*endp == PATH_SEPARATOR) || *endp == 0)\r
+         {\r
+           strncpy (nstore, startp, size_fromInt (endp - startp));\r
+           if (endp == startp)\r
+             {\r
+               strcpy (nstore, ".");\r
+             }\r
+           else\r
+             {\r
+               nstore[endp-startp] = '\0';\r
+             }\r
+\r
+           include_defaults[num_dirs].fname = cstring_fromCharsNew (nstore);\r
+           include_defaults[num_dirs].cplusplus = opts->cplusplus;\r
+           include_defaults[num_dirs].cxx_aware = 1;\r
+           num_dirs++;\r
+\r
+           if (*endp == '\0')\r
+             {\r
+               break;\r
+             }\r
+           endp = startp = endp + 1;\r
+         }\r
+       else\r
+         {\r
+           endp++;\r
+         }\r
+      }\r
+      /* Put the usual defaults back in at the end.  */\r
+      memcpy ((char *) &include_defaults[num_dirs],\r
+             (char *) include_defaults_array,\r
+             sizeof (include_defaults_array));\r
+\r
+      sfree (nstore);\r
+      /*@-branchstate@*/ } /*@=branchstate@*/\r
+  }\r
+\r
+  cppReader_appendIncludeChain (pfile, opts->before_system,\r
+                               opts->last_before_system);\r
+  opts->first_system_include = opts->before_system;\r
+\r
+  /* Unless -fnostdinc,\r
+     tack on the standard include file dirs to the specified list */\r
+  if (!opts->no_standard_includes) {\r
+    struct default_include *p = include_defaults;\r
+    char *specd_prefix = opts->include_prefix;\r
+    char *default_prefix = mstring_copy (GCC_INCLUDE_DIR);\r
+    int default_len = 0;\r
+\r
+       /* Remove the `include' from /usr/local/lib/gcc.../include.  */\r
+       if (default_prefix != NULL) {\r
+    if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) {\r
+      default_len = strlen (default_prefix) - 7;\r
+      default_prefix[default_len] = 0;\r
+    }\r
+       }\r
+\r
+    /* Search "translated" versions of GNU directories.\r
+       These have /usr/local/lib/gcc... replaced by specd_prefix.  */\r
+    if (specd_prefix != 0 && default_len != 0)\r
+      for (p = include_defaults; p->fname != NULL; p++) {\r
+       /* Some standard dirs are only for C++.  */\r
+       if (!p->cplusplus\r
+           || (opts->cplusplus && !opts->no_standard_cplusplus_includes)) {\r
+         /* Does this dir start with the prefix?  */\r
+         if (!strncmp (cstring_toCharsSafe (p->fname), default_prefix,\r
+                       size_fromInt (default_len)))\r
+           {\r
+             /* Yes; change prefix and add to search list.  */\r
+             struct file_name_list *nlist\r
+               = (struct file_name_list *) dmalloc (sizeof (*nlist));\r
+             size_t this_len = strlen (specd_prefix) + cstring_length (p->fname) - default_len;\r
+             char *str = (char *) dmalloc (this_len + 1);\r
+             strcpy (str, specd_prefix);\r
+             strcat (str, cstring_toCharsSafe (p->fname) + default_len);\r
+\r
+             nlist->next = NULL;\r
+             nlist->fname = cstring_fromChars (str);\r
+             nlist->control_macro = 0;\r
+             nlist->c_system_include_path = !p->cxx_aware;\r
+             nlist->got_name_map = 0;\r
+\r
+             cppReader_addIncludeChain (pfile, nlist);\r
+             if (opts->first_system_include == 0)\r
+               {\r
+                 opts->first_system_include = nlist;\r
+               }\r
+           }\r
+       }\r
+      }\r
+\r
+    /* Search ordinary names for GNU include directories.  */\r
+\r
+    for (p = include_defaults; p->fname != NULL; p++)\r
+      {\r
+       /* Some standard dirs are only for C++.  */\r
+       if (!p->cplusplus\r
+           || (opts->cplusplus && !opts->no_standard_cplusplus_includes))\r
+         {\r
+           struct file_name_list *nlist\r
+             = (struct file_name_list *) dmalloc (sizeof (*nlist));\r
+           nlist->control_macro = 0;\r
+           nlist->c_system_include_path = !p->cxx_aware;\r
+           nlist->fname = p->fname;\r
+           nlist->got_name_map = 0;\r
+           nlist->next = NULL;\r
+\r
+           cppReader_addIncludeChain (pfile, nlist);\r
+\r
+           if (opts->first_system_include == 0)\r
+             {\r
+               opts->first_system_include = nlist;\r
+             }\r
+         }\r
+      }\r
+    sfree (default_prefix);\r
+  }\r
+\r
+  /* Tack the after_include chain at the end of the include chain.  */\r
+  cppReader_appendIncludeChain (pfile, opts->after_include,\r
+                               opts->last_after_include);\r
+\r
+  if (opts->first_system_include == 0)\r
+    {\r
+      opts->first_system_include = opts->after_include;\r
+    }\r
+\r
+  /* With -v, print the list of dirs to search.  */\r
+  if (opts->verbose) {\r
+    struct file_name_list *p;\r
+    fprintf (stderr, "#include \"...\" search starts here:\n");\r
+\r
+    for (p = opts->include; p != NULL; p = p->next) {\r
+      if (p == opts->first_bracket_include)\r
+       fprintf (stderr, "#include <...> search starts here:\n");\r
+\r
+      fprintf (stderr, " %s\n", cstring_toCharsSafe (p->fname));\r
+    }\r
+    fprintf (stderr, "End of search list.\n");\r
+  }\r
+}\r
+\r
+int cppReader_startProcess (cppReader *pfile, cstring fname)\r
+{\r
+  cppBuffer *fp;\r
+  int f;\r
+  struct cppOptions *opts = CPPOPTIONS (pfile);\r
+\r
+  fp = cppReader_pushBuffer (pfile, NULL, 0);\r
+\r
+  if (fp == NULL)\r
+    {\r
+      return 0;\r
+    }\r
+\r
+  if (opts->in_fname == NULL)\r
+    {\r
+      opts->in_fname = cstring_makeLiteralTemp ("");\r
+    }\r
+\r
+  fp->fname = opts->in_fname;\r
+  fp->nominal_fname = fp->fname;\r
+  fp->lineno = 0;\r
+\r
+  /* Copy the entire contents of the main input file into\r
+     the stacked input buffer previously allocated for it.  */\r
+\r
+  if (cstring_isEmpty (fname))\r
+    {\r
+      fname = cstring_makeLiteralTemp ("");\r
+      f = 0;\r
+    }\r
+  else if ((f = open (cstring_toCharsSafe (fname), O_RDONLY, 0666)) < 0)\r
+    {\r
+      cppReader_error (pfile,\r
+                      message ("Error opening %s for reading: %s",\r
+                               fname, lldecodeerror (errno)));\r
+\r
+      return 0;\r
+    }\r
+  else\r
+    {\r
+      ;\r
+    }\r
+\r
+  if (finclude (pfile, f, fname, 0, NULL))\r
+    {\r
+      output_line_command (pfile, 0, same_file);\r
+    }\r
+\r
+  return 1;\r
+}\r
+\r
+static /*@exposed@*/ /*@null@*/ cppBuffer *cppReader_getBuffer (cppReader *pfile)\r
+{\r
+  return pfile->buffer;\r
+}\r
+\r
+/*@exposed@*/ cppBuffer *cppReader_getBufferSafe (cppReader *pfile)\r
+{\r
+  llassert (pfile->buffer != NULL);\r
+  return pfile->buffer;\r
+}\r
+\r
+/*@exposed@*/ char *cppLineBase (cppBuffer *buf)\r
+{\r
+  llassert (buf->buf != NULL);\r
+  return (buf->buf + buf->line_base);\r
+}\r
+\r
+int cppBufPeek (cppBuffer *buf)\r
+{\r
+  if (buf->cur == NULL || buf->rlimit == NULL) {\r
+    return EOF;\r
+  }\r
+\r
+  if (buf->cur < buf->rlimit) {\r
+    return *(buf->cur);\r
+  }\r
+\r
+  return EOF;\r
+}\r
+\r
+bool cppBuffer_isMacro (cppBuffer *buf)\r
+{\r
+  if (buf != NULL)\r
+    {\r
+      return (buf->cleanup == cppReader_macroCleanup);\r
+    }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/*\r
+** Returns true if the macro should be checked, false\r
+** if it should be expanded normally.\r
+*/\r
+\r
+static bool notparseable = FALSE;  /* preceeded by @notparseable@ */\r
+static bool notfunction = FALSE;   /* preceeded by @notfunction@ */\r
+static bool expectiter = FALSE;    /* preceeded by @iter@ */\r
+static bool expectenditer = FALSE; /* second after @iter@ */\r
+static bool expectfunction = FALSE;    /* preceeded by @function@ */\r
+static bool expectconstant = FALSE;   /* preceeded by @constant@ */\r
+static bool expectmacro = FALSE;   /* preceeded by notfunction or notparseable */\r
+\r
+static void cpp_setLocation (cppReader *pfile)\r
+{\r
+  fileId fid;\r
+  int line;\r
+\r
+  if (pfile->buffer != NULL)\r
+    {\r
+      if (cstring_isDefined (cppReader_getBuffer (pfile)->nominal_fname))\r
+       {\r
+         cstring fname = cppReader_getBuffer (pfile)->nominal_fname;\r
+         \r
+         DPRINTF (("Looking up: %s", fname));\r
+         \r
+         if (fileTable_exists (context_fileTable (), fname))\r
+           {\r
+             fid = fileTable_lookup (context_fileTable (), fname);\r
+           }\r
+         else\r
+           {\r
+             DPRINTF (("Trying %s", cppReader_getBuffer (pfile)->fname));\r
+\r
+             fid = fileTable_lookup (context_fileTable (),\r
+                                     cppReader_getBuffer (pfile)->fname);\r
+           }\r
+       }\r
+      else\r
+       {\r
+         fid = fileTable_lookup (context_fileTable (),\r
+                                 cppReader_getBuffer (pfile)->fname);\r
+       }\r
+      \r
+      line = cppReader_getBuffer (pfile)->lineno;\r
+      fileloc_free (g_currentloc);\r
+\r
+      if (fileId_isValid (fid))\r
+       {\r
+         g_currentloc = fileloc_create (fid, line, 1);\r
+       }\r
+      else\r
+       {\r
+         g_currentloc = fileloc_createBuiltin ();\r
+       }\r
+    }\r
+  else\r
+    {\r
+      fileloc_free (g_currentloc);\r
+      g_currentloc = fileloc_createBuiltin ();\r
+    }\r
+}\r
+\r
+static bool cpp_shouldCheckMacro (cppReader *pfile, char *p) /*@*/\r
+{\r
+  bool checkmacro = FALSE;\r
+  bool hasParams = FALSE;\r
+  bool noexpand = FALSE;\r
+  cstring sname;\r
+  char c;\r
+\r
+  cpp_setLocation (pfile);\r
+\r
+  DPRINTF (("Should check macro? %s", p));\r
+\r
+  if (expectiter || expectconstant || expectenditer)\r
+    {\r
+      if (expectiter)\r
+       {\r
+         expectiter = FALSE;\r
+         expectenditer = TRUE;\r
+       }\r
+      else\r
+       {\r
+         expectiter = FALSE;\r
+         expectconstant = FALSE;\r
+         expectenditer = FALSE;\r
+       }\r
+\r
+      if (notfunction || notparseable)\r
+       {\r
+         notfunction = FALSE;\r
+         notparseable = FALSE;\r
+         return FALSE;\r
+       }\r
+      else\r
+       {\r
+         return TRUE;\r
+       }\r
+    }\r
+\r
+  llassert (*p == '#');\r
+  p++;\r
+\r
+  while (*p == ' ' || *p == '\t')\r
+    {\r
+      p++;\r
+    }\r
+\r
+  llassert (*p == 'd'); /* define starts */\r
+\r
+  p += 6;\r
+\r
+  while (*p == ' ' || *p == '\t')\r
+    {\r
+      p++;\r
+    }\r
+\r
+  sname = cstring_fromChars (p);\r
+  DPRINTF (("Check macro: %s", sname));\r
+\r
+  while (((c = *p) != ' ')\r
+        && c != '\0' && c != '('\r
+        && c != '\t' && c != '\\' && c != '\n'\r
+        && !iscntrl (c))\r
+    {\r
+      p++;\r
+    }\r
+\r
+  hasParams = (c == '(');\r
+  *p = '\0';\r
+\r
+\r
+  if (notparseable)\r
+    {\r
+      notparseable = FALSE;\r
+    }\r
+  else if (notfunction || fileloc_isStandardLib (g_currentloc))\r
+    {\r
+      DPRINTF (("Clear notfunction"));\r
+      notfunction = FALSE;\r
+    }\r
+  else\r
+    {\r
+      if (noexpand)\r
+       {\r
+         checkmacro = TRUE;\r
+\r
+         if (!expectenditer)\r
+           {\r
+             noexpand = FALSE;\r
+           }\r
+       }\r
+      else\r
+       {\r
+         if (usymtab_existsReal (sname))\r
+           {\r
+             uentry ue = usymtab_lookup (sname);\r
+\r
+             DPRINTF (("Lookup macro: %s", uentry_unparse (ue)));\r
+\r
+             if (fileloc_isPreproc (uentry_whereLast (ue)))\r
+               {\r
+                 goto macroDne;\r
+               }\r
+             else\r
+               {\r
+                 if (uentry_isSpecified (ue))\r
+                   {\r
+                     checkmacro = context_getFlag (FLG_SPECMACROS);\r
+                   }\r
+                 else\r
+                   {\r
+                     if (hasParams)\r
+                       {\r
+                         checkmacro = context_getFlag (FLG_LIBMACROS)\r
+                           || context_getFlag (FLG_FCNMACROS);\r
+                       }\r
+                   }\r
+               }\r
+           }\r
+         else\r
+           {\r
+           macroDne:\r
+             DPRINTF (("Macro doesn't exist: %s", bool_unparse (checkmacro)));\r
+\r
+             if (fileloc_isSystemFile (g_currentloc)\r
+                 && context_getFlag (FLG_SYSTEMDIREXPAND))\r
+               {\r
+                 ; /* don't check this macro */\r
+                 DPRINTF (("Don't check 1"));\r
+               }\r
+             else\r
+               {\r
+                 uentry le;\r
+                 \r
+                 if (hasParams)\r
+                   {\r
+                     DPRINTF (("Has params..."));\r
+\r
+                     if (context_getFlag (FLG_FCNMACROS))\r
+                       {\r
+                         if (usymtab_exists (sname))\r
+                           {\r
+                              /*\r
+                             ** only get here is macro is redefined\r
+                             ** error reported elsewhere\r
+                             */\r
+\r
+                             DPRINTF (("It exists!"));\r
+                           }\r
+                         else\r
+                           {\r
+                             /*\r
+                             ** We make it a forward function, since it might be declared elsewhere.\r
+                             ** After all headers have been processed, we should check the forward\r
+                             ** functions.\r
+                             */\r
+\r
+                             fileloc loc = fileloc_makePreproc (g_currentloc);\r
+\r
+                             /* the line is off-by-one, since the newline was already read */\r
+                             decLine ();\r
+\r
+                             if (expectfunction)\r
+                               {\r
+                                 expectfunction = FALSE;\r
+                               }\r
+\r
+                             le = uentry_makeForwardFunction (sname,\r
+                                                              typeId_invalid, loc);\r
+\r
+                             fileloc_free (loc);\r
+\r
+                             incLine ();\r
+\r
+                             /* Do not define here! */\r
+\r
+                             (void) usymtab_addEntry (le);\r
+                           }\r
+\r
+                         checkmacro = TRUE;\r
+                         DPRINTF (("Check: TRUE"));\r
+                       }\r
+                     else \r
+                       {\r
+                         DPRINTF (("Flag FCN_MACROS not set!"));\r
+                       }\r
+                   }\r
+                 else\r
+                   {\r
+                     DPRINTF (("No params"));\r
+\r
+                     if (context_getFlag (FLG_CONSTMACROS))\r
+                       {\r
+                         bool nocontent = FALSE;\r
+\r
+                         if (c == '\0')\r
+                           {\r
+                             nocontent = TRUE;\r
+                           }\r
+                         else\r
+                           {\r
+                             if (isspace (c))\r
+                               {\r
+                                 char *rest = p + 1;\r
+\r
+                                 /*\r
+                                 ** Check if there is nothing after the define.\r
+                                 */\r
+\r
+                                 while ((*rest) != '\0' && isspace (*rest))\r
+                                   {\r
+                                     rest++;\r
+                                   }\r
+\r
+                                 if (*rest == '\0')\r
+                                   {\r
+                                     nocontent = TRUE; /* empty macro, don't check */\r
+                                   }\r
+                               }\r
+                           }\r
+\r
+                         if (usymtab_exists (sname))\r
+                           {\r
+                             ;\r
+                           }\r
+                         else\r
+                           {\r
+                             fileloc loc = fileloc_makePreproc (g_currentloc);\r
+                             DPRINTF (("Make constant: %s", sname));\r
+                             le = uentry_makeConstant (sname,\r
+                                                       ctype_unknown, loc);\r
+                             (void) usymtab_addEntry (le);\r
+                           }\r
+\r
+                         checkmacro = !nocontent;\r
+                       }\r
+                   }\r
+               }\r
+\r
+             if (checkmacro && usymtab_existsType (sname))\r
+               {\r
+                 DPRINTF (("Making false..."));\r
+                 decLine ();\r
+                 ppllerror (message ("Specified type implemented as macro: %s", sname));\r
+                 checkmacro = FALSE;\r
+                 incLine ();\r
+               }\r
+           }\r
+       }\r
+    }\r
+\r
+  if (!checkmacro)\r
+    {\r
+      if (usymtab_exists (sname))\r
+       {\r
+         uentry ue = usymtab_lookupExpose (sname);\r
+         fileloc tloc = fileloc_makePreproc (g_currentloc);\r
+\r
+         uentry_setDefined (ue, tloc);\r
+         fileloc_free (tloc);\r
+         uentry_setUsed (ue, fileloc_undefined);\r
+       }\r
+      else\r
+       {\r
+         fileloc tloc = fileloc_makePreproc (g_currentloc);\r
+         uentry ue = uentry_makeExpandedMacro (sname, tloc);\r
+         DPRINTF (("Make expanded macro: %s", sname));\r
+         DPRINTF (("Not in symbol table: %s", sname));\r
+         \r
+         (void) usymtab_addGlobalEntry (ue);\r
+         fileloc_free (tloc);\r
+       }\r
+    }\r
+\r
+  *p = c;\r
+  DPRINTF (("Returning: %s", bool_unparse (checkmacro)));\r
+  return checkmacro;\r
+}\r
+\r
+static enum cpp_token\r
+cpp_handleComment (cppReader *pfile, struct parse_marker *smark)\r
+{\r
+  cppBuffer *pbuf = cppReader_getBuffer (pfile);\r
+  char *start;\r
+  int len;\r
+  bool eliminateComment = FALSE;\r
+\r
+  llassert (pbuf->buf != NULL);\r
+\r
+  start = pbuf->buf + smark->position;\r
+\r
+  llassert (pbuf->cur != NULL);\r
+  len = pbuf->cur - start;\r
+\r
+  if (start[0] == '*'\r
+      && start[1] == context_getCommentMarkerChar ())\r
+    {\r
+      int i;\r
+      char c = ' ';\r
+      char *scomment = start + 2;\r
+      char savec = start[len];\r
+\r
+      start[0] = BEFORE_COMMENT_MARKER[0];\r
+      start[1] = BEFORE_COMMENT_MARKER[1];\r
+\r
+      llassert (start[len - 2] == '*');\r
+      start[len - 2] = AFTER_COMMENT_MARKER[0];\r
+\r
+      llassert (start[len - 1] == '/');\r
+      start[len - 1] = AFTER_COMMENT_MARKER[1];\r
+\r
+      cppReader_reserve(pfile, size_fromInt (1 + len));\r
+      cppReader_putCharQ (pfile, c);\r
+\r
+      cpp_setLocation (pfile);\r
+\r
+      start[len] = '\0';\r
+\r
+      if (mstring_containsString (scomment, "/*"))\r
+       {\r
+         (void) cppoptgenerror \r
+           (FLG_NESTCOMMENT,\r
+            message ("Comment starts inside syntactic comment: %s", \r
+                     cstring_fromChars (scomment)),\r
+            pfile);\r
+       }\r
+\r
+      start[len] = savec;\r
+\r
+      if (mstring_equalPrefix (scomment, "ignore"))\r
+       {\r
+         if (!context_getFlag (FLG_NOCOMMENTS))\r
+           {\r
+             context_enterSuppressRegion ();\r
+           }\r
+       }\r
+      else if (mstring_equalPrefix (scomment, "end"))\r
+       {\r
+         if (!context_getFlag (FLG_NOCOMMENTS))\r
+           {\r
+             context_exitSuppressRegion ();\r
+           }\r
+       }\r
+      else if (mstring_equalPrefix (scomment, "notparseable"))\r
+       {\r
+         notparseable = TRUE;\r
+         expectmacro = TRUE;\r
+         eliminateComment = TRUE;\r
+       }\r
+      else if (mstring_equalPrefix (scomment, "notfunction"))\r
+       {\r
+         notfunction = TRUE;\r
+         expectmacro = TRUE;\r
+         eliminateComment = TRUE;\r
+       }\r
+      else if (mstring_equalPrefix (scomment, "iter"))\r
+       {\r
+         expectiter = TRUE;\r
+       }\r
+      else if (mstring_equalPrefix (scomment, "function"))\r
+       {\r
+         expectfunction = TRUE;\r
+       }\r
+      else if (mstring_equalPrefix (scomment, "constant"))\r
+       {\r
+         expectconstant = TRUE;\r
+       }\r
+      else\r
+       {\r
+         char sChar = *scomment;\r
+\r
+         if (sChar == '='\r
+             || sChar == '-'\r
+             || sChar == '+')\r
+           {\r
+             char *rest = scomment + 1;\r
+\r
+             if (mstring_equalPrefix (rest, "commentchar"))\r
+               {\r
+                 eliminateComment = TRUE;\r
+\r
+                 if (sChar == '=')\r
+                   {\r
+                     ppllerror (cstring_makeLiteral\r
+                                ("Cannot restore commentchar"));\r
+                   }\r
+                 else\r
+                   {\r
+                     char *next = scomment + 12; /* strlen commentchar = 12 */\r
+\r
+                     if (*next != ' ' && *next != '\t' && *next != '\n')\r
+                       {\r
+                         ppllerror\r
+                           (message\r
+                            ("Syntactic commentchar comment is not followed by a "\r
+                             "whitespace character: %c",\r
+                             *next));\r
+                       }\r
+                     else\r
+                       {\r
+                         char cchar = *(next + 1);\r
+\r
+                         if (cchar == '\0')\r
+                           {\r
+                             ppllerror\r
+                               (cstring_makeLiteral\r
+                                ("Cannot set commentchar to NUL"));\r
+                           }\r
+                         else\r
+                           {\r
+                             context_setCommentMarkerChar (cchar);\r
+                             /* setComment = TRUE; */\r
+                           }\r
+                       }\r
+                   }\r
+               }\r
+             else if (mstring_equalPrefix (scomment, "nestcomment"))\r
+               {\r
+                 /* fix from Mike Miller <MikeM@xata.com> */\r
+                 context_fileSetFlag (FLG_NESTCOMMENT,\r
+                                      ynm_fromCodeChar (sChar));\r
+               }\r
+             else if (mstring_equalPrefix (rest, "namechecks"))\r
+               {\r
+                 context_fileSetFlag (FLG_NAMECHECKS,\r
+                                      ynm_fromCodeChar (sChar));\r
+               }\r
+             else if (mstring_equalPrefix (rest, "macroredef"))\r
+               {\r
+                 context_fileSetFlag (FLG_MACROREDEF,\r
+                                      ynm_fromCodeChar (sChar));\r
+               }\r
+             else if (mstring_equalPrefix (rest, "usevarargs"))\r
+               {\r
+                 context_fileSetFlag (FLG_USEVARARGS,\r
+                                      ynm_fromCodeChar (sChar));\r
+               }\r
+             else if (mstring_equalPrefix (rest, "nextlinemacros"))\r
+               {\r
+                 context_fileSetFlag (FLG_MACRONEXTLINE,\r
+                                      ynm_fromCodeChar (sChar));\r
+               }\r
+             else if (mstring_equalPrefix (rest, "allmacros")\r
+                      || mstring_equalPrefix (rest, "fcnmacros")\r
+                      || mstring_equalPrefix (rest, "constmacros"))\r
+               {\r
+                 flagcode fl;\r
+\r
+                 if (mstring_equalPrefix (rest, "allmacros"))\r
+                   {\r
+                     fl = FLG_ALLMACROS;\r
+                   }\r
+                 else if (mstring_equalPrefix (rest, "fcnmacros"))\r
+                   {\r
+                     fl = FLG_FCNMACROS;\r
+                   }\r
+                 else\r
+                   {\r
+                     llassert (mstring_equalPrefix (rest, "constmacros"));\r
+                     fl = FLG_CONSTMACROS;\r
+                   }\r
+\r
+\r
+                 context_fileSetFlag (fl, ynm_fromCodeChar (sChar));\r
+                 notfunction = FALSE;\r
+               }\r
+             else\r
+               {\r
+                 ;\r
+               }\r
+           }\r
+         else\r
+           {\r
+             ;\r
+           }\r
+       }\r
+\r
+      if (eliminateComment)\r
+       {\r
+         goto removeComment;\r
+       }\r
+\r
+      /* Replaces comment char's in start with spaces */\r
+\r
+      for (i = 2; i < len - 2; i++)\r
+       {\r
+         if (start[i] == BEFORE_COMMENT_MARKER[0]\r
+             || start[i] == BEFORE_COMMENT_MARKER[1]\r
+             || start[i] == context_getCommentMarkerChar ())\r
+           {\r
+             start[i] = ' ';\r
+           }\r
+       }\r
+\r
+      cppReader_putStrN (pfile, start, size_fromInt (len));\r
+      parseClearMark (smark);\r
+      return CPP_COMMENT;\r
+    }\r
+  else\r
+    {\r
+    removeComment:\r
+      {\r
+       int i;\r
+\r
+       /*\r
+       ** Output the comment as all spaces so line/column\r
+       ** in output file is still correct.\r
+       */\r
+\r
+       char c = ' ';\r
+       cstring lintcomment = cstring_undefined;\r
+\r
+       if (context_getFlag (FLG_LINTCOMMENTS))\r
+         {\r
+           if (mstring_equalPrefix (start, "*NOTREACHED*/"))\r
+             {\r
+               lintcomment = cstring_makeLiteralTemp ("l_notreach");\r
+             }\r
+           else if (mstring_equalPrefix (start, "*PRINTFLIKE*/"))\r
+             {\r
+               lintcomment = cstring_makeLiteralTemp ("l_printfli");\r
+             }\r
+           else if (mstring_equalPrefix (start, "*FALLTHROUGH*/"))\r
+             {\r
+               lintcomment = cstring_makeLiteralTemp ("l_fallthrou");\r
+             }\r
+           else if (mstring_equalPrefix (start, "*ARGSUSED*/"))\r
+             {\r
+               lintcomment = cstring_makeLiteralTemp ("l_argsus");\r
+             }\r
+           else if (mstring_equalPrefix (start, "*FALLTHRU*/"))\r
+             {\r
+               lintcomment = cstring_makeLiteralTemp ("l_fallth");\r
+             }\r
+           else\r
+             {\r
+               lintcomment = cstring_undefined;\r
+             }\r
+         }\r
+       else\r
+         {\r
+           lintcomment = cstring_undefined;\r
+         }\r
+\r
+       if (cstring_isDefined (lintcomment))\r
+         {\r
+           c = BEFORE_COMMENT_MARKER[0];\r
+           start[0] = BEFORE_COMMENT_MARKER[1];\r
+\r
+           llassert (cstring_length (lintcomment) == len - 3);\r
+\r
+           for (i = 1; i < len - 2; i++)\r
+             {\r
+               start[i] = cstring_getChar (lintcomment, i);\r
+             }\r
+           \r
+           start[len - 2] = AFTER_COMMENT_MARKER[0];\r
+           start[len - 1] = AFTER_COMMENT_MARKER[1];\r
+         }\r
+       else\r
+         {\r
+           /* Replaces  char's in start with spaces */\r
+           for (i = 0; i < len; i++)\r
+             {\r
+               if (start[i] == '/'\r
+                   && i < len - 1\r
+                   && start[i + 1] == '*') {\r
+                 (void) cppoptgenerror (FLG_NESTCOMMENT,\r
+                                        message ("Comment starts inside comment"),\r
+                                        pfile);\r
+               }\r
+               \r
+               if (start[i] != '\n')\r
+                 {\r
+                   start[i] = ' ';\r
+                 }\r
+             }\r
+         }\r
+\r
+       cppReader_reserve (pfile, size_fromInt (1 + len));\r
+       cppReader_putCharQ (pfile, c);\r
+       cppReader_putStrN (pfile, start, size_fromInt (len));\r
+       parseClearMark (smark);\r
+       return CPP_COMMENT;\r
+      }\r
+    }\r
+}\r
+\r
+static int cpp_openIncludeFile (char *filename)\r
+{\r
+  int res = open (filename, O_RDONLY, 0666);\r
+\r
+  /* evans 2001-08-23: was (res) - open returns -1 on error! reported by Robin Watts */\r
+  if (res >= 0)\r
+    {\r
+      if (!fileTable_exists (context_fileTable (),\r
+                            cstring_fromChars (filename)))\r
+       {\r
+         (void) fileTable_addHeaderFile (context_fileTable (),\r
+                                         cstring_fromChars (filename));\r
+       }\r
+      else\r
+       {\r
+         DPRINTF (("File already exists: %s", filename));\r
+       }\r
+    }\r
+\r
+  return res;\r
+}\r
+\r
+static bool cpp_skipIncludeFile (cstring fname)\r
+{\r
+  if (context_isSystemDir (fname))\r
+    {\r
+      DPRINTF (("System dir: %s", fname));\r
+\r
+      if (lcllib_isSkipHeader (fname))\r
+       {\r
+         DPRINTF (("Skip include TRUE: %s", fname));\r
+         return TRUE;\r
+       }\r
+      \r
+      if (context_getFlag (FLG_SKIPSYSHEADERS))\r
+       {\r
+         DPRINTF (("Skip include TRUE: %s", fname));\r
+         return TRUE;\r
+       }\r
+    }\r
+\r
+  if (context_getFlag (FLG_SINGLEINCLUDE))\r
+    {\r
+      fname = removePreDirs (fname);\r
+\r
+# if defined (WIN32) || defined (OS2)\r
+      cstring_replaceAll (fname, '\\', '/');\r
+# endif\r
+\r
+      if (fileTable_exists (context_fileTable (), fname))\r
+       {\r
+         DPRINTF (("Skip include TRUE: %s", fname));\r
+         return TRUE;\r
+       }\r
+    }\r
+\r
+  DPRINTF (("Skip include FALSE: %s", fname));\r
+  return FALSE;\r
+}\r
+\r
+static int cpp_peekN (cppReader *pfile, int n)\r
+{\r
+  cppBuffer *buf = cppReader_getBuffer (pfile);\r
+\r
+  llassert (buf->cur != NULL);\r
+\r
+  return (buf->rlimit - buf->cur >= (n)\r
+         ? buf->cur[n]\r
+         : EOF);\r
+}\r
+\r
+cppBuffer *cppBuffer_prevBuffer (cppBuffer *buf)\r
+{\r
+  return buf + 1;\r
+}\r
+\r
+void cppBuffer_forward (cppBuffer *buf, int n)\r
+{\r
+  llassert (buf->cur != NULL);\r
+  buf->cur += n;\r
+}\r
This page took 1.164634 seconds and 4 git commands to generate.