]> andersk Git - splint.git/blobdiff - src/cpplib.c
noexpand always false.
[splint.git] / src / cpplib.c
index 8a069f098e4061b063e799cddd0c24acf743ad3c..a18e1218508ead358c1919c33bf3ae358f2ae465 100644 (file)
-/*\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
+/*
+** Splint - annotation-assisted static program checker
+** Copyright (C) 1994-2003 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 splint: info@splint.org
+** To report a bug: splint-bug@splint.org
+** For more information: http://www.splint.org
+*/
+/*
+** 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>
+/* SMF */
+# ifndef BCC32
+# include <sys/utime.h>                /* for __DATE__ and __TIME__ */
+# endif
+
+# include <time.h>
+# else
+# ifndef VMS
+/*
+** evans 2002-07-03: exception for WATCOM 10.6 compiler suggest by Adam Clarke 
+*/
+# if !defined (USG) && !defined (__WATCOMC__)
+# 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 "splintMacros.nf"
+# include "basic.h"
+# include "lcllib.h"
+# include "cpplib.h"
+# include "cpperror.h"
+# include "cpphash.h"
+# include "cppexp.h"
+# include "version.h"
+# include "osd.h"
+
+/*
+** This is really kludgey code...
+*/
+
+/*@+boolint@*/
+/*@+charint@*/
+
+/* Warnings for using sprintf - suppress them all for now... */
+/*@-bufferoverflowhigh@*/
+/*@-bounds@*/
+
+#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) /*@modifies p_p@*/ ;
+
+static size_t cppReader_checkMacroNameLoc (fileloc p_loc, char *p_symname, cstring p_usage) ;
+
+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)
+
+/*@function static int cppBuffer_reachedEOF (sef cppBuffer *p_b) modifies nothing; @*/
+# define cppBuffer_reachedEOF(b) \
+  ((b)->cur < (b)->rlimit ? FALSE : TRUE)
+
+/* 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) \
+  cpplib_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))
+/*
+static void cppReader_putCharQ (cppReader *p_file, char p_ch)
+{
+  fprintf (stderr, "put char: %c\n", p_ch);
+  (*(p_file)->limit++ = (p_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) (cpplib_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) \
+  (cpplib_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_reachedEOF (sef cppReader *p_pfile) modifies *p_pfile; @*/
+# define cppReader_reachedEOF(pfile)   (cppBuffer_reachedEOF (cppReader_getBufferSafe (pfile)))
+
+/*@function static int cppReader_peekC (cppReader *) modifies nothing;@*/
+# define cppReader_peekC(pfile)  (cpplib_bufPeek (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__)
+
+/* SMF */
+# ifndef BCC32
+/*
+** WIN32 (at least the VC++ include files) does not define mode_t.
+*/
+
+/*@-incondefs@*/ /*@-czechtypes@*/
+typedef unsigned int mode_t;
+/*@=incondefs@*/ /*@=czechtypes@*/
+# endif
+
+# 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 *, 
+                     /*@exposed@*/ char *, char *);
+static int do_defineAux (cppReader *, /*@null@*/ struct directive *,
+                        /*@exposed@*/ 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, NULL, "", 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 (cpplib_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 = cpplib_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) {
+       size_t 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, /*@only@*/ struct file_name_list *dir)
+{
+  struct cppOptions *opts = CPPOPTIONS (pfile);
+
+  if (dir == NULL)
+    {
+      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)
+    {
+      size_t 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;
+
+  /* Added 2003-07-10: */
+  opts->traditional = FALSE;
+  opts->c89 = TRUE;
+  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)
+    {
+      
+      (void) cppoptgenerror 
+       (FLG_SLASHSLASHCOMMENT,
+        message ("C++ style // comment" 
+                ),
+        pfile);
+      
+      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 '\\':
+         /*
+         ** Patch from Brian St. Pierre for handling MS-DOS files.
+         */
+
+         DPRINTF (("Reading directive: %d", (int) c));
+
+         if (cppReader_peekC (pfile) == '\n'
+             || cppReader_peekC (pfile) == '\r')
+           {
+             DPRINTF (("Reading directive..."));
+             if (cppReader_peekC (pfile) == '\r')
+               {
+                 DPRINTF (("Reading directive..."));
+                 cppReader_forward (pfile, 1);
+               }
+             
+             DPRINTF (("Reading directive..."));
+             cppReader_forward (pfile, 1);
+             continue;
+           }
+
+         DPRINTF (("Falling..."));
+       /*@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) cpplib_getToken (pfile);
+         continue;
+       }
+      cppReader_putChar (pfile, c);
+    }
+end_directive: ;
+  cppReader_nullTerminate (pfile);
+}
+
+void
+cppReader_skipRestOfLine (cppReader *pfile)
+{
+  size_t old = cpplib_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 = cpplib_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 = cpplib_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 = cpplib_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 = cpplib_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;
+
+  cpplib_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->expansion = '\0'; /* convince splint it is initialized */
+
+  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 cpplib_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;
+      size_t id_len;
+
+      --exp_p;
+      while (p != limit && is_idchar[(int) *p])
+       {
+         p++;
+       }
+
+      id_len = size_fromInt (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, 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; /* Spurious warning here */
+}
+
+/*
+** evans 2001-12-31
+** Gasp...cut-and-pasted from above to deal with pfile (should replace throughout with this...)
+*/
+
+static DEFINITION *
+collect_expansionLoc (fileloc loc, 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)
+    {
+      llfatalbug (message ("%q: Limit is less than initial buffer pointer",
+                          fileloc_unparse (loc)));
+    }
+
+  /* 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 cpplib_macroExpand).  */
+  *exp_p++ = '@';
+  *exp_p++ = ' ';
+
+  if (limit - p >= 2 && p[0] == '#' && p[1] == '#') {
+    voptgenerror (FLG_PREPROC,
+                 cstring_makeLiteral ("Paste marker ## at start of macro definition"),
+                 loc);
+    p += 2;
+  }
+
+  /* Process the main body of the definition.  */
+  while (p < limit) {
+    int skipped_arg = 0;
+    register char c = *p++;
+
+    *exp_p++ = c;
+
+    if (TRUE) { /* !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)
+           {
+               voptgenerror (FLG_PREPROC,
+                             cstring_makeLiteral ("`##' at end of macro definition"),
+                             loc);
+           }
+       } 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] == '\"')))
+           {
+               voptgenerror 
+                 (FLG_PREPROC,
+                  cstring_makeLiteral ("`#' operator is not followed by a macro argument name"),
+                  loc);
+           }
+         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;
+      size_t id_len;
+
+      --exp_p;
+      while (p != limit && is_idchar[(int) *p])
+       {
+         p++;
+       }
+
+      id_len = size_fromInt (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, id_len) == 0) {
+           char *p1;
+
+           if (expected_delimiter) { /* && CPPOPTIONS (pfile)->warn_stringify) { */
+             if (FALSE) { /* cppReader_isTraditional (pfile)) { */
+               voptgenerror (FLG_PREPROC,
+                             message ("macro argument `%x' is stringified.",
+                                      cstring_prefix (cstring_fromChars (arg->name), id_len)),
+                             loc);
+
+             } else {
+               voptgenerror (FLG_PREPROC,
+                             message ("Macro arg `%x' would be stringified with -traditional.",
+                                      cstring_prefix (cstring_fromChars (arg->name), id_len)),
+                             loc);
+               
+             }
+           }
+           /* If ANSI, don't actually substitute inside a string.  */
+           if (TRUE /* !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 = (FALSE /* 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)
+         {
+           voptgenerror
+             (FLG_PREPROC,
+              cstring_makeLiteral ("# operator should be followed by a macro argument name"),
+              loc);
+         }
+      }
+    }
+  }
+
+  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."));
+    }
+  
+  /*@-compdef@*/ /* defn->expansion defined? */
+  return defn; 
+  /*@=compdef@*/
+}
+
+/*
+ * 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 (/*@exposed@*/ char *buf, char *limit,
+                  cppReader *pfile, bool predefinition,
+                  bool noExpand)
+{
+  char *bp;                    /* temp ptr into input buffer */
+  char *symname;               /* remember where symbol name starts */
+  size_t 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;
+  char save = *limit;
+  *limit = '\0';
+  DPRINTF (("Create definition: %s", buf));
+  *limit = save;
+
+  cppBuffer_getLineAndColumn (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 = size_fromInt (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, 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, 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;
+}
+
+/*@null@*/ macroDef
+cpplib_createDefinition (cstring def,
+                        fileloc loc,
+                        bool predefinition,
+                        bool noExpand)
+{
+  char *buf = cstring_toCharsSafe (def);
+  char *limit = buf + cstring_length (def);
+  char *bp;                    /* temp ptr into input buffer */
+  char *symname;               /* remember where symbol name starts */
+  size_t sym_length;           /* and how long it is */
+  int rest_args = 0;   /* really int! */
+  int line = fileloc_lineno (loc);
+  cstring file = fileloc_filename (loc);
+  DEFINITION *defn;
+  int arglengths = 0;          /* Accumulate lengths of arg names
+                                  plus number of args.  */
+  macroDef mdef;
+
+  bp = buf;
+
+  DPRINTF (("Creating definition: %s", buf));
+
+  while (is_hor_space[(int) *bp])
+    {
+      bp++;
+    }
+
+  symname = bp;        /* remember where it starts */
+
+  sym_length = cppReader_checkMacroNameLoc (loc, symname, cstring_makeLiteralTemp ("macro"));
+
+  DPRINTF (("length: %d", sym_length));
+
+  bp += sym_length;
+
+  DPRINTF (("Here: %s", bp));
+
+  /* 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)
+         {
+           voptgenerror (FLG_PREPROC,
+                         message ("Another parameter follows %s",
+                                  cstring_fromChars (rest_extension)),
+                         loc);
+         }
+
+       if (!is_idstart[(int) *bp])
+         {
+           voptgenerror (FLG_PREPROC,
+                         message ("Invalid character in macro parameter name: %c", *bp),
+                         loc);
+         }
+
+       /* 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 = size_fromInt (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 != ')')) {
+         voptgenerror (FLG_PREPROC,
+                       cstring_makeLiteral ("Parameter list for #define is not parseable"),
+                       loc);
+         goto nope;
+       }
+
+       if (*bp == ',') {
+         bp++;
+         SKIP_WHITE_SPACE (bp);
+       }
+       if (bp >= limit) {
+         voptgenerror (FLG_PREPROC,
+                       cstring_makeLiteral ("Unterminated parameter list in #define'"),
+                       loc);
+         goto nope;
+       }
+       {
+         struct arglist *otemp;
+
+         for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
+           {
+             if (temp->length == otemp->length &&
+                 strncmp (temp->name, otemp->name, temp->length) == 0) {
+               cstring name = cstring_copyLength (temp->name, temp->length);
+
+               voptgenerror (FLG_PREPROC,
+                             message ("Duplicate argument name in #define: %s", name),
+                             loc);
+               goto nope;
+             }
+           }
+       }
+      }
+    
+    ++bp;                      /* skip paren */
+    SKIP_WHITE_SPACE (bp);
+    /* now everything from bp before limit is the definition.  */
+    defn = collect_expansionLoc (loc, 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, 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 '~':
+           voptgenerror (FLG_PREPROC,
+                         message ("Missing white space after #define %x",
+                                  cstring_prefix (cstring_fromChars (symname),
+                                                  sym_length)),
+                         loc);
+           break;
+
+         default:
+           voptgenerror (FLG_PREPROC,
+                         message ("Missing white space after #define %x",
+                                  cstring_prefix (cstring_fromChars (symname),
+                                                  sym_length)),
+                         loc);
+           break;
+         }
+       }
+      }
+
+    /* now everything from bp before limit is the definition.  */
+    llassert (limit > bp);
+    defn = collect_expansionLoc (loc, 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.  */
+
+size_t 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 sym_length;
+}
+  
+/*
+** evans 2001-12-31
+** Gasp...cut-and-pasted from above to deal with pfile (should replace throughout with this...)
+*/
+
+size_t cppReader_checkMacroNameLoc (fileloc loc, 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 == '\"')))
+    {
+      voptgenerror (FLG_PREPROC, message ("Invalid %s name: %s", usage, 
+                                         cstring_fromChars (symname)), loc);
+    }
+  else if (!is_idstart[(int) *symname])
+    {
+      char *msg = (char *) dmalloc (sym_length + 1);
+      memcpy (msg, symname, sym_length);
+      msg[sym_length] = '\0';
+      voptgenerror (FLG_PREPROC, message ("Invalid %s name: %s", usage, 
+                                         cstring_fromChars (msg)),
+                   loc);
+      sfree (msg);
+    }
+  else
+    {
+      if ((strncmp (symname, "defined", 7) == 0) && sym_length == 7)
+       {
+         voptgenerror (FLG_PREPROC, message ("Invalid %s name: defined", usage), loc);
+       }
+    }
+
+  return 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, size_toInt (d1->length - (p1 - d1->expansion)),
+                    p2, size_toInt (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,
+             /*@exposed@*/ char *buf, char *limit, bool noExpand)
+{
+  int hashcode;
+  macroDef mdef;
+  hashNode hp;
+
+  mdef = create_definition (buf, limit, pfile, keyword == NULL, noExpand);
+
+  if (mdef.defn == 0)
+    goto nope;
+
+  hashcode = cpphash_hashCode (mdef.symnam, mdef.symlen, CPP_HASHSIZE);
+
+  if ((hp = cpphash_lookup (mdef.symnam, size_toInt (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 {
+       ok = FALSE; /* Redefining anything else is bad. */
+      }
+
+      /* 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 = cpphash_installMacro (mdef.symnam, mdef.symlen, mdef.defn, hashcode);
+      /*@-branchstate@*/
+    } /*@=branchstate@*/
+
+  return 0;
+
+nope:
+  return 1;
+}
+
+static int
+do_define (cppReader *pfile, struct directive *keyword,
+          /*@exposed@*/ 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_getBufferSafe (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));
+  DPRINTF (("Pushing buffer: %s", cstring_copyLength (buffer, length)));
+  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 = cpplib_getToken (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 cpplib_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;
+
+  DPRINTF (("Expand to buffer: %s", cstring_copyLength (buf, length)));
+
+  /* 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_getLineAndColumn (/*@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)
+      {
+       cpplib_reserve (pfile, 20);
+       while (line > pfile->lineno)
+         {
+           cppReader_putCharQ (pfile, '\n');
+           pfile->lineno++;
+         }
+
+       return;
+      }
+  }
+
+  cpplib_reserve (pfile, 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 (cpplib_getPWritten (pfile), "%d ", line);
+  cppReader_adjustWritten (pfile, strlen (cpplib_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 = cpplib_getToken (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 = "";
+         }
+
+       cpplib_reserve (pfile, 3 + 4 * strlen (string));
+       quote_string (pfile, string);
+       return;
+      }
+    case T_FUNC: /* added in ISO C99 */
+      {
+       /* We don't know the actual name of the function, but it doesn't matter */
+       char *string = "** function-name **";
+       cpplib_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 = cstring_makeLiteral ("\"--- 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 != NULL);
+      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 = cpphash_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 = cstring_length (buf);
+
+  cpplib_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);
+  cpplib_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
+cpplib_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) cpphash_install (name, len, type, ivalue, value, hash);
+  cstring_free (sname);
+}
+
+static void
+cpplib_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 splint */
+
+  llassert (usymtab_inGlobalScope ());
+
+  if (!usymtab_existsTypeEither (sname))
+    {
+      uentry ue = uentry_makeDatatype (sname, ctyp,
+                                      NO, qual_createConcrete (),
+                                      fileloc_createBuiltin ());
+      llassert (!usymtab_existsEither (sname));
+      usymtab_addGlobalEntry (ue);
+    }
+
+  (void) cpphash_install (name, len, type, ivalue, value, hash);
+}
+
+static void
+initialize_builtins (cppReader *pfile)
+{
+  cpplib_installBuiltin ("__LINE__", ctype_int, -1, T_SPECLINE, 0, NULL, -1);
+  cpplib_installBuiltin ("__DATE__", ctype_string, -1, T_DATE, 0, NULL, -1);
+  cpplib_installBuiltin ("__FILE__", ctype_string, -1, T_FILE, 0, NULL, -1);
+  cpplib_installBuiltin ("__BASE_FILE__", ctype_string, -1, T_BASE_FILE, 0, NULL, -1);
+  cpplib_installBuiltin ("__func__", ctype_string, -1, T_FUNC, 0, NULL, -1);
+  cpplib_installBuiltin ("__INCLUDE_LEVEL__", ctype_int, -1, T_INCLUDE_LEVEL, 0, NULL, -1);
+  cpplib_installBuiltin ("__VERSION__", ctype_string, -1, T_VERSION, 0, NULL, -1);
+#ifndef NO_BUILTIN_SIZE_TYPE
+  cpplib_installBuiltinType ("__SIZE_TYPE__", ctype_anyintegral, -1, T_SIZE_TYPE, 0, NULL, -1);
+#endif
+#ifndef NO_BUILTIN_PTRDIFF_TYPE
+  cpplib_installBuiltinType ("__PTRDIFF_TYPE__", ctype_anyintegral, -1, T_PTRDIFF_TYPE, 0, NULL, -1);
+#endif
+  cpplib_installBuiltinType ("__WCHAR_TYPE__", ctype_anyintegral, -1, T_WCHAR_TYPE, 0, NULL, -1);
+  cpplib_installBuiltin ("__USER_LABEL_PREFIX__", ctype_string, -1, T_USER_LABEL_PREFIX_TYPE, 0, NULL, -1);
+  cpplib_installBuiltin ("__REGISTER_PREFIX__", ctype_string, -1, T_REGISTER_PREFIX_TYPE, 0, NULL, -1);
+  cpplib_installBuiltin ("__TIME__", ctype_string, -1, T_TIME, 0, NULL, -1);
+
+  if (!cppReader_isTraditional (pfile))
+    {
+      cpplib_installBuiltin ("__STDC__", ctype_int, -1, T_CONST, STDC_VALUE, NULL, -1);
+    }
+
+# ifdef WIN32
+    cpplib_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.
+  */
+
+  /*  cpplib_install ("__GNUC__", -1, T_CONST, 2, 0, -1);  */
+
+  cpplib_installBuiltin ("S_SPLINT_S", ctype_int, -1, T_CONST, 2, NULL, -1);
+  cpplib_installBuiltin ("__LCLINT__", ctype_int, -1, T_CONST, 2, NULL, -1);
+
+  /*drl 1/9/2001/ try to define the right symbol for the architecture
+    We use autoconf to determine the target cpu 
+   */
+# ifndef S_SPLINT_S
+  cpplib_installBuiltin ("__" TARGET_CPU, ctype_int, -1, T_CONST, 2, NULL, -1);
+# endif
+
+  /*drl 1/2/2002  set some flags based on uname
+    I'd like to be able to do this with autoconf macro instead...
+   */
+
+  /*Thanks to Nelson Beebe for suggesting possible values for these */
+  
+  if (! strcmp (UNAME, "Linux"))
+    {
+#ifdef __ppc
+      cpplib_installBuiltin ("__BIG_ENDIAN__", ctype_int, -1, T_CONST, 2, NULL, -1);
+#endif
+    }
+  
+  else if(! strcmp (UNAME, "Darwin"))
+    {
+      cpplib_installBuiltin ("__ppc__", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__BIG_ENDIAN__", ctype_int, -1, T_CONST, 2, NULL, -1);
+    }
+  else if(! strcmp (UNAME, "HP-UX"))
+    {
+      cpplib_installBuiltin ("PWB", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("_HIUX_SOURCE", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("_HPUX_SOURCE", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("_PA_RISC1_1", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__PWB", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__PWB__", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__STDC_EXT__", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__hp9000s700", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__hp9000s800", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__hp9000s800__", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__hp9k8", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__hp9k8__", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__hppa", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__hppa__", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__hpux", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__hpux__", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__unix", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__unix__", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("hp9000s800", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("hp9k8", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("hppa", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("hpux", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("unix", ctype_int, -1, T_CONST, 2, NULL, -1);
+    }
+  else if(! strcmp (UNAME, "IRIX64"))
+    {
+      cpplib_installBuiltin ("LANGUAGE_C", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("MIPSEB", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("_ABIN32", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("_COMPILER_VERSION", ctype_int, -1, T_CONST, 730, NULL, -1);
+      cpplib_installBuiltin ("_LANGUAGE_C", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("_LONGLONG", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("_MIPSEB", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("_MIPS_FPSET", ctype_int, -1, T_CONST, 32, NULL, -1);
+      cpplib_installBuiltin ("_MIPS_ISA", ctype_int, -1, T_CONST, 3, NULL, -1);
+      /*_MIPS_SIM=_ABIN32*/
+      cpplib_installBuiltin ("_MIPS_SIM", ctype_int, -1, T_CONST, 2, NULL , -1);
+      cpplib_installBuiltin ("_MIPS_SZINT", ctype_int, -1, T_CONST, 32, NULL, -1);
+      cpplib_installBuiltin ("_MIPS_SZLONG", ctype_int, -1, T_CONST, 32, NULL, -1);
+      cpplib_installBuiltin ("_MIPS_SZPTR", ctype_int, -1, T_CONST, 32, NULL, -1);
+      cpplib_installBuiltin ("_MODERN_C", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("_PIC", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("_SGI_SOURCE", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("_SIZE_INT", ctype_int, -1, T_CONST, 32, NULL, -1);
+      cpplib_installBuiltin ("_SIZE_LONG", ctype_int, -1, T_CONST, 32, NULL, -1);
+      cpplib_installBuiltin ("_SIZE_PTR", ctype_int, -1, T_CONST, 32, NULL, -1);
+      cpplib_installBuiltin ("_SVR4_SOURCE", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("_SYSTYPE_SVR4", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__DSO__", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__EXTENSIONS__", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__INLINE_INTRINSICS", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__MATH_HAS_NO_SIDE_EFFECTS", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__host_mips", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__mips", ctype_int, -1, T_CONST, 3, NULL, -1);
+      cpplib_installBuiltin ("__sgi", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__unix", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("host_mips", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("mips", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("sgi", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("unix", ctype_int, -1, T_CONST, 2, NULL, -1);
+    }
+  else if(! strcmp (UNAME, "OSF1"))
+    {
+      cpplib_installBuiltin ("__alpha", ctype_int, -1, T_CONST, 2, NULL, -1);
+    }
+  else if (!strcmp (UNAME, "Rhapsody"))
+    {
+      cpplib_installBuiltin ("__ppc__", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__BIG_ENDIAN__", ctype_int, -1, T_CONST, 2, NULL, -1);
+    }
+
+  else if (!strcmp (UNAME, "SunOS"))
+    {
+      cpplib_installBuiltin ("__OPEN_MAX", ctype_int, -1, T_CONST, 20, NULL, -1);
+      cpplib_installBuiltin ("__STDC__", ctype_int, -1, T_CONST, 2, NULL, -1);
+      cpplib_installBuiltin ("__sparc", ctype_int, -1, T_CONST, 2, NULL, -1);
+      /*       This define  "-Dfileno(f)=0" should be inserted but we're going to stick to deinfe constants for now...*/
+    }
+  else
+    {
+      /*
+       types which we have not explictedly handled.
+       AIX, FreeBSD, IRIX, Mach
+       */
+
+    }
+  
+  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
+cpplib_macroExpand (cppReader *pfile, /*@dependent@*/ hashNode hp)
+{
+  int nargs;
+  DEFINITION *defn = hp->value.defn;
+  char *xbuf;
+  char *oxbuf = NULL;
+  int start_line;
+  int start_column;
+  int end_line;
+  int end_column;
+  size_t xbuf_len;
+  size_t old_written = cpplib_getWritten (pfile);
+  int rest_args;
+  int rest_zero = 0;
+  int i;
+  struct argdata *args = NULL;
+
+  pfile->output_escapes++;
+  cppBuffer_getLineAndColumn (cppReader_fileBuffer (pfile), &start_line, &start_column);
+  DPRINTF (("Expand macro: %d:%d", 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 (cpplib_getWritten (pfile));
+             token = macarg (pfile, rest_args);
+             args[i].raw_length = size_toInt (cpplib_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 the agrument list was multiple lines, need to insert new lines to keep line
+  ** numbers accurate.
+  */
+
+  cppBuffer_getLineAndColumn (cppReader_fileBuffer (pfile), &end_line, &end_column);
+  DPRINTF (("Expand macro: %d:%d", end_line, end_column));
+  
+  /* 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 = cpplib_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 (cpplib_getWritten (pfile) > arg->stringified
+                                 && (cpplib_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
+                       {
+                         cpplib_reserve (pfile, 4);
+                         sprintf (cpplib_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 (cpplib_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); /* Splint 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); /* shouldn't need this */
+
+             if (args[ap->argno].expand_length < 0)
+               {
+                 args[ap->argno].expanded = cpplib_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 (cpplib_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.  */
+  DPRINTF (("Pushing expansion: %s", cstring_copyLength (xbuf, xbuf_len)));
+  
+  if (end_line != start_line)
+    {
+      /* xbuf must have enough newlines */
+      int newlines = end_line - start_line;
+      int foundnewlines = 0;
+      char *xbufptr = xbuf;
+
+      while ((xbufptr = strchr (xbufptr, '\n')) != NULL && foundnewlines <= newlines)
+       {
+         foundnewlines++;
+         xbufptr++;
+
+         if (*xbufptr == '\0') 
+           {
+             break;
+           }
+       }
+         
+      if (foundnewlines < newlines)
+       {
+         cstring newbuf = cstring_copyLength (xbuf, xbuf_len);
+         
+         while (foundnewlines < newlines)
+           {
+             newbuf = cstring_appendChar (newbuf, '\n');
+             foundnewlines++;
+           }
+
+         sfree (oxbuf);
+         xbuf = cstring_toCharsSafe (newbuf);
+         xbuf_len = cstring_length (newbuf);
+         /*@-branchstate@*/ 
+       } /*@=branchstate@*/ 
+    }
+  
+  DPRINTF (("Pushing expansion: %s", cstring_copyLength (xbuf, xbuf_len)));
+
+  push_macro_expansion (pfile, xbuf, xbuf_len, hp);
+  DPRINTF (("After pushing expansion: %s", cstring_copyLength (xbuf, xbuf_len)));
+  cppReader_getBufferSafe (pfile)->has_escapes = 1;
+
+  /* Pop the space we've used in the token_buffer for argument expansion.  */
+  cppReader_setWritten (pfile, old_written);
+  DPRINTF (("Done set 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);
+    DPRINTF (("Eating: %c", xbuf[2]));
+    mbuf->cur += 2;
+  }
+  
+}
+
+
+/* Like cpplib_getToken, 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 = cpplib_getWritten (pfile);
+      enum cpp_token token;
+      cppSkipHspace (pfile);
+      if (cppReader_peekC (pfile) == '\n')
+       {
+         return CPP_VSPACE;
+       }
+
+      token = cpplib_getToken (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
+   cpplib_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 = cpplib_getWritten (pfile);
+  size_t 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 = cpplib_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 > size_toInt (pfile->max_include_len))
+                       pfile->max_include_len = size_fromInt (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 = cpplib_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 = size_fromInt (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)
+         && (cpphash_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;
+         size_t 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 = cpplib_getWritten (pfile);
+  enum file_change_code file_change = same_file;
+  enum cpp_token token;
+
+  llassert (ip != NULL);
+  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;
+    size_t 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, cpplib_getPWritten (pfile), 1);
+    if (end_name == NULL)
+      {
+       cppReader_errorLit (pfile,
+                     cstring_makeLiteralTemp ("invalid format `#line' command"));
+       goto bad_line_directive;
+      }
+
+    fname_length = size_fromInt (end_name - fname);
+    num_start = cpplib_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[cpphash_hashCode (fname, fname_length, FNAME_HASHSIZE)];
+
+    for (hp = *hash_bucket; hp != NULL; hp = hp->next)
+      {
+       if (hp->length == fname_length)
+         {
+           llassert (hp->value.cpval != NULL);
+           
+           if (strncmp (hp->value.cpval, fname, 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, 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)
+{
+
+  size_t sym_length;
+  hashNode hp;
+  char *orig_buf = buf;
+
+  SKIP_WHITE_SPACE (buf);
+
+  sym_length = cppReader_checkMacroName (pfile, buf, cstring_makeLiteralTemp ("macro"));
+
+  while ((hp = cpphash_lookup (buf, size_toInt (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)
+{
+  size_t length = size_fromInt (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)
+{
+  size_t length = size_fromInt (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_getBufferSafe (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 cpplib_getToken.  */
+
+  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;
+    size_t fname_len;
+    SKIP_WHITE_SPACE (p);
+    if (*p == '\n' || *p != '\"')
+      return 0;
+
+    fname = p + 1;
+    p = (char *) strchr (fname, '\"');
+    fname_len = p != NULL ? size_fromInt (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, 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;
+  DPRINTF (("Do if: %s", buf));
+  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_getBufferSafe (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_getBufferSafe (pfile)->fname != NULL
+             && !cstring_equal (pfile->if_stack->fname,
+                                cppReader_getBufferSafe (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 = cpplib_getWritten (pfile);
+
+  DPRINTF (("Saving defined..."));
+  save_defined = cpphash_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 */
+  DPRINTF (("Removing defined..."));
+  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_getBufferSafe (pfile);
+  char *ident;
+  size_t ident_length;
+  enum cpp_token token;
+  int start_of_file = 0;
+  char *control_macro = 0;
+  size_t old_written = cpplib_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;
+  DPRINTF (("Ident: %s", ident));
+
+  ident_length = cpplib_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 = cpphash_lookup (ident, size_toInt (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 (ident_length + 1);
+         memcpy (control_macro, ident, 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_getBufferSafe (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_getBufferSafe (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 = cpplib_getWritten (pfile);
+      cppSkipHspace (pfile);
+
+      parse_name (pfile, cppReader_getC (pfile));
+      ident_length = size_toInt (cpplib_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_getBufferSafe (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_getBufferSafe (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@*/ 
+#if defined (OS2) && defined (__IBMC__)
+      /* Dummy code to eleminate optimization problems with icc */
+      c = 0;
+# endif
+
+               }
+             /*@=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 = cpplib_getWritten (pfile);
+       (void) cpplib_getToken (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_getBufferSafe (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_getBufferSafe (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_getBufferSafe (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
+cpplib_getToken (cppReader *pfile)
+{
+  return cpplib_getTokenAux (pfile, FALSE);
+}
+
+enum cpp_token
+cpplib_getTokenForceExpand (cppReader *pfile)
+{
+  return cpplib_getTokenAux (pfile, TRUE);
+}
+
+enum cpp_token
+cpplib_getTokenAux (cppReader *pfile, bool forceExpand)
+{
+  int c, c2, c3;
+  size_t old_written = 0;
+  int start_line, start_column;
+  enum cpp_token token;
+  struct cppOptions *opts = CPPOPTIONS (pfile);
+  cppReader_getBufferSafe (pfile)->prev = cppReader_getBufferSafe (pfile)->cur;
+
+get_next:
+  c = cppReader_getC (pfile);
+  DPRINTF (("Get next token: %c", c));
+
+  if (c == EOF)
+    {
+    handle_eof:
+      if (cppReader_getBufferSafe (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_getBufferSafe (pfile));
+         cppReader_getBufferSafe (pfile)->seen_eof = 1;
+
+         if (cstring_isDefined (cppReader_getBufferSafe (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_getLineAndColumn (cppReader_fileBuffer (pfile),
+                                  &start_line, &start_column);
+         c = skip_comment (pfile, &newlines);
+         DPRINTF (("c = %c", c));
+         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
+           {
+             cpplib_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_getLineAndColumn (cppReader_fileBuffer (pfile),
+                                     &start_line, &start_column);
+         old_written = cpplib_getWritten (pfile);
+       string:
+         DPRINTF (("Reading string: %c", c));
+         cppReader_putChar (pfile, c);
+         while (TRUE)
+           {
+             /* evans-2003-06-07
+             ** Because of ISO8859-1 characters in string literals, we need a special test here.
+             */
+
+             if (cppReader_reachedEOF (pfile)) 
+               {
+                 
+                 DPRINTF (("Matches 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_getBufferSafe (pfile));
+                     (*cppReader_getBufferSafe (pfile)->cleanup)
+                       (cppReader_getBufferSafe (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;                  
+               } 
+             else
+               {
+                 int cc = cppReader_getC (pfile); 
+                 DPRINTF (("cc: %c [%d] [%d]", cc, cc, EOF));
+                 DPRINTF (("putting char: %c", cc));
+                 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.  */
+                         pfile->lineno++; /* 2003-11-03: AMiller suggested adding this, but
+                                             its not clear why it is needed. */
+                         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,
+                                          cpplib_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);
+         cpplib_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 '@':
+         DPRINTF (("Macro @!"));
+         if (cppReader_getBufferSafe (pfile)->has_escapes)
+           {
+             c = cppReader_getC (pfile);
+             DPRINTF (("got c: %c", c));
+             if (c == '-')
+               {
+                 if (pfile->output_escapes)
+                   cppReader_puts (pfile, "@-", 2);
+                 parse_name (pfile, cppReader_getC (pfile));
+                 return CPP_NAME;
+               }
+             else if (is_space [c])
+               {
+                 cpplib_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))
+           {
+             cpplib_reserve(pfile, 2);
+             cppReader_putCharQ (pfile, '.');
+             c = cppReader_getC (pfile);
+             goto number;
+           }
+
+         /* FIXME - misses the case "..\\\n." */
+         if (c2 == '.' && cpp_peekN (pfile, 1) == '.')
+           {
+             cpplib_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: /* jumped to for \ continuations */
+         cpplib_reserve(pfile, 3);
+         cppReader_putCharQ (pfile, c);
+
+         /* evans 2003-08-24: This is a hack to fix line output for \
+            continuations.  Someday I really should get a decent pre-processor! 
+         */
+
+         if (c == '\\') {
+           (void) cppReader_getC (pfile); /* skip the newline to avoid extra lines */
+         } else {
+           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 (;;)
+           {
+             cpplib_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;
+             cpplib_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 == '\'')
+               {
+                 cpplib_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 = cpplib_getWritten (pfile);
+           size_t ident_len;
+           parse_name (pfile, c);
+           pfile->only_seen_white = 0;
+
+           if (pfile->no_macro_expand)
+             {
+               DPRINTF (("Not expanding: %s", pfile->token_buffer));
+               return CPP_NAME;
+             }
+
+           ident = pfile->token_buffer + before_name_written;
+           DPRINTF (("Ident: %s", ident));
+
+           ident_len = size_fromInt ((cpplib_getPWritten (pfile)) - ident);
+
+           hp = cpphash_lookupExpand (ident, size_toInt (ident_len), -1, forceExpand);
+
+           if (hp == NULL)
+             {
+               DPRINTF (("No expand: %s %d", ident, ident_len));
+               return CPP_NAME;
+             }
+
+           if (hp->type == T_DISABLED)
+             {
+               DPRINTF (("Disabled!"));
+
+               if (pfile->output_escapes)
+                 { /* Return "@-IDENT", followed by '\0'.  */
+                   int i;
+                   cpplib_reserve (pfile, 3);
+                   ident = pfile->token_buffer + before_name_written;
+                   cppReader_adjustWritten (pfile, 2);
+
+                   for (i = size_toInt (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;
+
+               DPRINTF (("Arglist macro!"));
+
+               /*
+               ** evans 2002-07-03: Moved this here (from below).
+               **   This bug caused necessary whitespace to be lost
+               **   when parsing parameterized macros without parameters.
+               */
+
+               parseSetMark (&macro_mark, pfile); 
+
+               while (cppBuffer_isMacro (CPPBUFFER (pfile)))
+                 {
+                   cppBuffer *next_buf;
+                   cppSkipHspace (pfile);
+                   if (cppReader_peekC (pfile) != EOF)
+                     {
+                       DPRINTF (("Peeking!"));
+                       /*@loopbreak@*/ break;
+                     }
+
+                 next_buf = cppBuffer_prevBuffer (cppReader_getBufferSafe (pfile));
+                 (*cppReader_getBufferSafe (pfile)->cleanup) (cppReader_getBufferSafe (pfile), pfile);
+                 CPPBUFFER (pfile) = next_buf;
+                 }
+
+               /* parseSetMark (&macro_mark, pfile); */
+
+               for (;;)
+                 {
+                   cppSkipHspace (pfile);
+                   c = cppReader_peekC (pfile);
+                   DPRINTF (("c: %c", c));
+                   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)
+                 {
+                   DPRINTF (("not 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 = cpplib_getWritten (pfile) - before_name_written;
+               xbuf = (char *) dmalloc (xbuf_len + 1);
+               cppReader_setWritten (pfile, before_name_written);
+               memcpy (xbuf, cpplib_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. 
+               */
+
+               cpplib_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 = cpplib_bufPeek (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);
+         /* allow other stuff here if a flag is set? */
+         DPRINTF (("Got continuation!"));
+         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"));
+       }
+
+      cpplib_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
+{
+  /*@only@*/ struct file_name_map_list *map_list_next;
+  /*@only@*/ cstring map_list_name;
+  /*@null@*/ 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_openReadFile (context_fileTable (), name);
+  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))
+      && (size_toInt (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; /* was __mode_t */
+  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_getBufferSafe (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 where file is expected: %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
+cpplib_init (cppReader *pfile)
+{
+  memset ((char *) pfile, 0, sizeof (*pfile));
+
+  pfile->get_token = cpplib_getToken;
+  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 (/*@special@*/ cppReader *pfile) 
+     /*@uses pfile@*/
+     /*@releases pfile@*/
+{
+  DPRINTF (("cppCleanup!"));
+
+  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);
+    }
+
+  /* evans 2002-07-12 */
+  while (pfile->opts->map_list != NULL)
+    {
+      struct file_name_map_list *temp = pfile->opts->map_list;
+      pfile->opts->map_list = pfile->opts->map_list->map_list_next;
+      cstring_free (temp->map_list_name);
+      sfree (temp);
+    }
+
+  while (pfile->opts->include != NULL)
+    {
+      struct file_name_list *temp = pfile->opts->include;
+      pfile->opts->include = pfile->opts->include->next;
+      /* cstring_free (temp->fname); */
+      sfree (temp);
+    }
+
+  sfree (pfile->opts);
+  pfile->opts = NULL;
+  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) {
+    *mode_pointer = 0;
+    *size_pointer = 0;
+    /*@-compdestroy@*/ /* possibly spurious warnings here (or memory leak) */
+    return (-1);
+    /*@=compdestroy@*/
+  }
+
+  if (mode_pointer != NULL)
+    {
+      /*@-type@*/ /* confusion between __mode_t and mode_t types */
+      *mode_pointer = sbuf.st_mode;
+      /*@=type@*/
+    }
+
+  if (size_pointer != NULL)
+    {
+      *size_pointer = (size_t) sbuf.st_size;
+    }
+
+  /*@-compdestroy@*/ /* possibly spurious warnings here (or memory leak) */
+  return 0;
+  /*@=compdestroy@*/
+}
+
+/* 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_getBufferSafe (pfile);
+
+  pmark->next = pbuf->marks;
+  /*@-temptrans@*/
+  pbuf->marks = pmark;
+  /*@=temptrans@*/
+
+  pmark->buf = pbuf;
+  pmark->position = pbuf->cur - pbuf->buf;
+  DPRINTF (("set mark: %d / %s", pmark->position, pbuf->cur));
+}
+
+/* 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_getBufferSafe (pfile);
+
+  if (pbuf != pmark->buf)
+    {
+      cpp_setLocation (pfile);
+      llfatalbug (cstring_makeLiteral ("Internal error parseGotoMark"));
+    }
+
+  llassert (pbuf->buf != NULL);
+  pbuf->cur = pbuf->buf + pmark->position;
+  DPRINTF (("goto mark: %d / %s", pmark->position, pbuf->cur));
+}
+
+/* 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_getBufferSafe (pfile);
+
+  if (pbuf != pmark->buf)
+    {
+      cpp_setLocation (pfile);
+      llfatalerror (cstring_makeLiteral ("Internal error parseMoveMark"));
+    }
+
+  pmark->position = pbuf->cur - pbuf->buf;
+  DPRINTF (("move mark: %d", pmark->position));
+}
+
+void cpplib_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);
+    size_t 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?  */
+         llassert (default_prefix != NULL);
+
+         if (!strncmp (cstring_toCharsSafe (p->fname), default_prefix, 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;
+
+             if (opts->first_system_include == 0)
+               {
+                 opts->first_system_include = nlist;
+               }
+         
+             cppReader_addIncludeChain (pfile, 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;
+
+           /* Spurious warning reported for opts->first_system_include */
+           /*@-usereleased@*/ if (opts->first_system_include == NULL) 
+             {
+               opts->first_system_include = nlist;
+             }
+           /*@=usereleased@*/
+
+           cppReader_addIncludeChain (pfile, 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);
+
+  /* Spurious warnings for opts->first_system_include */
+  /*@-usereleased@*/
+  if (opts->first_system_include == NULL)
+    {
+      opts->first_system_include = opts->after_include;
+    }
+  /*@=usereleased@*/
+  
+  /* 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 cpplib_bufPeek (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_getBufferSafe (pfile)->nominal_fname))
+       {
+         cstring fname = cppReader_getBufferSafe (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_getBufferSafe (pfile)->fname);
+           }
+       }
+      else
+       {
+         fid = fileTable_lookup (context_fileTable (),
+                                 cppReader_getBufferSafe (pfile)->fname);
+       }
+      
+      line = cppReader_getBufferSafe (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) /*@modifies p*/
+{
+  bool checkmacro = FALSE;
+  bool hasParams = 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 (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_makeMacroConstant (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_getBufferSafe (pfile);
+  char *start;
+  int len;
+  fileloc loc;
+  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];
+      
+      cpp_setLocation (pfile);
+      loc = fileloc_copy (g_currentloc);
+
+      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];
+
+      cpplib_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 (loc);
+           }
+       }
+      else if (mstring_equalPrefix (scomment, "end"))
+       {
+         if (!context_getFlag (FLG_NOCOMMENTS))
+           {
+             context_exitSuppressRegion (loc);
+           }
+       }
+      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),
+                                      loc);
+               }
+             else if (mstring_equalPrefix (rest, "namechecks"))
+               {
+                 context_fileSetFlag (FLG_NAMECHECKS,
+                                      ynm_fromCodeChar (sChar),
+                                      loc);
+               }
+             else if (mstring_equalPrefix (rest, "macroredef"))
+               {
+                 context_fileSetFlag (FLG_MACROREDEF,
+                                      ynm_fromCodeChar (sChar),
+                                      loc);
+               }
+             else if (mstring_equalPrefix (rest, "usevarargs"))
+               {
+                 context_fileSetFlag (FLG_USEVARARGS,
+                                      ynm_fromCodeChar (sChar),
+                                      loc);
+               }
+             else if (mstring_equalPrefix (rest, "nextlinemacros"))
+               {
+                 context_fileSetFlag (FLG_MACRONEXTLINE,
+                                      ynm_fromCodeChar (sChar),
+                                      loc);
+               }
+             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), loc);
+                 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 (size_toLong (cstring_length (lintcomment)) == len - 3);
+
+           for (i = 1; i < len - 2; i++)
+             {
+               start[i] = cstring_getChar (lintcomment, size_fromInt (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] = ' ';
+                 }
+             }
+         }
+
+       cpplib_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)))
+       {
+         if (fileloc_isXHFile (g_currentloc))
+           {
+             /*
+             ** Files includes by XH files are also XH files
+             */
+
+             (void) fileTable_addXHFile (context_fileTable (),
+                                         cstring_fromChars (filename));
+           }
+         else
+           {
+             (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))
+       {
+         /*
+         ** 2003-04-18: Patch from Randal Parsons
+         */
+
+         /*
+         ** Don't skip include file unless the file actually exists.  
+         ** It may be in a different directory.
+         */
+
+         int f = open (cstring_toCharsSafe (fname), O_RDONLY, 0666);
+
+         if (f >= 0)
+           {
+             check (close (f) == 0);
+             DPRINTF (("Skip include TRUE: %s", fname));
+             return TRUE;
+           }
+         else
+           {
+             /* Keep looking... */
+           }
+       }
+    }
+
+  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_getBufferSafe (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;
+}
+
+/*@=bufferoverflowhigh@*/
+/*@=bounds@*/
This page took 0.664852 seconds and 4 git commands to generate.