Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

cpplib.c

Go to the documentation of this file.
00001 /*
00002 ** LCLint - annotation-assisted static program checker
00003 ** Copyright (C) 1994-2000 University of Virginia,
00004 **         Massachusetts Institute of Technology
00005 **
00006 ** This program is free software; you can redistribute it and/or modify it
00007 ** under the terms of the GNU General Public License as published by the
00008 ** Free Software Foundation; either version 2 of the License, or (at your
00009 ** option) any later version.
00010 ** 
00011 ** This program is distributed in the hope that it will be useful, but
00012 ** WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 ** General Public License for more details.
00015 ** 
00016 ** The GNU General Public License is available from http://www.gnu.org/ or
00017 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018 ** MA 02111-1307, USA.
00019 **
00020 ** For information on lclint: lclint-request@cs.virginia.edu
00021 ** To report a bug: lclint-bug@cs.virginia.edu
00022 ** For more information: http://lclint.cs.virginia.edu
00023 */
00024 /*
00025 ** cpplib.c
00026 */
00027 /*
00028    Copyright (C) 1986, 87, 89, 92-6, 1997 Free Software Foundation, Inc.
00029    Contributed by Per Bothner, 1994-95.
00030    Based on CCCP program by Paul Rubin, June 1986
00031    Adapted to ANSI C, Richard Stallman, Jan 1987
00032 
00033 This program is free software; you can redistribute it and/or modify it
00034 under the terms of the GNU General Public License as published by the
00035 Free Software Foundation; either version 2, or (at your option) any
00036 later version.
00037 
00038 This program is distributed in the hope that it will be useful,
00039 but WITHOUT ANY WARRANTY; without even the implied warranty of
00040 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00041 GNU General Public License for more details.
00042 
00043 You should have received a copy of the GNU General Public License
00044 along with this program; if not, write to the Free Software
00045 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00046 
00047  In other words, you are welcome to use, share and improve this program.
00048  You are forbidden to forbid anyone else to use, share and improve
00049  what you give them.   Help stamp out software-hoarding!  */
00050 
00051 /*
00052  * Herbert 06/12/2000:
00053  * - OS2 drive specs like WIN32
00054  * - Includes for IBMs OS/2 compiler
00055  */
00056 
00057 # include <ctype.h>
00058 # include <stdio.h>
00059 # include <signal.h>
00060 # ifdef __STDC__
00061 # include <stdlib.h>
00062 # endif
00063 
00064 # include <string.h>
00065 
00066 # if !(defined (WIN32) || defined (OS2) && defined (__IBMC__))
00067 # include <unistd.h>
00068 # endif
00069 
00070 # include <sys/types.h>
00071 # include <sys/stat.h>
00072 # include <fcntl.h>
00073 
00074 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
00075 # include <io.h>
00076 # include <sys/utime.h>         /* for __DATE__ and __TIME__ */
00077 # include <time.h>
00078 # else
00079 # ifndef VMS
00080 # ifndef USG
00081 # include <sys/time.h>
00082 # include <sys/resource.h>
00083 # else
00084 # include <sys/times.h>
00085 # include <time.h>
00086 # include <fcntl.h>
00087 # endif /* USG */
00088 # endif /* not VMS */
00089 # endif /* not WIN32 */
00090 
00091 /* This defines "errno" properly for VMS, and gives us EACCES.  */
00092 # include <errno.h>
00093 
00094 # include "lclintMacros.nf"
00095 # include "llbasic.h"
00096 # include "lcllib.h"
00097 # include "cpp.h"
00098 # include "cpplib.h"
00099 # include "cpperror.h"
00100 # include "cpphash.h"
00101 # include "cppexp.h"
00102 # include "version.h"
00103 # include "portab.h"
00104 # include "osd.h"
00105 
00106 /*
00107 ** This is really kludgey code...
00108 */
00109 
00110 /*@+boolint@*/
00111 /*@+charint@*/
00112 
00113 #define NO_SHORTNAMES
00114 
00115 # ifdef open
00116 # undef open
00117 # undef read
00118 # undef write
00119 # endif /* open */
00120 
00121 /*@constant int IMPORT_FOUND@*/
00122 # define IMPORT_FOUND -2
00123 
00124 /*@constant int SKIP_INCLUDE@*/
00125 # define SKIP_INCLUDE IMPORT_FOUND
00126 
00127 /*@constant unused int IMPORT_NOT_FOUND@*/
00128 # define IMPORT_NOT_FOUND -1
00129 
00130 #ifndef STDC_VALUE
00131 /*@constant unused int STDC_VALUE@*/
00132 #define STDC_VALUE 1
00133 #endif
00134 
00135 /* By default, colon separates directories in a path.  */
00136 #ifndef PATH_SEPARATOR
00137 /*@constant char PATH_SEPARATOR@*/
00138 #define PATH_SEPARATOR ':'
00139 #endif
00140 
00141 static void parse_name (cppReader *, int);
00142 
00143 static int cpp_openIncludeFile (char *p_filename)
00144      /*@modifies fileSystem @*/ ;
00145 
00146 static void cpp_setLocation (cppReader *p_pfile)
00147      /*@modifies g_currentloc@*/ ;
00148 
00149 static enum cpp_token cpp_handleComment (cppReader *p_pfile,
00150                                          struct parse_marker *p_smark)
00151      /*@modifies *p_pfile, *p_smark@*/;
00152 
00153 static bool cpp_shouldCheckMacro (cppReader *p_pfile, char *p_p) /*@*/ ;
00154 
00155 static bool cpp_skipIncludeFile (cstring p_fname) /*@*/ ;
00156 
00157 #ifndef O_RDONLY
00158 #define O_RDONLY 0
00159 #endif
00160 
00161 /* Symbols to predefine.  */
00162 
00163 #ifdef CPP_PREDEFINES
00164 static /*@observer@*/ char *predefs = CPP_PREDEFINES;
00165 #else
00166 static /*@observer@*/ char *predefs = "";
00167 #endif
00168 
00169 /* We let tm.h override the types used here, to handle trivial differences
00170    such as the choice of unsigned int or long unsigned int for size_t.
00171    When machines start needing nontrivial differences in the size type,
00172    it would be best to do something here to figure out automatically
00173    from other information what type to use.  */
00174 
00175 /* The string value for __SIZE_TYPE__.  */
00176 
00177 #ifndef SIZE_TYPE
00178 /*@constant observer char *SIZE_TYPE@*/
00179 #define SIZE_TYPE "long unsigned int"
00180 #endif
00181 
00182 /* The string value for __PTRDIFF_TYPE__.  */
00183 
00184 #ifndef PTRDIFF_TYPE
00185 /*@constant observer char *PTRDIFF_TYPE@*/
00186 #define PTRDIFF_TYPE "long int"
00187 #endif
00188 
00189 /* The string value for __WCHAR_TYPE__.  */
00190 
00191 #ifndef WCHAR_TYPE
00192 /*@constant observer char *WCHAR_TYPE@*/
00193 #define WCHAR_TYPE "int"
00194 #endif
00195 
00196 /* The string value for __USER_LABEL_PREFIX__ */
00197 
00198 #ifndef USER_LABEL_PREFIX
00199 /*@constant observer char *USER_LABEL_PREFIX@*/
00200 #define USER_LABEL_PREFIX ""
00201 #endif
00202 
00203 /* The string value for __REGISTER_PREFIX__ */
00204 
00205 #ifndef REGISTER_PREFIX
00206 /*@constant observer char *REGISTER_PREFIX@*/
00207 #define REGISTER_PREFIX ""
00208 #endif
00209 
00210 /* table to tell if char can be part of a C identifier.  */
00211 static bool is_idchar[256];
00212 /* table to tell if char can be first char of a c identifier.  */
00213 static bool is_idstart[256];
00214 /* table to tell if c is horizontal space.  */
00215 static bool is_hor_space[256];
00216 /* table to tell if c is horizontal or vertical space.  */
00217 static bool is_space[256];
00218 
00219 static /*@exposed@*/ /*@null@*/ cppBuffer *
00220 cppReader_getBuffer (/*@special@*/ cppReader *p_pfile)
00221      /*@uses p_pfile->buffer@*/
00222      /*@modifies nothing@*/ ;
00223 
00224 /*@notfunction@*/
00225 # define SKIP_WHITE_SPACE(p) do { /*@access cstring@*/ while (is_hor_space[(int) *(p)]) { (p)++; } } /*@noaccess cstring@*/ while (0)
00226 
00227 /*@notfunction@*/
00228 # define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*(p)]) { (p)++; } } while (0)
00229 
00230 static int cpp_peekN (cppReader *p_pfile, int p_n) /*@*/ ;
00231 
00232 /*@function static int cppBuffer_get (sef cppBuffer *p_b) modifies *p_b ; @*/
00233 # define cppBuffer_get(BUFFER) \
00234   ((BUFFER)->cur < (BUFFER)->rlimit ? *(BUFFER)->cur++ : EOF)
00235 
00236 /* Append string STR (of length N) to PFILE's output buffer.  Make space. */
00237 /*@function static void cppReader_puts (sef cppReader *p_file, char *p_str, sef size_t p_n)
00238                      modifies *p_file; @*/
00239 # define cppReader_puts(PFILE, STR, N) \
00240   cppReader_reserve(PFILE, N), cppReader_putStrN (PFILE, STR,N)
00241 
00242 /* Append character CH to PFILE's output buffer.  Assume sufficient space. */
00243 
00244 /*@function static void cppReader_putCharQ (cppReader *p_file, char p_ch)
00245                     modifies *p_file; @*/
00246 # define cppReader_putCharQ(PFILE, CH) (*(PFILE)->limit++ = (CH))
00247 
00248 /* Append character CH to PFILE's output buffer.  Make space if need be. */
00249 
00250 /*@function static void cppReader_putChar (sef cppReader *p_file, char p_ch)
00251                     modifies *p_file; @*/
00252 #define cppReader_putChar(PFILE, CH) (cppReader_reserve (PFILE, (size_t) 1), cppReader_putCharQ (PFILE, CH))
00253 
00254 /* Make sure PFILE->limit is followed by '\0'. */
00255 /*@function static void cppReader_nullTerminateQ (cppReader *p_file)
00256       modifies *p_file; @*/
00257 
00258 #define cppReader_nullTerminateQ(PFILE) (*(PFILE)->limit = 0)
00259 
00260 /*@function static void cppReader_nullTerminate (sef cppReader *p_file)
00261                            modifies *p_file; @*/
00262 # define cppReader_nullTerminate(PFILE) \
00263   (cppReader_reserve (PFILE, (size_t) 1), *(PFILE)->limit = 0)
00264 
00265 /*@function static void cppReader_adjustWritten (cppReader *p_file, size_t)
00266                            modifies *p_file; @*/
00267 #define cppReader_adjustWritten(PFILE,DELTA) ((PFILE)->limit += (DELTA))
00268 
00269 /*@function static bool cppReader_isC89 (cppReader *) modifies nothing; @*/
00270 #define cppReader_isC89(PFILE) (CPPOPTIONS(PFILE)->c89)
00271 
00272 /*@function static observer char *cppReader_wcharType (cppReader *)
00273      modifies nothing; @*/
00274 
00275 # define cppReader_wcharType(PFILE) \
00276   (CPPOPTIONS (PFILE)->cplusplus ? "__wchar_t" : WCHAR_TYPE)
00277 
00278 static void cppBuffer_forward (cppBuffer *p_buf, int p_n) /*@modifies *p_buf@*/ ;
00279 
00280 /*@function static void cppReader_forward (cppReader *p_pfile, int) modifies *p_pfile; @*/
00281 # define cppReader_forward(pfile, N) \
00282   (cppBuffer_forward (cppReader_getBufferSafe (pfile), (N)))
00283 
00284 /*@function static int cppReader_getC (cppReader *p_pfile) modifies *p_pfile; @*/
00285 # define cppReader_getC(pfile)   (cppBuffer_get (cppReader_getBufferSafe (pfile)))
00286 
00287 /*@function static int cppReader_peekC (cppReader *) modifies nothing;@*/
00288 # define cppReader_peekC(pfile)  (cppBufPeek (cppReader_getBufferSafe (pfile)))
00289 
00290 /* Move all backslash-newline pairs out of embarrassing places.
00291    Exchange all such pairs following BP
00292    with any potentially-embarrassing characters that follow them.
00293    Potentially-embarrassing characters are / and *
00294    (because a backslash-newline inside a comment delimiter
00295    would cause it not to be recognized).  */
00296 
00297 /*@notfunction@*/
00298 # define NEWLINE_FIX \
00299    do { while (cppReader_peekC (pfile) == '\\' && cpp_peekN (pfile, 1) == '\n') { cppReader_forward (pfile, 2); } } while(FALSE)
00300 
00301      /* Same, but assume we've already read the potential '\\' into C.  */
00302 /*@notfunction@*/
00303 # define NEWLINE_FIX1(C) do { \
00304      while ((C) == '\\' && cppReader_peekC (pfile) == '\n') { cppReader_forward (pfile, 1); (C) = cppReader_getC (pfile); }\
00305                                                                            } while(0)
00306 
00307 static void parseSetMark (/*@out@*/ struct parse_marker *,
00308                           cppReader *);
00309 static void parseClearMark (struct parse_marker *);
00310 static void parseGotoMark (struct parse_marker *, cppReader *);
00311 static void parseMoveMark (struct parse_marker *, cppReader *);
00312 
00313 /* If we have a huge buffer, may need to cache more recent counts */
00314 static /*@exposed@*/ char *cppLineBase (/*@sef@*/ cppBuffer *);
00315 
00316 static /*@exposed@*/ /*@null@*/ cppBuffer *
00317    cppReader_pushBuffer (cppReader *p_pfile,
00318                          /*@owned@*/ /*@null@*/ char *, size_t)
00319      /*@modifies p_pfile@*/ ;
00320 
00321 static void cppReader_appendIncludeChain
00322 (cppReader *p_pfile,
00323  /*@keep@*/ struct file_name_list *p_first,
00324  /*@dependent@*/ struct file_name_list *p_last);
00325 
00326 static void cppReader_macroCleanup (cppBuffer *p_pbuf, cppReader *p_pfile);
00327 static enum cpp_token cppReader_nullUnderflow (/*@unused@*/ cppReader *p_pfile);
00328 
00329 static void cppReader_nullCleanup (/*@unused@*/ cppBuffer *p_pbuf,
00330                                    /*@unused@*/ cppReader *p_pfile);
00331 
00332 static void cppReader_fileCleanup (cppBuffer *p_pbuf,
00333                                    /*@unused@*/ cppReader *p_pfile);
00334 
00335 static int cppReader_handleDirective (cppReader *p_pfile);
00336 
00337 static void cppReader_scanBuffer (cppReader *p_pfile);
00338 
00339 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
00340 
00341 /*
00342 ** WIN32 (at least the VC++ include files) does not define mode_t.
00343 */
00344 
00345 /*@-incondefs@*/ /*@-czechtypes@*/
00346 typedef unsigned int mode_t;
00347 /*@=incondefs@*/ /*@=czechtypes@*/
00348 
00349 # endif
00350 
00351 static int file_size_and_mode (int p_fd, /*@out@*/ mode_t *p_mode_pointer,
00352                                /*@out@*/ size_t *p_size_pointer);
00353 static int safe_read (int p_desc, /*@out@*/ char *p_ptr, int p_len);
00354 
00355 
00356 /*
00357 ** cppBuffer_isMacro is true if the buffer contains macro expansion.
00358 ** (Note that it is false while we're expanding marco *arguments*.)
00359 */
00360 
00361 static bool cppBuffer_isMacro (/*@null@*/ cppBuffer *) /*@*/ ;
00362 
00363 static void path_include (cppReader *p_pfile, char *p_path)
00364      /*@modifies p_pfile@*/ ;
00365 
00366 static void initialize_builtins (cppReader *p_pfile)
00367      /*@modifies p_pfile@*/ ;
00368 
00369 static void initialize_char_syntax (struct cppOptions *p_opts) ;
00370 
00371 static int /*@alt void@*/ finclude (cppReader *p_pfile, int p_f,
00372                                     cstring p_fname,
00373                                     bool p_system_header_p,
00374                                     /*@dependent@*/ /*@null@*/ struct file_name_list *p_dirptr);
00375 
00376 static void validate_else (cppReader *p_pfile, cstring p_directive);
00377 
00378 static void conditional_skip (cppReader *p_pfile, int p_skip,
00379                               enum node_type p_type,
00380                               /*@dependent@*/ /*@null@*/ char *p_control_macro);
00381 
00382 static HOST_WIDE_INT eval_if_expression (cppReader *p_pfile,
00383                                          char *p_buf,
00384                                          int p_length);
00385 
00386 static void skip_if_group (cppReader *p_pfile, int p_any);
00387 
00388 static bool comp_def_part (bool p_first, char *p_beg1, int p_len1,
00389                            char *p_beg2, int p_len2, bool p_last);
00390 
00391 #ifdef abort
00392 extern void fancy_abort ();
00393 #endif
00394 
00395 static bool redundant_include_p (cppReader *p_pfile, /*@null@*/ cstring p_name);
00396 static bool is_system_include (cppReader *p_pfile, cstring p_filename);
00397 
00398 static /*@observer@*/ /*@null@*/ struct file_name_map *
00399 read_name_map (cppReader *p_pfile, cstring p_dirname);
00400 
00401 static cstring read_filename_string (int p_ch, FILE *p_f);
00402 
00403 static int open_include_file (cppReader *p_pfile,
00404                               /*@owned@*/ cstring p_fname,
00405                               /*@null@*/ struct file_name_list *p_searchptr);
00406 
00407 static void push_macro_expansion (cppReader *,
00408                                   /*@owned@*/ char *, size_t,
00409                                   /*@dependent@*/ HASHNODE *);
00410 
00411 /* Last arg to output_line_command.  */
00412 enum file_change_code {
00413   same_file, enter_file, leave_file
00414 };
00415 
00416 /* `struct directive' defines one #-directive, including how to handle it.  */
00417 
00418 struct directive {
00419   int length;                   /* Length of name */
00420   /*@null@*/ int (*func)();     /* Function to handle directive */
00421   /*@observer@*/ cstring name;  /* Name of directive */
00422   enum node_type type;          /* Code which describes which directive.  */
00423   bool command_reads_line;      /* One if rest of line is read by func.  */
00424   bool traditional_comments;    /* Nonzero: keep comments if -traditional.  */
00425   bool pass_thru;               /* Copy preprocessed directive to output file.*/
00426 };
00427 
00428 /* These functions are declared to return int instead of void since they
00429    are going to be placed in a table and some old compilers have trouble with
00430    pointers to functions returning void.  */
00431 
00432 static int do_define (cppReader *, /*@null@*/ struct directive *, 
00433                       char *, char *);
00434 static int do_defineAux (cppReader *, /*@null@*/ struct directive *,
00435                          char *, char *, bool);
00436      
00437 static int do_line (cppReader *, /*@null@*/ struct directive *);
00438 static int do_include (cppReader *, struct directive *, char *, char *);
00439 static int do_undef (cppReader *, struct directive *, char *, char *);
00440 static int do_error (cppReader *, struct directive *, char *, char *);
00441 static int do_pragma (cppReader *, struct directive *, char *, char *);
00442 static int do_ident (cppReader *, struct directive *, char *, char *);
00443 static int do_if (cppReader *, struct directive *, char *, char *);
00444 static int do_xifdef (cppReader *, struct directive *, char *, char *);
00445 static int do_else (cppReader *, struct directive *, char *, char *);
00446 static int do_elif (cppReader *, struct directive *, char *, char *);
00447 static int do_endif (cppReader *, struct directive *, char *, char *);
00448 static int do_warning (cppReader *, struct directive *, char *, char *);
00449 
00450 /* If a buffer's dir field is SELF_DIR_DUMMY, it means the file was found
00451    via the same directory as the file that #included it.  */
00452 
00453 /*@constant observer struct file_name_list *SELF_DIR_DUMMY@*/
00454 #define SELF_DIR_DUMMY ((struct file_name_list *) (~0))
00455 
00456 /* #include "file" looks in source file dir, then stack.  */
00457 /* #include <file> just looks in the stack.  */
00458 /* -I directories are added to the end, then the defaults are added.  */
00459 
00460 /*@access cstring@*/
00461 
00462 static struct default_include {
00463   /*@dependent@*/ /*@observer@*/ cstring fname; /* The name of the directory.  */
00464   int cplusplus;                /* Only look here if we're compiling C++.  */
00465   int cxx_aware;                /* Includes in this directory don't need to
00466                                    be wrapped in extern "C" when compiling
00467                                    C++.  */
00468 } include_defaults_array[]
00469 = {
00470   /* This is the dir for fixincludes.  Put it just before
00471      the files that we fix.  */
00472   { GCC_INCLUDE_DIR, 0, 0 },
00473   { GCC_INCLUDE_DIR2, 0, 0 },
00474   { cstring_undefined, 0, 0 }
00475 };
00476 
00477 /*@noaccess cstring@*/
00478 
00479 /* Here is the actual list of #-directives, most-often-used first.
00480    The initialize_builtins function assumes #define is the very first.  */
00481 
00482 /*@access cstring@*/
00483 
00484 static struct directive directive_table[] = {
00485   {  6, do_define, "define", T_DEFINE, FALSE, TRUE, FALSE },
00486   {  5, do_xifdef, "ifdef", T_IFDEF, TRUE, FALSE, FALSE },
00487   {  6, do_xifdef, "ifndef", T_IFNDEF, TRUE, FALSE, FALSE },
00488   {  7, do_include, "include", T_INCLUDE, TRUE, FALSE, FALSE },
00489   {  5, do_endif, "endif", T_ENDIF, TRUE, FALSE, FALSE },
00490   {  4, do_else, "else", T_ELSE, TRUE, FALSE, FALSE },
00491   {  2, do_if, "if", T_IF, TRUE, FALSE, FALSE },
00492   {  4, do_elif, "elif", T_ELIF, TRUE, FALSE, FALSE },
00493   {  5, do_undef, "undef", T_UNDEF, FALSE, FALSE, FALSE },
00494   {  5, do_error, "error", T_ERROR, FALSE, FALSE, FALSE },
00495   {  7, do_warning, "warning", T_WARNING, FALSE, FALSE, FALSE },
00496   {  6, do_pragma, "pragma", T_PRAGMA, FALSE, FALSE, TRUE},
00497   {  4, do_line, "line", T_LINE, TRUE, FALSE, FALSE },
00498   {  5, do_ident, "ident", T_IDENT, TRUE, FALSE, TRUE },
00499   /* {  8, do_unassert, "unassert", T_UNASSERT, TRUE, FALSE, FALSE }, */
00500   {  -1, 0, "", T_UNUSED, FALSE, FALSE, FALSE },
00501 };
00502 
00503 /*@noaccess cstring@*/
00504 /*@+charint@*/
00505 
00506 static void
00507 initialize_char_syntax (struct cppOptions *opts)
00508 {
00509   char i;
00510 
00511   /*
00512    * Set up is_idchar and is_idstart tables.  These should be
00513    * faster than saying (is_alpha (c) || c == '_'), etc.
00514    * Set up these things before calling any routines tthat
00515    * refer to them.
00516    */
00517 
00518   for (i = 'a'; i <= 'z'; i++) {
00519     is_idchar[i - 'a' + 'A'] = TRUE;
00520     is_idchar[(int) i] = TRUE;
00521     is_idstart[i - 'a' + 'A'] = TRUE;
00522     is_idstart[(int) i] = TRUE;
00523   }
00524 
00525   for (i = '0'; i <= '9'; i++)
00526     {
00527       is_idchar[(int) i] = TRUE;
00528     }
00529 
00530   is_idchar['_'] = TRUE;
00531   is_idstart['_'] = TRUE;
00532   is_idchar['$'] = opts->dollars_in_ident;
00533   is_idstart['$'] = opts->dollars_in_ident;
00534 
00535   /* horizontal space table */
00536   is_hor_space[' '] = TRUE;
00537   is_hor_space['\t'] = TRUE;
00538   is_hor_space['\v'] = TRUE;
00539   is_hor_space['\f'] = TRUE;
00540   is_hor_space['\r'] = TRUE;
00541 
00542   is_space[' '] = TRUE;
00543   is_space['\t'] = TRUE;
00544   is_space['\v'] = TRUE;
00545   is_space['\f'] = TRUE;
00546   is_space['\n'] = TRUE;
00547   is_space['\r'] = TRUE;
00548 }
00549 
00550 bool isIdentifierChar (char c)
00551 {
00552   return is_idchar[(int) c];
00553 }
00554 
00555 /* Place into P_PFILE a quoted string representing the string SRC.
00556    Caller must reserve enough space in pfile->token_buffer.  */
00557 
00558 static void
00559 quote_string (cppReader *pfile, char *src)
00560 {
00561   char c;
00562 
00563   cppReader_putCharQ (pfile, '\"');
00564   for (;;)
00565     {
00566       switch ((c = *src++))
00567         {
00568         default:
00569           if (isprint (c))
00570             cppReader_putCharQ (pfile, c);
00571           else
00572             {
00573               sprintf (cppReader_getPWritten (pfile), "\\%03o",
00574                        (unsigned int) c);
00575               cppReader_adjustWritten (pfile, (size_t) 4);
00576             }
00577           /*@switchbreak@*/ break;
00578 
00579         case '\"':
00580         case '\\':
00581           cppReader_putCharQ (pfile, '\\');
00582           cppReader_putCharQ (pfile, c);
00583           /*@switchbreak@*/ break;
00584 
00585         case '\0':
00586           cppReader_putCharQ (pfile, '\"');
00587           cppReader_nullTerminateQ (pfile);
00588           return;
00589         }
00590     }
00591 }
00592 
00593 /* Re-allocates PFILE->token_buffer so it will hold at least N more chars.  */
00594 
00595 void
00596 cppReader_growBuffer (cppReader *pfile, size_t n)
00597 {
00598   size_t old_written = cppReader_getWritten (pfile);
00599   pfile->token_buffer_size = n + 2 * pfile->token_buffer_size;
00600   pfile->token_buffer = (char *)
00601     drealloc (pfile->token_buffer, pfile->token_buffer_size);
00602   cppReader_setWritten (pfile, old_written);
00603 }
00604 
00605 /*
00606  * process a given definition string, for initialization
00607  * If STR is just an identifier, define it with value 1.
00608  * If STR has anything after the identifier, then it should
00609  * be identifier=definition.
00610  */
00611 
00612 void
00613 cppReader_define (cppReader *pfile, char *str)
00614 {
00615   char *buf = NULL;
00616   char *p = str;
00617 
00618   DPRINTF (("Cpp reader define: %s", str));
00619 
00620   if (!is_idstart[(int) *p])
00621     {
00622       DPRINTF (("ERROR 1"));
00623       cppReader_error (pfile,
00624                        message ("Malformed option `-D%s'",
00625                                 cstring_fromChars (str)));
00626       
00627       return;
00628     }
00629 
00630   p++;
00631 
00632   DPRINTF (("Here 2"));
00633 
00634   while (is_idchar[(int) *p])
00635     {
00636       p++;
00637     }
00638 
00639   if (*p == '(') {
00640     p++;
00641     while (*p != ')' && *p != '\0') {
00642       p++;
00643     }
00644 
00645     if (*p == ')') {
00646       p++;
00647     } else {
00648       cppReader_error 
00649         (pfile,
00650          message ("Malformed option: -D%s (no closing parenthesis)", 
00651                   cstring_fromChars (str)));
00652     }
00653   }
00654 
00655   DPRINTF (("Here 2"));
00656 
00657   if (*p == '\0')
00658     {
00659       buf = (char *) dmalloc (size_fromInt (p - str + 4));
00660       strcpy ((char *) buf, str);
00661       strcat ((char *) buf, " 1");
00662     }
00663   else if (*p != '=')
00664     {
00665       DPRINTF (("ERROR 2"));
00666       cppReader_error (pfile,
00667                        message ("Malformed option: -D%s (expected '=', found '%c')",
00668                                 cstring_fromChars (str),
00669                                 *p));
00670       return;
00671     }
00672   else
00673     {
00674       char *q;
00675       /* Copy the entire option so we can modify it.  */
00676       DPRINTF (("Copying..."));
00677       buf = (char *) dmalloc (2 * strlen (str) + 1);
00678       strncpy (buf, str, size_fromInt (p - str));
00679 
00680       /* Change the = to a space.  */
00681       buf[p - str] = ' ';
00682       /* Scan for any backslash-newline and remove it.  */
00683       p++;
00684       q = &buf[p - str];
00685 
00686       while (*p != '\0')
00687         {
00688           if (*p == '\\' && p[1] == '\n')
00689             p += 2;
00690           else
00691             *q++ = *p++;
00692         }
00693 
00694       DPRINTF (("Here we are..."));
00695       *q = '\0';
00696     }
00697 
00698   llassert (buf != NULL);
00699   DPRINTF (("Do define: %s / %ld", buf, size_toLong (strlen (buf))));
00700   (void) do_define (pfile, NULL, buf, buf + strlen (buf));
00701   sfree (buf);
00702 }
00703 
00704 /* Append a chain of `struct file_name_list's
00705    to the end of the main include chain.
00706    FIRST is the beginning of the chain to append, and LAST is the end.  */
00707 
00708 void
00709 cppReader_appendIncludeChain (cppReader *pfile,
00710                       struct file_name_list *first,
00711                       struct file_name_list *last)
00712 {
00713   struct cppOptions *opts = CPPOPTIONS (pfile);
00714   struct file_name_list *dir;
00715 
00716   if (first == NULL || last == NULL)
00717     {
00718       return;
00719     }
00720 
00721   if (opts->include == 0)
00722     {
00723       opts->include = first;
00724     }
00725   else
00726     {
00727       llassert (opts->last_include->next == NULL);
00728       opts->last_include->next = first;
00729     }
00730 
00731   if (opts->first_bracket_include == 0)
00732     {
00733       opts->first_bracket_include = first;
00734 
00735       for (dir = first; ; dir = dir->next) {
00736         int len = cstring_length (dir->fname) + INCLUDE_LEN_FUDGE;
00737         if (len > pfile->max_include_len)
00738           pfile->max_include_len = len;
00739         if (dir == last)
00740           break;
00741       }
00742     }
00743 
00744   llassert (last->next == NULL);
00745   /* last->next = NULL; */
00746   opts->last_include = last;
00747 }
00748 
00749 static /*@unused@*/ void 
00750 cppReader_showIncludeChain (cppReader *pfile)
00751 {
00752   struct file_name_list *dirs = CPPOPTIONS (pfile)->include;
00753 
00754   if (dirs != NULL)
00755     {
00756       while (dirs != NULL)
00757         {
00758           fprintf (stderr, "*%s*:", cstring_toCharsSafe (dirs->fname));
00759           dirs = dirs->next;
00760         }
00761 
00762       fprintf (stderr, "\n");
00763     }
00764   else
00765     {
00766       fprintf (stderr, "No includes\n");
00767     }
00768 }
00769 
00770 void
00771 cppReader_addIncludeChain (cppReader *pfile, struct file_name_list *dir)
00772 {
00773   struct cppOptions *opts = CPPOPTIONS (pfile);
00774 
00775   if (dir == 0)
00776     {
00777       return;
00778     }
00779 
00780   if (opts->include == 0)
00781     {
00782       opts->include = dir;
00783     }
00784   else
00785     {
00786       llassert (opts->last_include->next == NULL);
00787       opts->last_include->next = dir;
00788     }
00789 
00790   if (opts->first_bracket_include == 0)
00791     {
00792       int len = cstring_length (dir->fname) + INCLUDE_LEN_FUDGE;
00793       opts->first_bracket_include = dir;
00794       if (len > pfile->max_include_len)
00795         {
00796           pfile->max_include_len = len;
00797         }
00798     }
00799 
00800   dir->next = NULL;
00801   opts->last_include = dir;
00802   /* cppReader_showIncludeChain (pfile); */
00803 }
00804 
00805 /* Given a colon-separated list of file names PATH,
00806    add all the names to the search path for include files.  */
00807 
00808 static void
00809 path_include (cppReader *pfile, char *path)
00810 {
00811   char *p;
00812 
00813 #ifdef __CYGWIN32__
00814   char *win32temp;
00815 
00816   /* if we have a posix path list, convert to win32 path list */
00817   win32temp = (char *) dmalloc /*@i4@*/
00818     (cygwin32_posix_to_win32_path_list_buf_size (path));
00819   cygwin32_posix_to_win32_path_list (path, win32temp);
00820   path = win32temp;
00821 #endif
00822 
00823   p = path;
00824 
00825   if (*p != '\0')
00826     while (1) {
00827       char *q = p;
00828       char *name;
00829       struct file_name_list *dirtmp;
00830 
00831       /* Find the end of this name.  */
00832       while (*q != '\0' && *q != PATH_SEPARATOR)
00833         {
00834           q++;
00835         }
00836 
00837       if (p == q)
00838         {
00839           /* An empty name in the path stands for the current directory.  */
00840           name = (char *) dmalloc ((size_t) 2);
00841           name[0] = '.';
00842           name[1] = '\0';
00843         }
00844       else
00845         {
00846           /* Otherwise use the directory that is named.  */
00847           name = (char *) dmalloc (size_fromInt (q - p + 1));
00848           memcpy (name, p, size_fromInt (q - p));
00849           name[q - p] = '\0';
00850         }
00851 
00852       dirtmp = (struct file_name_list *) dmalloc (sizeof (*dirtmp));
00853       dirtmp->next = 0;         /* New one goes on the end */
00854       dirtmp->control_macro = 0;
00855       dirtmp->c_system_include_path = 0;
00856       dirtmp->fname = cstring_fromChars (name);
00857       dirtmp->got_name_map = 0;
00858       cppReader_addIncludeChain (pfile, dirtmp);
00859 
00860       /* Advance past this name.  */
00861       p = q;
00862       if (*p == '\0')
00863         break;
00864       /* Skip the colon.  */
00865       p++;
00866     }
00867 }
00868 
00869 void
00870 cppOptions_init (cppOptions *opts)
00871 {
00872   memset ((char *) opts, 0, sizeof *opts);
00873   assertSet (opts);
00874 
00875   opts->in_fname = NULL;
00876   opts->out_fname = NULL;
00877 
00878   /* Initialize is_idchar to allow $.  */
00879   opts->dollars_in_ident = TRUE;
00880 
00881   opts->no_line_commands = 0;
00882   opts->no_trigraphs = TRUE;
00883   opts->put_out_comments = 1;
00884   opts->print_include_names = 0;
00885   opts->dump_macros = DUMP_DEFINITIONS; /* DUMP_NONE; */
00886   opts->no_output = 0;
00887   opts->cplusplus = 0;
00888 
00889   opts->cplusplus_comments = 1;
00890   opts->verbose = 0;
00891   opts->lang_asm = 0;
00892   opts->for_lint = 0;
00893   opts->chill = 0;
00894   opts->pedantic_errors = 0;
00895   opts->inhibit_warnings = 0;
00896   opts->warn_comments = 0;
00897   opts->warnings_are_errors = 0;
00898 
00899   initialize_char_syntax (opts);
00900 }
00901 
00902 enum cpp_token
00903 cppReader_nullUnderflow (/*@unused@*/ cppReader *pfile)
00904 {
00905   return CPP_EOF;
00906 }
00907 
00908 void
00909 cppReader_nullCleanup (/*@unused@*/ cppBuffer *pbuf,
00910               /*@unused@*/ cppReader *pfile)
00911 {
00912   ;
00913 }
00914 
00915 void
00916 cppReader_macroCleanup (cppBuffer *pbuf, /*@unused@*/ cppReader *pfile)
00917 {
00918   HASHNODE *macro = pbuf->hnode;
00919 
00920   if (macro->type == T_DISABLED)
00921     {
00922       macro->type = T_MACRO;
00923     }
00924 
00925   if (macro->type != T_MACRO || pbuf->buf != macro->value.defn->expansion)
00926     {
00927       sfree (pbuf->buf);
00928       pbuf->buf = NULL;
00929     }
00930 }
00931 
00932 void
00933 cppReader_fileCleanup (cppBuffer *pbuf, /*@unused@*/ cppReader *pfile)
00934 {
00935   if (pbuf->buf != NULL)
00936     {
00937       sfree (pbuf->buf);
00938       pbuf->buf = NULL;
00939     }
00940 }
00941 
00942 /* Assuming we have read '/'.
00943    If this is the start of a comment (followed by '*' or '/'),
00944    skip to the end of the comment, and return ' '.
00945    Return EOF if we reached the end of file before the end of the comment.
00946    If not the start of a comment, return '/'.  */
00947 
00948 static int
00949 skip_comment (cppReader *pfile, /*@null@*/ long *linep)
00950 {
00951   int c = 0;
00952 
00953   llassert (pfile->buffer != NULL);
00954   llassert (pfile->buffer->cur != NULL);
00955 
00956   while (cppReader_peekC (pfile) == '\\' && cpp_peekN (pfile, 1) == '\n')
00957     {
00958       if (linep != NULL)
00959         {
00960           (*linep)++;
00961         }
00962 
00963       cppReader_forward (pfile, 2);
00964     }
00965 
00966   if (cppReader_peekC (pfile) == '*')
00967     {
00968       cppReader_forward (pfile, 1);
00969 
00970       for (;;)
00971         {
00972           int prev_c = c;
00973           c = cppReader_getC (pfile);
00974 
00975           if (c == EOF)
00976             {
00977               return EOF;
00978             }
00979 
00980           while (c == (int) '\\' && cppReader_peekC (pfile) == (int) '\n')
00981             {
00982               if (linep != NULL )
00983                 {
00984                   (*linep)++;
00985                 }
00986 
00987               cppReader_forward (pfile, 1), c = cppReader_getC (pfile);
00988             }
00989 
00990           if (prev_c == (int) '*' && c == (int) '/')
00991             {
00992               return (int) ' ';
00993             }
00994 
00995           if (c == (int) '\n' && (linep != NULL))
00996             {
00997               (*linep)++;
00998             }
00999         }
01000     }
01001   else if (cppReader_peekC (pfile) == '/' 
01002            && CPPOPTIONS (pfile)->cplusplus_comments)
01003     {
01004       cppReader_forward (pfile, 1);
01005 
01006       for (;;)
01007         {
01008           c = cppReader_getC (pfile);
01009 
01010           if (c == EOF)
01011             {
01012               /* Allow hash comment to be terminated by EOF.  */
01013               return (int) ' '; 
01014             }
01015 
01016           while (c == (int) '\\' && cppReader_peekC (pfile) == '\n')
01017             {
01018               cppReader_forward (pfile, 1);
01019               c = cppReader_getC (pfile);
01020 
01021               if (linep != NULL)
01022                 {
01023                   (*linep)++;
01024                 }
01025             }
01026 
01027           if (c == (int) '\n')
01028             {
01029               /* Don't consider final '\n' to be part of comment.  */
01030               cppReader_forward (pfile, -1);
01031               return (int) ' ';
01032             }
01033         }
01034     }
01035   else
01036     {
01037       return (int) '/';
01038     }
01039 }
01040 
01041 /* Skip whitespace \-newline and comments.  Does not macro-expand.  */
01042 int /*@alt void@*/
01043 cppSkipHspace (cppReader *pfile)
01044 {
01045   int nspaces = 0;
01046 
01047   while (TRUE)
01048     {
01049       int c;
01050 
01051       llassert (pfile->buffer != NULL);
01052 
01053       c = cppReader_peekC (pfile);
01054 
01055       if (c == EOF)
01056         {
01057           return 0; /* FIXME */
01058         }
01059 
01060       if (is_hor_space[c])
01061         {
01062           if ((c == '\f' || c == '\v') && cppReader_isPedantic (pfile))
01063             cppReader_pedwarn (pfile,
01064                          message ("%s in preprocessing directive",
01065                                   c == '\f'
01066                                   ? cstring_makeLiteralTemp ("formfeed")
01067                                   : cstring_makeLiteralTemp ("vertical tab")));
01068 
01069           nspaces++;
01070           cppReader_forward (pfile, 1);
01071         }
01072       else if (c == '/')
01073         {
01074           cppReader_forward (pfile, 1);
01075           c = skip_comment (pfile, NULL);
01076 
01077           if (c == '/')
01078             {
01079               cppReader_forward (pfile, -1);
01080             }
01081 
01082           if (c == EOF || c == '/')
01083             {
01084               return nspaces;
01085             }
01086         }
01087       else if (c == '\\' && cpp_peekN (pfile, 1) == '\n')
01088         {
01089           cppReader_forward (pfile, 2);
01090         }
01091       else if (c == '@' && CPPBUFFER (pfile)->has_escapes
01092                && is_hor_space [cpp_peekN (pfile, 1)])
01093         {
01094           cppReader_forward (pfile, 2);
01095         }
01096       else
01097         {
01098           return nspaces;
01099         }
01100     }
01101 }
01102 
01103 /* Read the rest of the current line.
01104    The line is appended to PFILE's output buffer.  */
01105 
01106 static void
01107 copy_rest_of_line (cppReader *pfile)
01108 {
01109   struct cppOptions *opts = CPPOPTIONS (pfile);
01110 
01111   for (;;)
01112     {
01113       int c;
01114       int nextc;
01115 
01116       llassert (pfile->buffer != NULL);
01117 
01118       c = cppReader_getC (pfile);
01119       switch (c)
01120         {
01121         case EOF:
01122           goto end_directive;
01123         case '\\':
01124           if (cppReader_peekC (pfile) == '\n')
01125             {
01126               cppReader_forward (pfile, 1);
01127               continue;
01128             }
01129 
01130         /*@fallthrough@*/ case '\'': case '\"':
01131           goto scan_directive_token;
01132 
01133         case '/':
01134           nextc = cppReader_peekC (pfile);
01135 
01136           /*
01137           ** was (opts->cplusplus_comments && nextc == '*')
01138           ** yoikes!
01139           */
01140 
01141           if (nextc == '*'
01142               || (opts->cplusplus_comments && nextc == '/'))
01143             {
01144               goto scan_directive_token;
01145             }
01146           /*@switchbreak@*/ break;
01147         case '\f':
01148         case '\v':
01149           if (cppReader_isPedantic (pfile))
01150             cppReader_pedwarn (pfile,
01151                          message ("%s in preprocessing directive",
01152                                   c == '\f'
01153                                   ? cstring_makeLiteralTemp ("formfeed")
01154                                   : cstring_makeLiteralTemp ("vertical tab")));
01155           /*@switchbreak@*/ break;
01156 
01157         case '\n':
01158           cppReader_forward (pfile, -1);
01159           goto end_directive;
01160         scan_directive_token:
01161           cppReader_forward (pfile, -1);
01162           (void) cppGetToken (pfile);
01163           continue;
01164         }
01165       cppReader_putChar (pfile, c);
01166     }
01167 end_directive: ;
01168   cppReader_nullTerminate (pfile);
01169 }
01170 
01171 void
01172 cppReader_skipRestOfLine (cppReader *pfile)
01173 {
01174   size_t old = cppReader_getWritten (pfile);
01175   copy_rest_of_line (pfile);
01176   cppReader_setWritten (pfile, old);
01177 }
01178 
01179 /* Handle a possible # directive.
01180    '#' has already been read.  */
01181 
01182 int
01183 cppReader_handleDirective (cppReader *pfile)
01184 {
01185   int c;
01186   struct directive *kt = NULL;
01187   int ident_length;
01188   size_t after_ident = 0;
01189   char *ident, *line_end = NULL;
01190   size_t old_written = cppReader_getWritten (pfile);
01191   int nspaces = cppSkipHspace (pfile);
01192 
01193   c = cppReader_peekC (pfile);
01194 
01195   if (c >= '0' && c <= '9')
01196     {
01197       /* Handle # followed by a line number.  */
01198       if (cppReader_isPedantic (pfile))
01199         {
01200           cppReader_pedwarnLit
01201             (pfile,
01202              cstring_makeLiteralTemp ("`#' followed by integer"));
01203         }
01204 
01205       (void) do_line (pfile, NULL);
01206       goto done_a_directive;
01207     }
01208 
01209 
01210   /* Now find the directive name.  */
01211 
01212   cppReader_putChar (pfile, '#');
01213 
01214   parse_name (pfile, cppReader_getC (pfile));
01215 
01216   llassert (pfile->token_buffer != NULL);
01217   ident = pfile->token_buffer + old_written + 1;
01218 
01219   ident_length = cppReader_getPWritten (pfile) - ident;
01220 
01221   if (ident_length == 0 && cppReader_peekC (pfile) == '\n')
01222     {
01223       /* A line of just `#' becomes blank.  */
01224       return 1; 
01225     }
01226 
01227   for (kt = directive_table; ; kt++) 
01228     {
01229       if (kt->length <= 0)
01230         {
01231           return 0; /* goto not_a_directive; */
01232         }
01233 
01234       if (kt->length == ident_length
01235           && (cstring_equalPrefix (kt->name, ident)))
01236         {
01237           break;
01238         }
01239     }
01240 
01241   if (kt->command_reads_line)
01242     {
01243       after_ident = 0;
01244     }
01245   else
01246     {
01247       /* Nonzero means do not delete comments within the directive.
01248          #define needs this when -traditional.  */
01249       bool comments = 1; /*cppReader_isTraditional (pfile) && kt->traditional_comments;  */
01250       int save_put_out_comments = CPPOPTIONS (pfile)->put_out_comments;
01251       CPPOPTIONS (pfile)->put_out_comments = comments;
01252       after_ident = cppReader_getWritten (pfile);
01253       copy_rest_of_line (pfile);
01254       CPPOPTIONS (pfile)->put_out_comments = save_put_out_comments;
01255     }
01256 
01257 
01258   /* For #pragma and #define, we may want to pass through the directive.
01259      Other directives may create output, but we don't want the directive
01260      itself out, so we pop it now.  For example #include may write a #line
01261      command (see comment in do_include), and conditionals may emit
01262      #failed ... #endfailed stuff.  But note that popping the buffer
01263      means the parameters to kt->func may point after pfile->limit
01264      so these parameters are invalid as soon as something gets appended
01265      to the token_buffer.  */
01266 
01267   line_end = cppReader_getPWritten (pfile);
01268 
01269 
01270   if (!kt->pass_thru && kt->type != T_DEFINE)
01271     {
01272       cppReader_setWritten (pfile, old_written);
01273     }
01274 
01275   llassert (pfile->token_buffer != NULL);
01276 
01277   /* was kt->pass_thru || */
01278 
01279   if (kt->type == T_DEFINE
01280       && cpp_shouldCheckMacro (pfile, pfile->token_buffer + old_written))
01281     {
01282       char *p = pfile->token_buffer + old_written;
01283 
01284       /*
01285       ** Still need to record value for preprocessing, so 
01286       ** #ifdef's, etc. using the value behave correctly.
01287       */
01288       
01289       (void) do_defineAux (pfile, kt, 
01290                            pfile->token_buffer + after_ident,
01291                            line_end,
01292                            TRUE);
01293       
01294       if (*p == '#')
01295         {
01296           *p = ' ';
01297         }
01298 
01299       SKIP_WHITE_SPACE (p);
01300 
01301       llassert (*p == 'd');
01302       *p++ = LLMRCODE[0];
01303 
01304       llassert (*p == 'e');
01305       *p++ = LLMRCODE[1];
01306 
01307       llassert (*p == 'f');
01308       *p++ = LLMRCODE[2];
01309 
01310       llassert (*p == 'i');
01311       *p++ = LLMRCODE[3];
01312 
01313       llassert (*p == 'n');
01314       *p++ = LLMRCODE[4];
01315 
01316       llassert (*p == 'e');
01317 
01318       /*
01319       ** This is way-bogus.  We use the last char to record the number of
01320       ** spaces.  Its too hard to get them back into the input stream.
01321       */
01322 
01323       if (nspaces > 9) nspaces = 9;
01324 
01325       *p++ = '0' + nspaces;
01326 
01327       return 0; /* not_a_directive */
01328     }
01329   else if (kt->pass_thru)
01330     {
01331       /* Just leave the entire #define in the output stack.  */
01332       return 0; /* not_a_directive */
01333 
01334     }
01335   else if (kt->type == T_DEFINE
01336            && CPPOPTIONS (pfile)->dump_macros == DUMP_NAMES)
01337     {
01338       char *p = pfile->token_buffer + old_written + 7;  /* Skip "#define". */
01339       SKIP_WHITE_SPACE (p);
01340 
01341       while (is_idchar[(int) *p])
01342         {
01343           p++;
01344         }
01345 
01346       pfile->limit = p;
01347       cppReader_putChar (pfile, '\n');
01348     }
01349   else if (kt->type == T_DEFINE)
01350     {
01351       cppReader_setWritten (pfile, old_written);
01352     }
01353   else
01354     {
01355       ;
01356     }
01357 
01358 done_a_directive:
01359   if (kt == NULL) {
01360     return 1;
01361   } else {
01362     llassert (kt->func != NULL);
01363     (void) (kt->func) (pfile, kt, pfile->token_buffer + after_ident, line_end);
01364     return 1;
01365   }
01366 }
01367 
01368 /* Pass a directive through to the output file.
01369    BUF points to the contents of the directive, as a contiguous string.
01370    LIMIT points to the first character past the end of the directive.
01371    KEYWORD is the keyword-table entry for the directive.  */
01372 
01373 static void
01374 pass_thru_directive (char *buf, char *limit,
01375                      cppReader *pfile,
01376                      struct directive *keyword)
01377 {
01378   int keyword_length = keyword->length;
01379 
01380   cppReader_reserve (pfile,
01381                      size_fromInt (2 + keyword_length + (limit - buf)));
01382   cppReader_putCharQ (pfile, '#');
01383   /*@-observertrans@*/
01384   cppReader_putStrN (pfile, cstring_toCharsSafe (keyword->name),
01385                      size_fromInt (keyword_length));
01386   /*:=observertrans@*/
01387 
01388   if (limit != buf && buf[0] != ' ')
01389     {
01390       /* Was a bug, since reserve only used 1 + ... */
01391       cppReader_putCharQ (pfile, ' ');
01392     }
01393 
01394   cppReader_putStrN (pfile, buf, size_fromInt (limit - buf));
01395 }
01396 
01397 /* Read a replacement list for a macro with parameters.
01398    Build the DEFINITION structure.
01399    Reads characters of text starting at BUF until END.
01400    ARGLIST specifies the formal parameters to look for
01401    in the text of the definition; NARGS is the number of args
01402    in that list, or -1 for a macro name that wants no argument list.
01403    MACRONAME is the macro name itself (so we can avoid recursive expansion)
01404    and NAMELEN is its length in characters.
01405 
01406    Note that comments, backslash-newlines, and leading white space
01407    have already been deleted from the argument.  */
01408 
01409 static DEFINITION *
01410 collect_expansion (cppReader *pfile, char *buf, char *limit,
01411                    int nargs, /*@null@*/ struct arglist *arglist)
01412 {
01413   DEFINITION *defn;
01414   char *p, *lastp, *exp_p;
01415   struct reflist *endpat = NULL;
01416   /* Pointer to first nonspace after last ## seen.  */
01417   char *concat = 0;
01418   /* Pointer to first nonspace after last single-# seen.  */
01419   char *stringify = 0;
01420   size_t maxsize;
01421   char expected_delimiter = '\0';
01422 
01423 
01424   /* Scan thru the replacement list, ignoring comments and quoted
01425      strings, picking up on the macro calls.  It does a linear search
01426      thru the arg list on every potential symbol.  Profiling might say
01427      that something smarter should happen.  */
01428 
01429   if (limit < buf)
01430     abort ();
01431 
01432   /* Find the beginning of the trailing whitespace.  */
01433   p = buf;
01434 
01435   while (p < limit && is_space[(int) limit[-1]])
01436     {
01437       limit--;
01438     }
01439 
01440   /* Allocate space for the text in the macro definition.
01441      Leading and trailing whitespace chars need 2 bytes each.
01442      Each other input char may or may not need 1 byte,
01443      so this is an upper bound.  The extra 5 are for invented
01444      leading and trailing newline-marker and final null.  */
01445   maxsize = (sizeof (*defn) + (limit - p) + 5);
01446 
01447   /* Occurrences of '@' get doubled, so allocate extra space for them.  */
01448   while (p < limit)
01449     {
01450       if (*p++ == '@')
01451         {
01452           maxsize++;
01453         }
01454     }
01455 
01456   defn = (DEFINITION *) dmalloc (maxsize);
01457   defn->noExpand = FALSE;
01458   defn->file = NULL;
01459   defn->pattern = NULL;
01460   defn->nargs = nargs;
01461   defn->predefined = NULL;
01462 
01463   exp_p = defn->expansion = (char *) defn + sizeof (*defn);
01464 
01465   defn->line = 0;
01466   defn->rest_args = NULL;
01467   defn->args.argnames = NULL;
01468 
01469   lastp = exp_p;
01470 
01471   p = buf;
01472 
01473   /* Add one initial space escape-marker to prevent accidental
01474      token-pasting (often removed by macroexpand).  */
01475   *exp_p++ = '@';
01476   *exp_p++ = ' ';
01477 
01478   if (limit - p >= 2 && p[0] == '#' && p[1] == '#') {
01479     cppReader_errorLit (pfile,
01480                   cstring_makeLiteralTemp ("`##' at start of macro definition"));
01481     p += 2;
01482   }
01483 
01484   /* Process the main body of the definition.  */
01485   while (p < limit) {
01486     int skipped_arg = 0;
01487     register char c = *p++;
01488 
01489     *exp_p++ = c;
01490 
01491     if (!cppReader_isTraditional (pfile)) {
01492       switch (c) {
01493       case '\'':
01494       case '\"':
01495         if (expected_delimiter != '\0')
01496           {
01497             if (c == expected_delimiter)
01498               expected_delimiter = '\0';
01499           }
01500         else
01501           {
01502             expected_delimiter = c;
01503           }
01504         /*@switchbreak@*/ break;
01505 
01506       case '\\':
01507         if (p < limit && (expected_delimiter != '\0'))
01508           {
01509             /* In a string, backslash goes through
01510                and makes next char ordinary.  */
01511             *exp_p++ = *p++;
01512           }
01513         /*@switchbreak@*/ break;
01514 
01515       case '@':
01516         /* An '@' in a string or character constant stands for itself,
01517            and does not need to be escaped.  */
01518         if (expected_delimiter == '\0')
01519           {
01520             *exp_p++ = c;
01521           }
01522 
01523         /*@switchbreak@*/ break;
01524 
01525       case '#':
01526         /* # is ordinary inside a string.  */
01527         if (expected_delimiter != '\0')
01528           {
01529             /*@switchbreak@*/ break;
01530           }
01531 
01532         if (p < limit && *p == '#') {
01533           /* ##: concatenate preceding and following tokens.  */
01534           /* Take out the first #, discard preceding whitespace.  */
01535           exp_p--;
01536 
01537           /*@-usedef@*/
01538           while (exp_p > lastp && is_hor_space[(int) exp_p[-1]])
01539             {
01540               --exp_p;
01541             }
01542           /*@=usedef@*/
01543 
01544           /* Skip the second #.  */
01545           p++;
01546           /* Discard following whitespace.  */
01547           SKIP_WHITE_SPACE (p);
01548           concat = p;
01549           if (p == limit)
01550             {
01551               cppReader_errorLit (pfile,
01552                             cstring_makeLiteralTemp ("`##' at end of macro definition"));
01553             }
01554         } else if (nargs >= 0) {
01555           /* Single #: stringify following argument ref.
01556              Don't leave the # in the expansion.  */
01557           exp_p--;
01558           SKIP_WHITE_SPACE (p);
01559           if (p == limit || ! is_idstart[(int) *p]
01560               || (*p == 'L' && p + 1 < limit && (p[1] == '\'' || p[1] == '"')))
01561             cppReader_errorLit (pfile,
01562                           cstring_makeLiteralTemp ("`#' operator is not followed by a macro argument name"));
01563           else
01564             stringify = p;
01565         } else {
01566           ; /* BADBRANCH; */
01567         }
01568 
01569         /*@switchbreak@*/ break;
01570       }
01571     } else {
01572       /* In -traditional mode, recognize arguments inside strings and
01573          and character constants, and ignore special properties of #.
01574          Arguments inside strings are considered "stringified", but no
01575          extra quote marks are supplied.  */
01576       switch (c) {
01577       case '\'':
01578       case '\"':
01579         if (expected_delimiter != '\0') {
01580           if (c == expected_delimiter)
01581             expected_delimiter = '\0';
01582         } else
01583           expected_delimiter = c;
01584         /*@switchbreak@*/ break;
01585 
01586       case '\\':
01587         /* Backslash quotes delimiters and itself, but not macro args.  */
01588         if (expected_delimiter != '\0' && p < limit
01589             && (*p == expected_delimiter || *p == '\\')) {
01590           *exp_p++ = *p++;
01591           continue;
01592         }
01593         /*@switchbreak@*/ break;
01594 
01595       case '/':
01596         if (expected_delimiter != '\0') /* No comments inside strings.  */
01597           /*@switchbreak@*/ break;
01598         if (*p == '*') {
01599           /* If we find a comment that wasn't removed by cppReader_handleDirective,
01600              this must be -traditional.  So replace the comment with
01601              nothing at all.  */
01602           exp_p--;
01603           p += 1;
01604           while (p < limit && !(p[-2] == '*' && p[-1] == '/'))
01605             {
01606               p++;
01607             }
01608         }
01609         /*@switchbreak@*/ break;
01610       }
01611     }
01612 
01613     /* Handle the start of a symbol.  */
01614     if (is_idchar[(int) c] && nargs > 0) {
01615       char *id_beg = p - 1;
01616       int id_len;
01617 
01618       --exp_p;
01619       while (p != limit && is_idchar[(int) *p])
01620         {
01621           p++;
01622         }
01623 
01624       id_len = p - id_beg;
01625 
01626       if (is_idstart[(int) c]
01627           && ! (id_len == 1 && c == 'L' && (*p == '\'' || *p == '"'))) {
01628         register struct arglist *arg;
01629 
01630         for (arg = arglist; arg != NULL; arg = arg->next) {
01631           struct reflist *tpat;
01632 
01633           if (arg->name[0] == c
01634               && arg->length == id_len
01635               && strncmp (arg->name, id_beg, size_fromInt (id_len)) == 0) {
01636             char *p1;
01637 
01638             if (expected_delimiter && CPPOPTIONS (pfile)->warn_stringify) {
01639               if (cppReader_isTraditional (pfile)) {
01640                 cppReader_warning (pfile,
01641                                    message ("macro argument `%x' is stringified.",
01642                                             cstring_prefix (cstring_fromChars (arg->name), id_len)));
01643               } else {
01644                 cppReader_warning (pfile,
01645                                    message ("macro arg `%x' would be stringified with -traditional.",
01646                                             cstring_prefix (cstring_fromChars (arg->name), id_len)));
01647               }
01648             }
01649             /* If ANSI, don't actually substitute inside a string.  */
01650             if (!cppReader_isTraditional (pfile) && expected_delimiter)
01651               /*@innerbreak@*/ break;
01652             /* make a pat node for this arg and append it to the end of
01653                the pat list */
01654             tpat = (struct reflist *) dmalloc (sizeof (*tpat));
01655             tpat->next = NULL;
01656             tpat->raw_before = (concat == id_beg);
01657             tpat->raw_after = 0;
01658             tpat->rest_args = arg->rest_args;
01659             tpat->stringify = (cppReader_isTraditional (pfile)
01660                                ? expected_delimiter != '\0'
01661                                : stringify == id_beg);
01662 
01663             if (endpat == NULL)
01664               {
01665                 defn->pattern = tpat;
01666               }
01667             else
01668               {
01669                 endpat->next = tpat;
01670                 /*@-branchstate@*/
01671               } /*@=branchstate@*/ /* evs 2000 was =branchstate */
01672 
01673             endpat = tpat;
01674 
01675             tpat->argno = arg->argno;
01676             tpat->nchars = exp_p - lastp;
01677 
01678             p1 = p;
01679 
01680             SKIP_WHITE_SPACE (p1);
01681 
01682             if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#')
01683               {
01684                 tpat->raw_after = 1;
01685               }
01686 
01687             lastp = exp_p;      /* place to start copying from next time */
01688             skipped_arg = 1;
01689 
01690             /*@innerbreak@*/ break;
01691           }
01692         }
01693       }
01694 
01695       /* If this was not a macro arg, copy it into the expansion.  */
01696       if (skipped_arg == 0) {
01697         register char *lim1 = p;
01698         p = id_beg;
01699 
01700         while (p != lim1)
01701           {
01702             *exp_p++ = *p++;
01703           }
01704 
01705         if (stringify == id_beg)
01706           cppReader_errorLit (pfile,
01707                               cstring_makeLiteralTemp ("`#' operator should be followed by a macro argument name"));
01708       }
01709     }
01710   }
01711 
01712   if (!cppReader_isTraditional (pfile) && expected_delimiter == '\0')
01713     {
01714       /* If ANSI, put in a "@ " marker to prevent token pasting.
01715          But not if "inside a string" (which in ANSI mode
01716          happens only for -D option).  */
01717       *exp_p++ = '@';
01718       *exp_p++ = ' ';
01719     }
01720 
01721   *exp_p = '\0';
01722 
01723   defn->length = size_fromInt (exp_p - defn->expansion);
01724 
01725   /* Crash now if we overrun the allocated size.  */
01726   if (defn->length + 1 > maxsize)
01727     {
01728       llfatalbug (cstring_makeLiteral ("Maximum definition size exceeded."));
01729     }
01730 
01731   return defn;
01732 }
01733 
01734 /*
01735  * special extension string that can be added to the last macro argument to
01736  * allow it to absorb the "rest" of the arguments when expanded.  Ex:
01737  *              #define wow(a, b...)            process (b, a, b)
01738  *              { wow (1, 2, 3); }      ->      { process (2, 3, 1, 2, 3); }
01739  *              { wow (one, two); }     ->      { process (two, one, two); }
01740  * if this "rest_arg" is used with the concat token '##' and if it is not
01741  * supplied then the token attached to with ## will not be outputted.  Ex:
01742  *              #define wow (a, b...)           process (b ## , a, ## b)
01743  *              { wow (1, 2); }         ->      { process (2, 1, 2); }
01744  *              { wow (one); }          ->      { process (one); {
01745  */
01746 
01747 /*@-readonlytrans@*/
01748 static char rest_extension[] = "...";
01749 /*:=readonlytrans@*/
01750 
01751 /*@notfunction@*/
01752 #define REST_EXTENSION_LENGTH   (sizeof (rest_extension) - 1)
01753 
01754 /* Create a DEFINITION node from a #define directive.  Arguments are
01755    as for do_define.  */
01756 
01757 static /*@null@*/ MACRODEF
01758 create_definition (char *buf, char *limit,
01759                    cppReader *pfile, bool predefinition,
01760                    bool noExpand)
01761 {
01762   char *bp;                     /* temp ptr into input buffer */
01763   char *symname;                /* remember where symbol name starts */
01764   int sym_length;               /* and how long it is */
01765   int rest_args = 0;   /* really int! */
01766   int line;
01767   int col;
01768   cstring file = (CPPBUFFER (pfile) != NULL)
01769     ? CPPBUFFER (pfile)->nominal_fname : cstring_makeLiteralTemp ("");
01770   DEFINITION *defn;
01771   int arglengths = 0;           /* Accumulate lengths of arg names
01772                                    plus number of args.  */
01773   MACRODEF mdef;
01774 
01775   cppBuffer_lineAndColumn (CPPBUFFER (pfile), &line, &col);
01776 
01777   bp = buf;
01778 
01779   while (is_hor_space[(int) *bp])
01780     {
01781       bp++;
01782     }
01783 
01784   symname = bp;                 /* remember where it starts */
01785 
01786   sym_length = cppReader_checkMacroName (pfile, bp, cstring_makeLiteralTemp ("macro"));
01787 
01788   bp += sym_length;
01789 
01790   /* Lossage will occur if identifiers or control keywords are broken
01791      across lines using backslash.  This is not the right place to take
01792      care of that.  */
01793 
01794   if (*bp == '(') {
01795     struct arglist *arg_ptrs = NULL;
01796     int argno = 0;
01797 
01798     bp++;                       /* skip '(' */
01799     SKIP_WHITE_SPACE (bp);
01800 
01801     /* Loop over macro argument names.  */
01802     while (*bp != ')')
01803       {
01804         struct arglist *temp = (struct arglist *) dmalloc (sizeof (*temp));
01805         temp->name = bp;
01806         temp->next = arg_ptrs;
01807         temp->argno = argno++;
01808         temp->rest_args = 0;
01809 
01810         arg_ptrs = temp;
01811 
01812         if (rest_args != 0)
01813           {
01814             cppReader_pedwarn (pfile,
01815                          message ("another parameter follows `%s'",
01816                                   cstring_fromChars (rest_extension)));
01817           }
01818 
01819         if (!is_idstart[(int) *bp])
01820           {
01821             cppReader_pedwarnLit (pfile,
01822                             cstring_makeLiteralTemp ("invalid character in macro parameter name"));
01823           }
01824 
01825         /* Find the end of the arg name.  */
01826         while (is_idchar[(int) *bp])
01827           {
01828             bp++;
01829             /* do we have a "special" rest-args extension here? */
01830             if (limit - bp > size_toInt (REST_EXTENSION_LENGTH)
01831                 && strncmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0)
01832               {
01833                 rest_args = 1;
01834                 temp->rest_args = 1;
01835                 /*@innerbreak@*/ break;
01836               }
01837           }
01838 
01839         temp->length = bp - temp->name;
01840 
01841         if (rest_args != 0)
01842           {
01843             bp += REST_EXTENSION_LENGTH;
01844           }
01845 
01846         arglengths += temp->length + 2;
01847         SKIP_WHITE_SPACE (bp);
01848 
01849         if (temp->length == 0 || (*bp != ',' && *bp != ')')) {
01850           cppReader_errorLit (pfile,
01851                         cstring_makeLiteralTemp ("Parameter list for #define is not parseable"));
01852           goto nope;
01853         }
01854 
01855         if (*bp == ',') {
01856           bp++;
01857           SKIP_WHITE_SPACE (bp);
01858         }
01859         if (bp >= limit) {
01860           cppReader_errorLit (pfile,
01861                         cstring_makeLiteralTemp ("unterminated parameter list in `#define'"));
01862           goto nope;
01863         }
01864         {
01865           struct arglist *otemp;
01866 
01867           for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
01868             {
01869               if (temp->length == otemp->length &&
01870                   strncmp (temp->name, otemp->name, size_fromInt (temp->length)) == 0) {
01871                 cstring name = cstring_copyLength (temp->name, temp->length);
01872                 cppReader_error (pfile,
01873                            message ("duplicate argument name `%x' in `#define'", name));
01874                 goto nope;
01875               }
01876             }
01877         }
01878       }
01879 
01880     ++bp;                       /* skip paren */
01881     SKIP_WHITE_SPACE (bp);
01882     /* now everything from bp before limit is the definition.  */
01883     defn = collect_expansion (pfile, bp, limit, argno, arg_ptrs);
01884     defn->rest_args = rest_args;
01885     
01886     /* Now set defn->args.argnames to the result of concatenating
01887        the argument names in reverse order
01888        with comma-space between them.  */
01889     defn->args.argnames = (char *) dmalloc (size_fromInt (arglengths + 1));
01890 
01891     {
01892       struct arglist *temp;
01893       int i = 0;
01894       for (temp = arg_ptrs; temp != NULL; temp = temp->next) {
01895         memcpy (&defn->args.argnames[i], temp->name, size_fromInt (temp->length));
01896         i += temp->length;
01897         if (temp->next != 0) {
01898           defn->args.argnames[i++] = ',';
01899           defn->args.argnames[i++] = ' ';
01900         }
01901       }
01902 
01903       defn->args.argnames[i] = '\0';
01904     }
01905 
01906     sfree (arg_ptrs);
01907   } else {
01908     /* Simple expansion or empty definition.  */
01909 
01910     if (bp < limit)
01911       {
01912         if (is_hor_space[(int) *bp]) {
01913           bp++;
01914           SKIP_WHITE_SPACE (bp);
01915         } else {
01916           switch (*bp) {
01917           case '!':  case '"':  case '#':  case '%':  case '&':  case '\'':
01918           case ')':  case '*':  case '+':  case ',':  case '-':  case '.':
01919           case '/':  case ':':  case ';':  case '<':  case '=':  case '>':
01920           case '?':  case '[':  case '\\': case ']':  case '^':  case '{':
01921           case '|':  case '}':  case '~':
01922             cppReader_warning (pfile,
01923                          message ("Missing white space after #define %x",
01924                                   cstring_prefix (cstring_fromChars (symname),
01925                                                   sym_length)));
01926             break;
01927 
01928           default:
01929             cppReader_pedwarn (pfile,
01930                          message ("Missing white space after #define %x",
01931                                   cstring_prefix (cstring_fromChars (symname),
01932                                                   sym_length)));
01933             break;
01934           }
01935         }
01936       }
01937     /* now everything from bp before limit is the definition.  */
01938     defn = collect_expansion (pfile, bp, limit, -1, NULL);
01939     defn->args.argnames = mstring_createEmpty ();
01940   }
01941 
01942   defn->noExpand = noExpand;
01943   DPRINTF (("No expand: %d", noExpand));
01944 
01945   defn->line = line;
01946 
01947   /* not: llassert (cstring_isUndefined (defn->file)); */
01948   defn->file = file;
01949 
01950   /* OP is null if this is a predefinition */
01951   defn->predefined = predefinition;
01952   mdef.defn = defn;
01953   mdef.symnam = symname;
01954   mdef.symlen = sym_length;
01955 
01956   return mdef;
01957 
01958 nope:
01959   mdef.defn = NULL;
01960   mdef.symnam = NULL;
01961   return mdef;
01962 }
01963 
01964 /* Check a purported macro name SYMNAME, and yield its length.
01965    USAGE is the kind of name this is intended for.  */
01966 
01967 int cppReader_checkMacroName (cppReader *pfile,
01968                       char *symname,
01969                       cstring usage)
01970 {
01971   char *p;
01972   size_t sym_length;
01973 
01974   for (p = symname; is_idchar[(int) *p]; p++)
01975     {
01976       ;
01977     }
01978 
01979   sym_length = size_fromInt (p - symname);
01980 
01981   if (sym_length == 0
01982       || (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))
01983     cppReader_error (pfile, message ("invalid %s name", usage));
01984   else if (!is_idstart[(int) *symname])
01985     {
01986       char *msg = (char *) dmalloc (sym_length + 1);
01987       memcpy (msg, symname, sym_length);
01988       msg[sym_length] = '\0';
01989       cppReader_error (pfile, message ("invalid %s name `%s'", usage,
01990                                        cstring_fromChars (msg)));
01991       sfree (msg);
01992     }
01993   else
01994     {
01995       if ((strncmp (symname, "defined", 7) == 0) && sym_length == 7)
01996         {
01997           cppReader_error (pfile, message ("invalid %s name `defined'", usage));
01998         }
01999     }
02000 
02001   return size_toInt (sym_length);
02002 }
02003 
02004 /* Return zero if two DEFINITIONs are isomorphic.  */
02005 
02006 static bool
02007 compare_defs (DEFINITION *d1, DEFINITION *d2)
02008 {
02009   register struct reflist *a1, *a2;
02010   register char *p1 = d1->expansion;
02011   register char *p2 = d2->expansion;
02012   bool first = TRUE;
02013 
02014   if (d1->nargs != d2->nargs)
02015     {
02016       return TRUE;
02017     }
02018 
02019   llassert (d1->args.argnames != NULL);
02020   llassert (d2->args.argnames != NULL);
02021 
02022   if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames) != 0)
02023     {
02024       return TRUE;
02025     }
02026 
02027   for (a1 = d1->pattern, a2 = d2->pattern;
02028        (a1 != NULL) && (a2 != NULL);
02029        a1 = a1->next, a2 = a2->next) {
02030     if (!((a1->nchars == a2->nchars
02031            && (strncmp (p1, p2, size_fromInt (a1->nchars)) == 0))
02032           || ! comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
02033         || a1->argno != a2->argno
02034         || a1->stringify != a2->stringify
02035         || a1->raw_before != a2->raw_before
02036         || a1->raw_after != a2->raw_after)
02037       return TRUE;
02038     first = 0;
02039     p1 += a1->nchars;
02040     p2 += a2->nchars;
02041   }
02042   if (a1 != a2)
02043     return TRUE;
02044 
02045   if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
02046                      p2, d2->length - (p2 - d2->expansion), 1))
02047     return TRUE;
02048 
02049   return FALSE;
02050 }
02051 
02052 /* Return TRUE if two parts of two macro definitions are effectively different.
02053    One of the parts starts at BEG1 and has LEN1 chars;
02054    the other has LEN2 chars at BEG2.
02055    Any sequence of whitespace matches any other sequence of whitespace.
02056    FIRST means these parts are the first of a macro definition;
02057    so ignore leading whitespace entirely.
02058    LAST means these parts are the last of a macro definition;
02059    so ignore trailing whitespace entirely.  */
02060 
02061 static bool
02062 comp_def_part (bool first, char *beg1, int len1, char *beg2, int len2, bool last)
02063 {
02064   char *end1 = beg1 + len1;
02065   char *end2 = beg2 + len2;
02066 
02067   if (first) {
02068     while (beg1 != end1 && is_space[(int) *beg1]) { beg1++; }
02069     while (beg2 != end2 && is_space[(int) *beg2]) { beg2++; }
02070   }
02071   if (last) {
02072     while (beg1 != end1 && is_space[(int) end1[-1]]) { end1--; }
02073     while (beg2 != end2 && is_space[(int) end2[-1]]) { end2--; }
02074   }
02075   while (beg1 != end1 && beg2 != end2) {
02076     if (is_space[(int) *beg1] && is_space[(int) *beg2]) {
02077       while (beg1 != end1 && is_space[(int) *beg1]) { beg1++; }
02078       while (beg2 != end2 && is_space[(int) *beg2]) { beg2++; }
02079     } else if (*beg1 == *beg2) {
02080       beg1++; beg2++;
02081     } else break;
02082   }
02083   return (beg1 != end1) || (beg2 != end2);
02084 }
02085 
02086 /* Process a #define command.
02087    BUF points to the contents of the #define command, as a contiguous string.
02088    LIMIT points to the first character past the end of the definition.
02089    KEYWORD is the keyword-table entry for #define,
02090    or NULL for a "predefined" macro.  */
02091 
02092 static int
02093 do_defineAux (cppReader *pfile, struct directive *keyword,
02094               char *buf, char *limit, bool noExpand)
02095 {
02096   int hashcode;
02097   MACRODEF mdef;
02098   HASHNODE *hp;
02099   
02100   DPRINTF (("Define aux: %d", noExpand));
02101 
02102   mdef = create_definition (buf, limit, pfile, keyword == NULL, noExpand);
02103 
02104   if (mdef.defn == 0)
02105     goto nope;
02106 
02107   hashcode = hashf (mdef.symnam, mdef.symlen, CPP_HASHSIZE);
02108 
02109   DPRINTF (("Macro: %s / %s", 
02110             cstring_copyLength (mdef.symnam, mdef.symlen),
02111             bool_unparse (noExpand)));
02112 
02113   if ((hp = cppReader_lookup (mdef.symnam, mdef.symlen, hashcode)) != NULL)
02114     {
02115       bool ok = FALSE;
02116 
02117       /* Redefining a precompiled key is ok.  */
02118       if (hp->type == T_PCSTRING)
02119         ok = TRUE;
02120       /* Redefining a macro is ok if the definitions are the same.  */
02121       else if (hp->type == T_MACRO)
02122         ok = !compare_defs (mdef.defn, hp->value.defn);
02123       /* Redefining a constant is ok with -D.  */
02124       else if (hp->type == T_CONST)
02125         ok = !CPPOPTIONS (pfile)->done_initializing;
02126       else {
02127         BADBRANCH;
02128       }
02129 
02130       /* Print the warning if it's not ok.  */
02131       if (!ok)
02132         {
02133           /*
02134           ** If we are passing through #define and #undef directives, do
02135           ** that for this re-definition now.
02136           */
02137 
02138           if (CPPOPTIONS (pfile)->debug_output && (keyword != NULL))
02139             {
02140               /* llassert (keyword != NULL); */
02141               pass_thru_directive (buf, limit, pfile, keyword);
02142             }
02143 
02144           cpp_setLocation (pfile);
02145 
02146           if (hp->type == T_MACRO)
02147             {
02148               if (hp->value.defn->noExpand)
02149                 {
02150                   ; /* error will be reported checking macros */
02151                 }
02152               else
02153                 {
02154                   genppllerrorhint
02155                     (FLG_MACROREDEF,
02156                      message ("Macro %q already defined",
02157                               cstring_copyLength (mdef.symnam, mdef.symlen)),
02158                      message ("%q: Previous definition of %q",
02159                               fileloc_unparseRaw (hp->value.defn->file,
02160                                                  (int) hp->value.defn->line),
02161                               cstring_copyLength (mdef.symnam, mdef.symlen)));
02162                 }
02163             }
02164           else
02165             {
02166               genppllerror (FLG_MACROREDEF,
02167                             message ("Macro %q already defined",
02168                                      cstring_copyLength (mdef.symnam,
02169                                                          mdef.symlen)));
02170 
02171             }
02172         }
02173 
02174       /* Replace the old definition.  */
02175       hp->type = T_MACRO;
02176       hp->value.defn = mdef.defn;
02177     }
02178   else
02179     {
02180       /*
02181       ** If we are passing through #define and #undef directives, do
02182       ** that for this new definition now.
02183       */
02184 
02185       HASHNODE *hn;
02186 
02187       if (CPPOPTIONS (pfile)->debug_output && (keyword != NULL))
02188         {
02189           pass_thru_directive (buf, limit, pfile, keyword);
02190         }
02191 
02192       DPRINTF (("Define macro: %s / %d", 
02193                 mdef.symnam, mdef.defn->noExpand));
02194       
02195       hn = cppReader_installMacro (mdef.symnam, mdef.symlen, mdef.defn, hashcode);
02196       /*@-branchstate@*/
02197     } /*@=branchstate@*/
02198 
02199   return 0;
02200 
02201 nope:
02202 
02203   return 1;
02204 }
02205 
02206 static int
02207 do_define (cppReader *pfile, struct directive *keyword,
02208            char *buf, char *limit)
02209 {
02210   DPRINTF (("Regular do define"));
02211   return do_defineAux (pfile, keyword, buf, limit, FALSE);
02212 }
02213 
02214 /* This structure represents one parsed argument in a macro call.
02215    `raw' points to the argument text as written (`raw_length' is its length).
02216    `expanded' points to the argument's macro-expansion
02217    (its length is `expand_length').
02218    `stringified_length' is the length the argument would have
02219    if stringified.
02220    `use_count' is the number of times this macro arg is substituted
02221    into the macro.  If the actual use count exceeds 10,
02222    the value stored is 10.  */
02223 
02224 /* raw and expanded are relative to ARG_BASE */
02225 /*@notfunction@*/
02226 #define ARG_BASE ((pfile)->token_buffer)
02227 
02228 struct argdata {
02229   /* Strings relative to pfile->token_buffer */
02230   long raw;
02231   size_t expanded;
02232   size_t stringified;
02233   int raw_length;
02234   int expand_length;
02235   int stringified_length;
02236   bool newlines;
02237   int use_count;
02238 };
02239 
02240 /* Allocate a new cppBuffer for PFILE, and push it on the input buffer stack.
02241    If BUFFER != NULL, then use the LENGTH characters in BUFFER
02242    as the new input buffer.
02243    Return the new buffer, or NULL on failure.  */
02244 
02245 /*@null@*/ /*@exposed@*/ cppBuffer *
02246 cppReader_pushBuffer (cppReader *pfile, char *buffer, size_t length)
02247 {
02248   cppBuffer *buf = cppReader_getBuffer (pfile);
02249 
02250   if (buf == pfile->buffer_stack)
02251     {
02252       cppReader_fatalError
02253         (pfile,
02254          message ("%s: macro or `#include' recursion too deep",
02255                   (buf->fname != NULL)
02256                   ? buf->fname
02257                   : cstring_makeLiteral ("<no name>")));
02258       sfreeEventually (buffer);
02259       return NULL;
02260     }
02261 
02262   llassert (buf != NULL);
02263 
02264   buf--;
02265   memset ((char *) buf, 0, sizeof (*buf));
02266   CPPBUFFER (pfile) = buf;
02267 
02268   buf->if_stack = pfile->if_stack;
02269   buf->cleanup = cppReader_nullCleanup;
02270   buf->underflow = cppReader_nullUnderflow;
02271   buf->buf = buffer;
02272   buf->cur = buf->buf;
02273 
02274   if (buffer != NULL)
02275     {
02276       buf->alimit = buf->rlimit = buffer + length;
02277     }
02278   else
02279     {
02280       buf->alimit = buf->rlimit = NULL;
02281     }
02282 
02283   return buf;
02284 }
02285 
02286 cppBuffer *
02287 cppReader_popBuffer (cppReader *pfile)
02288 {
02289   cppBuffer *buf = CPPBUFFER (pfile);
02290 
02291   llassert (buf != NULL);
02292 
02293   (void) (*buf->cleanup) (buf, pfile);
02294   return ++CPPBUFFER (pfile);
02295 }
02296 
02297 /* Scan until CPPBUFFER (PFILE) is exhausted into PFILE->token_buffer.
02298    Pop the buffer when done.  */
02299 
02300 void
02301 cppReader_scanBuffer (cppReader *pfile)
02302 {
02303   cppBuffer *buffer = CPPBUFFER (pfile);
02304   for (;;)
02305     {
02306       enum cpp_token token;
02307       
02308       token = cppGetToken (pfile);
02309 
02310       if (token == CPP_EOF) /* Should not happen ...  */
02311         {
02312           break;
02313         }
02314 
02315       if (token == CPP_POP && CPPBUFFER (pfile) == buffer)
02316         {
02317           (void) cppReader_popBuffer (pfile);
02318           break;
02319         }
02320     }
02321 }
02322 
02323 /*
02324  * Rescan a string (which may have escape marks) into pfile's buffer.
02325  * Place the result in pfile->token_buffer.
02326  *
02327  * The input is copied before it is scanned, so it is safe to pass
02328  * it something from the token_buffer that will get overwritten
02329  * (because it follows cppReader_getWritten).  This is used by do_include.
02330  */
02331 
02332 static void
02333 cpp_expand_to_buffer (cppReader *pfile, char *buf, size_t length)
02334 {
02335   register cppBuffer *ip;
02336   char *limit = buf + length;
02337   char *buf1, *p1, *p2;
02338 
02339   if (length < 0)
02340     abort ();
02341 
02342   /* Set up the input on the input stack.  */
02343 
02344   buf1 = (char *) dmalloc (length + 1);
02345 
02346   p1 = buf;
02347   p2 = buf1;
02348 
02349   while (p1 != limit)
02350     {
02351       *p2++ = *p1++;
02352     }
02353 
02354   buf1[length] = '\0';
02355 
02356   ip = cppReader_pushBuffer (pfile, buf1, length);
02357 
02358   if (ip == NULL)
02359     return;
02360 
02361   ip->has_escapes = TRUE;
02362 
02363   /* Scan the input, create the output.  */
02364   cppReader_scanBuffer (pfile);
02365 
02366   cppReader_nullTerminate (pfile);
02367 }
02368 
02369 static void
02370 adjust_position (char *buf, char *limit, int *linep, int *colp)
02371 {
02372   while (buf < limit)
02373     {
02374       char ch = *buf++;
02375       if (ch == '\n')
02376         (*linep)++, (*colp) = 1;
02377       else
02378         (*colp)++;
02379     }
02380 }
02381 
02382 /* Move line_base forward, updating lineno and colno.  */
02383 
02384 static void
02385 update_position (cppBuffer *pbuf)
02386 {
02387   char *old_pos;
02388   char *new_pos = pbuf->cur;
02389   register struct parse_marker *mark;
02390 
02391   llassert (pbuf->buf != NULL);
02392   old_pos = pbuf->buf + pbuf->line_base;
02393 
02394   for (mark = pbuf->marks;  mark != NULL; mark = mark->next)
02395     {
02396       if (pbuf->buf + mark->position < new_pos)
02397         new_pos = pbuf->buf + mark->position;
02398     }
02399   pbuf->line_base += new_pos - old_pos;
02400 
02401   llassert (old_pos != NULL);
02402   llassert (new_pos != NULL);
02403 
02404   adjust_position (old_pos, new_pos, &pbuf->lineno, &pbuf->colno);
02405 }
02406 
02407 void
02408 cppBuffer_lineAndColumn (/*@null@*/ cppBuffer *pbuf, /*@out@*/ int *linep,
02409                          /*@null@*/ /*@out@*/ int *colp)
02410 {
02411   int dummy;
02412 
02413   if (colp == NULL)
02414     {
02415       colp = &dummy;
02416       /*@-branchstate@*/
02417     } /*@=branchstate@*/
02418 
02419   if (pbuf != NULL)
02420     {
02421       *linep = pbuf->lineno;
02422       *colp = pbuf->colno;
02423 
02424       llassert (pbuf->buf != NULL);
02425       llassert (pbuf->cur != NULL);
02426 
02427       adjust_position (pbuf->buf + pbuf->line_base, pbuf->cur, linep, colp);
02428     }
02429   else
02430     {
02431       *linep = 0;
02432       *colp = 0;
02433     }
02434 }
02435 
02436 /* Return the cppBuffer that corresponds to a file (not a macro).  */
02437 
02438 /*@exposed@*/ /*@null@*/ cppBuffer *cppReader_fileBuffer (cppReader *pfile)
02439 {
02440   cppBuffer *ip = cppReader_getBuffer (pfile);
02441 
02442   for ( ;
02443         ip != NULL && ip != cppReader_nullBuffer (pfile); 
02444         ip = cppBuffer_prevBuffer (ip))
02445     {
02446       if (ip->fname != NULL)
02447         {
02448           return ip;
02449         }
02450     }
02451   
02452   return NULL;
02453 }
02454 
02455 static long
02456 count_newlines (char *buf, char *limit)
02457 {
02458   register long count = 0;
02459 
02460   while (buf < limit)
02461     {
02462       char ch = *buf++;
02463       if (ch == '\n')
02464         count++;
02465     }
02466   return count;
02467 }
02468 
02469 /*
02470  * write out a #line command, for instance, after an #include file.
02471  * If CONDITIONAL is nonzero, we can omit the #line if it would
02472  * appear to be a no-op, and we can output a few newlines instead
02473  * if we want to increase the line number by a small amount.
02474  * FILE_CHANGE says whether we are entering a file, leaving, or neither.
02475  */
02476 
02477 static void
02478 output_line_command (cppReader *pfile, bool conditional,
02479                      enum file_change_code file_change)
02480 {
02481   int line, col;
02482   cppBuffer *ip = CPPBUFFER (pfile);
02483   cppBuffer *buf;
02484 
02485   llassert (ip != NULL);
02486 
02487   if (ip->fname == NULL)
02488     return;
02489 
02490   update_position (ip);
02491 
02492   if (CPPOPTIONS (pfile)->no_line_commands
02493       || CPPOPTIONS (pfile)->no_output)
02494     return;
02495 
02496   buf = CPPBUFFER (pfile);
02497 
02498   llassert (buf != NULL);
02499 
02500   line = buf->lineno;
02501   col = buf->colno;
02502 
02503   llassert (ip->cur != NULL);
02504 
02505   adjust_position (cppLineBase (ip), ip->cur, &line, &col);
02506 
02507   if (CPPOPTIONS (pfile)->no_line_commands)
02508     return;
02509 
02510   if (conditional) {
02511     if (line == pfile->lineno)
02512       return;
02513 
02514     /* If the inherited line number is a little too small,
02515        output some newlines instead of a #line command.  */
02516 
02517     if (line > pfile->lineno && line < pfile->lineno + 8)
02518       {
02519         cppReader_reserve (pfile, 20);
02520         while (line > pfile->lineno)
02521           {
02522             cppReader_putCharQ (pfile, '\n');
02523             pfile->lineno++;
02524           }
02525 
02526         return;
02527       }
02528   }
02529 
02530   cppReader_reserve (pfile,
02531                      size_fromInt (4 * cstring_length (ip->nominal_fname) + 50));
02532 
02533   {
02534 #ifdef OUTPUT_LINE_COMMANDS
02535     static char sharp_line[] = "#line ";
02536 #else
02537     static char sharp_line[] = "# ";
02538 #endif
02539     cppReader_putStrN (pfile, sharp_line, sizeof(sharp_line)-1);
02540   }
02541 
02542   sprintf (cppReader_getPWritten (pfile), "%d ", line);
02543   cppReader_adjustWritten (pfile, strlen (cppReader_getPWritten (pfile)));
02544 
02545   quote_string (pfile, cstring_toCharsSafe (ip->nominal_fname));
02546 
02547   if (file_change != same_file) {
02548     cppReader_putCharQ (pfile, ' ');
02549     cppReader_putCharQ (pfile, file_change == enter_file ? '1' : '2');
02550   }
02551   /* Tell cc1 if following text comes from a system header file.  */
02552   if (ip->system_header_p != '\0') {
02553     cppReader_putCharQ (pfile, ' ');
02554     cppReader_putCharQ (pfile, '3');
02555   }
02556 #ifndef NO_IMPLICIT_EXTERN_C
02557   /* Tell cc1plus if following text should be treated as C.  */
02558   if (ip->system_header_p == (char) 2 && CPPOPTIONS (pfile)->cplusplus) {
02559     cppReader_putCharQ (pfile, ' ');
02560     cppReader_putCharQ (pfile, '4');
02561   }
02562 #endif
02563   cppReader_putCharQ (pfile, '\n');
02564   pfile->lineno = line;
02565 }
02566 
02567 
02568 /*
02569  * Parse a macro argument and append the info on PFILE's token_buffer.
02570  * REST_ARGS means to absorb the rest of the args.
02571  * Return nonzero to indicate a syntax error.
02572  */
02573 
02574 static enum cpp_token
02575 macarg (cppReader *pfile, int rest_args)
02576 {
02577   int paren = 0;
02578   enum cpp_token token;
02579   char save_put_out_comments = CPPOPTIONS (pfile)->put_out_comments;
02580   bool oldexpand = pfile->no_macro_expand;
02581   CPPOPTIONS (pfile)->put_out_comments = 1;
02582 
02583   /* Try to parse as much of the argument as exists at this
02584      input stack level.  */
02585 
02586   pfile->no_macro_expand = TRUE;
02587 
02588   for (;;)
02589     {
02590       token = cppGetToken (pfile);
02591 
02592       switch (token)
02593         {
02594         case CPP_EOF:
02595           goto done;
02596         case CPP_POP:
02597           /* If we've hit end of file, it's an error (reported by caller).
02598              Ditto if it's the end of cpp_expand_to_buffer text.
02599              If we've hit end of macro, just continue.  */
02600           if (!cppBuffer_isMacro (CPPBUFFER (pfile)))
02601             goto done;
02602           /*@switchbreak@*/ break;
02603         case CPP_LPAREN:
02604           paren++;
02605           /*@switchbreak@*/ break;
02606         case CPP_RPAREN:
02607           if (--paren < 0)
02608             goto found;
02609           /*@switchbreak@*/ break;
02610         case CPP_COMMA:
02611           /* if we've returned to lowest level and
02612              we aren't absorbing all args */
02613           if (paren == 0 && rest_args == 0)
02614             goto found;
02615           /*@switchbreak@*/ break;
02616         found:
02617           /* Remove ',' or ')' from argument buffer.  */
02618           cppReader_adjustWritten (pfile, -1);
02619           goto done;
02620         default:
02621           ;
02622         }
02623     }
02624 
02625 done:
02626   CPPOPTIONS (pfile)->put_out_comments = save_put_out_comments;
02627   pfile->no_macro_expand = oldexpand;
02628 
02629   return token;
02630 }
02631 
02632 
02633 /* Turn newlines to spaces in the string of length LENGTH at START,
02634    except inside of string constants.
02635    The string is copied into itself with its beginning staying fixed.  */
02636 
02637 static int
02638 change_newlines (char *start, int length)
02639 {
02640   register char *ibp;
02641   register char *obp;
02642   register char *limit;
02643   char c;
02644 
02645   ibp = start;
02646   limit = start + length;
02647   obp = start;
02648 
02649   while (ibp < limit) {
02650     *obp++ = c = *ibp++;
02651     switch (c) {
02652 
02653     case '\'':
02654     case '\"':
02655       /* Notice and skip strings, so that we don't delete newlines in them.  */
02656       {
02657         char quotec = c;
02658         while (ibp < limit) {
02659           *obp++ = c = *ibp++;
02660           if (c == quotec)
02661             /*@innerbreak@*/ break;
02662           if (c == '\n' && quotec == '\'')
02663             /*@innerbreak@*/ break;
02664         }
02665       }
02666     /*@switchbreak@*/ break;
02667     }
02668   }
02669 
02670   return obp - start;
02671 }
02672 
02673 static /*@observer@*/ struct tm *
02674 timestamp (/*@returned@*/ cppReader *pfile)
02675 {
02676   if (pfile->timebuf == NULL)
02677     {
02678       time_t t = time ((time_t *) 0);
02679       pfile->timebuf = localtime (&t);
02680     }
02681 
02682   llassert (pfile->timebuf != NULL);
02683 
02684   return pfile->timebuf;
02685 }
02686 
02687 static ob_mstring monthnames[] = {
02688   "Jan", "Feb", "Mar", "Apr", "May", "Jun",
02689   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
02690 } ;
02691 
02692 /*
02693  * expand things like __FILE__.  Place the expansion into the output
02694  * buffer *without* rescanning.
02695  */
02696 
02697 static void
02698 special_symbol (HASHNODE *hp, cppReader *pfile)
02699 {
02700   cstring buf = cstring_undefined;
02701   size_t len;
02702   int true_indepth;
02703   cppBuffer *ip;
02704   struct tm *timebuf;
02705 
02706   int paren = 0;                /* For special `defined' keyword */
02707 
02708   for (ip = cppReader_getBuffer (pfile); ip != NULL; ip = cppBuffer_prevBuffer (ip))
02709     {
02710       if (ip == cppReader_nullBuffer (pfile))
02711         {
02712           cppReader_errorLit (pfile,
02713                         cstring_makeLiteralTemp ("cccp error: not in any file?!"));
02714           return;                       /* the show must go on */
02715         }
02716 
02717       if (ip != NULL && ip->fname != NULL)
02718         {
02719           break;
02720         }
02721     }
02722 
02723   switch (hp->type)
02724     {
02725     case T_FILE:
02726     case T_BASE_FILE:
02727       {
02728         char *string;
02729         if (hp->type == T_BASE_FILE)
02730           {
02731             while (cppBuffer_prevBuffer (ip) != cppReader_nullBuffer (pfile))
02732               {
02733                 ip = cppBuffer_prevBuffer (ip);
02734               }
02735           }
02736 
02737         llassert (ip != NULL);
02738         string = cstring_toCharsSafe (ip->nominal_fname);
02739 
02740         if (string == NULL)
02741           {
02742             string = "";
02743           }
02744 
02745         cppReader_reserve (pfile, 3 + 4 * strlen (string));
02746         quote_string (pfile, string);
02747         return;
02748       }
02749 
02750     case T_INCLUDE_LEVEL:
02751       true_indepth = 0;
02752       ip = cppReader_getBuffer (pfile);
02753 
02754       for (;  ip != cppReader_nullBuffer (pfile) && ip != NULL;
02755            ip = cppBuffer_prevBuffer (ip))
02756         {
02757           if (ip != NULL && ip->fname != NULL)
02758             {
02759               true_indepth++;
02760             }
02761         }
02762 
02763       buf = message ("%d", true_indepth - 1);
02764       break;
02765 
02766     case T_VERSION:
02767       buf = message ("\"%s\"", cstring_makeLiteralTemp (CPP_VERSION));
02768       break;
02769 
02770 #ifndef NO_BUILTIN_SIZE_TYPE
02771     case T_SIZE_TYPE:
02772       buf = cstring_makeLiteral (SIZE_TYPE);
02773       break;
02774 #endif
02775 
02776 #ifndef NO_BUILTIN_PTRDIFF_TYPE
02777     case T_PTRDIFF_TYPE:
02778       buf = cstring_makeLiteral (PTRDIFF_TYPE);
02779       break;
02780 #endif
02781 
02782     case T_WCHAR_TYPE:
02783       buf = cstring_makeLiteral (cppReader_wcharType (pfile));
02784       break;
02785 
02786     case T_USER_LABEL_PREFIX_TYPE:
02787       buf = cstring_makeLiteral (USER_LABEL_PREFIX);
02788       break;
02789 
02790     case T_REGISTER_PREFIX_TYPE:
02791       buf = cstring_makeLiteral (REGISTER_PREFIX);
02792       break;
02793 
02794     case T_CONST:
02795       buf = message ("%d", hp->value.ival);
02796       break;
02797 
02798     case T_SPECLINE:
02799       {
02800         if (ip != NULL)
02801           {
02802             int line = ip->lineno;
02803             int col = ip->colno;
02804 
02805             llassert (ip->cur != NULL);
02806             adjust_position (cppLineBase (ip), ip->cur, &line, &col);
02807 
02808             buf = message ("%d", (int) line);
02809           }
02810         else
02811           {
02812             BADBRANCH;
02813           }
02814       }
02815     break;
02816 
02817     case T_DATE:
02818     case T_TIME:
02819       {
02820         char *sbuf = (char *) dmalloc (20);
02821         timebuf = timestamp (pfile);
02822         if (hp->type == T_DATE)
02823           {
02824             sprintf (sbuf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon],
02825                      timebuf->tm_mday, timebuf->tm_year + 1900);
02826           }
02827         else
02828           {
02829             sprintf (sbuf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min,
02830                      timebuf->tm_sec);
02831           }
02832 
02833         buf = cstring_fromCharsNew (sbuf);
02834         sfree (sbuf);
02835         break;
02836       }
02837 
02838     case T_SPEC_DEFINED:
02839       buf = cstring_makeLiteral (" 0 ");     /* Assume symbol is not defined */
02840       ip = cppReader_getBuffer (pfile);
02841 
02842       llassert (ip->cur != NULL);
02843       SKIP_WHITE_SPACE (ip->cur);
02844 
02845       if (*ip->cur == '(')
02846         {
02847           paren++;
02848           ip->cur++;                    /* Skip over the paren */
02849           SKIP_WHITE_SPACE (ip->cur);
02850         }
02851 
02852       if (!is_idstart[(int) *ip->cur])
02853         goto oops;
02854       if (ip->cur[0] == 'L' && (ip->cur[1] == '\'' || ip->cur[1] == '"'))
02855         goto oops;
02856 
02857       if ((hp = cppReader_lookup (ip->cur, -1, -1)) != 0)
02858         {
02859           cstring_free (buf);
02860           buf = cstring_makeLiteral (" 1 ");
02861         }
02862 
02863       while (is_idchar[(int) *ip->cur])
02864         {
02865           ++ip->cur;
02866         }
02867 
02868       SKIP_WHITE_SPACE (ip->cur);
02869 
02870       if (paren != 0)
02871         {
02872           if (*ip->cur != ')')
02873             goto oops;
02874           ++ip->cur;
02875         }
02876       break;
02877 
02878     oops:
02879 
02880       cppReader_errorLit (pfile,
02881                     cstring_makeLiteralTemp ("`defined' without an identifier"));
02882       break;
02883 
02884     default:
02885       cpp_setLocation (pfile);
02886       llfatalerror (message ("Pre-processing error: invalid special hash type"));
02887     }
02888 
02889   len = size_fromInt (cstring_length (buf));
02890 
02891   cppReader_reserve (pfile, len + 1);
02892   cppReader_putStrN (pfile, cstring_toCharsSafe (buf), len);
02893   cppReader_nullTerminateQ (pfile);
02894 
02895   cstring_free (buf);
02896   return;
02897 }
02898 
02899 /* Write out a #define command for the special named MACRO_NAME
02900    to PFILE's token_buffer.  */
02901 
02902 static void
02903 dump_special_to_buffer (cppReader *pfile, char *macro_name)
02904 {
02905   static char define_directive[] = "#define ";
02906   size_t macro_name_length = strlen (macro_name);
02907   output_line_command (pfile, 0, same_file);
02908   cppReader_reserve (pfile, sizeof(define_directive) + macro_name_length);
02909   cppReader_putStrN (pfile, define_directive, sizeof(define_directive)-1);
02910   cppReader_putStrN (pfile, macro_name, macro_name_length);
02911   cppReader_putCharQ (pfile, ' ');
02912   cpp_expand_to_buffer (pfile, macro_name, macro_name_length);
02913   cppReader_putChar (pfile, '\n');
02914 }
02915 
02916 /* Initialize the built-in macros.  */
02917 
02918 static void
02919 cppReader_installBuiltin (/*@observer@*/ char *name, ctype ctyp,
02920                           int len, enum node_type type,
02921                           int ivalue, /*@null@*/ /*@only@*/ char *value,
02922                           int hash)
02923 {
02924   cstring sname = cstring_fromCharsNew (name);
02925 
02926   llassert (usymtab_inGlobalScope ());
02927 
02928   /*
02929   ** Be careful here: this is done before the ctype table has
02930   ** been initialized.
02931   */
02932 
02933   if (!usymtab_exists (sname))
02934     {
02935       uentry ue = uentry_makeConstant (sname, ctyp, fileloc_createBuiltin ());
02936 
02937       if (ctype_equal (ctyp, ctype_string))
02938         {
02939           qualList ql = qualList_new ();
02940           ql = qualList_add (ql, QU_OBSERVER);
02941           uentry_reflectQualifiers (ue, ql);
02942           qualList_free (ql);
02943         }
02944 
02945       usymtab_addGlobalEntry (ue);
02946     }
02947   else
02948     {
02949       ;
02950     }
02951 
02952   (void) cppReader_install (name, len, type, ivalue, value, hash);
02953   cstring_free (sname);
02954 }
02955 
02956 static void
02957 cppReader_installBuiltinType (/*@observer@*/ char *name, ctype ctyp,
02958                               int len, enum node_type type,
02959                               int ivalue,
02960                               /*@only@*/ /*@null@*/ char *value, int hash)
02961 {
02962   cstring sname = cstring_fromChars (name);
02963   /* evs 2000 07 10 - removed a memory leak, detected by lclint */
02964 
02965   llassert (usymtab_inGlobalScope ());
02966 
02967   if (!usymtab_exists (sname))
02968     {
02969       uentry ue = uentry_makeDatatype (sname, ctyp,
02970                                        NO, NO,
02971                                        fileloc_createBuiltin ());
02972       usymtab_addGlobalEntry (ue);
02973     }
02974 
02975   (void) cppReader_install (name, len, type, ivalue, value, hash);
02976 }
02977 
02978 static void
02979 initialize_builtins (cppReader *pfile)
02980 {
02981   cppReader_installBuiltin ("__LINE__", ctype_int, -1, T_SPECLINE, 0, NULL, -1);
02982   cppReader_installBuiltin ("__DATE__", ctype_string, -1, T_DATE, 0, NULL, -1);
02983   cppReader_installBuiltin ("__FILE__", ctype_string, -1, T_FILE, 0, NULL, -1);
02984   cppReader_installBuiltin ("__BASE_FILE__", ctype_string, -1, T_BASE_FILE, 0, NULL, -1);
02985   cppReader_installBuiltin ("__INCLUDE_LEVEL__", ctype_int, -1, T_INCLUDE_LEVEL, 0, NULL, -1);
02986   cppReader_installBuiltin ("__VERSION__", ctype_string, -1, T_VERSION, 0, NULL, -1);
02987 #ifndef NO_BUILTIN_SIZE_TYPE
02988   cppReader_installBuiltinType ("__SIZE_TYPE__", ctype_anyintegral, -1, T_SIZE_TYPE, 0, NULL, -1);
02989 #endif
02990 #ifndef NO_BUILTIN_PTRDIFF_TYPE
02991   cppReader_installBuiltinType ("__PTRDIFF_TYPE__ ", ctype_anyintegral, -1, T_PTRDIFF_TYPE, 0, NULL, -1);
02992 #endif
02993   cppReader_installBuiltinType ("__WCHAR_TYPE__", ctype_anyintegral, -1, T_WCHAR_TYPE, 0, NULL, -1);
02994   cppReader_installBuiltin ("__USER_LABEL_PREFIX__", ctype_string, -1, T_USER_LABEL_PREFIX_TYPE, 0, NULL, -1);
02995   cppReader_installBuiltin ("__REGISTER_PREFIX__", ctype_string, -1, T_REGISTER_PREFIX_TYPE, 0, NULL, -1);
02996   cppReader_installBuiltin ("__TIME__", ctype_string, -1, T_TIME, 0, NULL, -1);
02997 
02998   /*
02999   ** No, don't define __STDC__
03000   **
03001 
03002   if (!cppReader_isTraditional (pfile))
03003     {
03004       cppReader_installBuiltin ("__STDC__", ctype_int, -1, T_CONST, STDC_VALUE, NULL, -1);
03005     }
03006 
03007   **
03008   */
03009 
03010 # ifdef WIN32
03011     cppReader_installBuiltin ("_WIN32", ctype_int, -1, T_CONST, STDC_VALUE, NULL, -1);
03012 # endif
03013 
03014   /*
03015   ** This is supplied using a -D by the compiler driver
03016   ** so that it is present only when truly compiling with GNU C.
03017   */
03018 
03019   /*  cppReader_install ("__GNUC__", -1, T_CONST, 2, 0, -1);  */
03020 
03021   cppReader_installBuiltin ("__LCLINT__", ctype_int, -1, T_CONST, 2, NULL, -1);
03022 
03023   if (CPPOPTIONS (pfile)->debug_output)
03024     {
03025       dump_special_to_buffer (pfile, "__BASE_FILE__");
03026       dump_special_to_buffer (pfile, "__VERSION__");
03027 #ifndef NO_BUILTIN_SIZE_TYPE
03028       dump_special_to_buffer (pfile, "__SIZE_TYPE__");
03029 #endif
03030 #ifndef NO_BUILTIN_PTRDIFF_TYPE
03031       dump_special_to_buffer (pfile, "__PTRDIFF_TYPE__");
03032 #endif
03033       dump_special_to_buffer (pfile, "__WCHAR_TYPE__");
03034       dump_special_to_buffer (pfile, "__DATE__");
03035       dump_special_to_buffer (pfile, "__TIME__");
03036       if (!cppReader_isTraditional (pfile))
03037         dump_special_to_buffer (pfile, "__STDC__");
03038     }
03039 }
03040 
03041 
03042 /* Return 1 iff a token ending in C1 followed directly by a token C2
03043    could cause mis-tokenization.  */
03044 
03045 static bool
03046 unsafe_chars (char c1, char c2)
03047 {
03048   switch (c1)
03049     {
03050     case '+': case '-':
03051       if (c2 == c1 || c2 == '=')
03052         return 1;
03053       goto letter;
03054     case '.':
03055     case '0': case '1': case '2': case '3': case '4':
03056     case '5': case '6': case '7': case '8': case '9':
03057     case 'e': case 'E': case 'p': case 'P':
03058       if (c2 == '-' || c2 == '+')
03059         return 1; /* could extend a pre-processing number */
03060       goto letter;
03061     case 'L':
03062       if (c2 == '\'' || c2 == '\"')
03063         return 1;   /* Could turn into L"xxx" or L'xxx'.  */
03064       goto letter;
03065     letter:
03066     case '_':
03067     case 'a': case 'b': case 'c': case 'd':           case 'f':
03068     case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
03069     case 'm': case 'n': case 'o':           case 'q': case 'r':
03070     case 's': case 't': case 'u': case 'v': case 'w': case 'x':
03071     case 'y': case 'z':
03072     case 'A': case 'B': case 'C': case 'D':           case 'F':
03073     case 'G': case 'H': case 'I': case 'J': case 'K':
03074     case 'M': case 'N': case 'O':           case 'Q': case 'R':
03075     case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
03076     case 'Y': case 'Z':
03077       /* We're in the middle of either a name or a pre-processing number.  */
03078       return (is_idchar[(int) c2] || c2 == '.');
03079     case '<': case '>': case '!': case '%': case '#': case ':':
03080     case '^': case '&': case '|': case '*': case '/': case '=':
03081       return (c2 == c1 || c2 == '=');
03082     }
03083   return 0;
03084 }
03085 
03086 /* Expand a macro call.
03087    HP points to the symbol that is the macro being called.
03088    Put the result of expansion onto the input stack
03089    so that subsequent input by our caller will use it.
03090 
03091    If macro wants arguments, caller has already verified that
03092    an argument list follows; arguments come from the input stack.  */
03093 
03094 static void
03095 macroexpand (cppReader *pfile, /*@dependent@*/ HASHNODE *hp)
03096 {
03097   int nargs;
03098   DEFINITION *defn = hp->value.defn;
03099   char *xbuf;
03100   char *oxbuf = NULL;
03101   int start_line;
03102   int start_column;
03103   size_t xbuf_len;
03104   size_t old_written = cppReader_getWritten (pfile);
03105   int rest_args;
03106   int rest_zero = 0;
03107   int i;
03108   struct argdata *args = NULL;
03109 
03110   pfile->output_escapes++;
03111 
03112   cppBuffer_lineAndColumn (cppReader_fileBuffer (pfile), &start_line, &start_column);
03113 
03114   nargs = defn->nargs;
03115 
03116   if (nargs >= 0)
03117     {
03118       enum cpp_token token = CPP_EOF;
03119 
03120       args = (struct argdata *) dmalloc ((nargs + 1) * sizeof (*args));
03121 
03122       for (i = 0; i < nargs; i++)
03123         {
03124           args[i].expanded = 0;
03125           args[i].raw = 0;
03126           args[i].raw_length = 0;
03127           args[i].expand_length = args[i].stringified_length = -1;
03128           args[i].use_count = 0;
03129         }
03130 
03131       /*
03132       ** Parse all the macro args that are supplied.  I counts them.
03133       ** The first NARGS args are stored in ARGS.
03134       ** The rest are discarded.  If rest_args is set then we assume
03135       ** macarg absorbed the rest of the args.
03136       */
03137 
03138       i = 0;
03139       rest_args = 0;
03140 
03141       cppReader_forward (pfile, 1); /* Discard the open-parenthesis before the first arg.  */
03142       do
03143         {
03144           if (rest_args != 0)
03145             {
03146               continue;
03147             }
03148 
03149           if (i < nargs || (nargs == 0 && i == 0))
03150             {
03151               /* if we are working on last arg which absorbs rest of args... */
03152               if (i == nargs - 1 && defn->rest_args)
03153                 {
03154                   rest_args = 1;
03155                 }
03156 
03157               args[i].raw = size_toLong (cppReader_getWritten (pfile));
03158               token = macarg (pfile, rest_args);
03159               args[i].raw_length = cppReader_getWritten (pfile) - args[i].raw;
03160               args[i].newlines = FALSE; /* FIXME */
03161             }
03162           else
03163             {
03164               token = macarg (pfile, 0);
03165             }
03166 
03167           if (token == CPP_EOF || token == CPP_POP)
03168             {
03169               cppReader_errorWithLine (pfile, start_line, start_column,
03170                                    cstring_fromCharsNew ("unterminated macro call"));
03171               sfree (args);
03172               return;
03173             }
03174           i++;
03175         } while (token == CPP_COMMA);
03176 
03177       /* If we got one arg but it was just whitespace, call that 0 args.  */
03178       if (i == 1)
03179         {
03180           char *bp;
03181           char *lim;
03182 
03183           assertSet (args);
03184 
03185           bp = ARG_BASE + args[0].raw;
03186           lim = bp + args[0].raw_length;
03187 
03188           /* cpp.texi says for foo ( ) we provide one argument.
03189              However, if foo wants just 0 arguments, treat this as 0.  */
03190 
03191           if (nargs == 0)
03192             {
03193               while (bp != lim && is_space[(int) *bp])
03194                 {
03195                   bp++;
03196                 }
03197             }
03198 
03199           if (bp == lim)
03200             i = 0;
03201         }
03202 
03203       /* Don't output an error message if we have already output one for
03204          a parse error above.  */
03205       rest_zero = 0;
03206 
03207       if (nargs == 0 && i > 0)
03208         {
03209           cppReader_error (pfile,
03210                      message ("arguments given to macro `%s'", hp->name));
03211         }
03212       else if (i < nargs)
03213         {
03214           /* traditional C allows foo() if foo wants one argument.  */
03215           if (nargs == 1 && i == 0 && cppReader_isTraditional (pfile))
03216             {
03217               ;
03218             }
03219           /* the rest args token is allowed to absorb 0 tokens */
03220           else if (i == nargs - 1 && defn->rest_args)
03221             rest_zero = 1;
03222           else if (i == 0)
03223             cppReader_error (pfile,
03224                        message ("macro `%s' used without args", hp->name));
03225           else if (i == 1)
03226             cppReader_error (pfile,
03227                        message ("macro `%s' used with just one arg", hp->name));
03228           else
03229             {
03230               cppReader_error (pfile,
03231                          message ("macro `%s' used with only %d args",
03232                                   hp->name, i));
03233             }
03234         }
03235       else if (i > nargs)
03236         {
03237           cppReader_error (pfile,
03238                      message ("macro `%s' used with too many (%d) args", hp->name, i));
03239         }
03240       else
03241         {
03242           ;
03243         }
03244     }
03245 
03246   /* If macro wants zero args, we parsed the arglist for checking only.
03247      Read directly from the macro definition.  */
03248 
03249   if (nargs <= 0)
03250     {
03251       xbuf = defn->expansion;
03252       xbuf_len = defn->length;
03253     }
03254   else
03255     {
03256       char *exp = defn->expansion;
03257       int offset;       /* offset in expansion,
03258                                    copied a piece at a time */
03259       size_t totlen;    /* total amount of exp buffer filled so far */
03260 
03261       register struct reflist *ap, *last_ap;
03262 
03263       /* Macro really takes args.  Compute the expansion of this call.  */
03264 
03265       /* Compute length in characters of the macro's expansion.
03266          Also count number of times each arg is used.  */
03267       xbuf_len = defn->length;
03268 
03269       llassert (args != NULL);
03270 
03271       for (ap = defn->pattern; ap != NULL; ap = ap->next)
03272         {
03273           if (ap->stringify)
03274             {
03275               struct argdata *arg = &args[ap->argno];
03276 
03277               /* Stringify it it hasn't already been */
03278               assertSet (arg);
03279 
03280               if (arg->stringified_length < 0)
03281                 {
03282                   int arglen = arg->raw_length;
03283                   bool escaped = FALSE;
03284                   char in_string = '\0';
03285                   char c;
03286 
03287                   /* Initially need_space is -1.  Otherwise, 1 means the
03288                      previous character was a space, but we suppressed it;
03289                      0 means the previous character was a non-space.  */
03290                   int need_space = -1;
03291 
03292                   i = 0;
03293                   arg->stringified = cppReader_getWritten (pfile);
03294                   if (!cppReader_isTraditional (pfile))
03295                     cppReader_putChar (pfile, '\"'); /* insert beginning quote */
03296                   for (; i < arglen; i++)
03297                     {
03298                       c = (ARG_BASE + arg->raw)[i];
03299 
03300                       if (in_string == '\0')
03301                         {
03302                           /* Internal sequences of whitespace are replaced by
03303                              one space except within an string or char token.*/
03304                           if (is_space[(int) c])
03305                             {
03306                               if (cppReader_getWritten (pfile) > arg->stringified
03307                                   && (cppReader_getPWritten (pfile))[-1] == '@')
03308                                 {
03309                                   /* "@ " escape markers are removed */
03310                                   cppReader_adjustWritten (pfile, -1);
03311                                   /*@innercontinue@*/ continue;
03312                                 }
03313                               if (need_space == 0)
03314                                 need_space = 1;
03315                               /*@innercontinue@*/ continue;
03316                             }
03317                           else if (need_space > 0)
03318                             cppReader_putChar (pfile, ' ');
03319                           else
03320                             {
03321                               ;
03322                             }
03323 
03324                           need_space = 0;
03325                         }
03326 
03327                       if (escaped)
03328                         escaped = 0;
03329                       else
03330                         {
03331                           if (c == '\\')
03332                             escaped = 1;
03333 
03334                           if (in_string != '\0')
03335                             {
03336                               if (c == in_string)
03337                                 in_string = '\0';
03338                             }
03339                           else if (c == '\"' || c == '\'')
03340                             {
03341                               in_string = c;
03342                             }
03343                           else
03344                             {
03345                               ;
03346                             }
03347                         }
03348 
03349                       /* Escape these chars */
03350                       if (c == '\"' || (in_string != '\0' && c == '\\'))
03351                         cppReader_putChar (pfile, '\\');
03352                       if (isprint (c))
03353                         cppReader_putChar (pfile, c);
03354                       else
03355                         {
03356                           cppReader_reserve (pfile, 4);
03357                           sprintf (cppReader_getPWritten (pfile), "\\%03o",
03358                                    (unsigned int) c);
03359                           cppReader_adjustWritten (pfile, 4);
03360                         }
03361                     }
03362                   if (!cppReader_isTraditional (pfile))
03363                     cppReader_putChar (pfile, '\"'); /* insert ending quote */
03364                   arg->stringified_length
03365                     = size_toInt (cppReader_getWritten (pfile) - arg->stringified);
03366                 }
03367 
03368               xbuf_len += args[ap->argno].stringified_length;
03369             }
03370           else if (ap->raw_before || ap->raw_after || cppReader_isTraditional (pfile))
03371             {
03372               /* Add 4 for two newline-space markers to prevent
03373                  token concatenation.  */
03374               xbuf_len += args[ap->argno].raw_length + 4;
03375             }
03376           else
03377             {
03378               /* We have an ordinary (expanded) occurrence of the arg.
03379                  So compute its expansion, if we have not already.  */
03380 
03381               if (args[ap->argno].expand_length < 0)
03382                 {
03383                   args[ap->argno].expanded = cppReader_getWritten (pfile);
03384                   cpp_expand_to_buffer (pfile,
03385                                         ARG_BASE + args[ap->argno].raw,
03386                                         size_fromInt (args[ap->argno].raw_length));
03387 
03388                   args[ap->argno].expand_length
03389                     = size_toInt (cppReader_getWritten (pfile) - args[ap->argno].expanded);
03390                 }
03391 
03392               /* Add 4 for two newline-space markers to prevent
03393                  token concatenation.  */
03394               xbuf_len += args[ap->argno].expand_length + 4;
03395            }
03396           if (args[ap->argno].use_count < 10)
03397             args[ap->argno].use_count++;
03398         }
03399 
03400       xbuf = (char *) dmalloc (xbuf_len + 1);
03401       oxbuf = xbuf;
03402 
03403       /*
03404       ** Generate in XBUF the complete expansion
03405       ** with arguments substituted in.
03406       ** TOTLEN is the total size generated so far.
03407       ** OFFSET is the index in the definition
03408       ** of where we are copying from.
03409       */
03410 
03411       offset = 0;
03412       totlen = 0;
03413 
03414       for (last_ap = NULL, ap = defn->pattern; ap != NULL;
03415            last_ap = ap, ap = ap->next)
03416         {
03417           register struct argdata *arg = &args[ap->argno];
03418           size_t count_before = totlen;
03419 
03420           /* Add chars to XBUF.  */
03421           for (i = 0; i < ap->nchars; i++, offset++)
03422             {
03423               xbuf[totlen++] = exp[offset];
03424             }
03425 
03426           /* If followed by an empty rest arg with concatenation,
03427              delete the last run of nonwhite chars.  */
03428           if (rest_zero && totlen > count_before
03429               && ((ap->rest_args && ap->raw_before)
03430                   || (last_ap != NULL && last_ap->rest_args
03431                       && last_ap->raw_after)))
03432             {
03433               /* Delete final whitespace.  */
03434               while (totlen > count_before && is_space[(int) xbuf[totlen - 1]])
03435                 {
03436                   totlen--;
03437                 }
03438 
03439               /* Delete the nonwhites before them.  */
03440               while (totlen > count_before && ! is_space[(int) xbuf[totlen - 1]])
03441                 {
03442                   totlen--;
03443                 }
03444             }
03445 
03446           if (ap->stringify != 0)
03447             {
03448               assertSet(arg);
03449               memcpy (xbuf + totlen,
03450                       ARG_BASE + arg->stringified,
03451                       size_fromInt (arg->stringified_length));
03452               totlen += arg->stringified_length;
03453             }
03454           else if (ap->raw_before || ap->raw_after || cppReader_isTraditional (pfile))
03455             {
03456               char *p1;
03457               char *l1;
03458 
03459               assertSet (arg);
03460 
03461               p1 = ARG_BASE + arg->raw;
03462               l1 = p1 + arg->raw_length;
03463 
03464               if (ap->raw_before)
03465                 {
03466                   while (p1 != l1 && is_space[(int) *p1])
03467                     {
03468                       p1++;
03469                     }
03470 
03471                   while (p1 != l1 && is_idchar[(int) *p1])
03472                     {
03473                       xbuf[totlen++] = *p1++;
03474                     }
03475 
03476                   /* Delete any no-reexpansion marker that follows
03477                      an identifier at the beginning of the argument
03478                      if the argument is concatenated with what precedes it.  */
03479                   if (p1[0] == '@' && p1[1] == '-')
03480                     p1 += 2;
03481                 }
03482               if (ap->raw_after)
03483                 {
03484                   /* Arg is concatenated after: delete trailing whitespace,
03485                      whitespace markers, and no-reexpansion markers.  */
03486                   while (p1 != l1)
03487                     {
03488                       if (is_space[(int) l1[-1]]) l1--;
03489                       else if (l1[-1] == '-')
03490                         {
03491                           char *p2 = l1 - 1;
03492                           /* If a `-' is preceded by an odd number of newlines then it
03493                              and the last newline are a no-reexpansion marker.  */
03494                           while (p2 != p1 && p2[-1] == '\n')
03495                             {
03496                               p2--;
03497                             }
03498 
03499                           if (((l1 - 1 - p2) & 1) != 0)
03500                             {
03501                               l1 -= 2;
03502                             }
03503                           else
03504                             {
03505                               /*@innerbreak@*/ break;
03506                             }
03507                         }
03508                       else
03509                         {
03510                           /*@innerbreak@*/ break;
03511                         }
03512                     }
03513                 }
03514 
03515               memcpy (xbuf + totlen, p1, size_fromInt (l1 - p1));
03516               totlen += l1 - p1;
03517             }
03518           else
03519             {
03520               char *expanded;
03521 
03522               assertSet (arg);
03523               expanded = ARG_BASE + arg->expanded;
03524 
03525               if (!ap->raw_before && totlen > 0
03526                   && (arg->expand_length != 0)
03527                   && !cppReader_isTraditional(pfile)
03528                   && unsafe_chars (xbuf[totlen-1], expanded[0]))
03529                 {
03530                   xbuf[totlen++] = '@';
03531                   xbuf[totlen++] = ' ';
03532                 }
03533 
03534               memcpy (xbuf + totlen, expanded,
03535                       size_fromInt (arg->expand_length));
03536               totlen += arg->expand_length;
03537 
03538               if (!ap->raw_after && totlen > 0
03539                   && offset < size_toInt (defn->length)
03540                   && !cppReader_isTraditional(pfile)
03541                   && unsafe_chars (xbuf[totlen-1], exp[offset]))
03542                 {
03543                   xbuf[totlen++] = '@';
03544                   xbuf[totlen++] = ' ';
03545                 }
03546 
03547               /* If a macro argument with newlines is used multiple times,
03548                  then only expand the newlines once.  This avoids creating
03549                  output lines which don't correspond to any input line,
03550                  which confuses gdb and gcov.  */
03551               if (arg->use_count > 1 && arg->newlines > 0)
03552                 {
03553                   /* Don't bother doing change_newlines for subsequent
03554                      uses of arg.  */
03555                   arg->use_count = 1;
03556                   arg->expand_length
03557                     = change_newlines (expanded, arg->expand_length);
03558                 }
03559             }
03560 
03561           if (totlen > xbuf_len)
03562             abort ();
03563         }
03564 
03565       /* if there is anything left of the definition
03566          after handling the arg list, copy that in too.  */
03567 
03568       for (i = offset; i < size_toInt (defn->length); i++)
03569         {
03570           /* if we've reached the end of the macro */
03571           if (exp[i] == ')')
03572             rest_zero = 0;
03573           if (! (rest_zero && last_ap != NULL && last_ap->rest_args
03574                  && last_ap->raw_after))
03575             xbuf[totlen++] = exp[i];
03576         }
03577 
03578       xbuf[totlen] = '\0';
03579       xbuf_len = totlen;
03580     }
03581 
03582   pfile->output_escapes--;
03583 
03584   /* Now put the expansion on the input stack
03585      so our caller will commence reading from it.  */
03586   push_macro_expansion (pfile, xbuf, xbuf_len, hp);
03587   cppReader_getBuffer (pfile)->has_escapes = 1;
03588 
03589   /* Pop the space we've used in the token_buffer for argument expansion.  */
03590   cppReader_setWritten (pfile, old_written);
03591 
03592   /* Recursive macro use sometimes works traditionally.
03593      #define foo(x,y) bar (x (y,0), y)
03594      foo (foo, baz)  */
03595 
03596   if (!cppReader_isTraditional (pfile))
03597     hp->type = T_DISABLED;
03598 
03599   sfree (args);
03600 }
03601 
03602 static void
03603 push_macro_expansion (cppReader *pfile, char *xbuf, size_t xbuf_len,
03604                       /*@dependent@*/ HASHNODE *hp)
03605 {
03606   cppBuffer *mbuf = cppReader_pushBuffer (pfile, xbuf, xbuf_len);
03607 
03608   if (mbuf == NULL)
03609     {
03610       return;
03611     }
03612 
03613   mbuf->cleanup = cppReader_macroCleanup;
03614 
03615   llassert (mbuf->hnode == NULL);
03616   mbuf->hnode = hp;
03617 
03618   /* The first chars of the expansion should be a "@ " added by
03619      collect_expansion.  This is to prevent accidental token-pasting
03620      between the text preceding the macro invocation, and the macro
03621      expansion text.
03622 
03623      We would like to avoid adding unneeded spaces (for the sake of
03624      tools that use cpp, such as imake).  In some common cases we can
03625      tell that it is safe to omit the space.
03626 
03627      The character before the macro invocation cannot have been an
03628      idchar (or else it would have been pasted with the idchars of
03629      the macro name).  Therefore, if the first non-space character
03630      of the expansion is an idchar, we do not need the extra space
03631      to prevent token pasting.
03632 
03633      Also, we don't need the extra space if the first char is '(',
03634      or some other (less common) characters.  */
03635 
03636   if (xbuf[0] == '@' && xbuf[1] == ' '
03637       && (is_idchar[(int) xbuf[2]] || xbuf[2] == '(' || xbuf[2] == '\''
03638           || xbuf[2] == '\"'))
03639   {
03640     llassert (mbuf->cur != NULL);
03641     mbuf->cur += 2;
03642   }
03643 }
03644 
03645 
03646 /* Like cppGetToken, except that it does not read past end-of-line.
03647    Also, horizontal space is skipped, and macros are popped.  */
03648 
03649 static enum cpp_token
03650 get_directive_token (cppReader *pfile)
03651 {
03652   for (;;)
03653     {
03654       size_t old_written = cppReader_getWritten (pfile);
03655       enum cpp_token token;
03656       cppSkipHspace (pfile);
03657       if (cppReader_peekC (pfile) == '\n')
03658         {
03659           return CPP_VSPACE;
03660         }
03661 
03662       token = cppGetToken (pfile);
03663 
03664       switch (token)
03665         {
03666         case CPP_POP:
03667           if (!cppBuffer_isMacro (cppReader_getBuffer (pfile)))
03668             return token;
03669           /*@fallthrough@*/
03670         case CPP_HSPACE:
03671         case CPP_COMMENT:
03672           cppReader_setWritten (pfile, old_written);
03673           /*@switchbreak@*/ break;
03674         default:
03675           return token;
03676         }
03677     }
03678 }
03679 
03680 
03681 /* Handle #include and #import.
03682    This function expects to see "fname" or <fname> on the input.
03683 
03684    The input is normally in part of the output_buffer following
03685    cppReader_getWritten, and will get overwritten by output_line_command.
03686    I.e. in input file specification has been popped by cppReader_handleDirective.
03687    This is safe.  */
03688 
03689 static int
03690 do_include (cppReader *pfile, struct directive *keyword,
03691             /*@unused@*/ char *unused1, /*@unused@*/ char *unused2)
03692 {
03693   bool skip_dirs = (keyword->type == T_INCLUDE_NEXT);
03694   cstring fname;
03695   char *fbeg, *fend;            /* Beginning and end of fname */
03696   enum cpp_token token;
03697 
03698   /* Chain of dirs to search */
03699   struct file_name_list *search_start = CPPOPTIONS (pfile)->include;
03700   struct file_name_list dsp[1]; /* First in chain, if #include "..." */
03701   struct file_name_list *searchptr = NULL;
03702   size_t old_written = cppReader_getWritten (pfile);
03703 
03704   int flen;
03705 
03706   int f;                        /* file number */
03707   int angle_brackets = 0;       /* 0 for "...", 1 for <...> */
03708   f= -1;                        /* JF we iz paranoid! */
03709 
03710   pfile->parsing_include_directive++;
03711   token = get_directive_token (pfile);
03712   pfile->parsing_include_directive--;
03713 
03714   if (token == CPP_STRING)
03715     {
03716       /* FIXME - check no trailing garbage */
03717       fbeg = pfile->token_buffer + old_written + 1;
03718       fend = cppReader_getPWritten (pfile) - 1;
03719       if (fbeg[-1] == '<')
03720         {
03721           angle_brackets = 1;
03722           /* If -I-, start with the first -I dir after the -I-.  */
03723           if (CPPOPTIONS (pfile)->first_bracket_include != NULL)
03724             search_start = CPPOPTIONS (pfile)->first_bracket_include;
03725         }
03726       /* If -I- was specified, don't search current dir, only spec'd ones.  */
03727       else if (!CPPOPTIONS (pfile)->ignore_srcdir)
03728         {
03729           cppBuffer *fp = CPPBUFFER (pfile);
03730           /* We have "filename".  Figure out directory this source
03731              file is coming from and put it on the front of the list.  */
03732 
03733           for ( ; fp != cppReader_nullBuffer (pfile); fp = cppBuffer_prevBuffer (fp))
03734             {
03735               int n;
03736               char *ep,*nam;
03737 
03738               llassert (fp != NULL);
03739 
03740               nam = NULL;
03741 
03742               if (cstring_isDefined (fp->nominal_fname))
03743                 {
03744                   nam = cstring_toCharsSafe (fp->nominal_fname);
03745 
03746                   /* Found a named file.  Figure out dir of the file,
03747                      and put it in front of the search list.  */
03748                   dsp[0].next = search_start;
03749                   search_start = dsp;
03750 
03751 #ifndef VMS
03752                   ep = strrchr (nam, CONNECTCHAR);
03753 #else                           /* VMS */
03754                   ep = strrchr (nam, ']');
03755                   if (ep == NULL) ep = strrchr (nam, '>');
03756                   if (ep == NULL) ep = strrchr (nam, ':');
03757                   if (ep != NULL) ep++;
03758 #endif                          /* VMS */
03759                   if (ep != NULL)
03760                     {
03761                       char save;
03762 
03763                       n = ep - nam;
03764                       save = nam[n];
03765                       nam[n] = '\0';
03766 
03767                       /*@-onlytrans@*/ /* This looks like a memory leak... */ 
03768                       dsp[0].fname = cstring_fromCharsNew (nam); /* evs 2000-07-20: was fromChars */
03769                       /*@=onlytrans@*/
03770                       nam[n] = save;
03771 
03772                       if (n + INCLUDE_LEN_FUDGE > pfile->max_include_len)
03773                         pfile->max_include_len = n + INCLUDE_LEN_FUDGE;
03774                     }
03775                   else
03776                     {
03777                       dsp[0].fname = cstring_undefined; /* Current directory */
03778                     }
03779 
03780                   dsp[0].got_name_map = 0;
03781                   break;
03782                 }
03783             }
03784         }
03785       else
03786         {
03787           ;
03788         }
03789     }
03790 #ifdef VMS
03791   else if (token == CPP_NAME)
03792     {
03793       /*
03794        * Support '#include xyz' like VAX-C to allow for easy use of all the
03795        * decwindow include files. It defaults to '#include <xyz.h>' (so the
03796        * code from case '<' is repeated here) and generates a warning.
03797        */
03798       cppReader_warning (pfile,
03799                    "VAX-C-style include specification found, use '#include <filename.h>' !");
03800       angle_brackets = 1;
03801       /* If -I-, start with the first -I dir after the -I-.  */
03802       if (CPPOPTIONS (pfile)->first_bracket_include)
03803         search_start = CPPOPTIONS (pfile)->first_bracket_include;
03804       fbeg = pfile->token_buffer + old_written;
03805       fend = cppReader_getPWritten (pfile);
03806     }
03807 #endif
03808   else
03809     {
03810       cppReader_error (pfile,
03811                  message ("Preprocessor command #%s expects \"FILENAME\" or <FILENAME>",
03812                           keyword->name));
03813 
03814       cppReader_setWritten (pfile, old_written);
03815       cppReader_skipRestOfLine (pfile);
03816       return 0;
03817     }
03818 
03819   *fend = 0;
03820 
03821   token = get_directive_token (pfile);
03822   if (token != CPP_VSPACE)
03823     {
03824       cppReader_errorLit (pfile,
03825                     cstring_makeLiteralTemp ("Junk at end of #include"));
03826 
03827       while (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP)
03828         {
03829           token = get_directive_token (pfile);
03830         }
03831     }
03832 
03833   /*
03834   ** For #include_next, skip in the search path
03835   ** past the dir in which the containing file was found.
03836   */
03837 
03838   if (skip_dirs)
03839     {
03840       cppBuffer *fp = CPPBUFFER (pfile);
03841 
03842       for (; fp != cppReader_nullBuffer (pfile); fp = cppBuffer_prevBuffer (fp))
03843         {
03844           llassert (fp != NULL);
03845 
03846           if (fp->fname != NULL)
03847             {
03848               /* fp->dir is null if the containing file was specified with
03849                  an absolute file name.  In that case, don't skip anything.  */
03850               if (fp->dir == SELF_DIR_DUMMY)
03851                 {
03852                   search_start = CPPOPTIONS (pfile)->include;
03853                 }
03854               else if (fp->dir != NULL)
03855                 {
03856                   search_start = fp->dir->next;
03857                 }
03858               else
03859                 {
03860                   ;
03861                 }
03862 
03863               break;
03864             }
03865         }
03866     }
03867 
03868   cppReader_setWritten (pfile, old_written);
03869 
03870   flen = fend - fbeg;
03871 
03872   DPRINTF (("fbeg: %s", fbeg));
03873 
03874   if (flen == 0)
03875     {
03876       cppReader_error (pfile,
03877                  message ("Empty file name in #%s", keyword->name));
03878       return 0;
03879     }
03880 
03881   /*
03882   ** Allocate this permanently, because it gets stored in the definitions
03883   ** of macros.
03884   */
03885 
03886   fname = cstring_undefined;
03887 
03888   /* + 2 above for slash and terminating null.  */
03889   /* + 2 added for '.h' on VMS (to support '#include filename') */
03890 
03891   /* If specified file name is absolute, just open it.  */
03892 
03893   if (osd_isConnectChar (*fbeg)
03894 # if defined (WIN32) || defined (OS2)
03895       || (*(fbeg + 1) == ':')
03896 # endif
03897       )
03898     {
03899       fname = cstring_copyLength (fbeg, flen);
03900       
03901       if (redundant_include_p (pfile, fname))
03902         {
03903           cstring_free (fname);
03904           return 0;
03905         }
03906       
03907       f = open_include_file (pfile, fname, NULL);
03908       
03909       if (f == IMPORT_FOUND)
03910         {
03911           return 0;             /* Already included this file */
03912         }
03913     } 
03914   else 
03915     {
03916       /* Search directory path, trying to open the file.
03917          Copy each filename tried into FNAME.  */
03918 
03919       for (searchptr = search_start; searchptr != NULL;
03920            searchptr = searchptr->next)
03921         {
03922           if (!cstring_isEmpty (searchptr->fname))
03923             {
03924               /* The empty string in a search path is ignored.
03925                  This makes it possible to turn off entirely
03926                  a standard piece of the list.  */
03927               if (cstring_isEmpty (searchptr->fname))
03928                 continue;
03929               
03930               fname = cstring_copy (searchptr->fname);
03931               fname = cstring_appendChar (fname, CONNECTCHAR);
03932               DPRINTF (("Here: %s", fname));
03933             }
03934           else
03935             {
03936               ;
03937             }
03938           
03939           fname = cstring_concatLength (fname, fbeg, flen);
03940 
03941           DPRINTF (("fname: %s", fname));
03942           
03943 #ifdef VMS
03944           /* Change this 1/2 Unix 1/2 VMS file specification into a
03945              full VMS file specification */
03946           if (searchptr->fname && (searchptr->fname[0] != 0)) {
03947             /* Fix up the filename */
03948             hack_vms_include_specification (fname);
03949           } else {
03950             /* This is a normal VMS filespec, so use it unchanged.  */
03951             strncpy (fname, fbeg, flen);
03952             fname[flen] = 0;
03953             /* if it's '#include filename', add the missing .h */
03954             if (strchr (fname,'.') == NULL) {
03955               strcat (fname, ".h");
03956             }
03957           }
03958 #endif /* VMS */
03959           /* ??? There are currently 3 separate mechanisms for avoiding processing
03960              of redundant include files: #import, #pragma once, and
03961              redundant_include_p.  It would be nice if they were unified.  */
03962           
03963           if (redundant_include_p (pfile, fname))
03964             {
03965               cstring_free (fname);
03966               return 0;
03967             }
03968 
03969           DPRINTF (("Trying: %s", fname));
03970 
03971           f = open_include_file (pfile, fname, searchptr);
03972           
03973           if (f == IMPORT_FOUND)
03974             {
03975               return 0;                 /* Already included this file */
03976             }
03977 #ifdef EACCES
03978           else if (f == IMPORT_NOT_FOUND && errno == EACCES)
03979             {
03980               cppReader_warning (pfile,
03981                                  message ("Header file %s exists, but is not readable", fname));
03982             }
03983 #endif
03984           
03985           if (f >= 0)
03986             {
03987               break;
03988             }
03989         }
03990     }
03991   
03992   if (f < 0)
03993     {
03994       /* A file that was not found.  */
03995       fname = cstring_copyLength (fbeg, flen);
03996 
03997       if (search_start != NULL)
03998         {
03999           cppReader_error (pfile,
04000                            message ("Cannot find include file %s", fname));
04001         }
04002       else
04003         {
04004           cppReader_error (pfile,
04005                            message ("No include path in which to find %s", fname));
04006         }
04007     }
04008   else {
04009     /*
04010     ** Check to see if this include file is a once-only include file.
04011     ** If so, give up.
04012     */
04013 
04014     struct file_name_list *ptr;
04015 
04016     for (ptr = pfile->all_include_files; ptr != NULL; ptr = ptr->next)
04017       {
04018         if (cstring_equal (ptr->fname, fname))
04019           {
04020             /* This file was included before.  */
04021             break;
04022           }
04023       }
04024 
04025     if (ptr == NULL)
04026       {
04027         /* This is the first time for this file.  */
04028         /* Add it to list of files included.  */
04029 
04030         ptr = (struct file_name_list *) dmalloc (sizeof (*ptr));
04031         ptr->control_macro = NULL;
04032         ptr->c_system_include_path = NULL;
04033         ptr->next = pfile->all_include_files;
04034         ptr->fname = fname;
04035         ptr->got_name_map = NULL;
04036 
04037         pfile->all_include_files = ptr;
04038         assertSet (pfile->all_include_files);
04039       }
04040 
04041     if (angle_brackets != 0)
04042       {
04043         pfile->system_include_depth++;
04044       }
04045 
04046     /* Actually process the file */
04047     if (cppReader_pushBuffer (pfile, NULL, 0) == NULL)
04048       {
04049         cstring_free (fname);
04050         return 0;
04051       }
04052 
04053     if (finclude (pfile, f, fname, is_system_include (pfile, fname),
04054                   searchptr != dsp ? searchptr : SELF_DIR_DUMMY))
04055       {
04056         output_line_command (pfile, 0, enter_file);
04057         pfile->only_seen_white = 2;
04058       }
04059 
04060     if (angle_brackets)
04061       {
04062         pfile->system_include_depth--;
04063       }
04064     /*@-branchstate@*/
04065   } /*@=branchstate@*/ 
04066 
04067   return 0;
04068 }
04069 
04070 /* Return nonzero if there is no need to include file NAME
04071    because it has already been included and it contains a conditional
04072    to make a repeated include do nothing.  */
04073 
04074 static bool
04075 redundant_include_p (cppReader *pfile, cstring name)
04076 {
04077   struct file_name_list *l = pfile->all_include_files;
04078 
04079   for (; l != NULL; l = l->next)
04080     {
04081       if (cstring_equal (name, l->fname)
04082           && (l->control_macro != NULL)
04083           && (cppReader_lookup (l->control_macro, -1, -1) != NULL))
04084         {
04085           return TRUE;
04086         }
04087     }
04088 
04089   return FALSE;
04090 }
04091 
04092 /* Return nonzero if the given FILENAME is an absolute pathname which
04093    designates a file within one of the known "system" include file
04094    directories.  We assume here that if the given FILENAME looks like
04095    it is the name of a file which resides either directly in a "system"
04096    include file directory, or within any subdirectory thereof, then the
04097    given file must be a "system" include file.  This function tells us
04098    if we should suppress pedantic errors/warnings for the given FILENAME.
04099 
04100    The value is 2 if the file is a C-language system header file
04101    for which C++ should (on most systems) assume `extern "C"'.  */
04102 
04103 static bool
04104 is_system_include (cppReader *pfile, cstring filename)
04105 {
04106   struct file_name_list *searchptr;
04107 
04108   for (searchptr = CPPOPTIONS (pfile)->first_system_include;
04109        searchptr != NULL;
04110        searchptr = searchptr->next)
04111     {
04112       if (!cstring_isEmpty (searchptr->fname)) {
04113         cstring sys_dir = searchptr->fname;
04114         int length = cstring_length (sys_dir);
04115 
04116         if (cstring_equalLen (sys_dir, filename, length)
04117             && osd_isConnectChar (cstring_getChar (filename, length)))
04118           {
04119             if (searchptr->c_system_include_path)
04120               return 2;
04121             else
04122               return 1;
04123           }
04124       }
04125     }
04126 
04127   return 0;
04128 }
04129 
04130 /* Convert a character string literal into a nul-terminated string.
04131    The input string is [IN ... LIMIT).
04132    The result is placed in RESULT.  RESULT can be the same as IN.
04133    The value returned in the end of the string written to RESULT,
04134    or NULL on error.  */
04135 
04136 static /*@null@*/ char *
04137 convert_string (cppReader *pfile, /*@returned@*/ char *result,
04138                 char *in, char *limit, int handle_escapes)
04139 {
04140   char c;
04141   c = *in++;
04142 
04143   if (c != '\"')
04144     {
04145       return NULL;
04146     }
04147 
04148   while (in < limit)
04149     {
04150       c = *in++;
04151 
04152       switch (c)
04153         {
04154         case '\0':
04155           return NULL;
04156         case '\"':
04157           limit = in;
04158           /*@switchbreak@*/ break;
04159         case '\\':
04160           if (handle_escapes)
04161             {
04162               char *bpc = (char *) in;
04163               int i = (char) cppReader_parseEscape (pfile, &bpc);
04164               in = (char *) bpc;
04165               if (i >= 0)
04166                 *result++ = (char) c;
04167               /*@switchbreak@*/ break;
04168             }
04169 
04170           /*@fallthrough@*/
04171         default:
04172           *result++ = c;
04173         }
04174     }
04175 
04176   *result = 0;
04177   return result;
04178 }
04179 
04180 /*
04181  * interpret #line command.  Remembers previously seen fnames
04182  * in its very own hash table.
04183  */
04184 
04185 /*@constant int FNAME_HASHSIZE@*/
04186 #define FNAME_HASHSIZE 37
04187 
04188 static int
04189 do_line (cppReader *pfile, /*@unused@*/ struct directive *keyword)
04190 {
04191   cppBuffer *ip = cppReader_getBuffer (pfile);
04192   int new_lineno;
04193   size_t old_written = cppReader_getWritten (pfile);
04194   enum file_change_code file_change = same_file;
04195   enum cpp_token token;
04196 
04197   token = get_directive_token (pfile);
04198 
04199   if (token != CPP_NUMBER
04200       || !isdigit(pfile->token_buffer[old_written]))
04201     {
04202       cppReader_errorLit (pfile,
04203                     cstring_makeLiteralTemp ("invalid format `#line' command"));
04204 
04205       goto bad_line_directive;
04206     }
04207 
04208   /* The Newline at the end of this line remains to be processed.
04209      To put the next line at the specified line number,
04210      we must store a line number now that is one less.  */
04211   new_lineno = atoi (pfile->token_buffer + old_written) - 1;
04212   cppReader_setWritten (pfile, old_written);
04213 
04214   /* NEW_LINENO is one less than the actual line number here.  */
04215   if (cppReader_isPedantic (pfile) && new_lineno < 0)
04216     cppReader_pedwarnLit (pfile,
04217                     cstring_makeLiteralTemp ("line number out of range in `#line' command"));
04218 
04219   token = get_directive_token (pfile);
04220 
04221   if (token == CPP_STRING) {
04222     char *fname = pfile->token_buffer + old_written;
04223     char *end_name;
04224     static HASHNODE *fname_table[FNAME_HASHSIZE];
04225     HASHNODE *hp, **hash_bucket;
04226     char *p;
04227     size_t num_start;
04228     int fname_length;
04229 
04230     /* Turn the file name, which is a character string literal,
04231        into a null-terminated string.  Do this in place.  */
04232     end_name = convert_string (pfile, fname, fname, cppReader_getPWritten (pfile), 1);
04233     if (end_name == NULL)
04234       {
04235         cppReader_errorLit (pfile,
04236                       cstring_makeLiteralTemp ("invalid format `#line' command"));
04237         goto bad_line_directive;
04238       }
04239 
04240     fname_length = end_name - fname;
04241     num_start = cppReader_getWritten (pfile);
04242 
04243     token = get_directive_token (pfile);
04244     if (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP) {
04245       p = pfile->token_buffer + num_start;
04246       if (cppReader_isPedantic (pfile))
04247         cppReader_pedwarnLit (pfile,
04248                         cstring_makeLiteralTemp ("garbage at end of `#line' command"));
04249 
04250       if (token != CPP_NUMBER || *p < '0' || *p > '4' || p[1] != '\0')
04251         {
04252           cppReader_errorLit (pfile,
04253                         cstring_makeLiteralTemp ("invalid format `#line' command"));
04254           goto bad_line_directive;
04255         }
04256       if (*p == '1')
04257         file_change = enter_file;
04258       else if (*p == 2)
04259         file_change = leave_file;
04260       else if (*p == 3)
04261         ip->system_header_p = 1;
04262       else /* if (*p == 4) */
04263         ip->system_header_p = 2;
04264 
04265       cppReader_setWritten (pfile, num_start);
04266       token = get_directive_token (pfile);
04267       p = pfile->token_buffer + num_start;
04268       if (token == CPP_NUMBER && p[1] == '\0' && (*p == '3' || *p== '4')) {
04269         ip->system_header_p = *p == 3 ? 1 : 2;
04270         token = get_directive_token (pfile);
04271       }
04272       if (token != CPP_VSPACE) {
04273         cppReader_errorLit (pfile,
04274                       cstring_makeLiteralTemp ("invalid format `#line' command"));
04275 
04276         goto bad_line_directive;
04277       }
04278     }
04279 
04280     hash_bucket =
04281       &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
04282     for (hp = *hash_bucket; hp != NULL; hp = hp->next)
04283       {
04284         if (hp->length == fname_length &&
04285             strncmp (hp->value.cpval, fname, size_fromInt (fname_length)) == 0) {
04286           ip->nominal_fname = cstring_fromChars (hp->value.cpval);
04287           break;
04288         }
04289       }
04290 
04291     if (hp == 0) {
04292       /* Didn't find it; cons up a new one.  */
04293       hp = (HASHNODE *) dmalloc (sizeof (*hp) + fname_length + 1);
04294 
04295       hp->prev = NULL;
04296       hp->bucket_hdr = NULL;
04297       hp->type = T_NONE;
04298       hp->name = cstring_undefined;
04299       hp->next = *hash_bucket;
04300 
04301       *hash_bucket = hp;
04302 
04303       hp->length = fname_length;
04304       hp->value.cpval = dmalloc (sizeof (*hp->value.cpval) * (fname_length + 1));
04305       memcpy (hp->value.cpval, fname, size_fromInt (fname_length));
04306       hp->value.cpval[fname_length] = '\0';
04307       ip->nominal_fname = cstring_fromChars (hp->value.cpval);
04308     }
04309   }
04310   else if (token != CPP_VSPACE && token != CPP_EOF)
04311     {
04312       cppReader_errorLit (pfile,
04313                     cstring_makeLiteralTemp ("invalid format `#line' command"));
04314       goto bad_line_directive;
04315     }
04316   else
04317     {
04318       ;
04319     }
04320 
04321   ip->lineno = new_lineno;
04322 bad_line_directive:
04323   cppReader_skipRestOfLine (pfile);
04324   cppReader_setWritten (pfile, old_written);
04325   output_line_command (pfile, 0, file_change);
04326   return 0;
04327 }
04328 
04329 /*
04330  * remove the definition of a symbol from the symbol table.
04331  * according to un*x /lib/cpp, it is not an error to undef
04332  * something that has no definitions, so it isn't one here either.
04333  */
04334 
04335 static int
04336 do_undef (cppReader *pfile, struct directive *keyword, char *buf, char *limit)
04337 {
04338 
04339   int sym_length;
04340   HASHNODE *hp;
04341   char *orig_buf = buf;
04342 
04343   SKIP_WHITE_SPACE (buf);
04344 
04345   sym_length = cppReader_checkMacroName (pfile, buf, cstring_makeLiteralTemp ("macro"));
04346 
04347   while ((hp = cppReader_lookup (buf, sym_length, -1)) != NULL)
04348     {
04349       /* If we are generating additional info for debugging (with -g) we
04350          need to pass through all effective #undef commands.  */
04351       if (CPPOPTIONS (pfile)->debug_output && (keyword != NULL))
04352         {
04353           pass_thru_directive (orig_buf, limit, pfile, keyword);
04354         }
04355 
04356       if (hp->type != T_MACRO)
04357         {
04358           cppReader_warning (pfile,
04359                        message ("Undefining preprocessor builtin: %s",
04360                                 hp->name));
04361         }
04362 
04363       cppReader_deleteMacro (hp);
04364     }
04365 
04366   if (cppReader_isPedantic (pfile)) {
04367     buf += sym_length;
04368     SKIP_WHITE_SPACE (buf);
04369     if (buf != limit)
04370       {
04371         cppReader_pedwarnLit (pfile,
04372                         cstring_makeLiteralTemp ("garbage after `#undef' directive"));
04373       }
04374   }
04375 
04376   return 0;
04377 }
04378 
04379 
04380 /*
04381  * Report an error detected by the program we are processing.
04382  * Use the text of the line in the error message.
04383  * (We use error because it prints the filename & line#.)
04384  */
04385 
04386 static int
04387 do_error (cppReader *pfile, /*@unused@*/ struct directive *keyword,
04388           char *buf, char *limit)
04389 {
04390   int length = limit - buf;
04391   cstring copy = cstring_copyLength (buf, length);
04392   cstring adv = cstring_advanceWhiteSpace (copy);
04393 
04394   cppReader_error (pfile, message ("#error %s", adv));
04395   cstring_free (copy);
04396   return 0;
04397 }
04398 
04399 /*
04400  * Report a warning detected by the program we are processing.
04401  * Use the text of the line in the warning message, then continue.
04402  * (We use error because it prints the filename & line#.)
04403  */
04404 
04405 static int
04406 do_warning (cppReader *pfile, /*@unused@*/ struct directive *keyword,
04407             char *buf, char *limit)
04408 {
04409   int length = limit - buf;
04410   cstring copy = cstring_copyLength (buf, length);
04411   cstring adv = cstring_advanceWhiteSpace (copy);
04412   cppReader_warning (pfile, message ("#warning %s", adv));
04413   cstring_free (copy);
04414   return 0;
04415 }
04416 
04417 
04418 /* #ident has already been copied to the output file, so just ignore it.  */
04419 
04420 static int
04421 do_ident (cppReader *pfile, /*@unused@*/ struct directive *keyword,
04422           /*@unused@*/ char *buf, /*@unused@*/ char *limit)
04423 {
04424   /* Allow #ident in system headers, since that's not user's fault.  */
04425   if (cppReader_isPedantic (pfile) && !cppReader_getBuffer (pfile)->system_header_p)
04426     cppReader_pedwarnLit (pfile,
04427                     cstring_makeLiteralTemp ("ANSI C does not allow `#ident'"));
04428 
04429   /* Leave rest of line to be read by later calls to cppGetToken.  */
04430 
04431   return 0;
04432 }
04433 
04434 /* #pragma and its argument line have already been copied to the output file.
04435    Just check for some recognized pragmas that need validation here.  */
04436 
04437 static int
04438 do_pragma (cppReader *pfile, /*@unused@*/ struct directive *keyword,
04439            /*@unused@*/ char *buf, /*@unused@*/ char *limit)
04440 {
04441   while (*buf == ' ' || *buf == '\t')
04442     {
04443       buf++;
04444     }
04445 
04446   if (!strncmp (buf, "implementation", 14)) {
04447     /* Be quiet about `#pragma implementation' for a file only if it hasn't
04448        been included yet.  */
04449     struct file_name_list *ptr;
04450     char *p = buf + 14, *fname, *inc_fname;
04451     int fname_len;
04452     SKIP_WHITE_SPACE (p);
04453     if (*p == '\n' || *p != '\"')
04454       return 0;
04455 
04456     fname = p + 1;
04457     p = (char *) strchr (fname, '\"');
04458     fname_len = p != NULL ? p - fname : mstring_length (fname);
04459 
04460     for (ptr = pfile->all_include_files; ptr != NULL; ptr = ptr->next)
04461       {
04462         inc_fname = (char *) strrchr (cstring_toCharsSafe (ptr->fname), CONNECTCHAR);
04463         inc_fname = (inc_fname != NULL)
04464           ? inc_fname + 1 : cstring_toCharsSafe (ptr->fname);
04465 
04466         if ((inc_fname != NULL)
04467             && (strncmp (inc_fname, fname, size_fromInt (fname_len)) == 0))
04468           {
04469             cpp_setLocation (pfile);
04470 
04471             ppllerror (message ("`#pragma implementation' for `%s' appears "
04472                                 "after file is included",
04473                                 cstring_fromChars (fname)));
04474           }
04475       }
04476   }
04477 
04478   return 0;
04479 }
04480 
04481 /*
04482  * handle #if command by
04483  *   1) inserting special `defined' keyword into the hash table
04484  *      that gets turned into 0 or 1 by special_symbol (thus,
04485  *      if the luser has a symbol called `defined' already, it won't
04486  *      work inside the #if command)
04487  *   2) rescan the input into a temporary output buffer
04488  *   3) pass the output buffer to the yacc parser and collect a value
04489  *   4) clean up the mess left from steps 1 and 2.
04490  *   5) call conditional_skip to skip til the next #endif (etc.),
04491  *      or not, depending on the value from step 3.
04492  */
04493 
04494 static int
04495 do_if (cppReader *pfile, /*@unused@*/ struct directive *keyword,
04496        char *buf, char *limit)
04497 {
04498   HOST_WIDE_INT value = eval_if_expression (pfile, buf, limit - buf);
04499   conditional_skip (pfile, value == 0, T_IF, NULL);
04500   return 0;
04501 }
04502 
04503 /*
04504  * handle a #elif directive by not changing  if_stack  either.
04505  * see the comment above do_else.
04506  */
04507 
04508 static int do_elif (cppReader *pfile, /*@unused@*/ struct directive *keyword,
04509                     char *buf, char *limit)
04510 {
04511   if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack)
04512     {
04513       cppReader_errorLit (pfile,
04514                     cstring_makeLiteralTemp ("Preprocessor command #elif is not within a conditional"));
04515       return 0;
04516     }
04517   else
04518     {
04519       llassert (pfile->if_stack != NULL);
04520 
04521       if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF)
04522         {
04523           cppReader_errorLit (pfile,
04524                         cstring_makeLiteralTemp ("`#elif' after `#else'"));
04525 
04526           if (pfile->if_stack->fname != NULL
04527               && cppReader_getBuffer (pfile)->fname != NULL
04528               && !cstring_equal (pfile->if_stack->fname,
04529                                  cppReader_getBuffer (pfile)->nominal_fname))
04530             fprintf (stderr, ", file %s", cstring_toCharsSafe (pfile->if_stack->fname));
04531           fprintf (stderr, ")\n");
04532         }
04533       pfile->if_stack->type = T_ELIF;
04534     }
04535 
04536   if (pfile->if_stack->if_succeeded)
04537     {
04538       skip_if_group (pfile, 0);
04539     }
04540   else
04541     {
04542       HOST_WIDE_INT value = eval_if_expression (pfile, buf, limit - buf);
04543       if (value == 0)
04544         skip_if_group (pfile, 0);
04545       else
04546         {
04547           ++pfile->if_stack->if_succeeded;      /* continue processing input */
04548           output_line_command (pfile, 1, same_file);
04549         }
04550     }
04551 
04552   return 0;
04553 }
04554 
04555 /*
04556  * evaluate a #if expression in BUF, of length LENGTH,
04557  * then parse the result as a C expression and return the value as an int.
04558  */
04559 
04560 static HOST_WIDE_INT
04561 eval_if_expression (cppReader *pfile,
04562                     /*@unused@*/ char *buf,
04563                     /*@unused@*/ int length)
04564 {
04565   HASHNODE *save_defined;
04566   HOST_WIDE_INT value;
04567   size_t old_written = cppReader_getWritten (pfile);
04568 
04569   save_defined = cppReader_install ("defined", -1, T_SPEC_DEFINED, 0, 0, -1);
04570   pfile->pcp_inside_if = 1;
04571 
04572   value = cppReader_parseExpression (pfile);
04573   pfile->pcp_inside_if = 0;
04574 
04575   /* Clean up special symbol */
04576   cppReader_deleteMacro (save_defined);
04577 
04578   cppReader_setWritten (pfile, old_written); /* Pop */
04579 
04580   return value;
04581 }
04582 
04583 /*
04584  * routine to handle ifdef/ifndef.  Try to look up the symbol,
04585  * then do or don't skip to the #endif/#else/#elif depending
04586  * on what directive is actually being processed.
04587  */
04588 
04589 static int
04590 do_xifdef (cppReader *pfile, struct directive *keyword,
04591            /*@unused@*/ char *unused1, /*@unused@*/ char *unused2)
04592 {
04593   int skip;
04594   cppBuffer *ip = cppReader_getBuffer (pfile);
04595   char *ident;
04596   int ident_length;
04597   enum cpp_token token;
04598   int start_of_file = 0;
04599   char *control_macro = 0;
04600   size_t old_written = cppReader_getWritten (pfile);
04601 
04602   DPRINTF (("do xifdef: %d",
04603             keyword->type == T_IFNDEF));
04604 
04605   /* Detect a #ifndef at start of file (not counting comments).  */
04606   if (cstring_isDefined (ip->fname) && keyword->type == T_IFNDEF)
04607     {
04608       start_of_file = pfile->only_seen_white == 2;
04609     }
04610 
04611   pfile->no_macro_expand++;
04612   token = get_directive_token (pfile);
04613   pfile->no_macro_expand--;
04614 
04615   ident = pfile->token_buffer + old_written;
04616   ident_length = size_toInt (cppReader_getWritten (pfile) - old_written);
04617   cppReader_setWritten (pfile, old_written); /* Pop */
04618 
04619   if (token == CPP_VSPACE || token == CPP_POP || token == CPP_EOF)
04620     {
04621       skip = (keyword->type == T_IFDEF);
04622       if (! cppReader_isTraditional (pfile))
04623         {
04624           cppReader_pedwarn (pfile,
04625                        message ("`#%s' with no argument", keyword->name));
04626         }
04627     }
04628   else if (token == CPP_NAME)
04629     {
04630       HASHNODE *hp = cppReader_lookup (ident, ident_length, -1);
04631       skip = (keyword->type == T_IFDEF) 
04632         ? (hp == NULL) : (hp != NULL);
04633 
04634       DPRINTF (("hp null: %d / %d / %d",
04635                 (hp == NULL),
04636                 (keyword->type == T_IFNDEF),
04637                 skip));
04638                 
04639       if (start_of_file && !skip)
04640         {
04641           DPRINTF (("Not skipping!"));
04642           control_macro = (char *) dmalloc (size_fromInt (ident_length + 1));
04643           memcpy (control_macro, ident, size_fromInt (ident_length + 1));
04644         }
04645     }
04646   else
04647     {
04648       skip = (keyword->type == T_IFDEF);
04649       if (! cppReader_isTraditional (pfile))
04650         {
04651           cppReader_error (pfile,
04652                      message ("`#%s' with invalid argument", keyword->name));
04653         }
04654     }
04655 
04656   if (!cppReader_isTraditional (pfile))
04657     {
04658       int c;
04659       cppSkipHspace (pfile);
04660       c = cppReader_peekC (pfile);
04661       if (c != EOF && c != '\n')
04662         {
04663           cppReader_pedwarn (pfile,
04664                              message ("garbage at end of `#%s' argument", keyword->name));
04665         }
04666     }
04667 
04668   cppReader_skipRestOfLine (pfile);
04669 
04670   DPRINTF (("Conditional skip: %d", skip));
04671   conditional_skip (pfile, skip, T_IF, control_macro);
04672   return 0;
04673 }
04674 
04675 /* Push TYPE on stack; then, if SKIP is nonzero, skip ahead.
04676    If this is a #ifndef starting at the beginning of a file,
04677    CONTROL_MACRO is the macro name tested by the #ifndef.
04678    Otherwise, CONTROL_MACRO is 0.  */
04679 
04680 static void
04681 conditional_skip (cppReader *pfile, int skip,
04682                   enum node_type type,
04683                   /*@dependent@*/ char *control_macro)
04684 {
04685   cppIfStackFrame *temp = (cppIfStackFrame *) dmalloc (sizeof (*temp));
04686 
04687   temp->fname = cppReader_getBuffer (pfile)->nominal_fname;
04688   temp->next = pfile->if_stack;
04689   temp->control_macro = control_macro;
04690   temp->lineno = 0;
04691   temp->if_succeeded = 0;
04692 
04693   pfile->if_stack = temp;
04694   pfile->if_stack->type = type;
04695 
04696   if (skip != 0)
04697     {
04698       skip_if_group (pfile, 0);
04699       return;
04700     }
04701   else
04702     {
04703       ++pfile->if_stack->if_succeeded;
04704       output_line_command (pfile, 1, same_file);
04705     }
04706 }
04707 
04708 /*
04709  * skip to #endif, #else, or #elif.  adjust line numbers, etc.
04710  * leaves input ptr at the sharp sign found.
04711  * If ANY is nonzero, return at next directive of any sort.
04712  */
04713 
04714 static void
04715 skip_if_group (cppReader *pfile, int any)
04716 {
04717   int c;
04718   struct directive *kt;
04719   cppIfStackFrame *save_if_stack = pfile->if_stack; /* don't pop past here */
04720   register int ident_length;
04721   char *ident;
04722   struct parse_marker line_start_mark;
04723 
04724   parseSetMark (&line_start_mark, pfile);
04725 
04726   if (CPPOPTIONS (pfile)->output_conditionals) {
04727     static char failed[] = "#failed\n";
04728     cppReader_puts (pfile, failed, sizeof(failed)-1);
04729     pfile->lineno++;
04730     output_line_command (pfile, 1, same_file);
04731   }
04732 
04733 beg_of_line:
04734   if (CPPOPTIONS (pfile)->output_conditionals)
04735     {
04736       cppBuffer *pbuf = cppReader_getBuffer (pfile);
04737       char *start_line;
04738 
04739       llassert (pbuf->buf != NULL);
04740 
04741       start_line = pbuf->buf + line_start_mark.position;
04742       cppReader_puts (pfile, start_line, size_fromInt (pbuf->cur - start_line));
04743     }
04744 
04745   parseMoveMark (&line_start_mark, pfile);
04746 
04747   if (!cppReader_isTraditional (pfile))
04748     {
04749       cppSkipHspace (pfile);
04750     }
04751 
04752   c  = cppReader_getC (pfile);
04753   if (c == '#')
04754     {
04755       size_t old_written = cppReader_getWritten (pfile);
04756       cppSkipHspace (pfile);
04757 
04758       parse_name (pfile, cppReader_getC (pfile));
04759       ident_length = size_toInt (cppReader_getWritten (pfile) - old_written);
04760       ident = pfile->token_buffer + old_written;
04761       pfile->limit = ident;
04762 
04763       for (kt = directive_table; kt->length >= 0; kt++)
04764         {
04765           cppIfStackFrame *temp;
04766           if (ident_length == kt->length
04767               && cstring_equalPrefix (kt->name, ident))
04768             {
04769               /* If we are asked to return on next directive, do so now.  */
04770               if (any)
04771                 {
04772                   goto done;
04773                 }
04774 
04775               switch (kt->type)
04776                 {
04777                 case T_IF:
04778                 case T_IFDEF:
04779                 case T_IFNDEF:
04780                   temp = (cppIfStackFrame *) dmalloc (sizeof (*temp));
04781                   temp->next = pfile->if_stack;
04782                   temp->fname = cppReader_getBuffer (pfile)->nominal_fname;
04783                   temp->type = kt->type;
04784                   temp->lineno = 0;
04785                   temp->if_succeeded = 0;
04786                   temp->control_macro = NULL;
04787 
04788                   pfile->if_stack = temp;
04789                   /*@switchbreak@*/ break;
04790                 case T_ELSE:
04791                 case T_ENDIF:
04792                   if (cppReader_isPedantic (pfile) && pfile->if_stack != save_if_stack)
04793                     validate_else (pfile,
04794                                    cstring_makeLiteralTemp (kt->type == T_ELSE ? "#else" : "#endif"));
04795                   /*@fallthrough@*/
04796                 case T_ELIF:
04797                   if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack)
04798                     {
04799                       cppReader_error (pfile,
04800                                  message ("Preprocessor command #%s is not within a conditional", kt->name));
04801                       /*@switchbreak@*/ break;
04802                     }
04803                   else if (pfile->if_stack == save_if_stack)
04804                     {
04805                       goto done;                /* found what we came for */
04806                     }
04807                   else
04808                     {
04809                       ;
04810                     }
04811 
04812                   if (kt->type != T_ENDIF)
04813                     {
04814                       llassert (pfile->if_stack != NULL);
04815 
04816                       if (pfile->if_stack->type == T_ELSE)
04817                         {
04818                           cppReader_errorLit (pfile,
04819                                         cstring_makeLiteralTemp ("`#else' or `#elif' after `#else'"));
04820                         }
04821 
04822                       pfile->if_stack->type = kt->type;
04823                       /*@switchbreak@*/ break;
04824                     }
04825 
04826                   temp = pfile->if_stack;
04827                   llassert (temp != NULL);
04828                   pfile->if_stack = temp->next;
04829                   sfree (temp);
04830                   /*@switchbreak@*/ break;
04831                 default: ;
04832                   /*@-branchstate@*/ 
04833                 }
04834               /*@=branchstate@*/
04835               break;
04836             }
04837           
04838           /* Don't let erroneous code go by.  */
04839           
04840           if (kt->length < 0 && !CPPOPTIONS (pfile)->lang_asm
04841               && cppReader_isPedantic (pfile))
04842             {
04843               cppReader_pedwarnLit (pfile,
04844                                     cstring_makeLiteralTemp ("Invalid preprocessor directive name"));
04845             }
04846         }
04847 
04848       c = cppReader_getC (pfile);
04849     }
04850   /* We're in the middle of a line.  Skip the rest of it.  */
04851   for (;;) {
04852     switch (c)
04853       {
04854         size_t old;
04855       case EOF:
04856         goto done;
04857       case '/':                 /* possible comment */
04858         c = skip_comment (pfile, NULL);
04859         if (c == EOF)
04860           goto done;
04861         /*@switchbreak@*/ break;
04862       case '\"':
04863       case '\'':
04864         cppReader_forward (pfile, -1);
04865         old = cppReader_getWritten (pfile);
04866         (void) cppGetToken (pfile);
04867         cppReader_setWritten (pfile, old);
04868         /*@switchbreak@*/ break;
04869       case '\\':
04870         /* Char after backslash loses its special meaning.  */
04871         if (cppReader_peekC (pfile) == '\n')
04872           {
04873             cppReader_forward (pfile, 1);
04874           }
04875 
04876         /*@switchbreak@*/ break;
04877       case '\n':
04878         goto beg_of_line;
04879       }
04880     c = cppReader_getC (pfile);
04881   }
04882 done:
04883   if (CPPOPTIONS (pfile)->output_conditionals) {
04884     static char end_failed[] = "#endfailed\n";
04885     cppReader_puts (pfile, end_failed, sizeof(end_failed)-1);
04886     pfile->lineno++;
04887   }
04888   pfile->only_seen_white = 1;
04889 
04890   parseGotoMark (&line_start_mark, pfile);
04891   parseClearMark (&line_start_mark);
04892 }
04893 
04894 /*
04895  * handle a #else directive.  Do this by just continuing processing
04896  * without changing  if_stack ;  this is so that the error message
04897  * for missing #endif's etc. will point to the original #if.  It
04898  * is possible that something different would be better.
04899  */
04900 
04901 static int
04902 do_else (cppReader *pfile, /*@unused@*/ struct directive *keyword,
04903         /*@unused@*/ char *buf, /*@unused@*/ char *limit)
04904 {
04905   if (cppReader_isPedantic (pfile))
04906     {
04907       validate_else (pfile, cstring_makeLiteralTemp ("#else"));
04908     }
04909 
04910   cppReader_skipRestOfLine (pfile);
04911 
04912   if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack) {
04913     cppReader_errorLit (pfile,
04914                   cstring_makeLiteralTemp ("Preprocessor command #else is not within a conditional"));
04915     return 0;
04916   } else {
04917     /* #ifndef can't have its special treatment for containing the whole file
04918        if it has a #else clause.  */
04919 
04920     llassert (pfile->if_stack != NULL);
04921 
04922     pfile->if_stack->control_macro = 0;
04923 
04924     if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF)
04925       {
04926         cpp_setLocation (pfile);
04927         genppllerrorhint (FLG_PREPROC,
04928                           message ("Pre-processor directive #else after #else"),
04929                           message ("%q: Location of match",
04930                                    fileloc_unparseRaw (pfile->if_stack->fname,
04931                                                        pfile->if_stack->lineno)));
04932       }
04933 
04934     pfile->if_stack->type = T_ELSE;
04935   }
04936 
04937   if (pfile->if_stack->if_succeeded)
04938     skip_if_group (pfile, 0);
04939   else {
04940     ++pfile->if_stack->if_succeeded;    /* continue processing input */
04941     output_line_command (pfile, 1, same_file);
04942   }
04943 
04944   return 0;
04945 }
04946 
04947 /*
04948  * unstack after #endif command
04949  */
04950 
04951 static int
04952 do_endif (cppReader *pfile, /*@unused@*/ struct directive *keyword,
04953           /*@unused@*/ char *buf, /*@unused@*/ char *limit)
04954 {
04955   if (cppReader_isPedantic (pfile))
04956     {
04957       validate_else (pfile, cstring_makeLiteralTemp ("#endif"));
04958     }
04959 
04960   cppReader_skipRestOfLine (pfile);
04961 
04962   if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack)
04963     {
04964       cppReader_errorLit (pfile, cstring_makeLiteralTemp ("Unbalanced #endif"));
04965     }
04966   else
04967     {
04968       cppIfStackFrame *temp = pfile->if_stack;
04969 
04970       llassert (temp != NULL);
04971 
04972       pfile->if_stack = temp->next;
04973       if (temp->control_macro != 0)
04974         {
04975           /* This #endif matched a #ifndef at the start of the file.
04976              See if it is at the end of the file.  */
04977           struct parse_marker start_mark;
04978           int c;
04979 
04980           parseSetMark (&start_mark, pfile);
04981 
04982           for (;;)
04983             {
04984               cppSkipHspace (pfile);
04985               c = cppReader_getC (pfile);
04986 
04987               if (c != '\n')
04988                 break;
04989             }
04990 
04991           parseGotoMark (&start_mark, pfile);
04992           parseClearMark (&start_mark);
04993 
04994           if (c == EOF)
04995             {
04996               /* If we get here, this #endif ends a #ifndef
04997                  that contains all of the file (aside from whitespace).
04998                  Arrange not to include the file again
04999                  if the macro that was tested is defined.
05000 
05001                  Do not do this for the top-level file in a -include or any
05002                  file in a -imacros.  */
05003               struct file_name_list *ifile = pfile->all_include_files;
05004 
05005               for ( ; ifile != NULL; ifile = ifile->next)
05006                 {
05007                   if (cstring_equal (ifile->fname, cppReader_getBuffer (pfile)->fname))
05008                     {
05009                       ifile->control_macro = temp->control_macro;
05010                       break;
05011                     }
05012                 }
05013             }
05014         }
05015 
05016       sfree (temp);
05017       output_line_command (pfile, 1, same_file);
05018     }
05019   return 0;
05020 }
05021 
05022 /* When an #else or #endif is found while skipping failed conditional,
05023    if -pedantic was specified, this is called to warn about text after
05024    the command name.  P points to the first char after the command name.  */
05025 
05026 static void
05027 validate_else (cppReader *pfile, cstring directive)
05028 {
05029   int c;
05030   cppSkipHspace (pfile);
05031   c = cppReader_peekC (pfile);
05032   if (c != EOF && c != '\n')
05033     {
05034       cppReader_pedwarn (pfile,
05035                    message ("text following `%s' violates ANSI standard", directive));
05036     }
05037 }
05038 
05039 /*
05040 ** Get the next token, and add it to the text in pfile->token_buffer.
05041 ** Return the kind of token we got.
05042 */
05043 
05044 enum cpp_token
05045 cppGetToken (cppReader *pfile)
05046 {
05047   int c, c2, c3;
05048   size_t old_written = 0;
05049   int start_line, start_column;
05050   enum cpp_token token;
05051   struct cppOptions *opts = CPPOPTIONS (pfile);
05052   cppReader_getBuffer (pfile)->prev = cppReader_getBuffer (pfile)->cur;
05053 
05054 get_next:
05055   c = cppReader_getC (pfile);
05056 
05057   if (c == EOF)
05058     {
05059     handle_eof:
05060       if (cppReader_getBuffer (pfile)->seen_eof)
05061         {
05062           cppBuffer *buf = cppReader_popBuffer (pfile);
05063 
05064           if (buf != cppReader_nullBuffer (pfile))
05065             {
05066               goto get_next;
05067             }
05068           else
05069             {
05070               return CPP_EOF;
05071             }
05072         }
05073       else
05074         {
05075           cppBuffer *next_buf = cppBuffer_prevBuffer (cppReader_getBuffer (pfile));
05076           cppReader_getBuffer (pfile)->seen_eof = 1;
05077 
05078           if (cstring_isDefined (cppReader_getBuffer (pfile)->nominal_fname)
05079               && next_buf != cppReader_nullBuffer (pfile))
05080             {
05081               /* We're about to return from an #include file.
05082                  Emit #line information now (as part of the CPP_POP) result.
05083                  But the #line refers to the file we will pop to.  */
05084               cppBuffer *cur_buffer = CPPBUFFER (pfile);
05085               CPPBUFFER (pfile) = next_buf;
05086               pfile->input_stack_listing_current = 0;
05087               output_line_command (pfile, 0, leave_file);
05088               CPPBUFFER (pfile) = cur_buffer;
05089             }
05090           return CPP_POP;
05091         }
05092     }
05093   else
05094     {
05095       long newlines;
05096       struct parse_marker start_mark;
05097 
05098       switch (c)
05099         {
05100         case '/':
05101           if (cppReader_peekC (pfile) == '=')
05102             {
05103               goto op2;
05104             }
05105 
05106           if (opts->put_out_comments)
05107             {
05108               parseSetMark (&start_mark, pfile);
05109             }
05110 
05111           newlines = 0;
05112           cppBuffer_lineAndColumn (cppReader_fileBuffer (pfile),
05113                                    &start_line, &start_column);
05114           c = skip_comment (pfile, &newlines);
05115 
05116           if (opts->put_out_comments && (c == '/' || c == EOF))
05117             {
05118               assertSet (&start_mark);
05119               parseClearMark (&start_mark);
05120             }
05121 
05122           if (c == '/')
05123             goto randomchar;
05124           if (c == EOF)
05125             {
05126               cppReader_errorWithLine (pfile, start_line, start_column,
05127                                        cstring_makeLiteral ("Unterminated comment"));
05128               goto handle_eof;
05129             }
05130           c = '/';  /* Initial letter of comment.  */
05131         return_comment:
05132           /* Comments are equivalent to spaces.
05133              For -traditional, a comment is equivalent to nothing.  */
05134 
05135           if (opts->put_out_comments)
05136             {
05137               enum cpp_token res;
05138 
05139               assertSet (&start_mark);
05140               res = cpp_handleComment (pfile, &start_mark);
05141               pfile->lineno += newlines;
05142               return res;
05143             }
05144           else if (cppReader_isTraditional (pfile))
05145             {
05146               return CPP_COMMENT;
05147             }
05148           else
05149             {
05150               cppReader_reserve(pfile, 1);
05151               cppReader_putCharQ (pfile, ' ');
05152               return CPP_HSPACE;
05153             }
05154 
05155         case '#':
05156           if (!pfile->only_seen_white)
05157             {
05158               goto randomchar;
05159             }
05160 
05161           if (cppReader_handleDirective (pfile))
05162             {
05163               return CPP_DIRECTIVE;
05164             }
05165 
05166           pfile->only_seen_white = 0;
05167           return CPP_OTHER;
05168 
05169         case '\"':
05170         case '\'':
05171           /* A single quoted string is treated like a double -- some
05172              programs (e.g., troff) are perverse this way */
05173           cppBuffer_lineAndColumn (cppReader_fileBuffer (pfile),
05174                                    &start_line, &start_column);
05175           old_written = cppReader_getWritten (pfile);
05176         string:
05177           cppReader_putChar (pfile, c);
05178           while (TRUE)
05179             {
05180               int cc = cppReader_getC (pfile);
05181               if (cc == EOF)
05182                 {
05183                   if (cppBuffer_isMacro (CPPBUFFER (pfile)))
05184                     {
05185                       /* try harder: this string crosses a macro expansion
05186                          boundary.  This can happen naturally if -traditional.
05187                          Otherwise, only -D can make a macro with an unmatched
05188                          quote.  */
05189                       cppBuffer *next_buf
05190                         = cppBuffer_prevBuffer (cppReader_getBuffer (pfile));
05191                       (*cppReader_getBuffer (pfile)->cleanup)
05192                         (cppReader_getBuffer (pfile), pfile);
05193                       CPPBUFFER (pfile) = next_buf;
05194                       continue;
05195                     }
05196                   if (!cppReader_isTraditional (pfile))
05197                     {
05198                       cpp_setLocation (pfile);
05199 
05200                       setLine (long_toInt (start_line));
05201                       setColumn (long_toInt (start_column));
05202 
05203                       if (pfile->multiline_string_line != long_toInt (start_line)
05204                           && pfile->multiline_string_line != 0)
05205                         {
05206                           genppllerrorhint
05207                             (FLG_PREPROC,
05208                              message ("Unterminated string or character constant"),
05209                              message ("%q: Possible real start of unterminated constant",
05210                                       fileloc_unparseRaw 
05211                                       (fileloc_filename (g_currentloc),
05212                                        pfile->multiline_string_line)));
05213                           pfile->multiline_string_line = 0;
05214                         }
05215                       else
05216                         {
05217                           genppllerror
05218                             (FLG_PREPROC,
05219                              message ("Unterminated string or character constant"));
05220                         }
05221                     }
05222                   /*@loopbreak@*/ break;
05223                 }
05224               cppReader_putChar (pfile, cc);
05225               switch (cc)
05226                 {
05227                 case '\n':
05228                   /* Traditionally, end of line ends a string constant with
05229                      no error.  So exit the loop and record the new line.  */
05230                   if (cppReader_isTraditional (pfile))
05231                     goto while2end;
05232                   if (c == '\'')
05233                     {
05234                       goto while2end;
05235                     }
05236                   if (cppReader_isPedantic (pfile)
05237                       && pfile->multiline_string_line == 0)
05238                     {
05239                       cppReader_pedwarnWithLine
05240                         (pfile, long_toInt (start_line),
05241                          long_toInt (start_column),
05242                          cstring_makeLiteral ("String constant runs past end of line"));
05243                     }
05244                   if (pfile->multiline_string_line == 0)
05245                     {
05246                       pfile->multiline_string_line = start_line;
05247                     }
05248 
05249                   /*@switchbreak@*/ break;
05250 
05251                 case '\\':
05252                   cc = cppReader_getC (pfile);
05253                   if (cc == '\n')
05254                     {
05255                       /* Backslash newline is replaced by nothing at all.  */
05256                       cppReader_adjustWritten (pfile, -1);
05257                       pfile->lineno++;
05258                     }
05259                   else
05260                     {
05261                       /* ANSI stupidly requires that in \\ the second \
05262                          is *not* prevented from combining with a newline.  */
05263                       NEWLINE_FIX1(cc);
05264                       if (cc != EOF)
05265                         cppReader_putChar (pfile, cc);
05266                     }
05267                   /*@switchbreak@*/ break;
05268 
05269                 case '\"':
05270                 case '\'':
05271                   if (cc == c)
05272                     goto while2end;
05273                   /*@switchbreak@*/ break;
05274                 }
05275             }
05276         while2end:
05277           pfile->lineno += count_newlines (pfile->token_buffer + old_written,
05278                                            cppReader_getPWritten (pfile));
05279           pfile->only_seen_white = 0;
05280           return c == '\'' ? CPP_CHAR : CPP_STRING;
05281 
05282         case '$':
05283           if (!opts->dollars_in_ident)
05284             goto randomchar;
05285           goto letter;
05286 
05287         case ':':
05288           if (opts->cplusplus && cppReader_peekC (pfile) == ':')
05289             goto op2;
05290           goto randomchar;
05291 
05292         case '&':
05293         case '+':
05294         case '|':
05295           NEWLINE_FIX;
05296           c2 = cppReader_peekC (pfile);
05297           if (c2 == c || c2 == '=')
05298             goto op2;
05299           goto randomchar;
05300 
05301         case '*':
05302         case '!':
05303         case '%':
05304         case '=':
05305         case '^':
05306           NEWLINE_FIX;
05307           if (cppReader_peekC (pfile) == '=')
05308             goto op2;
05309           goto randomchar;
05310 
05311         case '-':
05312           NEWLINE_FIX;
05313           c2 = cppReader_peekC (pfile);
05314           if (c2 == '-' && opts->chill)
05315             {
05316               /* Chill style comment */
05317               if (opts->put_out_comments)
05318                 {
05319                   parseSetMark (&start_mark, pfile);
05320                 }
05321 
05322               cppReader_forward (pfile, 1);  /* Skip second '-'.  */
05323 
05324               for (;;)
05325                 {
05326                   c = cppReader_getC (pfile);
05327                   if (c == EOF)
05328                     /*@loopbreak@*/ break;
05329                   if (c == '\n')
05330                     {
05331                       /* Don't consider final '\n' to be part of comment.  */
05332                       cppReader_forward (pfile, -1);
05333                       /*@loopbreak@*/ break;
05334                     }
05335                 }
05336               c = '-';
05337               goto return_comment;
05338             }
05339           if (c2 == '-' || c2 == '=' || c2 == '>')
05340             goto op2;
05341           goto randomchar;
05342 
05343         case '<':
05344           if (pfile->parsing_include_directive)
05345             {
05346               for (;;)
05347                 {
05348                   cppReader_putChar (pfile, c);
05349                   if (c == '>')
05350                     /*@loopbreak@*/ break;
05351                   c = cppReader_getC (pfile);
05352                   NEWLINE_FIX1 (c);
05353                   if (c == '\n' || c == EOF)
05354                     {
05355                       cppReader_errorLit (pfile,
05356                                     cstring_makeLiteralTemp ("Missing '>' in \"#include <FILENAME>\""));
05357                       /*@loopbreak@*/ break;
05358                     }
05359                 }
05360               return CPP_STRING;
05361             }
05362           /*@fallthrough@*/
05363         case '>':
05364           NEWLINE_FIX;
05365           c2 = cppReader_peekC (pfile);
05366           if (c2 == '=')
05367             goto op2;
05368           if (c2 != c)
05369             goto randomchar;
05370           cppReader_forward (pfile, 1);
05371           cppReader_reserve (pfile, 4);
05372           cppReader_putChar (pfile, c);
05373           cppReader_putChar (pfile, c2);
05374           NEWLINE_FIX;
05375           c3 = cppReader_peekC (pfile);
05376           if (c3 == '=')
05377             cppReader_putCharQ (pfile, cppReader_getC (pfile));
05378           cppReader_nullTerminateQ (pfile);
05379           pfile->only_seen_white = 0;
05380           return CPP_OTHER;
05381 
05382         case '@':
05383           if (cppReader_getBuffer (pfile)->has_escapes)
05384             {
05385               c = cppReader_getC (pfile);
05386               if (c == '-')
05387                 {
05388                   if (pfile->output_escapes)
05389                     cppReader_puts (pfile, "@-", 2);
05390                   parse_name (pfile, cppReader_getC (pfile));
05391                   return CPP_NAME;
05392                 }
05393               else if (is_space [c])
05394                 {
05395                   cppReader_reserve (pfile, 2);
05396                   if (pfile->output_escapes)
05397                     cppReader_putCharQ (pfile, '@');
05398                   cppReader_putCharQ (pfile, c);
05399                   return CPP_HSPACE;
05400                 }
05401               else
05402                 {
05403                   ;
05404                 }
05405             }
05406           if (pfile->output_escapes)
05407             {
05408               cppReader_puts (pfile, "@@", 2);
05409               return CPP_OTHER;
05410             }
05411           goto randomchar;
05412         case '.':
05413           NEWLINE_FIX;
05414           c2 = cppReader_peekC (pfile);
05415           if (isdigit(c2))
05416             {
05417               cppReader_reserve(pfile, 2);
05418               cppReader_putCharQ (pfile, '.');
05419               c = cppReader_getC (pfile);
05420               goto number;
05421             }
05422 
05423           /* FIXME - misses the case "..\\\n." */
05424           if (c2 == '.' && cpp_peekN (pfile, 1) == '.')
05425             {
05426               cppReader_reserve(pfile, 4);
05427               cppReader_putCharQ (pfile, '.');
05428               cppReader_putCharQ (pfile, '.');
05429               cppReader_putCharQ (pfile, '.');
05430               cppReader_forward (pfile, 2);
05431               cppReader_nullTerminateQ (pfile);
05432               pfile->only_seen_white = 0;
05433               return CPP_3DOTS;
05434             }
05435           goto randomchar;
05436         op2:
05437           token = CPP_OTHER;
05438           pfile->only_seen_white = 0;
05439         op2any:
05440           cppReader_reserve(pfile, 3);
05441           cppReader_putCharQ (pfile, c);
05442           cppReader_putCharQ (pfile, cppReader_getC (pfile));
05443           cppReader_nullTerminateQ (pfile);
05444           return token;
05445 
05446         case 'L':
05447           NEWLINE_FIX;
05448           c2 = cppReader_peekC (pfile);
05449           if ((c2 == '\'' || c2 == '\"') && !cppReader_isTraditional (pfile))
05450             {
05451               cppReader_putChar (pfile, c);
05452               c = cppReader_getC (pfile);
05453               goto string;
05454             }
05455           goto letter;
05456 
05457         case '0': case '1': case '2': case '3': case '4':
05458         case '5': case '6': case '7': case '8': case '9':
05459         number:
05460           c2  = '.';
05461           for (;;)
05462             {
05463               cppReader_reserve (pfile, 2);
05464               cppReader_putCharQ (pfile, c);
05465               NEWLINE_FIX;
05466               c = cppReader_peekC (pfile);
05467               if (c == EOF)
05468                 /*@loopbreak@*/ break;
05469               if (!is_idchar[c] && c != '.'
05470                   && ((c2 != 'e' && c2 != 'E'
05471                        && ((c2 != 'p' && c2 != 'P') || cppReader_isC89 (pfile)))
05472                       || (c != '+' && c != '-')))
05473                 /*@loopbreak@*/ break;
05474               cppReader_forward (pfile, 1);
05475               c2= c;
05476             }
05477 
05478           cppReader_nullTerminateQ (pfile);
05479           pfile->only_seen_white = 0;
05480           return CPP_NUMBER;
05481 
05482         case 'b': case 'c': case 'd': case 'h': case 'o':
05483         case 'B': case 'C': case 'D': case 'H': case 'O':
05484           if (opts->chill && cppReader_peekC (pfile) == '\'')
05485             {
05486               pfile->only_seen_white = 0;
05487               cppReader_reserve (pfile, 2);
05488               cppReader_putCharQ (pfile, c);
05489               cppReader_putCharQ (pfile, '\'');
05490               cppReader_forward (pfile, 1);
05491               for (;;)
05492                 {
05493                   c = cppReader_getC (pfile);
05494                   if (c == EOF)
05495                     goto chill_number_eof;
05496                   if (!is_idchar[c])
05497                     {
05498                       if (c == '\\' && cppReader_peekC (pfile) == '\n')
05499                         {
05500                           cppReader_forward (pfile, 2);
05501                           continue;
05502                         }
05503                       /*@loopbreak@*/ break;
05504                     }
05505                   cppReader_putChar (pfile, c);
05506                 }
05507               if (c == '\'')
05508                 {
05509                   cppReader_reserve (pfile, 2);
05510                   cppReader_putCharQ (pfile, c);
05511                   cppReader_nullTerminateQ (pfile);
05512                   return CPP_STRING;
05513                 }
05514               else
05515                 {
05516                   cppReader_forward (pfile, -1);
05517                 chill_number_eof:
05518                   cppReader_nullTerminate (pfile);
05519                   return CPP_NUMBER;
05520                 }
05521             }
05522           else
05523             goto letter;
05524         case '_':
05525         case 'a': case 'e': case 'f': case 'g': case 'i': case 'j':
05526         case 'k': case 'l': case 'm': case 'n': case 'p': case 'q':
05527         case 'r': case 's': case 't': case 'u': case 'v': case 'w':
05528         case 'x': case 'y': case 'z':
05529         case 'A': case 'E': case 'F': case 'G': case 'I': case 'J':
05530         case 'K': case 'M': case 'N': case 'P': case 'Q': case 'R':
05531         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
05532         case 'Y': case 'Z':
05533         letter:
05534           {
05535             HASHNODE *hp;
05536             char *ident;
05537             size_t before_name_written = cppReader_getWritten (pfile);
05538             int ident_len;
05539             parse_name (pfile, c);
05540             pfile->only_seen_white = 0;
05541             if (pfile->no_macro_expand)
05542               {
05543                 return CPP_NAME;
05544               }
05545 
05546             ident = pfile->token_buffer + before_name_written;
05547             ident_len = (cppReader_getPWritten (pfile)) - ident;
05548 
05549             hp = cppReader_lookupExpand (ident, ident_len, -1);
05550 
05551             if (hp == NULL)
05552               {
05553                 return CPP_NAME;
05554               }
05555 
05556             if (hp->type == T_DISABLED)
05557               {
05558                 if (pfile->output_escapes)
05559                   { /* Return "@-IDENT", followed by '\0'.  */
05560                     int i;
05561                     cppReader_reserve (pfile, 3);
05562                     ident = pfile->token_buffer + before_name_written;
05563                     cppReader_adjustWritten (pfile, 2);
05564 
05565                     for (i = ident_len; i >= 0; i--)
05566                       {
05567                         ident[i+2] = ident[i];
05568                       }
05569 
05570                     ident[0] = '@';
05571                     ident[1] = '-';
05572                   }
05573                 return CPP_NAME;
05574               }
05575 
05576             /* If macro wants an arglist, verify that a '(' follows.
05577                first skip all whitespace, copying it to the output
05578                after the macro name.  Then, if there is no '(',
05579                decide this is not a macro call and leave things that way.  */
05580 
05581             if (hp->type == T_MACRO && hp->value.defn->nargs >= 0)
05582               {
05583                 struct parse_marker macro_mark;
05584                 int is_macro_call;
05585 
05586                 while (cppBuffer_isMacro (CPPBUFFER (pfile)))
05587                   {
05588                     cppBuffer *next_buf;
05589                     cppSkipHspace (pfile);
05590                     if (cppReader_peekC (pfile) != EOF)
05591                       {
05592                         /*@loopbreak@*/ break;
05593                       }
05594 
05595                   next_buf = cppBuffer_prevBuffer (cppReader_getBuffer (pfile));
05596                   (*cppReader_getBuffer (pfile)->cleanup) (cppReader_getBuffer (pfile), pfile);
05597                   CPPBUFFER (pfile) = next_buf;
05598                   }
05599 
05600                 parseSetMark (&macro_mark, pfile);
05601 
05602                 for (;;)
05603                   {
05604                     cppSkipHspace (pfile);
05605                     c = cppReader_peekC (pfile);
05606                     is_macro_call = c == '(';
05607                     if (c != '\n')
05608                       /*@loopbreak@*/ break;
05609                     cppReader_forward (pfile, 1);
05610                   }
05611 
05612                 if (!is_macro_call)
05613                   {
05614                     parseGotoMark (&macro_mark, pfile);
05615                   }
05616 
05617                 parseClearMark (&macro_mark);
05618 
05619                 if (!is_macro_call)
05620                   {
05621                     return CPP_NAME;
05622                   }
05623               }
05624             /* This is now known to be a macro call.  */
05625 
05626             /* it might not actually be a macro.  */
05627             if (hp->type != T_MACRO)
05628               {
05629                 size_t xbuf_len;
05630                 char *xbuf;
05631 
05632                 cppReader_setWritten (pfile, before_name_written);
05633                 special_symbol (hp, pfile);
05634                 xbuf_len = cppReader_getWritten (pfile) - before_name_written;
05635                 xbuf = (char *) dmalloc (xbuf_len + 1);
05636                 cppReader_setWritten (pfile, before_name_written);
05637                 memcpy (xbuf, cppReader_getPWritten (pfile), xbuf_len + 1);
05638                 push_macro_expansion (pfile, xbuf, xbuf_len, hp);
05639               }
05640             else
05641               {
05642                 /* Expand the macro, reading arguments as needed,
05643                    and push the expansion on the input stack.  */
05644                                 macroexpand (pfile, hp);
05645                 cppReader_setWritten (pfile, before_name_written);
05646               }
05647 
05648             /* An extra "@ " is added to the end of a macro expansion
05649                to prevent accidental token pasting.  We prefer to avoid
05650                unneeded extra spaces (for the sake of cpp-using tools like
05651                imake).  Here we remove the space if it is safe to do so.  */
05652 
05653             llassert (pfile->buffer->rlimit != NULL);
05654 
05655             if (pfile->buffer->rlimit - pfile->buffer->cur >= 3
05656                 && pfile->buffer->rlimit[-2] == '@'
05657                 && pfile->buffer->rlimit[-1] == ' ')
05658               {
05659                 int c1 = pfile->buffer->rlimit[-3];
05660                 int cl2 = cppBufPeek (cppBuffer_prevBuffer (CPPBUFFER (pfile)));
05661 
05662                 if (cl2 == EOF || !unsafe_chars ((char) c1, (char) cl2))
05663                   pfile->buffer->rlimit -= 2;
05664               }
05665           }
05666           goto get_next;
05667 
05668         case ' ':  case '\t':  case '\v':  case '\r':
05669           for (;;)
05670             {
05671               cppReader_putChar (pfile, c);
05672               c = cppReader_peekC (pfile);
05673               if (c == EOF || !is_hor_space[c])
05674                 /*@loopbreak@*/ break;
05675               cppReader_forward (pfile, 1);
05676             }
05677           return CPP_HSPACE;
05678 
05679         case '\\':
05680           c2 = cppReader_peekC (pfile);
05681           if (c2 != '\n')
05682             goto randomchar;
05683           token = CPP_HSPACE;
05684           goto op2any;
05685 
05686         case '\n':
05687           cppReader_putChar (pfile, c);
05688           if (pfile->only_seen_white == 0)
05689             pfile->only_seen_white = 1;
05690           pfile->lineno++;
05691           output_line_command (pfile, 1, same_file);
05692           return CPP_VSPACE;
05693 
05694         case '(': token = CPP_LPAREN;    goto char1;
05695         case ')': token = CPP_RPAREN;    goto char1;
05696         case '{': token = CPP_LBRACE;    goto char1;
05697         case '}': token = CPP_RBRACE;    goto char1;
05698         case ',': token = CPP_COMMA;     goto char1;
05699         case ';': token = CPP_SEMICOLON; goto char1;
05700 
05701         randomchar:
05702         default:
05703           token = CPP_OTHER;
05704         char1:
05705           pfile->only_seen_white = 0;
05706           cppReader_putChar (pfile, c);
05707           return token;
05708         }
05709     }
05710 
05711   BADBRANCH;
05712   /*@notreached@*/
05713 }
05714 
05715 /* Parse an identifier starting with C.  */
05716 
05717 void
05718 parse_name (cppReader *pfile, int c)
05719 {
05720   for (;;)
05721     {
05722       if (!is_idchar[c])
05723         {
05724           if (c == '\\' && cppReader_peekC (pfile) == '\n')
05725             {
05726               cppReader_forward (pfile, 2);
05727               continue;
05728             }
05729 
05730           cppReader_forward (pfile, -1);
05731           break;
05732         }
05733 
05734       if (c == '$' && cppReader_isPedantic (pfile))
05735         {
05736           cppReader_pedwarnLit (pfile,
05737                           cstring_makeLiteralTemp ("`$' in identifier"));
05738         }
05739 
05740       cppReader_reserve(pfile, 2); /* One more for final NUL.  */
05741       cppReader_putCharQ (pfile, c);
05742       c = cppReader_getC (pfile);
05743 
05744       if (c == EOF)
05745         break;
05746     }
05747 
05748   cppReader_nullTerminateQ (pfile);
05749 }
05750 
05751 /* The file_name_map structure holds a mapping of file names for a
05752    particular directory.  This mapping is read from the file named
05753    FILE_NAME_MAP_FILE in that directory.  Such a file can be used to
05754    map filenames on a file system with severe filename restrictions,
05755    such as DOS.  The format of the file name map file is just a series
05756    of lines with two tokens on each line.  The first token is the name
05757    to map, and the second token is the actual name to use.  */
05758 
05759 struct file_name_map
05760 {
05761   struct file_name_map *map_next;
05762   cstring map_from;
05763   cstring map_to;
05764 };
05765 
05766 /*@constant observer char *FILE_NAME_MAP_FILE*/
05767 #define FILE_NAME_MAP_FILE "header.gcc"
05768 
05769 /* Read a space delimited string of unlimited length from a stdio
05770    file.  */
05771 
05772 static cstring read_filename_string (int ch, FILE *f)
05773 {
05774   char *alloc, *set;
05775   size_t len;
05776 
05777   len = 20;
05778   set = alloc = dmalloc (len + 1);
05779 
05780   if (!is_space[ch])
05781     {
05782       *set++ = ch;
05783       while ((ch = getc (f)) != EOF && ! is_space[ch])
05784         {
05785           if (set - alloc == size_toInt (len))
05786             {
05787               len *= 2;
05788               alloc = drealloc (alloc, len + 1);
05789               set = alloc + len / 2;
05790               /*@-branchstate@*/ }
05791 
05792           *set++ = ch;
05793         } /*@=branchstate@*/
05794     }
05795   *set = '\0';
05796   check (ungetc (ch, f) != EOF);
05797 
05798   return cstring_fromChars (alloc);
05799 }
05800 
05801 /* This structure holds a linked list of file name maps, one per directory.  */
05802 
05803 struct file_name_map_list
05804 {
05805   struct file_name_map_list *map_list_next;
05806   cstring map_list_name;
05807   struct file_name_map *map_list_map;
05808 };
05809 
05810 /* Read the file name map file for DIRNAME.  */
05811 
05812 static struct file_name_map *
05813 read_name_map (cppReader *pfile, cstring dirname)
05814 {
05815   struct file_name_map_list *map_list_ptr;
05816   cstring name;
05817   FILE *f;
05818 
05819   for (map_list_ptr = CPPOPTIONS (pfile)->map_list;
05820        map_list_ptr != NULL;
05821        map_list_ptr = map_list_ptr->map_list_next)
05822     {
05823       if (cstring_equal (map_list_ptr->map_list_name, dirname))
05824         {
05825           return map_list_ptr->map_list_map;
05826         }
05827     }
05828 
05829   map_list_ptr = (struct file_name_map_list *) dmalloc (sizeof (*map_list_ptr));
05830   map_list_ptr->map_list_name = cstring_copy (dirname);
05831   map_list_ptr->map_list_map = NULL;
05832 
05833   name = cstring_copy (dirname);
05834 
05835   if (cstring_length (dirname) > 0)
05836     {
05837       name = cstring_appendChar (name, CONNECTCHAR);
05838     }
05839 
05840   name = cstring_concatFree1 (name, cstring_makeLiteralTemp (FILE_NAME_MAP_FILE));
05841 
05842   f = fopen (cstring_toCharsSafe (name), "r");
05843   cstring_free (name);
05844 
05845   if (f == NULL)
05846     {
05847       map_list_ptr->map_list_map = NULL;
05848     }
05849   else
05850     {
05851       int ch;
05852 
05853       while ((ch = getc (f)) != EOF)
05854         {
05855           cstring from, to;
05856           struct file_name_map *ptr;
05857 
05858           if (is_space[ch])
05859             {
05860               continue;
05861             }
05862 
05863           from = read_filename_string (ch, f);
05864           while ((ch = getc (f)) != EOF && is_hor_space[ch])
05865             {
05866               ;
05867             }
05868 
05869           to = read_filename_string (ch, f);
05870 
05871           ptr = (struct file_name_map *) dmalloc (sizeof (*ptr));
05872           ptr->map_from = from;
05873 
05874           /* Make the real filename absolute.  */
05875           if (cstring_length (to) > 1 
05876               && osd_isConnectChar (cstring_firstChar (to)))
05877             {
05878               ptr->map_to = to;
05879             }
05880           else
05881             {
05882               ptr->map_to = cstring_copy (dirname);
05883               ptr->map_to = cstring_appendChar (ptr->map_to, CONNECTCHAR);
05884               ptr->map_to = cstring_concatFree (ptr->map_to, to);
05885             }
05886 
05887           ptr->map_next = map_list_ptr->map_list_map;
05888           map_list_ptr->map_list_map = ptr;
05889 
05890           while ((ch = getc (f)) != '\n')
05891             {
05892               if (ch == EOF)
05893                 {
05894                   /*@innerbreak@*/ break;
05895                 }
05896             }
05897         }
05898 
05899       assertSet (map_list_ptr->map_list_map);
05900       check (fclose (f) == 0);
05901     }
05902 
05903   map_list_ptr->map_list_next = pfile->opts->map_list;
05904   pfile->opts->map_list = map_list_ptr;
05905 
05906   return map_list_ptr->map_list_map;
05907 }
05908 
05909 /* Try to open include file FILENAME.  SEARCHPTR is the directory
05910    being tried from the include file search path.  This function maps
05911    filenames on file systems based on information read by
05912    read_name_map.  */
05913 
05914 static int
05915 open_include_file (cppReader *pfile,
05916                    cstring fname,
05917                    struct file_name_list *searchptr)
05918 {
05919   char *filename = cstring_toCharsSafe (fname);
05920   struct file_name_map *map;
05921   char *from;
05922   char *p, *dir;
05923 
05924   cstring_markOwned (fname);
05925 
05926   cpp_setLocation (pfile);
05927 
05928   if (context_getFlag (FLG_NEVERINCLUDE))
05929     {
05930       if (isHeaderFile (fname))
05931         {
05932           return SKIP_INCLUDE;
05933         }
05934     }
05935 
05936   if ((searchptr != NULL) && ! searchptr->got_name_map)
05937     {
05938       searchptr->name_map = read_name_map (pfile,
05939                                            !cstring_isEmpty (searchptr->fname)
05940                                            ? searchptr->fname :
05941                                            cstring_makeLiteralTemp ("."));
05942       searchptr->got_name_map = 1;
05943     }
05944 
05945   /* First check the mapping for the directory we are using.  */
05946 
05947   if ((searchptr != NULL)
05948       && (searchptr->name_map != NULL))
05949     {
05950       from = filename;
05951 
05952       if (!cstring_isEmpty (searchptr->fname))
05953         {
05954           from += cstring_length (searchptr->fname) + 1;
05955         }
05956 
05957       for (map = searchptr->name_map;
05958            map != NULL;
05959            map = map->map_next)
05960         {
05961           if (cstring_equal (map->map_from, cstring_fromChars (from)))
05962             {
05963               /*
05964               ** Found a match.  Check if the file should be skipped
05965               */
05966               
05967               if (cpp_skipIncludeFile (map->map_to))
05968                 {
05969                   return SKIP_INCLUDE;
05970                 }
05971               else
05972                 {
05973                   return cpp_openIncludeFile (cstring_toCharsSafe (map->map_to));
05974                 }
05975             }
05976         }
05977     }
05978 
05979   /*
05980   ** Try to find a mapping file for the particular directory we are
05981   ** looking in.  Thus #include <sys/types.h> will look up sys/types.h
05982   ** in /usr/include/header.gcc and look up types.h in
05983   ** /usr/include/sys/header.gcc.
05984   */
05985 
05986   p = strrchr (filename, CONNECTCHAR);
05987 
05988   if (p == NULL)
05989     {
05990       p = filename;
05991     }
05992 
05993   if ((searchptr != NULL)
05994       && (cstring_isDefined (searchptr->fname))
05995       && (cstring_length (searchptr->fname) == p - filename)
05996       && !strncmp (cstring_toCharsSafe (searchptr->fname),
05997                    filename,
05998                    size_fromInt (p - filename)))
05999     {
06000       /* filename is in SEARCHPTR, which we've already checked.  */
06001 
06002       if (cpp_skipIncludeFile (cstring_fromChars (filename)))
06003         {
06004           return SKIP_INCLUDE;
06005         }
06006       else
06007         {
06008           return cpp_openIncludeFile (filename);
06009         }
06010     }
06011 
06012   if (p == filename)
06013     {
06014       dir = mstring_copy (".");
06015       from = filename;
06016     }
06017   else
06018     {
06019       dir = (char *) dmalloc (size_fromInt (p - filename + 1));
06020       memcpy (dir, filename, size_fromInt (p - filename));
06021       dir[p - filename] = '\0';
06022       from = p + 1;
06023     }
06024 
06025   for (map = read_name_map (pfile, cstring_fromChars (dir));
06026        map != NULL;
06027        map = map->map_next)
06028     {
06029       if (cstring_equal (map->map_from, cstring_fromChars (from)))
06030         {
06031           sfree (dir);
06032 
06033           if (cpp_skipIncludeFile (map->map_to))
06034             {
06035               return SKIP_INCLUDE;
06036             }
06037           else
06038             {
06039               return cpp_openIncludeFile (cstring_toCharsSafe (map->map_to));
06040             }
06041         }
06042     }
06043 
06044   sfree (dir);
06045 
06046   if (cpp_skipIncludeFile (cstring_fromChars (filename)))
06047     {
06048       return SKIP_INCLUDE;
06049     }
06050   else
06051     {
06052       return cpp_openIncludeFile (filename);
06053     }
06054 }
06055 
06056 /* Process the contents of include file FNAME, already open on descriptor F,
06057    with output to OP.
06058    SYSTEM_HEADER_P is 1 if this file resides in any one of the known
06059    "system" include directories (as decided by the `is_system_include'
06060    function above).
06061    DIRPTR is the link in the dir path through which this file was found,
06062    or 0 if the file name was absolute or via the current directory.
06063    Return 1 on success, 0 on failure.
06064 
06065    The caller is responsible for the cppReader_pushBuffer.  */
06066 
06067 static int
06068 finclude (cppReader *pfile, int f,
06069           cstring fname,
06070           bool system_header_p,
06071           /*@dependent@*/ struct file_name_list *dirptr)
06072 {
06073   mode_t st_mode;
06074   size_t st_size;
06075   long i;
06076   int length = 0;
06077   cppBuffer *fp;                        /* For input stack frame */
06078 
06079   if (file_size_and_mode (f, &st_mode, &st_size) < 0)
06080     {
06081       cppReader_perrorWithName (pfile, fname);
06082       check (close (f) == 0);
06083       (void) cppReader_popBuffer (pfile);
06084       /*@-mustfree@*/
06085       return 0;
06086       /*@=mustfree@*/
06087     }
06088 
06089   fp = cppReader_getBuffer (pfile);
06090 
06091   /*@-temptrans@*/ /* fname shouldn't really be temp */
06092   fp->nominal_fname = fp->fname = fname;
06093   /*@=temptrans@*/
06094 
06095   fp->dir = dirptr;
06096   fp->system_header_p = system_header_p;
06097   fp->lineno = 1;
06098   fp->colno = 1;
06099   fp->cleanup = cppReader_fileCleanup;
06100 
06101   if (S_ISREG (st_mode))
06102     {
06103       sfree (fp->buf);
06104       fp->buf = (char *) dmalloc (st_size + 2);
06105       fp->alimit = fp->buf + st_size + 2;
06106       fp->cur = fp->buf;
06107 
06108       /* Read the file contents, knowing that st_size is an upper bound
06109          on the number of bytes we can read.  */
06110       length = safe_read (f, fp->buf, size_toInt (st_size));
06111       fp->rlimit = fp->buf + length;
06112       if (length < 0) goto nope;
06113     }
06114   else if (S_ISDIR (st_mode))
06115     {
06116       cppReader_error (pfile,
06117                        message ("directory `%s' specified in #include", fname));
06118       check (close (f) == 0);
06119       return 0;
06120     }
06121   else
06122     {
06123       /*
06124       ** Cannot count its file size before reading.
06125       ** First read the entire file into heap and
06126       ** copy them into buffer on stack.
06127       */
06128 
06129       size_t bsize = 2000;
06130 
06131       st_size = 0;
06132 
06133       sfree (fp->buf);
06134       fp->buf = (char *) dmalloc (bsize + 2);
06135 
06136       for (;;) {
06137         i = safe_read (f, fp->buf + st_size, size_toInt (bsize - st_size));
06138 
06139         if (i < 0)
06140           goto nope;      /* error! */
06141         st_size += i;
06142 
06143         if (st_size != bsize)
06144           {
06145             break;      /* End of file */
06146           }
06147 
06148         bsize *= 2;
06149         fp->buf = (char *) drealloc (fp->buf, bsize + 2);
06150       }
06151 
06152       fp->cur = fp->buf;
06153       length = size_toInt (st_size);
06154     }
06155 
06156   if ((length > 0 && fp->buf[length - 1] != '\n')
06157       /* Backslash-newline at end is not good enough.  */
06158       || (length > 1 && fp->buf[length - 2] == '\\')) {
06159     fp->buf[length++] = '\n';
06160   }
06161 
06162   fp->buf[length] = '\0';
06163   fp->rlimit = fp->buf + length;
06164 
06165 
06166   /* Close descriptor now, so nesting does not use lots of descriptors.  */
06167   check (close (f) == 0);
06168 
06169   /* Must do this before calling trigraph_pcp, so that the correct file name
06170      will be printed in warning messages.  */
06171 
06172   pfile->input_stack_listing_current = 0;
06173   return 1;
06174 
06175  nope:
06176 
06177   cppReader_perrorWithName (pfile, fname);
06178   check (close (f) == 0);
06179   sfree (fp->buf);
06180   return 1;
06181 }
06182 
06183 void
06184 cppReader_init (cppReader *pfile)
06185 {
06186   memset ((char *) pfile, 0, sizeof (*pfile));
06187 
06188   pfile->get_token = cppGetToken;
06189   pfile->token_buffer_size = 200;
06190   pfile->token_buffer = (char *) dmalloc (pfile->token_buffer_size);
06191   pfile->all_include_files = NULL;
06192 
06193   assertSet (pfile);
06194 
06195   cppReader_setWritten (pfile, 0);
06196 
06197   pfile->system_include_depth = 0;
06198   pfile->max_include_len = 0;
06199   pfile->timebuf = NULL;
06200   pfile->only_seen_white = 1;
06201 
06202   pfile->buffer = cppReader_nullBuffer (pfile);
06203 }
06204 
06205 void
06206 cppReader_finish (/*@unused@*/ cppReader *pfile)
06207 {
06208   ;
06209 }
06210 
06211 /* Free resources used by PFILE.
06212    This is the cppReader 'finalizer' or 'destructor' (in C++ terminology).  */
06213 
06214 void
06215 cppCleanup (cppReader *pfile)
06216 {
06217   while (CPPBUFFER (pfile) != cppReader_nullBuffer (pfile))
06218     {
06219       (void) cppReader_popBuffer (pfile);
06220     }
06221 
06222   if (pfile->token_buffer != NULL)
06223     {
06224       sfree (pfile->token_buffer);
06225       pfile->token_buffer = NULL;
06226     }
06227 
06228   while (pfile->if_stack != NULL)
06229     {
06230       cppIfStackFrame *temp = pfile->if_stack;
06231       pfile->if_stack = temp->next;
06232       sfree (temp);
06233     }
06234 
06235   while (pfile->all_include_files != NULL)
06236     {
06237       struct file_name_list *temp = pfile->all_include_files;
06238       pfile->all_include_files = temp->next;
06239       /*@-dependenttrans@*/
06240       cstring_free (temp->fname);
06241       /*@=dependenttrans@*/
06242       sfree (temp);
06243     }
06244 
06245   cppReader_hashCleanup ();
06246 }
06247 
06248 /*
06249 ** Get the file-mode and data size of the file open on FD
06250 ** and store them in *MODE_POINTER and *SIZE_POINTER.
06251 */
06252 
06253 static int
06254 file_size_and_mode (int fd, mode_t *mode_pointer, size_t *size_pointer)
06255 {
06256   struct stat sbuf;
06257 
06258   if (fstat (fd, &sbuf) < 0) {
06259     return (-1);
06260   }
06261 
06262   if (mode_pointer != NULL)
06263     {
06264       *mode_pointer = sbuf.st_mode;
06265     }
06266 
06267   if (size_pointer != NULL)
06268     {
06269       *size_pointer = (size_t) sbuf.st_size;
06270     }
06271 
06272   return 0;
06273 }
06274 
06275 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
06276    retrying if necessary.  Return a negative value if an error occurs,
06277    otherwise return the actual number of bytes read,
06278    which must be LEN unless end-of-file was reached.  */
06279 
06280 static int safe_read (int desc, char *ptr, int len)
06281 {
06282   int left = len;
06283 
06284   while (left > 0)
06285     {
06286 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
06287           /*@-compdef@*/ /* ptr is an out parameter */
06288       int nchars = _read (desc, ptr, (unsigned) left);
06289           /*@=compdef@*/
06290 # else
06291       ssize_t nchars = read (desc, ptr, size_fromInt (left));
06292 # endif
06293 
06294       if (nchars < 0)
06295         {
06296 #ifdef EINTR
06297           if (errno == EINTR)
06298             continue;
06299 #endif
06300           return (int) nchars;
06301         }
06302 
06303       if (nchars == 0) {
06304         break;
06305       }
06306 
06307       ptr += nchars;
06308       left -= nchars;
06309     }
06310 
06311   return len - left;
06312 }
06313 
06314 /* Initialize PMARK to remember the current position of PFILE.  */
06315 
06316 void
06317 parseSetMark (struct parse_marker *pmark, cppReader *pfile)
06318 {
06319   cppBuffer *pbuf = cppReader_getBuffer (pfile);
06320 
06321   pmark->next = pbuf->marks;
06322   /*@-temptrans@*/
06323   pbuf->marks = pmark;
06324   /*@=temptrans@*/
06325 
06326   pmark->buf = pbuf;
06327   pmark->position = pbuf->cur - pbuf->buf;
06328 }
06329 
06330 /* Cleanup PMARK - we no longer need it.  */
06331 
06332 void parseClearMark (struct parse_marker *pmark)
06333 {
06334   struct parse_marker **pp = &pmark->buf->marks;
06335 
06336   for (; ; pp = &(*pp)->next)
06337     {
06338       llassert (*pp != NULL);
06339       if (*pp == pmark) break;
06340     }
06341 
06342   *pp = pmark->next;
06343 }
06344 
06345 /* Backup the current position of PFILE to that saved in PMARK.  */
06346 
06347 void
06348 parseGotoMark (struct parse_marker *pmark, cppReader *pfile)
06349 {
06350   cppBuffer *pbuf = cppReader_getBuffer (pfile);
06351 
06352   if (pbuf != pmark->buf)
06353     {
06354       cpp_setLocation (pfile);
06355       llfatalbug (cstring_makeLiteral ("Internal error parseGotoMark"));
06356     }
06357 
06358   llassert (pbuf->buf != NULL);
06359   pbuf->cur = pbuf->buf + pmark->position;
06360 }
06361 
06362 /* Reset PMARK to point to the current position of PFILE.  (Same
06363    as parseClearMark (PMARK), parseSetMark (PMARK, PFILE) but faster.  */
06364 
06365 void
06366 parseMoveMark (struct parse_marker *pmark, cppReader *pfile)
06367 {
06368   cppBuffer *pbuf = cppReader_getBuffer (pfile);
06369 
06370   if (pbuf != pmark->buf)
06371     {
06372       cpp_setLocation (pfile);
06373       llfatalerror (cstring_makeLiteral ("Internal error parseMoveMark"));
06374     }
06375 
06376   pmark->position = pbuf->cur - pbuf->buf;
06377 }
06378 
06379 void cppReader_initializeReader (cppReader *pfile)
06380 {
06381   struct cppOptions *opts = CPPOPTIONS (pfile);
06382   char *xp;
06383 
06384   /* The code looks at the defaults through this pointer, rather than through
06385      the constant structure above.  This pointer gets changed if an environment
06386      variable specifies other defaults.  */
06387 
06388   struct default_include *include_defaults = include_defaults_array;
06389 
06390   /* Add dirs from CPATH after dirs from -I.  */
06391   /* There seems to be confusion about what CPATH should do,
06392      so for the moment it is not documented.  */
06393   /* Some people say that CPATH should replace the standard include dirs,
06394      but that seems pointless: it comes before them, so it overrides them
06395      anyway.  */
06396 
06397   xp = (char *) getenv ("CPATH");
06398 
06399   if (xp != 0 && ! opts->no_standard_includes)
06400     {
06401       path_include (pfile, xp);
06402     }
06403 
06404   /* Now that dollars_in_ident is known, initialize is_idchar.  */
06405   initialize_char_syntax (opts);
06406 
06407   /* CppReader_Install __LINE__, etc.  Must follow initialize_char_syntax
06408      and option processing.  */
06409 
06410   initialize_builtins (pfile);
06411 
06412   /* Do standard #defines and assertions
06413      that identify system and machine type.  */
06414 
06415   if (!opts->inhibit_predefs) {
06416     char *p = (char *) dmalloc (strlen (predefs) + 1);
06417     strcpy (p, predefs);
06418 
06419     while (*p)
06420       {
06421         char *q;
06422 
06423         while (*p == ' ' || *p == '\t')
06424           {
06425             p++;
06426           }
06427 
06428         /* Handle -D options.  */
06429         if (p[0] == '-' && p[1] == 'D')
06430           {
06431             q = &p[2];
06432 
06433             while (*p && *p != ' ' && *p != '\t')
06434               {
06435                 p++;
06436               }
06437 
06438             if (*p != 0)
06439               {
06440                 *p++= 0;
06441               }
06442 
06443             if (opts->debug_output)
06444               {
06445                 output_line_command (pfile, 0, same_file);
06446               }
06447 
06448             cppReader_define (pfile, q);
06449 
06450             while (*p == ' ' || *p == '\t')
06451               {
06452                 p++;
06453               }
06454           }
06455         else
06456           {
06457             abort ();
06458           }
06459       }
06460 
06461     sfree (p);
06462   }
06463 
06464   opts->done_initializing = 1;
06465 
06466   { /* Read the appropriate environment variable and if it exists
06467        replace include_defaults with the listed path.  */
06468     char *epath = 0;
06469 #ifdef __CYGWIN32__
06470   char *win32epath;
06471   int win32_buf_size = 0; /* memory we need to allocate */
06472 #endif
06473 
06474   if (opts->cplusplus)
06475     {
06476       epath = getenv ("CPLUS_INCLUDE_PATH");
06477     }
06478   else
06479     {
06480       epath = getenv ("C_INCLUDE_PATH");
06481     }
06482 
06483   /*
06484   ** If the environment var for this language is set,
06485   ** add to the default list of include directories.
06486   */
06487 
06488     if (epath != NULL) {
06489       char *nstore = (char *) dmalloc (strlen (epath) + 2);
06490       int num_dirs;
06491       char *startp, *endp;
06492 
06493 #ifdef __CYGWIN32__
06494       /* if we have a posix path list, convert to win32 path list */
06495       if (cygwin32_posix_path_list_p (epath))
06496         {
06497           win32_buf_size = cygwin32_posix_to_win32_path_list_buf_size (epath);
06498           win32epath = (char *) dmalloc /*@i4@*/ (win32_buf_size);
06499           cygwin32_posix_to_win32_path_list (epath, win32epath);
06500           epath = win32epath;
06501         }
06502 #endif
06503       for (num_dirs = 1, startp = epath; *startp; startp++)
06504         {
06505           if (*startp == PATH_SEPARATOR)
06506             num_dirs++;
06507         }
06508 
06509       /*@-sizeoftype@*/
06510       include_defaults
06511         = (struct default_include *) dmalloc ((num_dirs
06512                                                * sizeof (struct default_include))
06513                                               + sizeof (include_defaults_array));
06514       /*@=sizeoftype@*/
06515 
06516       startp = endp = epath;
06517       num_dirs = 0;
06518       while (1) {
06519         /* Handle cases like c:/usr/lib:d:/gcc/lib */
06520         if ((*endp == PATH_SEPARATOR) || *endp == 0)
06521           {
06522             strncpy (nstore, startp, size_fromInt (endp - startp));
06523             if (endp == startp)
06524               {
06525                 strcpy (nstore, ".");
06526               }
06527             else
06528               {
06529                 nstore[endp-startp] = '\0';
06530               }
06531 
06532             include_defaults[num_dirs].fname = cstring_fromCharsNew (nstore);
06533             include_defaults[num_dirs].cplusplus = opts->cplusplus;
06534             include_defaults[num_dirs].cxx_aware = 1;
06535             num_dirs++;
06536 
06537             if (*endp == '\0')
06538               {
06539                 break;
06540               }
06541             endp = startp = endp + 1;
06542           }
06543         else
06544           {
06545             endp++;
06546           }
06547       }
06548       /* Put the usual defaults back in at the end.  */
06549       memcpy ((char *) &include_defaults[num_dirs],
06550               (char *) include_defaults_array,
06551               sizeof (include_defaults_array));
06552 
06553       sfree (nstore);
06554       /*@-branchstate@*/ } /*@=branchstate@*/
06555   }
06556 
06557   cppReader_appendIncludeChain (pfile, opts->before_system,
06558                                 opts->last_before_system);
06559   opts->first_system_include = opts->before_system;
06560 
06561   /* Unless -fnostdinc,
06562      tack on the standard include file dirs to the specified list */
06563   if (!opts->no_standard_includes) {
06564     struct default_include *p = include_defaults;
06565     char *specd_prefix = opts->include_prefix;
06566     char *default_prefix = mstring_copy (GCC_INCLUDE_DIR);
06567     int default_len = 0;
06568 
06569         /* Remove the `include' from /usr/local/lib/gcc.../include.  */
06570         if (default_prefix != NULL) {
06571     if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) {
06572       default_len = strlen (default_prefix) - 7;
06573       default_prefix[default_len] = 0;
06574     }
06575         }
06576 
06577     /* Search "translated" versions of GNU directories.
06578        These have /usr/local/lib/gcc... replaced by specd_prefix.  */
06579     if (specd_prefix != 0 && default_len != 0)
06580       for (p = include_defaults; p->fname != NULL; p++) {
06581         /* Some standard dirs are only for C++.  */
06582         if (!p->cplusplus
06583             || (opts->cplusplus && !opts->no_standard_cplusplus_includes)) {
06584           /* Does this dir start with the prefix?  */
06585           if (!strncmp (cstring_toCharsSafe (p->fname), default_prefix,
06586                         size_fromInt (default_len)))
06587             {
06588               /* Yes; change prefix and add to search list.  */
06589               struct file_name_list *nlist
06590                 = (struct file_name_list *) dmalloc (sizeof (*nlist));
06591               size_t this_len = strlen (specd_prefix) + cstring_length (p->fname) - default_len;
06592               char *str = (char *) dmalloc (this_len + 1);
06593               strcpy (str, specd_prefix);
06594               strcat (str, cstring_toCharsSafe (p->fname) + default_len);
06595 
06596               nlist->next = NULL;
06597               nlist->fname = cstring_fromChars (str);
06598               nlist->control_macro = 0;
06599               nlist->c_system_include_path = !p->cxx_aware;
06600               nlist->got_name_map = 0;
06601 
06602               cppReader_addIncludeChain (pfile, nlist);
06603               if (opts->first_system_include == 0)
06604                 {
06605                   opts->first_system_include = nlist;
06606                 }
06607             }
06608         }
06609       }
06610 
06611     /* Search ordinary names for GNU include directories.  */
06612 
06613     for (p = include_defaults; p->fname != NULL; p++)
06614       {
06615         /* Some standard dirs are only for C++.  */
06616         if (!p->cplusplus
06617             || (opts->cplusplus && !opts->no_standard_cplusplus_includes))
06618           {
06619             struct file_name_list *nlist
06620               = (struct file_name_list *) dmalloc (sizeof (*nlist));
06621             nlist->control_macro = 0;
06622             nlist->c_system_include_path = !p->cxx_aware;
06623             nlist->fname = p->fname;
06624             nlist->got_name_map = 0;
06625             nlist->next = NULL;
06626 
06627             cppReader_addIncludeChain (pfile, nlist);
06628 
06629             if (opts->first_system_include == 0)
06630               {
06631                 opts->first_system_include = nlist;
06632               }
06633           }
06634       }
06635     sfree (default_prefix);
06636   }
06637 
06638   /* Tack the after_include chain at the end of the include chain.  */
06639   cppReader_appendIncludeChain (pfile, opts->after_include,
06640                                 opts->last_after_include);
06641 
06642   if (opts->first_system_include == 0)
06643     {
06644       opts->first_system_include = opts->after_include;
06645     }
06646 
06647   /* With -v, print the list of dirs to search.  */
06648   if (opts->verbose) {
06649     struct file_name_list *p;
06650     fprintf (stderr, "#include \"...\" search starts here:\n");
06651 
06652     for (p = opts->include; p != NULL; p = p->next) {
06653       if (p == opts->first_bracket_include)
06654         fprintf (stderr, "#include <...> search starts here:\n");
06655 
06656       fprintf (stderr, " %s\n", cstring_toCharsSafe (p->fname));
06657     }
06658     fprintf (stderr, "End of search list.\n");
06659   }
06660 }
06661 
06662 int cppReader_startProcess (cppReader *pfile, cstring fname)
06663 {
06664   cppBuffer *fp;
06665   int f;
06666   struct cppOptions *opts = CPPOPTIONS (pfile);
06667 
06668   fp = cppReader_pushBuffer (pfile, NULL, 0);
06669 
06670   if (fp == NULL)
06671     {
06672       return 0;
06673     }
06674 
06675   if (opts->in_fname == NULL)
06676     {
06677       opts->in_fname = cstring_makeLiteralTemp ("");
06678     }
06679 
06680   fp->fname = opts->in_fname;
06681   fp->nominal_fname = fp->fname;
06682   fp->lineno = 0;
06683 
06684   /* Copy the entire contents of the main input file into
06685      the stacked input buffer previously allocated for it.  */
06686 
06687   if (cstring_isEmpty (fname))
06688     {
06689       fname = cstring_makeLiteralTemp ("");
06690       f = 0;
06691     }
06692   else if ((f = open (cstring_toCharsSafe (fname), O_RDONLY, 0666)) < 0)
06693     {
06694       cppReader_pfatalWithName (pfile, fname);
06695     }
06696   else
06697     {
06698       ;
06699     }
06700 
06701   if (finclude (pfile, f, fname, 0, NULL))
06702     {
06703       output_line_command (pfile, 0, same_file);
06704     }
06705 
06706   return 1;
06707 }
06708 
06709 static /*@exposed@*/ /*@null@*/ cppBuffer *cppReader_getBuffer (cppReader *pfile)
06710 {
06711   return pfile->buffer;
06712 }
06713 
06714 /*@exposed@*/ cppBuffer *cppReader_getBufferSafe (cppReader *pfile)
06715 {
06716   llassert (pfile->buffer != NULL);
06717   return pfile->buffer;
06718 }
06719 
06720 /*@exposed@*/ char *cppLineBase (cppBuffer *buf)
06721 {
06722   llassert (buf->buf != NULL);
06723   return (buf->buf + buf->line_base);
06724 }
06725 
06726 int cppBufPeek (cppBuffer *buf)
06727 {
06728   if (buf->cur == NULL || buf->rlimit == NULL) {
06729     return EOF;
06730   }
06731 
06732   if (buf->cur < buf->rlimit) {
06733     return *(buf->cur);
06734   }
06735 
06736   return EOF;
06737 }
06738 
06739 bool cppBuffer_isMacro (cppBuffer *buf)
06740 {
06741   if (buf != NULL)
06742     {
06743       return (buf->cleanup == cppReader_macroCleanup);
06744     }
06745 
06746   return FALSE;
06747 }
06748 
06749 /*
06750 ** Returns true if the macro should be checked, false
06751 ** if it should be expanded normally.
06752 */
06753 
06754 static bool notparseable = FALSE;  /* preceeded by @notparseable@ */
06755 static bool notfunction = FALSE;   /* preceeded by @notfunction@ */
06756 static bool expectiter = FALSE;    /* preceeded by @iter@ */
06757 static bool expectenditer = FALSE; /* second after @iter@ */
06758 static bool expectfunction = FALSE;    /* preceeded by @function@ */
06759 static bool expectconstant = FALSE;   /* preceeded by @constant@ */
06760 static bool expectmacro = FALSE;   /* preceeded by notfunction or notparseable */
06761 
06762 static void cpp_setLocation (cppReader *pfile)
06763 {
06764   fileId fid;
06765   int line;
06766 
06767   if (pfile->buffer != NULL)
06768   {
06769   if (cstring_isDefined (cppReader_getBuffer (pfile)->nominal_fname))
06770     {
06771       cstring fname = cppReader_getBuffer (pfile)->nominal_fname;
06772 
06773       if (fileTable_exists (context_fileTable (), fname))
06774           {
06775             fid = fileTable_lookup (context_fileTable (), fname);
06776           }
06777       else
06778         {
06779           fid = fileTable_lookup (context_fileTable (),
06780                                   cppReader_getBuffer (pfile)->fname);
06781         }
06782     }
06783   else
06784     {
06785       fid = fileTable_lookup (context_fileTable (),
06786                               cppReader_getBuffer (pfile)->fname);
06787     }
06788 
06789   line = cppReader_getBuffer (pfile)->lineno;
06790   fileloc_free (g_currentloc);
06791   g_currentloc = fileloc_create (fid, line, 1);
06792   }
06793   else
06794     {
06795       fileloc_free (g_currentloc);
06796       g_currentloc = fileloc_createBuiltin ();
06797     }
06798 }
06799 
06800 static bool cpp_shouldCheckMacro (cppReader *pfile, char *p) /*@*/
06801 {
06802   bool checkmacro = FALSE;
06803   bool hasParams = FALSE;
06804   bool noexpand = FALSE;
06805   cstring sname;
06806   char c;
06807 
06808   cpp_setLocation (pfile);
06809 
06810   DPRINTF (("Should check macro? %s", p));
06811 
06812   if (expectiter || expectconstant || expectenditer)
06813     {
06814       if (expectiter)
06815         {
06816           expectiter = FALSE;
06817           expectenditer = TRUE;
06818         }
06819       else
06820         {
06821           expectiter = FALSE;
06822           expectconstant = FALSE;
06823           expectenditer = FALSE;
06824         }
06825 
06826       if (notfunction || notparseable)
06827         {
06828           notfunction = FALSE;
06829           notparseable = FALSE;
06830           return FALSE;
06831         }
06832       else
06833         {
06834           return TRUE;
06835         }
06836     }
06837 
06838   llassert (*p == '#');
06839   p++;
06840 
06841   while (*p == ' ' || *p == '\t')
06842     {
06843       p++;
06844     }
06845 
06846   llassert (*p == 'd'); /* define starts */
06847 
06848   p += 6;
06849 
06850   while (*p == ' ' || *p == '\t')
06851     {
06852       p++;
06853     }
06854 
06855   sname = cstring_fromChars (p);
06856   DPRINTF (("Check macro: %s", sname));
06857 
06858   while (((c = *p) != ' ')
06859          && c != '\0' && c != '('
06860          && c != '\t' && c != '\\' && c != '\n'
06861          && !iscntrl (c))
06862     {
06863       p++;
06864     }
06865 
06866   hasParams = (c == '(');
06867   *p = '\0';
06868 
06869 
06870   if (notparseable)
06871     {
06872       notparseable = FALSE;
06873     }
06874   else if (notfunction || fileloc_isStandardLib (g_currentloc))
06875     {
06876       DPRINTF (("Clear notfunction"));
06877       notfunction = FALSE;
06878     }
06879   else
06880     {
06881       if (noexpand)
06882         {
06883           checkmacro = TRUE;
06884 
06885           if (!expectenditer)
06886             {
06887               noexpand = FALSE;
06888             }
06889         }
06890       else
06891         {
06892           if (usymtab_existsReal (sname))
06893             {
06894               uentry ue = usymtab_lookup (sname);
06895 
06896               DPRINTF (("Lookup macro: %s", uentry_unparse (ue)));
06897 
06898               if (fileloc_isPreproc (uentry_whereLast (ue)))
06899                 {
06900                   goto macroDne;
06901                 }
06902               else
06903                 {
06904                   if (uentry_isSpecified (ue))
06905                     {
06906                       checkmacro = context_getFlag (FLG_SPECMACROS);
06907                     }
06908                   else
06909                     {
06910                       if (hasParams)
06911                         {
06912                           checkmacro = context_getFlag (FLG_LIBMACROS)
06913                             || context_getFlag (FLG_FCNMACROS);
06914                         }
06915                     }
06916                 }
06917             }
06918           else
06919             {
06920             macroDne:
06921               DPRINTF (("Macro doesn't exist: %s", bool_unparse (checkmacro)));
06922 
06923               if (fileloc_isSystemFile (g_currentloc)
06924                   && context_getFlag (FLG_SYSTEMDIREXPAND))
06925                 {
06926                   ; /* don't check this macro */
06927                   DPRINTF (("Don't check 1"));
06928                 }
06929               else
06930                 {
06931                   uentry le;
06932                   
06933                   if (hasParams)
06934                     {
06935                       DPRINTF (("Has params..."));
06936 
06937                       if (context_getFlag (FLG_FCNMACROS))
06938                         {
06939                           if (usymtab_exists (sname))
06940                             {
06941                               /*
06942                               ** only get here is macro is redefined
06943                               ** error reported elsewhere
06944                               */
06945 
06946                               DPRINTF (("It exists!"));
06947                             }
06948                           else
06949                             {
06950                               /*
06951                               ** We make it a forward function, since it might be declared elsewhere.
06952                               ** After all headers have been processed, we should check the forward
06953                               ** functions.
06954                               */
06955 
06956                               fileloc loc = fileloc_makePreproc (g_currentloc);
06957 
06958                               /* the line is off-by-one, since the newline was already read */
06959                               decLine ();
06960 
06961                               if (expectfunction)
06962                                 {
06963                                   expectfunction = FALSE;
06964                                 }
06965 
06966                               le = uentry_makeForwardFunction (sname,
06967                                                                typeId_invalid, loc);
06968 
06969                               fileloc_free (loc);
06970 
06971                               incLine ();
06972 
06973                               /* Do not define here! */
06974 
06975                               (void) usymtab_addEntry (le);
06976                             }
06977 
06978                           checkmacro = TRUE;
06979                           DPRINTF (("Check: TRUE"));
06980                         }
06981                       else 
06982                         {
06983                           DPRINTF (("Flag FCN_MACROS not set!"));
06984                         }
06985                     }
06986                   else
06987                     {
06988                       DPRINTF (("No params"));
06989 
06990                       if (context_getFlag (FLG_CONSTMACROS))
06991                         {
06992                           bool nocontent = FALSE;
06993 
06994                           if (c == '\0')
06995                             {
06996                               nocontent = TRUE;
06997                             }
06998                           else
06999                             {
07000                               if (isspace (c))
07001                                 {
07002                                   char *rest = p + 1;
07003 
07004                                   /*
07005                                   ** Check if there is nothing after the define.
07006                                   */
07007 
07008                                   while ((*rest) != '\0' && isspace (*rest))
07009                                     {
07010                                       rest++;
07011                                     }
07012 
07013                                   if (*rest == '\0')
07014                                     {
07015                                       nocontent = TRUE; /* empty macro, don't check */
07016                                     }
07017                                 }
07018                             }
07019 
07020                           if (usymtab_exists (sname))
07021                             {
07022                               ;
07023                             }
07024                           else
07025                             {
07026                               fileloc loc = fileloc_makePreproc (g_currentloc);
07027                               DPRINTF (("Make constant: %s", sname));
07028                               le = uentry_makeConstant (sname,
07029                                                         ctype_unknown, loc);
07030                               (void) usymtab_addEntry (le);
07031                             }
07032 
07033                           checkmacro = !nocontent;
07034                         }
07035                     }
07036                 }
07037 
07038               if (checkmacro && usymtab_existsType (sname))
07039                 {
07040                   DPRINTF (("Making false..."));
07041                   decLine ();
07042                   ppllerror (message ("Specified type implemented as macro: %s", sname));
07043                   checkmacro = FALSE;
07044                   incLine ();
07045                 }
07046             }
07047         }
07048     }
07049 
07050   if (!checkmacro)
07051     {
07052       if (usymtab_exists (sname))
07053         {
07054           uentry ue = usymtab_lookupExpose (sname);
07055           fileloc tloc = fileloc_makePreproc (g_currentloc);
07056 
07057           uentry_setDefined (ue, tloc);
07058           fileloc_free (tloc);
07059           uentry_setUsed (ue, fileloc_undefined);
07060         }
07061       else
07062         {
07063           fileloc tloc = fileloc_makePreproc (g_currentloc);
07064           uentry ue = uentry_makeExpandedMacro (sname, tloc);
07065           DPRINTF (("Make expanded macro: %s", sname));
07066           DPRINTF (("Not in symbol table: %s", sname));
07067           
07068           (void) usymtab_addGlobalEntry (ue);
07069           fileloc_free (tloc);
07070         }
07071     }
07072 
07073   *p = c;
07074   DPRINTF (("Returning: %s", bool_unparse (checkmacro)));
07075   return checkmacro;
07076 }
07077 
07078 static enum cpp_token
07079 cpp_handleComment (cppReader *pfile, struct parse_marker *smark)
07080 {
07081   cppBuffer *pbuf = cppReader_getBuffer (pfile);
07082   char *start;
07083   int len;
07084   bool eliminateComment = FALSE;
07085 
07086   llassert (pbuf->buf != NULL);
07087 
07088   start = pbuf->buf + smark->position;
07089 
07090   llassert (pbuf->cur != NULL);
07091   len = pbuf->cur - start;
07092 
07093   if (start[0] == '*'
07094       && start[1] == context_getCommentMarkerChar ())
07095     {
07096       int i;
07097       char c = ' ';
07098       char *scomment = start + 2;
07099 
07100       start[0] = BEFORE_COMMENT_MARKER[0];
07101       start[1] = BEFORE_COMMENT_MARKER[1];
07102 
07103       llassert (start[len - 2] == '*');
07104       start[len - 2] = AFTER_COMMENT_MARKER[0];
07105 
07106       llassert (start[len - 1] == '/');
07107       start[len - 1] = AFTER_COMMENT_MARKER[1];
07108 
07109       cppReader_reserve(pfile, size_fromInt (1 + len));
07110       cppReader_putCharQ (pfile, c);
07111 
07112       cpp_setLocation (pfile);
07113 
07114       if (mstring_equalPrefix (scomment, "ignore"))
07115         {
07116           if (!context_getFlag (FLG_NOCOMMENTS))
07117             {
07118               context_enterSuppressRegion ();
07119             }
07120         }
07121       else if (mstring_equalPrefix (scomment, "end"))
07122         {
07123           if (!context_getFlag (FLG_NOCOMMENTS))
07124             {
07125               context_exitSuppressRegion ();
07126             }
07127         }
07128       else if (mstring_equalPrefix (scomment, "notparseable"))
07129         {
07130           notparseable = TRUE;
07131           expectmacro = TRUE;
07132           eliminateComment = TRUE;
07133         }
07134       else if (mstring_equalPrefix (scomment, "notfunction"))
07135         {
07136           notfunction = TRUE;
07137           expectmacro = TRUE;
07138           eliminateComment = TRUE;
07139         }
07140       else if (mstring_equalPrefix (scomment, "iter"))
07141         {
07142           expectiter = TRUE;
07143         }
07144       else if (mstring_equalPrefix (scomment, "function"))
07145         {
07146           expectfunction = TRUE;
07147         }
07148       else if (mstring_equalPrefix (scomment, "constant"))
07149         {
07150           expectconstant = TRUE;
07151         }
07152       else
07153         {
07154           char sChar = *scomment;
07155 
07156           if (sChar == '='
07157               || sChar == '-'
07158               || sChar == '+')
07159             {
07160               char *rest = scomment + 1;
07161 
07162               if (mstring_equalPrefix (rest, "commentchar"))
07163                 {
07164                   eliminateComment = TRUE;
07165 
07166                   if (sChar == '=')
07167                     {
07168                       ppllerror (cstring_makeLiteral
07169                                  ("Cannot restore commentchar"));
07170                     }
07171                   else
07172                     {
07173                       char *next = scomment + 12; /* strlen commentchar = 12 */
07174 
07175                       if (*next != ' ' && *next != '\t' && *next != '\n')
07176                         {
07177                           ppllerror
07178                             (message
07179                              ("Syntactic commentchar comment is not followed by a "
07180                               "whitespace character: %c",
07181                               *next));
07182                         }
07183                       else
07184                         {
07185                           char cchar = *(next + 1);
07186 
07187                           if (cchar == '\0')
07188                             {
07189                               ppllerror
07190                                 (cstring_makeLiteral
07191                                  ("Cannot set commentchar to NUL"));
07192                             }
07193                           else
07194                             {
07195                               context_setCommentMarkerChar (cchar);
07196                               /* setComment = TRUE; */
07197                             }
07198                         }
07199                     }
07200                 }
07201               else if (mstring_equalPrefix (rest, "namechecks"))
07202                 {
07203                   context_fileSetFlag (FLG_NAMECHECKS,
07204                                        ynm_fromCodeChar (sChar));
07205                 }
07206               else if (mstring_equalPrefix (rest, "macroredef"))
07207                 {
07208                   context_fileSetFlag (FLG_MACROREDEF,
07209                                        ynm_fromCodeChar (sChar));
07210                 }
07211               else if (mstring_equalPrefix (rest, "usevarargs"))
07212                 {
07213                   context_fileSetFlag (FLG_USEVARARGS,
07214                                        ynm_fromCodeChar (sChar));
07215                 }
07216               else if (mstring_equalPrefix (rest, "nextlinemacros"))
07217                 {
07218                   context_fileSetFlag (FLG_MACRONEXTLINE,
07219                                        ynm_fromCodeChar (sChar));
07220                 }
07221               else if (mstring_equalPrefix (rest, "allmacros")
07222                        || mstring_equalPrefix (rest, "fcnmacros")
07223                        || mstring_equalPrefix (rest, "constmacros"))
07224                 {
07225                   flagcode fl;
07226 
07227                   if (mstring_equalPrefix (rest, "allmacros"))
07228                     {
07229                       fl = FLG_ALLMACROS;
07230                     }
07231                   else if (mstring_equalPrefix (rest, "fcnmacros"))
07232                     {
07233                       fl = FLG_FCNMACROS;
07234                     }
07235                   else
07236                     {
07237                       llassert (mstring_equalPrefix (rest, "constmacros"));
07238                       fl = FLG_CONSTMACROS;
07239                     }
07240 
07241 
07242                   context_fileSetFlag (fl, ynm_fromCodeChar (sChar));
07243                   notfunction = FALSE;
07244                 }
07245               else
07246                 {
07247                   ;
07248                 }
07249             }
07250           else
07251             {
07252               ;
07253             }
07254         }
07255 
07256       if (eliminateComment)
07257         {
07258           goto removeComment;
07259         }
07260 
07261       /* Replaces comment char's in start with spaces */
07262 
07263       for (i = 2; i < len - 2; i++)
07264         {
07265           if (start[i] == BEFORE_COMMENT_MARKER[0]
07266               || start[i] == BEFORE_COMMENT_MARKER[1]
07267               || start[i] == context_getCommentMarkerChar ())
07268             {
07269               start[i] = ' ';
07270             }
07271         }
07272 
07273       cppReader_putStrN (pfile, start, size_fromInt (len));
07274       parseClearMark (smark);
07275       return CPP_COMMENT;
07276     }
07277   else
07278     {
07279     removeComment:
07280       {
07281         int i;
07282 
07283         /*
07284         ** Output the comment as all spaces so line/column
07285         ** in output file is still correct.
07286         */
07287 
07288         char c = ' ';
07289         cstring lintcomment = cstring_undefined;
07290 
07291         if (context_getFlag (FLG_LINTCOMMENTS))
07292           {
07293             if (mstring_equalPrefix (start, "*NOTREACHED*/"))
07294               {
07295                 lintcomment = cstring_makeLiteralTemp ("l_notreach");
07296               }
07297             else if (mstring_equalPrefix (start, "*PRINTFLIKE*/"))
07298               {
07299                 lintcomment = cstring_makeLiteralTemp ("l_printfli");
07300               }
07301             else if (mstring_equalPrefix (start, "*FALLTHROUGH*/"))
07302               {
07303                 lintcomment = cstring_makeLiteralTemp ("l_fallthrou");
07304               }
07305             else if (mstring_equalPrefix (start, "*ARGSUSED*/"))
07306               {
07307                 lintcomment = cstring_makeLiteralTemp ("l_argsus");
07308               }
07309             else if (mstring_equalPrefix (start, "*FALLTHRU*/"))
07310               {
07311                 lintcomment = cstring_makeLiteralTemp ("l_fallth");
07312               }
07313             else
07314               {
07315                 lintcomment = cstring_undefined;
07316               }
07317           }
07318         else
07319           {
07320             lintcomment = cstring_undefined;
07321           }
07322 
07323         if (cstring_isDefined (lintcomment))
07324           {
07325             c = BEFORE_COMMENT_MARKER[0];
07326             start[0] = BEFORE_COMMENT_MARKER[1];
07327 
07328             llassert (cstring_length (lintcomment) == len - 3);
07329 
07330             for (i = 1; i < len - 2; i++)
07331               {
07332                 start[i] = cstring_getChar (lintcomment, i);
07333               }
07334             
07335             start[len - 2] = AFTER_COMMENT_MARKER[0];
07336             start[len - 1] = AFTER_COMMENT_MARKER[1];
07337           }
07338         else
07339           {
07340             /* Replaces  char's in start with spaces */
07341             for (i = 0; i < len; i++)
07342               {
07343                 if (start[i] == '/'
07344                     && i < len - 1
07345                     && start[i + 1] == '*') {
07346                   cppReader_warning 
07347                     (pfile,
07348                      message ("Start comment inside comment"));
07349                 }
07350                 
07351                 if (start[i] != '\n')
07352                   {
07353                     start[i] = ' ';
07354                   }
07355               }
07356           }
07357 
07358         cppReader_reserve (pfile, size_fromInt (1 + len));
07359         cppReader_putCharQ (pfile, c);
07360         cppReader_putStrN (pfile, start, size_fromInt (len));
07361         parseClearMark (smark);
07362         return CPP_COMMENT;
07363       }
07364     }
07365 }
07366 
07367 static int cpp_openIncludeFile (char *filename)
07368 {
07369   int res = open (filename, O_RDONLY, 0666);
07370 
07371   if (res 
07372       && !fileTable_exists (context_fileTable (),
07373                             cstring_fromChars (filename)))
07374     {
07375       DPRINTF (("Add header: %s", filename));
07376       (void) fileTable_addHeaderFile (context_fileTable (),
07377                                       cstring_fromChars (filename));
07378     }
07379 
07380   return res;
07381 }
07382 
07383 static bool cpp_skipIncludeFile (cstring fname)
07384 {
07385   if (context_isSystemDir (fname))
07386     {
07387       DPRINTF (("System dir: %s", fname));
07388 
07389       if (lcllib_isSkipHeader (fname))
07390         {
07391           DPRINTF (("Skip include TRUE: %s", fname));
07392           return TRUE;
07393         }
07394       
07395       if (context_getFlag (FLG_SKIPSYSHEADERS))
07396         {
07397           DPRINTF (("Skip include TRUE: %s", fname));
07398           return TRUE;
07399         }
07400     }
07401 
07402   if (context_getFlag (FLG_SINGLEINCLUDE))
07403     {
07404       fname = cstring_fromChars (removePreDirs (cstring_toCharsSafe (fname)));
07405 
07406 # if defined (WIN32) || defined (OS2)
07407       cstring_replaceAll (fname, '\\', '/');
07408 # endif
07409 
07410       if (fileTable_exists (context_fileTable (), fname))
07411         {
07412           DPRINTF (("Skip include TRUE: %s", fname));
07413           return TRUE;
07414         }
07415     }
07416 
07417   DPRINTF (("Skip include FALSE: %s", fname));
07418   return FALSE;
07419 }
07420 
07421 static int cpp_peekN (cppReader *pfile, int n)
07422 {
07423   cppBuffer *buf = cppReader_getBuffer (pfile);
07424 
07425   llassert (buf->cur != NULL);
07426 
07427   return (buf->rlimit - buf->cur >= (n)
07428           ? buf->cur[n]
07429           : EOF);
07430 }
07431 
07432 cppBuffer *cppBuffer_prevBuffer (cppBuffer *buf)
07433 {
07434   return buf + 1;
07435 }
07436 
07437 void cppBuffer_forward (cppBuffer *buf, int n)
07438 {
07439   llassert (buf->cur != NULL);
07440   buf->cur += n;
07441 }

Generated at Fri Nov 3 18:57:40 2000 for LCLint by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000