]> andersk Git - splint.git/blob - src/cpplib.c
*** empty log message ***
[splint.git] / src / cpplib.c
1 /*
2 See
3 http://src.openresources.com/debian/src/devel/HTML/S/altgcc_2.7.2.2.orig%20altgcc-2.7.2.2.orig%20protoize.c.html
4 static char *
5 abspath (cwd, rel_filename)
6
7 */
8
9 /*!!!!
10 *** cpplib.c.old Tue Nov 28 2000 09:04:09 AM
11 --- cpplib.c Tue Nov 28 2000 08:55:18 AM
12 ***************
13 *** 5715,5722 ****
14      c2 = cppReader_peekC (pfile)
15      if (c2 != '\n'
16        goto randomchar
17 !    token = CPP_HSPACE
18 !    goto op2any
19 --- 5714,5723 ----
20           case '\\'
21      c2 = cppReader_peekC (pfile)
22      if (c2 != '\n'
23        goto randomchar
24 !    cppReader_forward (pfile, 1)
25 !    pfile->lineno++
26 !    return CPP_HSPACE
27   
28  
29    case '\n'
30      cppReader_putChar (pfile, c)
31
32
33 Carl J. Appellof ( mailto:cappello@legato.com <mailto:cappello@legato.com> )
34 */ /*@i8@*/
35
36 /*
37 ** LCLint - annotation-assisted static program checker
38 ** Copyright (C) 1994-2001 University of Virginia,
39 **         Massachusetts Institute of Technology
40 **
41 ** This program is free software; you can redistribute it and/or modify it
42 ** under the terms of the GNU General Public License as published by the
43 ** Free Software Foundation; either version 2 of the License, or (at your
44 ** option) any later version.
45 ** 
46 ** This program is distributed in the hope that it will be useful, but
47 ** WITHOUT ANY WARRANTY; without even the implied warranty of
48 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
49 ** General Public License for more details.
50 ** 
51 ** The GNU General Public License is available from http://www.gnu.org/ or
52 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
53 ** MA 02111-1307, USA.
54 **
55 ** For information on lclint: lclint-request@cs.virginia.edu
56 ** To report a bug: lclint-bug@cs.virginia.edu
57 ** For more information: http://lclint.cs.virginia.edu
58 */
59 /*
60 ** cpplib.c
61 */
62 /*
63    Copyright (C) 1986, 87, 89, 92-6, 1997 Free Software Foundation, Inc.
64    Contributed by Per Bothner, 1994-95.
65    Based on CCCP program by Paul Rubin, June 1986
66    Adapted to ANSI C, Richard Stallman, Jan 1987
67
68 This program is free software; you can redistribute it and/or modify it
69 under the terms of the GNU General Public License as published by the
70 Free Software Foundation; either version 2, or (at your option) any
71 later version.
72
73 This program is distributed in the hope that it will be useful,
74 but WITHOUT ANY WARRANTY; without even the implied warranty of
75 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
76 GNU General Public License for more details.
77
78 You should have received a copy of the GNU General Public License
79 along with this program; if not, write to the Free Software
80 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
81
82  In other words, you are welcome to use, share and improve this program.
83  You are forbidden to forbid anyone else to use, share and improve
84  what you give them.   Help stamp out software-hoarding!  */
85
86 /*
87  * Herbert 06/12/2000:
88  * - OS2 drive specs like WIN32
89  * - Includes for IBMs OS/2 compiler
90  */
91
92 # include <ctype.h>
93 # include <stdio.h>
94 # include <signal.h>
95 # ifdef __STDC__
96 # include <stdlib.h>
97 # endif
98
99 # include <string.h>
100
101 # if !(defined (WIN32) || defined (OS2) && defined (__IBMC__))
102 # include <unistd.h>
103 # endif
104
105 # include <sys/types.h>
106 # include <sys/stat.h>
107 # include <fcntl.h>
108
109 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
110 # include <io.h>
111 # include <sys/utime.h>         /* for __DATE__ and __TIME__ */
112 # include <time.h>
113 # else
114 # ifndef VMS
115 # ifndef USG
116 # include <time.h> /* Reported by Paul Smith */
117 # include <sys/time.h>
118 # include <sys/resource.h>
119 # else
120 # include <sys/times.h>
121 # include <time.h>
122 # include <fcntl.h>
123 # endif /* USG */
124 # endif /* not VMS */
125 # endif /* not WIN32 */
126
127 /* This defines "errno" properly for VMS, and gives us EACCES.  */
128 # include <errno.h>
129
130 # include "lclintMacros.nf"
131 # include "llbasic.h"
132 # include "lcllib.h"
133 # include "cpplib.h"
134 # include "cpperror.h"
135 # include "cpphash.h"
136 # include "cppexp.h"
137 # include "version.h"
138 # include "portab.h"
139 # include "osd.h"
140
141 /*
142 ** This is really kludgey code...
143 */
144
145 /*@+boolint@*/
146 /*@+charint@*/
147
148 #define NO_SHORTNAMES
149
150 # ifdef open
151 # undef open
152 # undef read
153 # undef write
154 # endif /* open */
155
156 /*@constant int IMPORT_FOUND@*/
157 # define IMPORT_FOUND -2
158
159 /*@constant int SKIP_INCLUDE@*/
160 # define SKIP_INCLUDE IMPORT_FOUND
161
162 /*@constant unused int IMPORT_NOT_FOUND@*/
163 # define IMPORT_NOT_FOUND -1
164
165 #ifndef STDC_VALUE
166 /*@constant unused int STDC_VALUE@*/
167 #define STDC_VALUE 1
168 #endif
169
170 /* By default, colon separates directories in a path.  */
171 #ifndef PATH_SEPARATOR
172 /*@constant char PATH_SEPARATOR@*/
173 #define PATH_SEPARATOR ':'
174 #endif
175
176 static void parse_name (cppReader *, int);
177
178 static int cpp_openIncludeFile (char *p_filename)
179      /*@modifies fileSystem @*/ ;
180
181 static void cpp_setLocation (cppReader *p_pfile)
182      /*@modifies g_currentloc@*/ ;
183
184 static enum cpp_token cpp_handleComment (cppReader *p_pfile,
185                                          struct parse_marker *p_smark)
186      /*@modifies p_pfile, p_smark@*/;
187
188 static bool cpp_shouldCheckMacro (cppReader *p_pfile, char *p_p) /*@*/ ;
189
190 static bool cpp_skipIncludeFile (cstring p_fname) /*@*/ ;
191
192 #ifndef O_RDONLY
193 #define O_RDONLY 0
194 #endif
195
196 /* Symbols to predefine.  */
197
198 #ifdef CPP_PREDEFINES
199 static /*@observer@*/ char *predefs = CPP_PREDEFINES;
200 #else
201 static /*@observer@*/ char *predefs = "";
202 #endif
203
204 /* We let tm.h override the types used here, to handle trivial differences
205    such as the choice of unsigned int or long unsigned int for size_t.
206    When machines start needing nontrivial differences in the size type,
207    it would be best to do something here to figure out automatically
208    from other information what type to use.  */
209
210 /* The string value for __SIZE_TYPE__.  */
211
212 #ifndef SIZE_TYPE
213 /*@constant observer char *SIZE_TYPE@*/
214 #define SIZE_TYPE "long unsigned int"
215 #endif
216
217 /* The string value for __PTRDIFF_TYPE__.  */
218
219 #ifndef PTRDIFF_TYPE
220 /*@constant observer char *PTRDIFF_TYPE@*/
221 #define PTRDIFF_TYPE "long int"
222 #endif
223
224 /* The string value for __WCHAR_TYPE__.  */
225
226 #ifndef WCHAR_TYPE
227 /*@constant observer char *WCHAR_TYPE@*/
228 #define WCHAR_TYPE "int"
229 #endif
230
231 /* The string value for __USER_LABEL_PREFIX__ */
232
233 #ifndef USER_LABEL_PREFIX
234 /*@constant observer char *USER_LABEL_PREFIX@*/
235 #define USER_LABEL_PREFIX ""
236 #endif
237
238 /* The string value for __REGISTER_PREFIX__ */
239
240 #ifndef REGISTER_PREFIX
241 /*@constant observer char *REGISTER_PREFIX@*/
242 #define REGISTER_PREFIX ""
243 #endif
244
245 /* table to tell if char can be part of a C identifier.  */
246 static bool is_idchar[256];
247 /* table to tell if char can be first char of a c identifier.  */
248 static bool is_idstart[256];
249 /* table to tell if c is horizontal space.  */
250 static bool is_hor_space[256];
251 /* table to tell if c is horizontal or vertical space.  */
252 static bool is_space[256];
253
254 static /*@exposed@*/ /*@null@*/ cppBuffer *
255 cppReader_getBuffer (/*@special@*/ cppReader *p_pfile)
256      /*@uses p_pfile->buffer@*/
257      /*@modifies nothing@*/ ;
258
259 /*@notfunction@*/
260 # define SKIP_WHITE_SPACE(p) do { /*@access cstring@*/ while (is_hor_space[(int) *(p)]) { (p)++; } } /*@noaccess cstring@*/ while (0)
261
262 /*@notfunction@*/
263 # define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*(p)]) { (p)++; } } while (0)
264
265 static int cpp_peekN (cppReader *p_pfile, int p_n) /*@*/ ;
266
267 /*@function static int cppBuffer_get (sef cppBuffer *p_b) modifies *p_b ; @*/
268 # define cppBuffer_get(BUFFER) \
269   ((BUFFER)->cur < (BUFFER)->rlimit ? *(BUFFER)->cur++ : EOF)
270
271 /* Append string STR (of length N) to PFILE's output buffer.  Make space. */
272 /*@function static void cppReader_puts (sef cppReader *p_file, char *p_str, sef size_t p_n)
273                      modifies *p_file; @*/
274 # define cppReader_puts(PFILE, STR, N) \
275   cppReader_reserve(PFILE, N), cppReader_putStrN (PFILE, STR,N)
276
277 /* Append character CH to PFILE's output buffer.  Assume sufficient space. */
278
279 /*@function static void cppReader_putCharQ (cppReader *p_file, char p_ch)
280                     modifies *p_file; @*/
281 # define cppReader_putCharQ(PFILE, CH) (*(PFILE)->limit++ = (CH))
282
283 /* Append character CH to PFILE's output buffer.  Make space if need be. */
284
285 /*@function static void cppReader_putChar (sef cppReader *p_file, char p_ch)
286                     modifies *p_file; @*/
287 #define cppReader_putChar(PFILE, CH) (cppReader_reserve (PFILE, (size_t) 1), cppReader_putCharQ (PFILE, CH))
288
289 /* Make sure PFILE->limit is followed by '\0'. */
290 /*@function static void cppReader_nullTerminateQ (cppReader *p_file)
291       modifies *p_file; @*/
292
293 #define cppReader_nullTerminateQ(PFILE) (*(PFILE)->limit = 0)
294
295 /*@function static void cppReader_nullTerminate (sef cppReader *p_file)
296                            modifies *p_file; @*/
297 # define cppReader_nullTerminate(PFILE) \
298   (cppReader_reserve (PFILE, (size_t) 1), *(PFILE)->limit = 0)
299
300 /*@function static void cppReader_adjustWritten (cppReader *p_file, size_t)
301                            modifies *p_file; @*/
302 #define cppReader_adjustWritten(PFILE,DELTA) ((PFILE)->limit += (DELTA))
303
304 /*@function static bool cppReader_isC89 (cppReader *) modifies nothing; @*/
305 #define cppReader_isC89(PFILE) (CPPOPTIONS(PFILE)->c89)
306
307 /*@function static observer char *cppReader_wcharType (cppReader *)
308      modifies nothing; @*/
309
310 # define cppReader_wcharType(PFILE) \
311   (CPPOPTIONS (PFILE)->cplusplus ? "__wchar_t" : WCHAR_TYPE)
312
313 static void cppBuffer_forward (cppBuffer *p_buf, int p_n) /*@modifies *p_buf@*/ ;
314
315 /*@function static void cppReader_forward (cppReader *p_pfile, int) modifies *p_pfile; @*/
316 # define cppReader_forward(pfile, N) \
317   (cppBuffer_forward (cppReader_getBufferSafe (pfile), (N)))
318
319 /*@function static int cppReader_getC (cppReader *p_pfile) modifies *p_pfile; @*/
320 # define cppReader_getC(pfile)   (cppBuffer_get (cppReader_getBufferSafe (pfile)))
321
322 /*@function static int cppReader_peekC (cppReader *) modifies nothing;@*/
323 # define cppReader_peekC(pfile)  (cppBufPeek (cppReader_getBufferSafe (pfile)))
324
325 /* Move all backslash-newline pairs out of embarrassing places.
326    Exchange all such pairs following BP
327    with any potentially-embarrassing characters that follow them.
328    Potentially-embarrassing characters are / and *
329    (because a backslash-newline inside a comment delimiter
330    would cause it not to be recognized).  */
331
332 /*@notfunction@*/
333 # define NEWLINE_FIX \
334    do { while (cppReader_peekC (pfile) == '\\' && cpp_peekN (pfile, 1) == '\n') { cppReader_forward (pfile, 2); } } while(FALSE)
335
336      /* Same, but assume we've already read the potential '\\' into C.  */
337 /*@notfunction@*/
338 # define NEWLINE_FIX1(C) do { \
339      while ((C) == '\\' && cppReader_peekC (pfile) == '\n') { cppReader_forward (pfile, 1); (C) = cppReader_getC (pfile); }\
340                                                                            } while(0)
341
342 static void parseSetMark (/*@out@*/ struct parse_marker *,
343                           cppReader *);
344 static void parseClearMark (struct parse_marker *);
345 static void parseGotoMark (struct parse_marker *, cppReader *);
346 static void parseMoveMark (struct parse_marker *, cppReader *);
347
348 /* If we have a huge buffer, may need to cache more recent counts */
349 static /*@exposed@*/ char *cppLineBase (/*@sef@*/ cppBuffer *);
350
351 static /*@exposed@*/ /*@null@*/ cppBuffer *
352    cppReader_pushBuffer (cppReader *p_pfile,
353                          /*@owned@*/ /*@null@*/ char *, size_t)
354      /*@modifies p_pfile@*/ ;
355
356 static void cppReader_appendIncludeChain
357 (cppReader *p_pfile,
358  /*@keep@*/ struct file_name_list *p_first,
359  /*@dependent@*/ struct file_name_list *p_last);
360
361 static void cppReader_macroCleanup (cppBuffer *p_pbuf, cppReader *p_pfile);
362 static enum cpp_token cppReader_nullUnderflow (/*@unused@*/ cppReader *p_pfile);
363
364 static void cppReader_nullCleanup (/*@unused@*/ cppBuffer *p_pbuf,
365                                    /*@unused@*/ cppReader *p_pfile);
366
367 static void cppReader_fileCleanup (cppBuffer *p_pbuf,
368                                    /*@unused@*/ cppReader *p_pfile);
369
370 static int cppReader_handleDirective (cppReader *p_pfile);
371
372 static void cppReader_scanBuffer (cppReader *p_pfile);
373
374 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
375
376 /*
377 ** WIN32 (at least the VC++ include files) does not define mode_t.
378 */
379
380 /*@-incondefs@*/ /*@-czechtypes@*/
381 typedef unsigned int mode_t;
382 /*@=incondefs@*/ /*@=czechtypes@*/
383
384 # endif
385
386 static int file_size_and_mode (int p_fd, /*@out@*/ mode_t *p_mode_pointer,
387                                /*@out@*/ size_t *p_size_pointer);
388 static int safe_read (int p_desc, /*@out@*/ char *p_ptr, int p_len);
389
390
391 /*
392 ** cppBuffer_isMacro is true if the buffer contains macro expansion.
393 ** (Note that it is false while we're expanding marco *arguments*.)
394 */
395
396 static bool cppBuffer_isMacro (/*@null@*/ cppBuffer *) /*@*/ ;
397
398 static void path_include (cppReader *p_pfile, char *p_path)
399      /*@modifies p_pfile@*/ ;
400
401 static void initialize_builtins (cppReader *p_pfile)
402      /*@modifies p_pfile@*/ ;
403
404 static void initialize_char_syntax (struct cppOptions *p_opts) ;
405
406 static int /*@alt void@*/ finclude (cppReader *p_pfile, int p_f,
407                                     cstring p_fname,
408                                     bool p_system_header_p,
409                                     /*@dependent@*/ /*@null@*/ struct file_name_list *p_dirptr);
410
411 static void validate_else (cppReader *p_pfile, cstring p_directive);
412
413 static void conditional_skip (cppReader *p_pfile, int p_skip,
414                               enum node_type p_type,
415                               /*@dependent@*/ /*@null@*/ char *p_control_macro);
416
417 static HOST_WIDE_INT eval_if_expression (cppReader *p_pfile,
418                                          char *p_buf,
419                                          int p_length);
420
421 static void skip_if_group (cppReader *p_pfile, int p_any);
422
423 static bool comp_def_part (bool p_first, char *p_beg1, int p_len1,
424                            char *p_beg2, int p_len2, bool p_last);
425
426 #ifdef abort
427 extern void fancy_abort ();
428 #endif
429
430 static bool redundant_include_p (cppReader *p_pfile, /*@null@*/ cstring p_name);
431 static bool is_system_include (cppReader *p_pfile, cstring p_filename);
432
433 static /*@observer@*/ /*@null@*/ struct file_name_map *
434 read_name_map (cppReader *p_pfile, cstring p_dirname);
435
436 static cstring read_filename_string (int p_ch, /*:open:*/ FILE *p_f);
437
438 static int open_include_file (cppReader *p_pfile,
439                               /*@owned@*/ cstring p_fname,
440                               /*@null@*/ struct file_name_list *p_searchptr);
441
442 static void push_macro_expansion (cppReader *,
443                                   /*@owned@*/ char *, size_t,
444                                   /*@dependent@*/ hashNode);
445
446 /* Last arg to output_line_command.  */
447 enum file_change_code {
448   same_file, enter_file, leave_file
449 };
450
451 /* `struct directive' defines one #-directive, including how to handle it.  */
452
453 struct directive {
454   int length;                   /* Length of name */
455   /*@null@*/ int (*func)();     /* Function to handle directive */
456   /*@observer@*/ cstring name;  /* Name of directive */
457   enum node_type type;          /* Code which describes which directive.  */
458   bool command_reads_line;      /* One if rest of line is read by func.  */
459   bool traditional_comments;    /* Nonzero: keep comments if -traditional.  */
460   bool pass_thru;               /* Copy preprocessed directive to output file.*/
461 };
462
463 /* These functions are declared to return int instead of void since they
464    are going to be placed in a table and some old compilers have trouble with
465    pointers to functions returning void.  */
466
467 static int do_define (cppReader *, /*@null@*/ struct directive *, 
468                       char *, char *);
469 static int do_defineAux (cppReader *, /*@null@*/ struct directive *,
470                          char *, char *, bool);
471      
472 static int do_line (cppReader *, /*@null@*/ struct directive *);
473 static int do_include (cppReader *, struct directive *, char *, char *);
474 static int do_undef (cppReader *, struct directive *, char *, char *);
475 static int do_error (cppReader *, struct directive *, char *, char *);
476 static int do_pragma (cppReader *, struct directive *, char *, char *);
477 static int do_ident (cppReader *, struct directive *, char *, char *);
478 static int do_if (cppReader *, struct directive *, char *, char *);
479 static int do_xifdef (cppReader *, struct directive *, char *, char *);
480 static int do_else (cppReader *, struct directive *, char *, char *);
481 static int do_elif (cppReader *, struct directive *, char *, char *);
482 static int do_endif (cppReader *, struct directive *, char *, char *);
483 static int do_warning (cppReader *, struct directive *, char *, char *);
484
485 /* If a buffer's dir field is SELF_DIR_DUMMY, it means the file was found
486    via the same directory as the file that #included it.  */
487
488 /*@constant observer struct file_name_list *SELF_DIR_DUMMY@*/
489 #define SELF_DIR_DUMMY ((struct file_name_list *) (~0))
490
491 /* #include "file" looks in source file dir, then stack.  */
492 /* #include <file> just looks in the stack.  */
493 /* -I directories are added to the end, then the defaults are added.  */
494
495 /*@access cstring@*/
496
497 static struct default_include {
498   /*@dependent@*/ /*@observer@*/ cstring fname; /* The name of the directory.  */
499   int cplusplus;                /* Only look here if we're compiling C++.  */
500   int cxx_aware;                /* Includes in this directory don't need to
501                                    be wrapped in extern "C" when compiling
502                                    C++.  */
503 } include_defaults_array[]
504 = {
505   /* This is the dir for fixincludes.  Put it just before
506      the files that we fix.  */
507   { GCC_INCLUDE_DIR, 0, 0 },
508   { GCC_INCLUDE_DIR2, 0, 0 },
509   { cstring_undefined, 0, 0 }
510 };
511
512 /*@noaccess cstring@*/
513
514 /* Here is the actual list of #-directives, most-often-used first.
515    The initialize_builtins function assumes #define is the very first.  */
516
517 /*@access cstring@*/
518
519 static struct directive directive_table[] = {
520   {  6, do_define, "define", T_DEFINE, FALSE, TRUE, FALSE },
521   {  5, do_xifdef, "ifdef", T_IFDEF, TRUE, FALSE, FALSE },
522   {  6, do_xifdef, "ifndef", T_IFNDEF, TRUE, FALSE, FALSE },
523   {  7, do_include, "include", T_INCLUDE, TRUE, FALSE, FALSE },
524   {  5, do_endif, "endif", T_ENDIF, TRUE, FALSE, FALSE },
525   {  4, do_else, "else", T_ELSE, TRUE, FALSE, FALSE },
526   {  2, do_if, "if", T_IF, TRUE, FALSE, FALSE },
527   {  4, do_elif, "elif", T_ELIF, TRUE, FALSE, FALSE },
528   {  5, do_undef, "undef", T_UNDEF, FALSE, FALSE, FALSE },
529   {  5, do_error, "error", T_ERROR, FALSE, FALSE, FALSE },
530   {  7, do_warning, "warning", T_WARNING, FALSE, FALSE, FALSE },
531   {  6, do_pragma, "pragma", T_PRAGMA, FALSE, FALSE, TRUE},
532   {  4, do_line, "line", T_LINE, TRUE, FALSE, FALSE },
533   {  5, do_ident, "ident", T_IDENT, TRUE, FALSE, TRUE },
534   /* {  8, do_unassert, "unassert", T_UNASSERT, TRUE, FALSE, FALSE }, */
535   {  -1, 0, "", T_UNUSED, FALSE, FALSE, FALSE },
536 };
537 /*@noaccess cstring@*/
538
539 static cstring searchPath_unparse (struct file_name_list *search_start) 
540 {
541   cstring res = cstring_newEmpty ();
542   struct file_name_list *searchptr = NULL;
543
544   for (searchptr = search_start; searchptr != NULL;
545        searchptr = searchptr->next)
546     {
547       if (!cstring_isEmpty (searchptr->fname)) {
548         res = cstring_concatFree1 (res, searchptr->fname);
549         if (searchptr->next != NULL) {
550           res = cstring_appendChar (res, ';');
551         }
552       }
553     }
554
555   return res;
556 }
557
558 /*@+charint@*/
559 static void
560 initialize_char_syntax (struct cppOptions *opts)
561 {
562   char i;
563
564   /*
565    * Set up is_idchar and is_idstart tables.  These should be
566    * faster than saying (is_alpha (c) || c == '_'), etc.
567    * Set up these things before calling any routines tthat
568    * refer to them.
569    */
570
571   for (i = 'a'; i <= 'z'; i++) {
572     is_idchar[i - 'a' + 'A'] = TRUE;
573     is_idchar[(int) i] = TRUE;
574     is_idstart[i - 'a' + 'A'] = TRUE;
575     is_idstart[(int) i] = TRUE;
576   }
577
578   for (i = '0'; i <= '9'; i++)
579     {
580       is_idchar[(int) i] = TRUE;
581     }
582
583   is_idchar['_'] = TRUE;
584   is_idstart['_'] = TRUE;
585   is_idchar['$'] = opts->dollars_in_ident;
586   is_idstart['$'] = opts->dollars_in_ident;
587
588   /* horizontal space table */
589   is_hor_space[' '] = TRUE;
590   is_hor_space['\t'] = TRUE;
591   is_hor_space['\v'] = TRUE;
592   is_hor_space['\f'] = TRUE;
593   is_hor_space['\r'] = TRUE;
594
595   is_space[' '] = TRUE;
596   is_space['\t'] = TRUE;
597   is_space['\v'] = TRUE;
598   is_space['\f'] = TRUE;
599   is_space['\n'] = TRUE;
600   is_space['\r'] = TRUE;
601 }
602
603 bool isIdentifierChar (char c)
604 {
605   return is_idchar[(int) c];
606 }
607
608 /* Place into P_PFILE a quoted string representing the string SRC.
609    Caller must reserve enough space in pfile->token_buffer.  */
610
611 static void
612 quote_string (cppReader *pfile, char *src)
613 {
614   char c;
615
616   cppReader_putCharQ (pfile, '\"');
617   for (;;)
618     {
619       switch ((c = *src++))
620         {
621         default:
622           if (isprint (c))
623             cppReader_putCharQ (pfile, c);
624           else
625             {
626               sprintf (cppReader_getPWritten (pfile), "\\%03o",
627                        (unsigned int) c);
628               cppReader_adjustWritten (pfile, (size_t) 4);
629             }
630           /*@switchbreak@*/ break;
631
632         case '\"':
633         case '\\':
634           cppReader_putCharQ (pfile, '\\');
635           cppReader_putCharQ (pfile, c);
636           /*@switchbreak@*/ break;
637
638         case '\0':
639           cppReader_putCharQ (pfile, '\"');
640           cppReader_nullTerminateQ (pfile);
641           return;
642         }
643     }
644 }
645
646 /* Re-allocates PFILE->token_buffer so it will hold at least N more chars.  */
647
648 void
649 cppReader_growBuffer (cppReader *pfile, size_t n)
650 {
651   size_t old_written = cppReader_getWritten (pfile);
652   pfile->token_buffer_size = n + 2 * pfile->token_buffer_size;
653   pfile->token_buffer = (char *)
654     drealloc (pfile->token_buffer, pfile->token_buffer_size);
655   cppReader_setWritten (pfile, old_written);
656 }
657
658 /*
659  * process a given definition string, for initialization
660  * If STR is just an identifier, define it with value 1.
661  * If STR has anything after the identifier, then it should
662  * be identifier=definition.
663  */
664
665 void
666 cppReader_define (cppReader *pfile, char *str)
667 {
668   char *buf = NULL;
669   char *p = str;
670
671   DPRINTF (("Cpp reader define: %s", str));
672
673   if (!is_idstart[(int) *p])
674     {
675       DPRINTF (("ERROR 1"));
676       cppReader_error (pfile,
677                        message ("Malformed option `-D%s'",
678                                 cstring_fromChars (str)));
679       
680       return;
681     }
682
683   p++;
684
685   DPRINTF (("Here 2"));
686
687   while (is_idchar[(int) *p])
688     {
689       p++;
690     }
691
692   if (*p == '(') {
693     p++;
694     while (*p != ')' && *p != '\0') {
695       p++;
696     }
697
698     if (*p == ')') {
699       p++;
700     } else {
701       cppReader_error 
702         (pfile,
703          message ("Malformed option: -D%s (no closing parenthesis)", 
704                   cstring_fromChars (str)));
705     }
706   }
707
708   DPRINTF (("Here 2"));
709
710   if (*p == '\0')
711     {
712       buf = (char *) dmalloc (size_fromInt (p - str + 4));
713       strcpy ((char *) buf, str);
714       strcat ((char *) buf, " 1");
715     }
716   else if (*p != '=')
717     {
718       DPRINTF (("ERROR 2"));
719       cppReader_error (pfile,
720                        message ("Malformed option: -D%s (expected '=', found '%c')",
721                                 cstring_fromChars (str),
722                                 *p));
723       return;
724     }
725   else
726     {
727       char *q;
728       /* Copy the entire option so we can modify it.  */
729       DPRINTF (("Copying..."));
730       buf = (char *) dmalloc (2 * strlen (str) + 1);
731       strncpy (buf, str, size_fromInt (p - str));
732
733       /* Change the = to a space.  */
734       buf[p - str] = ' ';
735       /* Scan for any backslash-newline and remove it.  */
736       p++;
737       q = &buf[p - str];
738
739       while (*p != '\0')
740         {
741           if (*p == '\\' && p[1] == '\n')
742             p += 2;
743           else
744             *q++ = *p++;
745         }
746
747       DPRINTF (("Here we are..."));
748       *q = '\0';
749     }
750
751   llassert (buf != NULL);
752   DPRINTF (("Do define: %s / %ld", buf, size_toLong (strlen (buf))));
753   (void) do_define (pfile, NULL, buf, buf + strlen (buf));
754   sfree (buf);
755 }
756
757 /* Append a chain of `struct file_name_list's
758    to the end of the main include chain.
759    FIRST is gthe beginning of the chain to append, and LAST is the end.  */
760
761 void
762 cppReader_appendIncludeChain (cppReader *pfile,
763                       struct file_name_list *first,
764                       struct file_name_list *last)
765 {
766   struct cppOptions *opts = CPPOPTIONS (pfile);
767   struct file_name_list *dir;
768
769   if (first == NULL || last == NULL)
770     {
771       return;
772     }
773
774   if (opts->include == 0)
775     {
776       opts->include = first;
777     }
778   else
779     {
780       llassert (opts->last_include->next == NULL);
781       opts->last_include->next = first;
782     }
783
784   if (opts->first_bracket_include == 0)
785     {
786       opts->first_bracket_include = first;
787
788       for (dir = first; ; dir = dir->next) {
789         int len = cstring_length (dir->fname) + INCLUDE_LEN_FUDGE;
790         if (len > pfile->max_include_len)
791           pfile->max_include_len = len;
792         if (dir == last)
793           break;
794       }
795     }
796
797   llassert (last->next == NULL);
798   /* last->next = NULL; */
799   opts->last_include = last;
800 }
801
802 static /*@unused@*/ void 
803 cppReader_showIncludeChain (cppReader *pfile)
804 {
805   struct file_name_list *dirs = CPPOPTIONS (pfile)->include;
806
807   if (dirs != NULL)
808     {
809       while (dirs != NULL)
810         {
811           fprintf (stderr, "*%s*:", cstring_toCharsSafe (dirs->fname));
812           dirs = dirs->next;
813         }
814
815       fprintf (stderr, "\n");
816     }
817   else
818     {
819       fprintf (stderr, "No includes\n");
820     }
821 }
822
823 cstring 
824 cppReader_getIncludePath ()
825 {
826   cppReader *pfile = &g_cppState;
827   struct file_name_list *dirs = CPPOPTIONS (pfile)->include;
828   cstring res = cstring_undefined;
829
830   if (dirs != NULL)
831     {
832       while (dirs != NULL)
833         {
834           res = message ("%q%c%s", res, PATH_SEPARATOR, dirs->fname);
835           dirs = dirs->next;
836         }
837     }
838   else
839     {
840       res = cstring_makeLiteral ("<no include path>");
841     }
842
843   return res;
844 }
845
846 void
847 cppReader_addIncludeChain (cppReader *pfile, struct file_name_list *dir)
848 {
849   struct cppOptions *opts = CPPOPTIONS (pfile);
850
851   if (dir == 0)
852     {
853       return;
854     }
855
856   if (opts->include == 0)
857     {
858       opts->include = dir;
859     }
860   else
861     {
862       llassert (opts->last_include->next == NULL);
863       opts->last_include->next = dir;
864     }
865
866   if (opts->first_bracket_include == 0)
867     {
868       int len = cstring_length (dir->fname) + INCLUDE_LEN_FUDGE;
869       opts->first_bracket_include = dir;
870       if (len > pfile->max_include_len)
871         {
872           pfile->max_include_len = len;
873         }
874     }
875
876   dir->next = NULL;
877   opts->last_include = dir;
878   /* cppReader_showIncludeChain (pfile); */
879 }
880
881 /* Given a colon-separated list of file names PATH,
882    add all the names to the search path for include files.  */
883
884 static void
885 path_include (cppReader *pfile, char *path)
886 {
887   char *p;
888
889 #ifdef __CYGWIN32__
890   char *win32temp;
891
892   /* if we have a posix path list, convert to win32 path list */
893   win32temp = (char *) dmalloc /*@i4@*/
894     (cygwin32_posix_to_win32_path_list_buf_size (path));
895   cygwin32_posix_to_win32_path_list (path, win32temp);
896   path = win32temp;
897 #endif
898
899   p = path;
900
901   if (*p != '\0')
902     while (1) {
903       char *q = p;
904       char *name;
905       struct file_name_list *dirtmp;
906
907       /* Find the end of this name.  */
908       while (*q != '\0' && *q != PATH_SEPARATOR)
909         {
910           q++;
911         }
912
913       if (p == q)
914         {
915           /* An empty name in the path stands for the current directory.  */
916           name = (char *) dmalloc ((size_t) 2);
917           name[0] = '.';
918           name[1] = '\0';
919         }
920       else
921         {
922           /* Otherwise use the directory that is named.  */
923           name = (char *) dmalloc (size_fromInt (q - p + 1));
924           memcpy (name, p, size_fromInt (q - p));
925           name[q - p] = '\0';
926         }
927
928       dirtmp = (struct file_name_list *) dmalloc (sizeof (*dirtmp));
929       dirtmp->next = 0;         /* New one goes on the end */
930       dirtmp->control_macro = 0;
931       dirtmp->c_system_include_path = 0;
932       dirtmp->fname = cstring_fromChars (name);
933       dirtmp->got_name_map = 0;
934       cppReader_addIncludeChain (pfile, dirtmp);
935
936       /* Advance past this name.  */
937       p = q;
938       if (*p == '\0')
939         break;
940       /* Skip the colon.  */
941       p++;
942     }
943 }
944
945 void
946 cppOptions_init (cppOptions *opts)
947 {
948   memset ((char *) opts, 0, sizeof *opts);
949   assertSet (opts);
950
951   opts->in_fname = NULL;
952   opts->out_fname = NULL;
953
954   /* Initialize is_idchar to allow $.  */
955   opts->dollars_in_ident = TRUE;
956
957   opts->no_line_commands = 0;
958   opts->no_trigraphs = TRUE;
959   opts->put_out_comments = 1;
960   opts->print_include_names = 0;
961   opts->dump_macros = DUMP_DEFINITIONS; /* DUMP_NONE; */
962   opts->no_output = 0;
963   opts->cplusplus = 0;
964
965   opts->cplusplus_comments = 1;
966   opts->verbose = 0;
967   opts->lang_asm = 0;
968   opts->for_lint = 0;
969   opts->chill = 0;
970   opts->pedantic_errors = 0;
971   opts->warn_comments = 0;
972   opts->warnings_are_errors = 0;
973
974   initialize_char_syntax (opts);
975 }
976
977 enum cpp_token
978 cppReader_nullUnderflow (/*@unused@*/ cppReader *pfile)
979 {
980   return CPP_EOF;
981 }
982
983 void
984 cppReader_nullCleanup (/*@unused@*/ cppBuffer *pbuf,
985               /*@unused@*/ cppReader *pfile)
986 {
987   ;
988 }
989
990 void
991 cppReader_macroCleanup (cppBuffer *pbuf, /*@unused@*/ cppReader *pfile)
992 {
993   hashNode macro = pbuf->hnode;
994
995   if (macro->type == T_DISABLED)
996     {
997       macro->type = T_MACRO;
998     }
999
1000   if (macro->type != T_MACRO || pbuf->buf != macro->value.defn->expansion)
1001     {
1002       sfree (pbuf->buf);
1003       pbuf->buf = NULL;
1004     }
1005 }
1006
1007 void
1008 cppReader_fileCleanup (cppBuffer *pbuf, /*@unused@*/ cppReader *pfile)
1009 {
1010   if (pbuf->buf != NULL)
1011     {
1012       sfree (pbuf->buf);
1013       pbuf->buf = NULL;
1014     }
1015 }
1016
1017 /* Assuming we have read '/'.
1018    If this is the start of a comment (followed by '*' or '/'),
1019    skip to the end of the comment, and return ' '.
1020    Return EOF if we reached the end of file before the end of the comment.
1021    If not the start of a comment, return '/'.  */
1022
1023 static int
1024 skip_comment (cppReader *pfile, /*@null@*/ long *linep)
1025 {
1026   int c = 0;
1027
1028   llassert (pfile->buffer != NULL);
1029   llassert (pfile->buffer->cur != NULL);
1030
1031   while (cppReader_peekC (pfile) == '\\' && cpp_peekN (pfile, 1) == '\n')
1032     {
1033       if (linep != NULL)
1034         {
1035           (*linep)++;
1036         }
1037
1038       cppReader_forward (pfile, 2);
1039     }
1040
1041   if (cppReader_peekC (pfile) == '*')
1042     {
1043       cppReader_forward (pfile, 1);
1044
1045       for (;;)
1046         {
1047           int prev_c = c;
1048           c = cppReader_getC (pfile);
1049
1050           if (c == EOF)
1051             {
1052               return EOF;
1053             }
1054
1055           while (c == (int) '\\' && cppReader_peekC (pfile) == (int) '\n')
1056             {
1057               if (linep != NULL )
1058                 {
1059                   (*linep)++;
1060                 }
1061
1062               cppReader_forward (pfile, 1), c = cppReader_getC (pfile);
1063             }
1064
1065           if (prev_c == (int) '*' && c == (int) '/')
1066             {
1067               return (int) ' ';
1068             }
1069
1070           if (c == (int) '\n' && (linep != NULL))
1071             {
1072               (*linep)++;
1073             }
1074         }
1075     }
1076   else if (cppReader_peekC (pfile) == '/' 
1077            && CPPOPTIONS (pfile)->cplusplus_comments)
1078     {
1079       cppReader_forward (pfile, 1);
1080
1081       for (;;)
1082         {
1083           c = cppReader_getC (pfile);
1084
1085           if (c == EOF)
1086             {
1087               /* Allow hash comment to be terminated by EOF.  */
1088               return (int) ' '; 
1089             }
1090
1091           while (c == (int) '\\' && cppReader_peekC (pfile) == '\n')
1092             {
1093               cppReader_forward (pfile, 1);
1094               c = cppReader_getC (pfile);
1095
1096               if (linep != NULL)
1097                 {
1098                   (*linep)++;
1099                 }
1100             }
1101
1102           if (c == (int) '\n')
1103             {
1104               /* Don't consider final '\n' to be part of comment.  */
1105               cppReader_forward (pfile, -1);
1106               return (int) ' ';
1107             }
1108         }
1109     }
1110   else
1111     {
1112       return (int) '/';
1113     }
1114 }
1115
1116 /* Skip whitespace \-newline and comments.  Does not macro-expand.  */
1117 int /*@alt void@*/
1118 cppSkipHspace (cppReader *pfile)
1119 {
1120   int nspaces = 0;
1121
1122   while (TRUE)
1123     {
1124       int c;
1125
1126       llassert (pfile->buffer != NULL);
1127
1128       c = cppReader_peekC (pfile);
1129
1130       if (c == EOF)
1131         {
1132           return 0; /* FIXME */
1133         }
1134
1135       if (is_hor_space[c])
1136         {
1137           if ((c == '\f' || c == '\v') && cppReader_isPedantic (pfile))
1138             cppReader_pedwarn (pfile,
1139                          message ("%s in preprocessing directive",
1140                                   c == '\f'
1141                                   ? cstring_makeLiteralTemp ("formfeed")
1142                                   : cstring_makeLiteralTemp ("vertical tab")));
1143
1144           nspaces++;
1145           cppReader_forward (pfile, 1);
1146         }
1147       else if (c == '/')
1148         {
1149           cppReader_forward (pfile, 1);
1150           c = skip_comment (pfile, NULL);
1151
1152           if (c == '/')
1153             {
1154               cppReader_forward (pfile, -1);
1155             }
1156
1157           if (c == EOF || c == '/')
1158             {
1159               return nspaces;
1160             }
1161         }
1162       else if (c == '\\' && cpp_peekN (pfile, 1) == '\n')
1163         {
1164           cppReader_forward (pfile, 2);
1165         }
1166       else if (c == '@' && CPPBUFFER (pfile)->has_escapes
1167                && is_hor_space [cpp_peekN (pfile, 1)])
1168         {
1169           cppReader_forward (pfile, 2);
1170         }
1171       else
1172         {
1173           return nspaces;
1174         }
1175     }
1176 }
1177
1178 /* Read the rest of the current line.
1179    The line is appended to PFILE's output buffer.  */
1180
1181 static void
1182 copy_rest_of_line (cppReader *pfile)
1183 {
1184   struct cppOptions *opts = CPPOPTIONS (pfile);
1185
1186   for (;;)
1187     {
1188       int c;
1189       int nextc;
1190
1191       llassert (pfile->buffer != NULL);
1192
1193       c = cppReader_getC (pfile);
1194       switch (c)
1195         {
1196         case EOF:
1197           goto end_directive;
1198         case '\\':
1199           if (cppReader_peekC (pfile) == '\n')
1200             {
1201               cppReader_forward (pfile, 1);
1202               continue;
1203             }
1204
1205         /*@fallthrough@*/ case '\'': case '\"':
1206           goto scan_directive_token;
1207
1208         case '/':
1209           nextc = cppReader_peekC (pfile);
1210
1211           /*
1212           ** was (opts->cplusplus_comments && nextc == '*')
1213           ** yoikes!
1214           */
1215
1216           if (nextc == '*'
1217               || (opts->cplusplus_comments && nextc == '/'))
1218             {
1219               goto scan_directive_token;
1220             }
1221           /*@switchbreak@*/ break;
1222         case '\f':
1223         case '\v':
1224           if (cppReader_isPedantic (pfile))
1225             cppReader_pedwarn (pfile,
1226                          message ("%s in preprocessing directive",
1227                                   c == '\f'
1228                                   ? cstring_makeLiteralTemp ("formfeed")
1229                                   : cstring_makeLiteralTemp ("vertical tab")));
1230           /*@switchbreak@*/ break;
1231
1232         case '\n':
1233           cppReader_forward (pfile, -1);
1234           goto end_directive;
1235         scan_directive_token:
1236           cppReader_forward (pfile, -1);
1237           (void) cppGetToken (pfile);
1238           continue;
1239         }
1240       cppReader_putChar (pfile, c);
1241     }
1242 end_directive: ;
1243   cppReader_nullTerminate (pfile);
1244 }
1245
1246 void
1247 cppReader_skipRestOfLine (cppReader *pfile)
1248 {
1249   size_t old = cppReader_getWritten (pfile);
1250   copy_rest_of_line (pfile);
1251   cppReader_setWritten (pfile, old);
1252 }
1253
1254 /* Handle a possible # directive.
1255    '#' has already been read.  */
1256
1257 int
1258 cppReader_handleDirective (cppReader *pfile)
1259 {
1260   int c;
1261   struct directive *kt = NULL;
1262   int ident_length;
1263   size_t after_ident = 0;
1264   char *ident, *line_end = NULL;
1265   size_t old_written = cppReader_getWritten (pfile);
1266   int nspaces = cppSkipHspace (pfile);
1267
1268   c = cppReader_peekC (pfile);
1269
1270   if (c >= '0' && c <= '9')
1271     {
1272       /* Handle # followed by a line number.  */
1273       if (cppReader_isPedantic (pfile))
1274         {
1275           cppReader_pedwarnLit
1276             (pfile,
1277              cstring_makeLiteralTemp ("`#' followed by integer"));
1278         }
1279
1280       (void) do_line (pfile, NULL);
1281       goto done_a_directive;
1282     }
1283
1284
1285   /* Now find the directive name.  */
1286
1287   cppReader_putChar (pfile, '#');
1288
1289   parse_name (pfile, cppReader_getC (pfile));
1290
1291   llassert (pfile->token_buffer != NULL);
1292   ident = pfile->token_buffer + old_written + 1;
1293
1294   ident_length = cppReader_getPWritten (pfile) - ident;
1295
1296   if (ident_length == 0 && cppReader_peekC (pfile) == '\n')
1297     {
1298       /* A line of just `#' becomes blank.  */
1299       return 1; 
1300     }
1301
1302   for (kt = directive_table; ; kt++) 
1303     {
1304       if (kt->length <= 0)
1305         {
1306           return 0; /* goto not_a_directive; */
1307         }
1308
1309       if (kt->length == ident_length
1310           && (cstring_equalPrefix (kt->name, ident)))
1311         {
1312           break;
1313         }
1314     }
1315
1316   if (kt->command_reads_line)
1317     {
1318       after_ident = 0;
1319     }
1320   else
1321     {
1322       /* Nonzero means do not delete comments within the directive.
1323          #define needs this when -traditional.  */
1324       bool comments = 1; /*cppReader_isTraditional (pfile) && kt->traditional_comments;  */
1325       int save_put_out_comments = CPPOPTIONS (pfile)->put_out_comments;
1326       CPPOPTIONS (pfile)->put_out_comments = comments;
1327       after_ident = cppReader_getWritten (pfile);
1328       copy_rest_of_line (pfile);
1329       CPPOPTIONS (pfile)->put_out_comments = save_put_out_comments;
1330     }
1331
1332
1333   /* For #pragma and #define, we may want to pass through the directive.
1334      Other directives may create output, but we don't want the directive
1335      itself out, so we pop it now.  For example #include may write a #line
1336      command (see comment in do_include), and conditionals may emit
1337      #failed ... #endfailed stuff.  But note that popping the buffer
1338      means the parameters to kt->func may point after pfile->limit
1339      so these parameters are invalid as soon as something gets appended
1340      to the token_buffer.  */
1341
1342   line_end = cppReader_getPWritten (pfile);
1343
1344
1345   if (!kt->pass_thru && kt->type != T_DEFINE)
1346     {
1347       cppReader_setWritten (pfile, old_written);
1348     }
1349
1350   llassert (pfile->token_buffer != NULL);
1351
1352   /* was kt->pass_thru || */
1353
1354   if (kt->type == T_DEFINE
1355       && cpp_shouldCheckMacro (pfile, pfile->token_buffer + old_written))
1356     {
1357       char *p = pfile->token_buffer + old_written;
1358
1359       /*
1360       ** Still need to record value for preprocessing, so 
1361       ** #ifdef's, etc. using the value behave correctly.
1362       */
1363       
1364       (void) do_defineAux (pfile, kt, 
1365                            pfile->token_buffer + after_ident,
1366                            line_end,
1367                            TRUE);
1368       
1369       if (*p == '#')
1370         {
1371           *p = ' ';
1372         }
1373
1374       SKIP_WHITE_SPACE (p);
1375
1376       llassert (*p == 'd');
1377       *p++ = LLMRCODE[0];
1378
1379       llassert (*p == 'e');
1380       *p++ = LLMRCODE[1];
1381
1382       llassert (*p == 'f');
1383       *p++ = LLMRCODE[2];
1384
1385       llassert (*p == 'i');
1386       *p++ = LLMRCODE[3];
1387
1388       llassert (*p == 'n');
1389       *p++ = LLMRCODE[4];
1390
1391       llassert (*p == 'e');
1392
1393       /*
1394       ** This is way-bogus.  We use the last char to record the number of
1395       ** spaces.  Its too hard to get them back into the input stream.
1396       */
1397
1398       if (nspaces > 9) nspaces = 9;
1399
1400       *p++ = '0' + nspaces;
1401
1402       return 0; /* not_a_directive */
1403     }
1404   else if (kt->pass_thru)
1405     {
1406       /* Just leave the entire #define in the output stack.  */
1407       return 0; /* not_a_directive */
1408
1409     }
1410   else if (kt->type == T_DEFINE
1411            && CPPOPTIONS (pfile)->dump_macros == DUMP_NAMES)
1412     {
1413       char *p = pfile->token_buffer + old_written + 7;  /* Skip "#define". */
1414       SKIP_WHITE_SPACE (p);
1415
1416       while (is_idchar[(int) *p])
1417         {
1418           p++;
1419         }
1420
1421       pfile->limit = p;
1422       cppReader_putChar (pfile, '\n');
1423     }
1424   else if (kt->type == T_DEFINE)
1425     {
1426       cppReader_setWritten (pfile, old_written);
1427     }
1428   else
1429     {
1430       ;
1431     }
1432
1433 done_a_directive:
1434   if (kt == NULL) {
1435     return 1;
1436   } else {
1437     llassert (kt->func != NULL);
1438     (void) (kt->func) (pfile, kt, pfile->token_buffer + after_ident, line_end);
1439     return 1;
1440   }
1441 }
1442
1443 /* Pass a directive through to the output file.
1444    BUF points to the contents of the directive, as a contiguous string.
1445    LIMIT points to the first character past the end of the directive.
1446    KEYWORD is the keyword-table entry for the directive.  */
1447
1448 static void
1449 pass_thru_directive (char *buf, char *limit,
1450                      cppReader *pfile,
1451                      struct directive *keyword)
1452 {
1453   int keyword_length = keyword->length;
1454
1455   cppReader_reserve (pfile,
1456                      size_fromInt (2 + keyword_length + (limit - buf)));
1457   cppReader_putCharQ (pfile, '#');
1458   /*@-observertrans@*/
1459   cppReader_putStrN (pfile, cstring_toCharsSafe (keyword->name),
1460                      size_fromInt (keyword_length));
1461   /*:=observertrans@*/
1462
1463   if (limit != buf && buf[0] != ' ')
1464     {
1465       /* Was a bug, since reserve only used 1 + ... */
1466       cppReader_putCharQ (pfile, ' ');
1467     }
1468
1469   cppReader_putStrN (pfile, buf, size_fromInt (limit - buf));
1470 }
1471
1472 /* Read a replacement list for a macro with parameters.
1473    Build the DEFINITION structure.
1474    Reads characters of text starting at BUF until END.
1475    ARGLIST specifies the formal parameters to look for
1476    in the text of the definition; NARGS is the number of args
1477    in that list, or -1 for a macro name that wants no argument list.
1478    MACRONAME is the macro name itself (so we can avoid recursive expansion)
1479    and NAMELEN is its length in characters.
1480
1481    Note that comments, backslash-newlines, and leading white space
1482    have already been deleted from the argument.  */
1483
1484 static DEFINITION *
1485 collect_expansion (cppReader *pfile, char *buf, char *limit,
1486                    int nargs, /*@null@*/ struct arglist *arglist)
1487 {
1488   DEFINITION *defn;
1489   char *p, *lastp, *exp_p;
1490   struct reflist *endpat = NULL;
1491   /* Pointer to first nonspace after last ## seen.  */
1492   char *concat = 0;
1493   /* Pointer to first nonspace after last single-# seen.  */
1494   char *stringify = 0;
1495   size_t maxsize;
1496   char expected_delimiter = '\0';
1497
1498
1499   /* Scan thru the replacement list, ignoring comments and quoted
1500      strings, picking up on the macro calls.  It does a linear search
1501      thru the arg list on every potential symbol.  Profiling might say
1502      that something smarter should happen.  */
1503
1504   if (limit < buf)
1505     abort ();
1506
1507   /* Find the beginning of the trailing whitespace.  */
1508   p = buf;
1509
1510   while (p < limit && is_space[(int) limit[-1]])
1511     {
1512       limit--;
1513     }
1514
1515   /* Allocate space for the text in the macro definition.
1516      Leading and trailing whitespace chars need 2 bytes each.
1517      Each other input char may or may not need 1 byte,
1518      so this is an upper bound.  The extra 5 are for invented
1519      leading and trailing newline-marker and final null.  */
1520   maxsize = (sizeof (*defn) + (limit - p) + 5);
1521
1522   /* Occurrences of '@' get doubled, so allocate extra space for them.  */
1523   while (p < limit)
1524     {
1525       if (*p++ == '@')
1526         {
1527           maxsize++;
1528         }
1529     }
1530
1531   defn = (DEFINITION *) dmalloc (maxsize);
1532   defn->noExpand = FALSE;
1533   defn->file = NULL;
1534   defn->pattern = NULL;
1535   defn->nargs = nargs;
1536   defn->predefined = NULL;
1537
1538   exp_p = defn->expansion = (char *) defn + sizeof (*defn);
1539
1540   defn->line = 0;
1541   defn->rest_args = NULL;
1542   defn->args.argnames = NULL;
1543
1544   lastp = exp_p;
1545
1546   p = buf;
1547
1548   /* Add one initial space escape-marker to prevent accidental
1549      token-pasting (often removed by macroexpand).  */
1550   *exp_p++ = '@';
1551   *exp_p++ = ' ';
1552
1553   if (limit - p >= 2 && p[0] == '#' && p[1] == '#') {
1554     cppReader_errorLit (pfile,
1555                         cstring_makeLiteralTemp ("`##' at start of macro definition"));
1556     p += 2;
1557   }
1558
1559   /* Process the main body of the definition.  */
1560   while (p < limit) {
1561     int skipped_arg = 0;
1562     register char c = *p++;
1563
1564     *exp_p++ = c;
1565
1566     if (!cppReader_isTraditional (pfile)) {
1567       switch (c) {
1568       case '\'':
1569       case '\"':
1570         if (expected_delimiter != '\0')
1571           {
1572             if (c == expected_delimiter)
1573               expected_delimiter = '\0';
1574           }
1575         else
1576           {
1577             expected_delimiter = c;
1578           }
1579         /*@switchbreak@*/ break;
1580
1581       case '\\':
1582         if (p < limit && (expected_delimiter != '\0'))
1583           {
1584             /* In a string, backslash goes through
1585                and makes next char ordinary.  */
1586             *exp_p++ = *p++;
1587           }
1588         /*@switchbreak@*/ break;
1589
1590       case '@':
1591         /* An '@' in a string or character constant stands for itself,
1592            and does not need to be escaped.  */
1593         if (expected_delimiter == '\0')
1594           {
1595             *exp_p++ = c;
1596           }
1597
1598         /*@switchbreak@*/ break;
1599
1600       case '#':
1601         /* # is ordinary inside a string.  */
1602         if (expected_delimiter != '\0')
1603           {
1604             /*@switchbreak@*/ break;
1605           }
1606
1607         if (p < limit && *p == '#') {
1608           /* ##: concatenate preceding and following tokens.  */
1609           /* Take out the first #, discard preceding whitespace.  */
1610           exp_p--;
1611
1612           /*@-usedef@*/
1613           while (exp_p > lastp && is_hor_space[(int) exp_p[-1]])
1614             {
1615               --exp_p;
1616             }
1617           /*@=usedef@*/
1618
1619           /* Skip the second #.  */
1620           p++;
1621           /* Discard following whitespace.  */
1622           SKIP_WHITE_SPACE (p);
1623           concat = p;
1624           if (p == limit)
1625             {
1626               cppReader_errorLit (pfile,
1627                             cstring_makeLiteralTemp ("`##' at end of macro definition"));
1628             }
1629         } else if (nargs >= 0) {
1630           /* Single #: stringify following argument ref.
1631              Don't leave the # in the expansion.  */
1632           exp_p--;
1633           SKIP_WHITE_SPACE (p);
1634           if (p == limit || ! is_idstart[(int) *p]
1635               || (*p == 'L' && p + 1 < limit && (p[1] == '\'' || p[1] == '"')))
1636             cppReader_errorLit (pfile,
1637                           cstring_makeLiteralTemp ("`#' operator is not followed by a macro argument name"));
1638           else
1639             stringify = p;
1640         } else {
1641           ; /* BADBRANCH; */
1642         }
1643
1644         /*@switchbreak@*/ break;
1645       }
1646     } else {
1647       /* In -traditional mode, recognize arguments inside strings and
1648          and character constants, and ignore special properties of #.
1649          Arguments inside strings are considered "stringified", but no
1650          extra quote marks are supplied.  */
1651       switch (c) {
1652       case '\'':
1653       case '\"':
1654         if (expected_delimiter != '\0') {
1655           if (c == expected_delimiter)
1656             expected_delimiter = '\0';
1657         } else
1658           expected_delimiter = c;
1659         /*@switchbreak@*/ break;
1660
1661       case '\\':
1662         /* Backslash quotes delimiters and itself, but not macro args.  */
1663         if (expected_delimiter != '\0' && p < limit
1664             && (*p == expected_delimiter || *p == '\\')) {
1665           *exp_p++ = *p++;
1666           continue;
1667         }
1668         /*@switchbreak@*/ break;
1669
1670       case '/':
1671         if (expected_delimiter != '\0') /* No comments inside strings.  */
1672           /*@switchbreak@*/ break;
1673         if (*p == '*') {
1674           /* If we find a comment that wasn't removed by cppReader_handleDirective,
1675              this must be -traditional.  So replace the comment with
1676              nothing at all.  */
1677           exp_p--;
1678           p += 1;
1679           while (p < limit && !(p[-2] == '*' && p[-1] == '/'))
1680             {
1681               p++;
1682             }
1683         }
1684         /*@switchbreak@*/ break;
1685       }
1686     }
1687
1688     /* Handle the start of a symbol.  */
1689     if (is_idchar[(int) c] && nargs > 0) {
1690       char *id_beg = p - 1;
1691       int id_len;
1692
1693       --exp_p;
1694       while (p != limit && is_idchar[(int) *p])
1695         {
1696           p++;
1697         }
1698
1699       id_len = p - id_beg;
1700
1701       if (is_idstart[(int) c]
1702           && ! (id_len == 1 && c == 'L' && (*p == '\'' || *p == '"'))) {
1703         register struct arglist *arg;
1704
1705         for (arg = arglist; arg != NULL; arg = arg->next) {
1706           struct reflist *tpat;
1707
1708           if (arg->name[0] == c
1709               && arg->length == id_len
1710               && strncmp (arg->name, id_beg, size_fromInt (id_len)) == 0) {
1711             char *p1;
1712
1713             if (expected_delimiter && CPPOPTIONS (pfile)->warn_stringify) {
1714               if (cppReader_isTraditional (pfile)) {
1715                 cppReader_warning (pfile,
1716                                    message ("macro argument `%x' is stringified.",
1717                                             cstring_prefix (cstring_fromChars (arg->name), id_len)));
1718               } else {
1719                 cppReader_warning (pfile,
1720                                    message ("macro arg `%x' would be stringified with -traditional.",
1721                                             cstring_prefix (cstring_fromChars (arg->name), id_len)));
1722               }
1723             }
1724             /* If ANSI, don't actually substitute inside a string.  */
1725             if (!cppReader_isTraditional (pfile) && expected_delimiter)
1726               /*@innerbreak@*/ break;
1727             /* make a pat node for this arg and append it to the end of
1728                the pat list */
1729             tpat = (struct reflist *) dmalloc (sizeof (*tpat));
1730             tpat->next = NULL;
1731             tpat->raw_before = (concat == id_beg);
1732             tpat->raw_after = 0;
1733             tpat->rest_args = arg->rest_args;
1734             tpat->stringify = (cppReader_isTraditional (pfile)
1735                                ? expected_delimiter != '\0'
1736                                : stringify == id_beg);
1737
1738             if (endpat == NULL)
1739               {
1740                 defn->pattern = tpat;
1741               }
1742             else
1743               {
1744                 endpat->next = tpat;
1745                 /*@-branchstate@*/
1746               } /*@=branchstate@*/ /* evs 2000 was =branchstate */
1747
1748             endpat = tpat;
1749
1750             tpat->argno = arg->argno;
1751             tpat->nchars = exp_p - lastp;
1752
1753             p1 = p;
1754
1755             SKIP_WHITE_SPACE (p1);
1756
1757             if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#')
1758               {
1759                 tpat->raw_after = 1;
1760               }
1761
1762             lastp = exp_p;      /* place to start copying from next time */
1763             skipped_arg = 1;
1764
1765             /*@innerbreak@*/ break;
1766           }
1767         }
1768       }
1769
1770       /* If this was not a macro arg, copy it into the expansion.  */
1771       if (skipped_arg == 0) {
1772         register char *lim1 = p;
1773         p = id_beg;
1774
1775         while (p != lim1)
1776           {
1777             *exp_p++ = *p++;
1778           }
1779
1780         if (stringify == id_beg)
1781           cppReader_errorLit (pfile,
1782                               cstring_makeLiteralTemp ("`#' operator should be followed by a macro argument name"));
1783       }
1784     }
1785   }
1786
1787   if (!cppReader_isTraditional (pfile) && expected_delimiter == '\0')
1788     {
1789       /* If ANSI, put in a "@ " marker to prevent token pasting.
1790          But not if "inside a string" (which in ANSI mode
1791          happens only for -D option).  */
1792       *exp_p++ = '@';
1793       *exp_p++ = ' ';
1794     }
1795
1796   *exp_p = '\0';
1797
1798   defn->length = size_fromInt (exp_p - defn->expansion);
1799
1800   /* Crash now if we overrun the allocated size.  */
1801   if (defn->length + 1 > maxsize)
1802     {
1803       llfatalbug (cstring_makeLiteral ("Maximum definition size exceeded."));
1804     }
1805
1806   return defn;
1807 }
1808
1809 /*
1810  * special extension string that can be added to the last macro argument to
1811  * allow it to absorb the "rest" of the arguments when expanded.  Ex:
1812  *              #define wow(a, b...)            process (b, a, b)
1813  *              { wow (1, 2, 3); }      ->      { process (2, 3, 1, 2, 3); }
1814  *              { wow (one, two); }     ->      { process (two, one, two); }
1815  * if this "rest_arg" is used with the concat token '##' and if it is not
1816  * supplied then the token attached to with ## will not be outputted.  Ex:
1817  *              #define wow (a, b...)           process (b ## , a, ## b)
1818  *              { wow (1, 2); }         ->      { process (2, 1, 2); }
1819  *              { wow (one); }          ->      { process (one); {
1820  */
1821
1822 /*@-readonlytrans@*/
1823 static char rest_extension[] = "...";
1824 /*:=readonlytrans@*/
1825
1826 /*@notfunction@*/
1827 #define REST_EXTENSION_LENGTH   (sizeof (rest_extension) - 1)
1828
1829 /* Create a DEFINITION node from a #define directive.  Arguments are
1830    as for do_define.  */
1831
1832 static /*@null@*/ MACRODEF
1833 create_definition (char *buf, char *limit,
1834                    cppReader *pfile, bool predefinition,
1835                    bool noExpand)
1836 {
1837   char *bp;                     /* temp ptr into input buffer */
1838   char *symname;                /* remember where symbol name starts */
1839   int sym_length;               /* and how long it is */
1840   int rest_args = 0;   /* really int! */
1841   int line;
1842   int col;
1843   cstring file = (CPPBUFFER (pfile) != NULL)
1844     ? CPPBUFFER (pfile)->nominal_fname : cstring_makeLiteralTemp ("");
1845   DEFINITION *defn;
1846   int arglengths = 0;           /* Accumulate lengths of arg names
1847                                    plus number of args.  */
1848   MACRODEF mdef;
1849
1850   cppBuffer_lineAndColumn (CPPBUFFER (pfile), &line, &col);
1851
1852   bp = buf;
1853
1854   while (is_hor_space[(int) *bp])
1855     {
1856       bp++;
1857     }
1858
1859   symname = bp;                 /* remember where it starts */
1860
1861   sym_length = cppReader_checkMacroName (pfile, bp, cstring_makeLiteralTemp ("macro"));
1862
1863   bp += sym_length;
1864
1865   /* Lossage will occur if identifiers or control keywords are broken
1866      across lines using backslash.  This is not the right place to take
1867      care of that.  */
1868
1869   if (*bp == '(') {
1870     struct arglist *arg_ptrs = NULL;
1871     int argno = 0;
1872
1873     bp++;                       /* skip '(' */
1874     SKIP_WHITE_SPACE (bp);
1875
1876     /* Loop over macro argument names.  */
1877     while (*bp != ')')
1878       {
1879         struct arglist *temp = (struct arglist *) dmalloc (sizeof (*temp));
1880         temp->name = bp;
1881         temp->next = arg_ptrs;
1882         temp->argno = argno++;
1883         temp->rest_args = 0;
1884
1885         arg_ptrs = temp;
1886
1887         if (rest_args != 0)
1888           {
1889             cppReader_pedwarn (pfile,
1890                          message ("another parameter follows `%s'",
1891                                   cstring_fromChars (rest_extension)));
1892           }
1893
1894         if (!is_idstart[(int) *bp])
1895           {
1896             cppReader_pedwarnLit (pfile,
1897                             cstring_makeLiteralTemp ("invalid character in macro parameter name"));
1898           }
1899
1900         /* Find the end of the arg name.  */
1901         while (is_idchar[(int) *bp])
1902           {
1903             bp++;
1904             /* do we have a "special" rest-args extension here? */
1905             if (limit - bp > size_toInt (REST_EXTENSION_LENGTH)
1906                 && strncmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0)
1907               {
1908                 rest_args = 1;
1909                 temp->rest_args = 1;
1910                 /*@innerbreak@*/ break;
1911               }
1912           }
1913
1914         temp->length = bp - temp->name;
1915
1916         if (rest_args != 0)
1917           {
1918             bp += REST_EXTENSION_LENGTH;
1919           }
1920
1921         arglengths += temp->length + 2;
1922         SKIP_WHITE_SPACE (bp);
1923
1924         if (temp->length == 0 || (*bp != ',' && *bp != ')')) {
1925           cppReader_errorLit (pfile,
1926                         cstring_makeLiteralTemp ("Parameter list for #define is not parseable"));
1927           goto nope;
1928         }
1929
1930         if (*bp == ',') {
1931           bp++;
1932           SKIP_WHITE_SPACE (bp);
1933         }
1934         if (bp >= limit) {
1935           cppReader_errorLit (pfile,
1936                         cstring_makeLiteralTemp ("unterminated parameter list in `#define'"));
1937           goto nope;
1938         }
1939         {
1940           struct arglist *otemp;
1941
1942           for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
1943             {
1944               if (temp->length == otemp->length &&
1945                   strncmp (temp->name, otemp->name, size_fromInt (temp->length)) == 0) {
1946                 cstring name = cstring_copyLength (temp->name, temp->length);
1947                 cppReader_error (pfile,
1948                            message ("duplicate argument name `%x' in `#define'", name));
1949                 goto nope;
1950               }
1951             }
1952         }
1953       }
1954
1955     ++bp;                       /* skip paren */
1956     SKIP_WHITE_SPACE (bp);
1957     /* now everything from bp before limit is the definition.  */
1958     defn = collect_expansion (pfile, bp, limit, argno, arg_ptrs);
1959     defn->rest_args = rest_args;
1960     
1961     /* Now set defn->args.argnames to the result of concatenating
1962        the argument names in reverse order
1963        with comma-space between them.  */
1964     defn->args.argnames = (char *) dmalloc (size_fromInt (arglengths + 1));
1965
1966     {
1967       struct arglist *temp;
1968       int i = 0;
1969       for (temp = arg_ptrs; temp != NULL; temp = temp->next) {
1970         memcpy (&defn->args.argnames[i], temp->name, size_fromInt (temp->length));
1971         i += temp->length;
1972         if (temp->next != 0) {
1973           defn->args.argnames[i++] = ',';
1974           defn->args.argnames[i++] = ' ';
1975         }
1976       }
1977
1978       defn->args.argnames[i] = '\0';
1979     }
1980
1981     sfree (arg_ptrs);
1982   } else {
1983     /* Simple expansion or empty definition.  */
1984
1985     if (bp < limit)
1986       {
1987         if (is_hor_space[(int) *bp]) {
1988           bp++;
1989           SKIP_WHITE_SPACE (bp);
1990         } else {
1991           switch (*bp) {
1992           case '!':  case '"':  case '#':  case '%':  case '&':  case '\'':
1993           case ')':  case '*':  case '+':  case ',':  case '-':  case '.':
1994           case '/':  case ':':  case ';':  case '<':  case '=':  case '>':
1995           case '?':  case '[':  case '\\': case ']':  case '^':  case '{':
1996           case '|':  case '}':  case '~':
1997             cppReader_warning (pfile,
1998                          message ("Missing white space after #define %x",
1999                                   cstring_prefix (cstring_fromChars (symname),
2000                                                   sym_length)));
2001             break;
2002
2003           default:
2004             cppReader_pedwarn (pfile,
2005                          message ("Missing white space after #define %x",
2006                                   cstring_prefix (cstring_fromChars (symname),
2007                                                   sym_length)));
2008             break;
2009           }
2010         }
2011       }
2012     /* now everything from bp before limit is the definition.  */
2013     defn = collect_expansion (pfile, bp, limit, -1, NULL);
2014     defn->args.argnames = mstring_createEmpty ();
2015   }
2016
2017   defn->noExpand = noExpand;
2018   DPRINTF (("No expand: %d", noExpand));
2019
2020   defn->line = line;
2021
2022   /* not: llassert (cstring_isUndefined (defn->file)); */
2023   defn->file = file;
2024
2025   /* OP is null if this is a predefinition */
2026   defn->predefined = predefinition;
2027   mdef.defn = defn;
2028   mdef.symnam = symname;
2029   mdef.symlen = sym_length;
2030
2031   return mdef;
2032
2033 nope:
2034   mdef.defn = NULL;
2035   mdef.symnam = NULL;
2036   return mdef;
2037 }
2038
2039 /* Check a purported macro name SYMNAME, and yield its length.
2040    USAGE is the kind of name this is intended for.  */
2041
2042 int cppReader_checkMacroName (cppReader *pfile,
2043                       char *symname,
2044                       cstring usage)
2045 {
2046   char *p;
2047   size_t sym_length;
2048
2049   for (p = symname; is_idchar[(int) *p]; p++)
2050     {
2051       ;
2052     }
2053
2054   sym_length = size_fromInt (p - symname);
2055
2056   if (sym_length == 0
2057       || (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))
2058     cppReader_error (pfile, message ("invalid %s name", usage));
2059   else if (!is_idstart[(int) *symname])
2060     {
2061       char *msg = (char *) dmalloc (sym_length + 1);
2062       memcpy (msg, symname, sym_length);
2063       msg[sym_length] = '\0';
2064       cppReader_error (pfile, message ("invalid %s name `%s'", usage,
2065                                        cstring_fromChars (msg)));
2066       sfree (msg);
2067     }
2068   else
2069     {
2070       if ((strncmp (symname, "defined", 7) == 0) && sym_length == 7)
2071         {
2072           cppReader_error (pfile, message ("invalid %s name `defined'", usage));
2073         }
2074     }
2075
2076   return size_toInt (sym_length);
2077 }
2078
2079 /* Return zero if two DEFINITIONs are isomorphic.  */
2080
2081 static bool
2082 compare_defs (DEFINITION *d1, DEFINITION *d2)
2083 {
2084   register struct reflist *a1, *a2;
2085   register char *p1 = d1->expansion;
2086   register char *p2 = d2->expansion;
2087   bool first = TRUE;
2088
2089   if (d1->nargs != d2->nargs)
2090     {
2091       return TRUE;
2092     }
2093
2094   llassert (d1->args.argnames != NULL);
2095   llassert (d2->args.argnames != NULL);
2096
2097   if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames) != 0)
2098     {
2099       return TRUE;
2100     }
2101
2102   for (a1 = d1->pattern, a2 = d2->pattern;
2103        (a1 != NULL) && (a2 != NULL);
2104        a1 = a1->next, a2 = a2->next) {
2105     if (!((a1->nchars == a2->nchars
2106            && (strncmp (p1, p2, size_fromInt (a1->nchars)) == 0))
2107           || ! comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
2108         || a1->argno != a2->argno
2109         || a1->stringify != a2->stringify
2110         || a1->raw_before != a2->raw_before
2111         || a1->raw_after != a2->raw_after)
2112       return TRUE;
2113     first = 0;
2114     p1 += a1->nchars;
2115     p2 += a2->nchars;
2116   }
2117   if (a1 != a2)
2118     return TRUE;
2119
2120   if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
2121                      p2, d2->length - (p2 - d2->expansion), 1))
2122     return TRUE;
2123
2124   return FALSE;
2125 }
2126
2127 /* Return TRUE if two parts of two macro definitions are effectively different.
2128    One of the parts starts at BEG1 and has LEN1 chars;
2129    the other has LEN2 chars at BEG2.
2130    Any sequence of whitespace matches any other sequence of whitespace.
2131    FIRST means these parts are the first of a macro definition;
2132    so ignore leading whitespace entirely.
2133    LAST means these parts are the last of a macro definition;
2134    so ignore trailing whitespace entirely.  */
2135
2136 static bool
2137 comp_def_part (bool first, char *beg1, int len1, char *beg2, int len2, bool last)
2138 {
2139   char *end1 = beg1 + len1;
2140   char *end2 = beg2 + len2;
2141
2142   if (first) {
2143     while (beg1 != end1 && is_space[(int) *beg1]) { beg1++; }
2144     while (beg2 != end2 && is_space[(int) *beg2]) { beg2++; }
2145   }
2146   if (last) {
2147     while (beg1 != end1 && is_space[(int) end1[-1]]) { end1--; }
2148     while (beg2 != end2 && is_space[(int) end2[-1]]) { end2--; }
2149   }
2150   while (beg1 != end1 && beg2 != end2) {
2151     if (is_space[(int) *beg1] && is_space[(int) *beg2]) {
2152       while (beg1 != end1 && is_space[(int) *beg1]) { beg1++; }
2153       while (beg2 != end2 && is_space[(int) *beg2]) { beg2++; }
2154     } else if (*beg1 == *beg2) {
2155       beg1++; beg2++;
2156     } else break;
2157   }
2158   return (beg1 != end1) || (beg2 != end2);
2159 }
2160
2161 /* Process a #define command.
2162    BUF points to the contents of the #define command, as a contiguous string.
2163    LIMIT points to the first character past the end of the definition.
2164    KEYWORD is the keyword-table entry for #define,
2165    or NULL for a "predefined" macro.  */
2166
2167 static int
2168 do_defineAux (cppReader *pfile, struct directive *keyword,
2169               char *buf, char *limit, bool noExpand)
2170 {
2171   int hashcode;
2172   MACRODEF mdef;
2173   hashNode hp;
2174   
2175   DPRINTF (("Define aux: %d", noExpand));
2176
2177   mdef = create_definition (buf, limit, pfile, keyword == NULL, noExpand);
2178
2179   if (mdef.defn == 0)
2180     goto nope;
2181
2182   hashcode = hashf (mdef.symnam, mdef.symlen, CPP_HASHSIZE);
2183
2184   DPRINTF (("Macro: %s / %s", 
2185             cstring_copyLength (mdef.symnam, mdef.symlen),
2186             bool_unparse (noExpand)));
2187
2188   if ((hp = cppReader_lookup (mdef.symnam, mdef.symlen, hashcode)) != NULL)
2189     {
2190       bool ok = FALSE;
2191
2192       /* Redefining a precompiled key is ok.  */
2193       if (hp->type == T_PCSTRING)
2194         ok = TRUE;
2195       /* Redefining a macro is ok if the definitions are the same.  */
2196       else if (hp->type == T_MACRO)
2197         ok = !compare_defs (mdef.defn, hp->value.defn);
2198       /* Redefining a constant is ok with -D.  */
2199       else if (hp->type == T_CONST)
2200         ok = !CPPOPTIONS (pfile)->done_initializing;
2201       else {
2202         BADBRANCH;
2203       }
2204
2205       /* Print the warning if it's not ok.  */
2206       if (!ok)
2207         {
2208           /*
2209           ** If we are passing through #define and #undef directives, do
2210           ** that for this re-definition now.
2211           */
2212
2213           if (CPPOPTIONS (pfile)->debug_output && (keyword != NULL))
2214             {
2215               /* llassert (keyword != NULL); */
2216               pass_thru_directive (buf, limit, pfile, keyword);
2217             }
2218
2219           cpp_setLocation (pfile);
2220
2221           if (hp->type == T_MACRO)
2222             {
2223               if (hp->value.defn->noExpand)
2224                 {
2225                   ; /* error will be reported checking macros */
2226                 }
2227               else
2228                 {
2229                   genppllerrorhint
2230                     (FLG_MACROREDEF,
2231                      message ("Macro %q already defined",
2232                               cstring_copyLength (mdef.symnam, mdef.symlen)),
2233                      message ("%q: Previous definition of %q",
2234                               fileloc_unparseRaw (hp->value.defn->file,
2235                                                  (int) hp->value.defn->line),
2236                               cstring_copyLength (mdef.symnam, mdef.symlen)));
2237                 }
2238             }
2239           else
2240             {
2241               genppllerror (FLG_MACROREDEF,
2242                             message ("Macro %q already defined",
2243                                      cstring_copyLength (mdef.symnam,
2244                                                          mdef.symlen)));
2245
2246             }
2247         }
2248
2249       /* Replace the old definition.  */
2250       hp->type = T_MACRO;
2251       hp->value.defn = mdef.defn;
2252     }
2253   else
2254     {
2255       /*
2256       ** If we are passing through #define and #undef directives, do
2257       ** that for this new definition now.
2258       */
2259
2260       hashNode hn;
2261
2262       if (CPPOPTIONS (pfile)->debug_output && (keyword != NULL))
2263         {
2264           pass_thru_directive (buf, limit, pfile, keyword);
2265         }
2266
2267       DPRINTF (("Define macro: %s / %d", 
2268                 mdef.symnam, mdef.defn->noExpand));
2269       
2270       hn = cppReader_installMacro (mdef.symnam, mdef.symlen, mdef.defn, hashcode);
2271       /*@-branchstate@*/
2272     } /*@=branchstate@*/
2273
2274   return 0;
2275
2276 nope:
2277
2278   return 1;
2279 }
2280
2281 static int
2282 do_define (cppReader *pfile, struct directive *keyword,
2283            char *buf, char *limit)
2284 {
2285   DPRINTF (("Regular do define"));
2286   return do_defineAux (pfile, keyword, buf, limit, FALSE);
2287 }
2288
2289 /* This structure represents one parsed argument in a macro call.
2290    `raw' points to the argument text as written (`raw_length' is its length).
2291    `expanded' points to the argument's macro-expansion
2292    (its length is `expand_length').
2293    `stringified_length' is the length the argument would have
2294    if stringified.
2295    `use_count' is the number of times this macro arg is substituted
2296    into the macro.  If the actual use count exceeds 10,
2297    the value stored is 10.  */
2298
2299 /* raw and expanded are relative to ARG_BASE */
2300 /*@notfunction@*/
2301 #define ARG_BASE ((pfile)->token_buffer)
2302
2303 struct argdata {
2304   /* Strings relative to pfile->token_buffer */
2305   long raw;
2306   size_t expanded;
2307   size_t stringified;
2308   int raw_length;
2309   int expand_length;
2310   int stringified_length;
2311   bool newlines;
2312   int use_count;
2313 };
2314
2315 /* Allocate a new cppBuffer for PFILE, and push it on the input buffer stack.
2316    If BUFFER != NULL, then use the LENGTH characters in BUFFER
2317    as the new input buffer.
2318    Return the new buffer, or NULL on failure.  */
2319
2320 /*@null@*/ /*@exposed@*/ cppBuffer *
2321 cppReader_pushBuffer (cppReader *pfile, char *buffer, size_t length)
2322 {
2323   cppBuffer *buf = cppReader_getBuffer (pfile);
2324
2325   if (buf == pfile->buffer_stack)
2326     {
2327       cppReader_fatalError
2328         (pfile,
2329          message ("%s: macro or `#include' recursion too deep",
2330                   (buf->fname != NULL)
2331                   ? buf->fname
2332                   : cstring_makeLiteral ("<no name>")));
2333       sfreeEventually (buffer);
2334       return NULL;
2335     }
2336
2337   llassert (buf != NULL);
2338
2339   buf--;
2340   memset ((char *) buf, 0, sizeof (*buf));
2341   CPPBUFFER (pfile) = buf;
2342
2343   buf->if_stack = pfile->if_stack;
2344   buf->cleanup = cppReader_nullCleanup;
2345   buf->underflow = cppReader_nullUnderflow;
2346   buf->buf = buffer;
2347   buf->cur = buf->buf;
2348
2349   if (buffer != NULL)
2350     {
2351       buf->alimit = buf->rlimit = buffer + length;
2352     }
2353   else
2354     {
2355       buf->alimit = buf->rlimit = NULL;
2356     }
2357
2358   return buf;
2359 }
2360
2361 cppBuffer *
2362 cppReader_popBuffer (cppReader *pfile)
2363 {
2364   cppBuffer *buf = CPPBUFFER (pfile);
2365
2366   llassert (buf != NULL);
2367
2368   (void) (*buf->cleanup) (buf, pfile);
2369   return ++CPPBUFFER (pfile);
2370 }
2371
2372 /* Scan until CPPBUFFER (PFILE) is exhausted into PFILE->token_buffer.
2373    Pop the buffer when done.  */
2374
2375 void
2376 cppReader_scanBuffer (cppReader *pfile)
2377 {
2378   cppBuffer *buffer = CPPBUFFER (pfile);
2379   for (;;)
2380     {
2381       enum cpp_token token;
2382       
2383       token = cppGetToken (pfile);
2384
2385       if (token == CPP_EOF) /* Should not happen ...  */
2386         {
2387           break;
2388         }
2389
2390       if (token == CPP_POP && CPPBUFFER (pfile) == buffer)
2391         {
2392           (void) cppReader_popBuffer (pfile);
2393           break;
2394         }
2395     }
2396 }
2397
2398 /*
2399  * Rescan a string (which may have escape marks) into pfile's buffer.
2400  * Place the result in pfile->token_buffer.
2401  *
2402  * The input is copied before it is scanned, so it is safe to pass
2403  * it something from the token_buffer that will get overwritten
2404  * (because it follows cppReader_getWritten).  This is used by do_include.
2405  */
2406
2407 static void
2408 cpp_expand_to_buffer (cppReader *pfile, char *buf, size_t length)
2409 {
2410   register cppBuffer *ip;
2411   char *limit = buf + length;
2412   char *buf1, *p1, *p2;
2413
2414   if (length < 0)
2415     abort ();
2416
2417   /* Set up the input on the input stack.  */
2418
2419   buf1 = (char *) dmalloc (length + 1);
2420
2421   p1 = buf;
2422   p2 = buf1;
2423
2424   while (p1 != limit)
2425     {
2426       *p2++ = *p1++;
2427     }
2428
2429   buf1[length] = '\0';
2430
2431   ip = cppReader_pushBuffer (pfile, buf1, length);
2432
2433   if (ip == NULL)
2434     return;
2435
2436   ip->has_escapes = TRUE;
2437
2438   /* Scan the input, create the output.  */
2439   cppReader_scanBuffer (pfile);
2440
2441   cppReader_nullTerminate (pfile);
2442 }
2443
2444 static void
2445 adjust_position (char *buf, char *limit, int *linep, int *colp)
2446 {
2447   while (buf < limit)
2448     {
2449       char ch = *buf++;
2450       if (ch == '\n')
2451         (*linep)++, (*colp) = 1;
2452       else
2453         (*colp)++;
2454     }
2455 }
2456
2457 /* Move line_base forward, updating lineno and colno.  */
2458
2459 static void
2460 update_position (cppBuffer *pbuf)
2461 {
2462   char *old_pos;
2463   char *new_pos = pbuf->cur;
2464   register struct parse_marker *mark;
2465
2466   llassert (pbuf->buf != NULL);
2467   old_pos = pbuf->buf + pbuf->line_base;
2468
2469   for (mark = pbuf->marks;  mark != NULL; mark = mark->next)
2470     {
2471       if (pbuf->buf + mark->position < new_pos)
2472         new_pos = pbuf->buf + mark->position;
2473     }
2474   pbuf->line_base += new_pos - old_pos;
2475
2476   llassert (old_pos != NULL);
2477   llassert (new_pos != NULL);
2478
2479   adjust_position (old_pos, new_pos, &pbuf->lineno, &pbuf->colno);
2480 }
2481
2482 void
2483 cppBuffer_lineAndColumn (/*@null@*/ cppBuffer *pbuf, /*@out@*/ int *linep,
2484                          /*@null@*/ /*@out@*/ int *colp)
2485 {
2486   int dummy;
2487
2488   if (colp == NULL)
2489     {
2490       colp = &dummy;
2491       /*@-branchstate@*/
2492     } /*@=branchstate@*/
2493
2494   if (pbuf != NULL)
2495     {
2496       *linep = pbuf->lineno;
2497       *colp = pbuf->colno;
2498
2499       llassert (pbuf->buf != NULL);
2500       llassert (pbuf->cur != NULL);
2501
2502       adjust_position (pbuf->buf + pbuf->line_base, pbuf->cur, linep, colp);
2503     }
2504   else
2505     {
2506       *linep = 0;
2507       *colp = 0;
2508     }
2509 }
2510
2511 /* Return the cppBuffer that corresponds to a file (not a macro).  */
2512
2513 /*@exposed@*/ /*@null@*/ cppBuffer *cppReader_fileBuffer (cppReader *pfile)
2514 {
2515   cppBuffer *ip = cppReader_getBuffer (pfile);
2516
2517   for ( ;
2518         ip != NULL && ip != cppReader_nullBuffer (pfile); 
2519         ip = cppBuffer_prevBuffer (ip))
2520     {
2521       if (ip->fname != NULL)
2522         {
2523           return ip;
2524         }
2525     }
2526   
2527   return NULL;
2528 }
2529
2530 static long
2531 count_newlines (char *buf, char *limit)
2532 {
2533   register long count = 0;
2534
2535   while (buf < limit)
2536     {
2537       char ch = *buf++;
2538       if (ch == '\n')
2539         count++;
2540     }
2541   return count;
2542 }
2543
2544 /*
2545  * write out a #line command, for instance, after an #include file.
2546  * If CONDITIONAL is nonzero, we can omit the #line if it would
2547  * appear to be a no-op, and we can output a few newlines instead
2548  * if we want to increase the line number by a small amount.
2549  * FILE_CHANGE says whether we are entering a file, leaving, or neither.
2550  */
2551
2552 static void
2553 output_line_command (cppReader *pfile, bool conditional,
2554                      enum file_change_code file_change)
2555 {
2556   int line, col;
2557   cppBuffer *ip = CPPBUFFER (pfile);
2558   cppBuffer *buf;
2559
2560   llassert (ip != NULL);
2561
2562   if (ip->fname == NULL)
2563     return;
2564
2565   update_position (ip);
2566
2567   if (CPPOPTIONS (pfile)->no_line_commands
2568       || CPPOPTIONS (pfile)->no_output)
2569     return;
2570
2571   buf = CPPBUFFER (pfile);
2572
2573   llassert (buf != NULL);
2574
2575   line = buf->lineno;
2576   col = buf->colno;
2577
2578   llassert (ip->cur != NULL);
2579
2580   adjust_position (cppLineBase (ip), ip->cur, &line, &col);
2581
2582   if (CPPOPTIONS (pfile)->no_line_commands)
2583     return;
2584
2585   if (conditional) {
2586     if (line == pfile->lineno)
2587       return;
2588
2589     /* If the inherited line number is a little too small,
2590        output some newlines instead of a #line command.  */
2591
2592     if (line > pfile->lineno && line < pfile->lineno + 8)
2593       {
2594         cppReader_reserve (pfile, 20);
2595         while (line > pfile->lineno)
2596           {
2597             cppReader_putCharQ (pfile, '\n');
2598             pfile->lineno++;
2599           }
2600
2601         return;
2602       }
2603   }
2604
2605   cppReader_reserve (pfile,
2606                      size_fromInt (4 * cstring_length (ip->nominal_fname) + 50));
2607
2608   {
2609 #ifdef OUTPUT_LINE_COMMANDS
2610     static char sharp_line[] = "#line ";
2611 #else
2612     static char sharp_line[] = "# ";
2613 #endif
2614     cppReader_putStrN (pfile, sharp_line, sizeof(sharp_line)-1);
2615   }
2616
2617   sprintf (cppReader_getPWritten (pfile), "%d ", line);
2618   cppReader_adjustWritten (pfile, strlen (cppReader_getPWritten (pfile)));
2619
2620   quote_string (pfile, cstring_toCharsSafe (ip->nominal_fname));
2621
2622   if (file_change != same_file) {
2623     cppReader_putCharQ (pfile, ' ');
2624     cppReader_putCharQ (pfile, file_change == enter_file ? '1' : '2');
2625   }
2626   /* Tell cc1 if following text comes from a system header file.  */
2627   if (ip->system_header_p != '\0') {
2628     cppReader_putCharQ (pfile, ' ');
2629     cppReader_putCharQ (pfile, '3');
2630   }
2631 #ifndef NO_IMPLICIT_EXTERN_C
2632   /* Tell cc1plus if following text should be treated as C.  */
2633   if (ip->system_header_p == (char) 2 && CPPOPTIONS (pfile)->cplusplus) {
2634     cppReader_putCharQ (pfile, ' ');
2635     cppReader_putCharQ (pfile, '4');
2636   }
2637 #endif
2638   cppReader_putCharQ (pfile, '\n');
2639   pfile->lineno = line;
2640 }
2641
2642
2643 /*
2644  * Parse a macro argument and append the info on PFILE's token_buffer.
2645  * REST_ARGS means to absorb the rest of the args.
2646  * Return nonzero to indicate a syntax error.
2647  */
2648
2649 static enum cpp_token
2650 macarg (cppReader *pfile, int rest_args)
2651 {
2652   int paren = 0;
2653   enum cpp_token token;
2654   char save_put_out_comments = CPPOPTIONS (pfile)->put_out_comments;
2655   bool oldexpand = pfile->no_macro_expand;
2656   CPPOPTIONS (pfile)->put_out_comments = 1;
2657
2658   /* Try to parse as much of the argument as exists at this
2659      input stack level.  */
2660
2661   pfile->no_macro_expand = TRUE;
2662
2663   for (;;)
2664     {
2665       token = cppGetToken (pfile);
2666
2667       switch (token)
2668         {
2669         case CPP_EOF:
2670           goto done;
2671         case CPP_POP:
2672           /* If we've hit end of file, it's an error (reported by caller).
2673              Ditto if it's the end of cpp_expand_to_buffer text.
2674              If we've hit end of macro, just continue.  */
2675           if (!cppBuffer_isMacro (CPPBUFFER (pfile)))
2676             goto done;
2677           /*@switchbreak@*/ break;
2678         case CPP_LPAREN:
2679           paren++;
2680           /*@switchbreak@*/ break;
2681         case CPP_RPAREN:
2682           if (--paren < 0)
2683             goto found;
2684           /*@switchbreak@*/ break;
2685         case CPP_COMMA:
2686           /* if we've returned to lowest level and
2687              we aren't absorbing all args */
2688           if (paren == 0 && rest_args == 0)
2689             goto found;
2690           /*@switchbreak@*/ break;
2691         found:
2692           /* Remove ',' or ')' from argument buffer.  */
2693           cppReader_adjustWritten (pfile, -1);
2694           goto done;
2695         default:
2696           ;
2697         }
2698     }
2699
2700 done:
2701   CPPOPTIONS (pfile)->put_out_comments = save_put_out_comments;
2702   pfile->no_macro_expand = oldexpand;
2703
2704   return token;
2705 }
2706
2707
2708 /* Turn newlines to spaces in the string of length LENGTH at START,
2709    except inside of string constants.
2710    The string is copied into itself with its beginning staying fixed.  */
2711
2712 static int
2713 change_newlines (char *start, int length)
2714 {
2715   register char *ibp;
2716   register char *obp;
2717   register char *limit;
2718   char c;
2719
2720   ibp = start;
2721   limit = start + length;
2722   obp = start;
2723
2724   while (ibp < limit) {
2725     *obp++ = c = *ibp++;
2726     switch (c) {
2727
2728     case '\'':
2729     case '\"':
2730       /* Notice and skip strings, so that we don't delete newlines in them.  */
2731       {
2732         char quotec = c;
2733         while (ibp < limit) {
2734           *obp++ = c = *ibp++;
2735           if (c == quotec)
2736             /*@innerbreak@*/ break;
2737           if (c == '\n' && quotec == '\'')
2738             /*@innerbreak@*/ break;
2739         }
2740       }
2741     /*@switchbreak@*/ break;
2742     }
2743   }
2744
2745   return obp - start;
2746 }
2747
2748 static /*@observer@*/ struct tm *
2749 timestamp (/*@returned@*/ cppReader *pfile)
2750 {
2751   if (pfile->timebuf == NULL)
2752     {
2753       time_t t = time ((time_t *) 0);
2754       pfile->timebuf = localtime (&t);
2755     }
2756
2757   llassert (pfile->timebuf != NULL);
2758
2759   return pfile->timebuf;
2760 }
2761
2762 static ob_mstring monthnames[] = {
2763   "Jan", "Feb", "Mar", "Apr", "May", "Jun",
2764   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
2765 } ;
2766
2767 /*
2768  * expand things like __FILE__.  Place the expansion into the output
2769  * buffer *without* rescanning.
2770  */
2771
2772 static void
2773 special_symbol (hashNode hp, cppReader *pfile)
2774 {
2775   cstring buf = cstring_undefined;
2776   size_t len;
2777   int true_indepth;
2778   cppBuffer *ip;
2779   struct tm *timebuf;
2780
2781   int paren = 0;                /* For special `defined' keyword */
2782
2783   for (ip = cppReader_getBuffer (pfile); ip != NULL; ip = cppBuffer_prevBuffer (ip))
2784     {
2785       if (ip == cppReader_nullBuffer (pfile))
2786         {
2787           cppReader_errorLit (pfile,
2788                         cstring_makeLiteralTemp ("cccp error: not in any file?!"));
2789           return;                       /* the show must go on */
2790         }
2791
2792       if (ip != NULL && ip->fname != NULL)
2793         {
2794           break;
2795         }
2796     }
2797
2798   switch (hp->type)
2799     {
2800     case T_FILE:
2801     case T_BASE_FILE:
2802       {
2803         char *string;
2804         if (hp->type == T_BASE_FILE)
2805           {
2806             while (cppBuffer_prevBuffer (ip) != cppReader_nullBuffer (pfile))
2807               {
2808                 ip = cppBuffer_prevBuffer (ip);
2809               }
2810           }
2811
2812         llassert (ip != NULL);
2813         string = cstring_toCharsSafe (ip->nominal_fname);
2814
2815         if (string == NULL)
2816           {
2817             string = "";
2818           }
2819
2820         cppReader_reserve (pfile, 3 + 4 * strlen (string));
2821         quote_string (pfile, string);
2822         return;
2823       }
2824
2825     case T_INCLUDE_LEVEL:
2826       true_indepth = 0;
2827       ip = cppReader_getBuffer (pfile);
2828
2829       for (;  ip != cppReader_nullBuffer (pfile) && ip != NULL;
2830            ip = cppBuffer_prevBuffer (ip))
2831         {
2832           if (ip != NULL && ip->fname != NULL)
2833             {
2834               true_indepth++;
2835             }
2836         }
2837
2838       buf = message ("%d", true_indepth - 1);
2839       break;
2840
2841     case T_VERSION:
2842       buf = message ("\"%s\"", cstring_makeLiteralTemp (CPP_VERSION));
2843       break;
2844
2845 #ifndef NO_BUILTIN_SIZE_TYPE
2846     case T_SIZE_TYPE:
2847       buf = cstring_makeLiteral (SIZE_TYPE);
2848       break;
2849 #endif
2850
2851 #ifndef NO_BUILTIN_PTRDIFF_TYPE
2852     case T_PTRDIFF_TYPE:
2853       buf = cstring_makeLiteral (PTRDIFF_TYPE);
2854       break;
2855 #endif
2856
2857     case T_WCHAR_TYPE:
2858       buf = cstring_makeLiteral (cppReader_wcharType (pfile));
2859       break;
2860
2861     case T_USER_LABEL_PREFIX_TYPE:
2862       buf = cstring_makeLiteral (USER_LABEL_PREFIX);
2863       break;
2864
2865     case T_REGISTER_PREFIX_TYPE:
2866       buf = cstring_makeLiteral (REGISTER_PREFIX);
2867       break;
2868
2869     case T_CONST:
2870       buf = message ("%d", hp->value.ival);
2871       break;
2872
2873     case T_SPECLINE:
2874       {
2875         if (ip != NULL)
2876           {
2877             int line = ip->lineno;
2878             int col = ip->colno;
2879
2880             llassert (ip->cur != NULL);
2881             adjust_position (cppLineBase (ip), ip->cur, &line, &col);
2882
2883             buf = message ("%d", (int) line);
2884           }
2885         else
2886           {
2887             BADBRANCH;
2888           }
2889       }
2890     break;
2891
2892     case T_DATE:
2893     case T_TIME:
2894       {
2895         char *sbuf = (char *) dmalloc (20);
2896         timebuf = timestamp (pfile);
2897         if (hp->type == T_DATE)
2898           {
2899             sprintf (sbuf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon],
2900                      timebuf->tm_mday, timebuf->tm_year + 1900);
2901           }
2902         else
2903           {
2904             sprintf (sbuf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min,
2905                      timebuf->tm_sec);
2906           }
2907
2908         buf = cstring_fromCharsNew (sbuf);
2909         sfree (sbuf);
2910         break;
2911       }
2912
2913     case T_SPEC_DEFINED:
2914       buf = cstring_makeLiteral (" 0 ");     /* Assume symbol is not defined */
2915       ip = cppReader_getBuffer (pfile);
2916
2917       llassert (ip->cur != NULL);
2918       SKIP_WHITE_SPACE (ip->cur);
2919
2920       if (*ip->cur == '(')
2921         {
2922           paren++;
2923           ip->cur++;                    /* Skip over the paren */
2924           SKIP_WHITE_SPACE (ip->cur);
2925         }
2926
2927       if (!is_idstart[(int) *ip->cur])
2928         goto oops;
2929       if (ip->cur[0] == 'L' && (ip->cur[1] == '\'' || ip->cur[1] == '"'))
2930         goto oops;
2931
2932       if ((hp = cppReader_lookup (ip->cur, -1, -1)) != 0)
2933         {
2934           cstring_free (buf);
2935           buf = cstring_makeLiteral (" 1 ");
2936         }
2937
2938       while (is_idchar[(int) *ip->cur])
2939         {
2940           ++ip->cur;
2941         }
2942
2943       SKIP_WHITE_SPACE (ip->cur);
2944
2945       if (paren != 0)
2946         {
2947           if (*ip->cur != ')')
2948             goto oops;
2949           ++ip->cur;
2950         }
2951       break;
2952
2953     oops:
2954
2955       cppReader_errorLit (pfile,
2956                     cstring_makeLiteralTemp ("`defined' without an identifier"));
2957       break;
2958
2959     default:
2960       cpp_setLocation (pfile);
2961       llfatalerror (message ("Pre-processing error: invalid special hash type"));
2962     }
2963
2964   len = size_fromInt (cstring_length (buf));
2965
2966   cppReader_reserve (pfile, len + 1);
2967   cppReader_putStrN (pfile, cstring_toCharsSafe (buf), len);
2968   cppReader_nullTerminateQ (pfile);
2969
2970   cstring_free (buf);
2971   return;
2972 }
2973
2974 /* Write out a #define command for the special named MACRO_NAME
2975    to PFILE's token_buffer.  */
2976
2977 static void
2978 dump_special_to_buffer (cppReader *pfile, char *macro_name)
2979 {
2980   static char define_directive[] = "#define ";
2981   size_t macro_name_length = strlen (macro_name);
2982   output_line_command (pfile, 0, same_file);
2983   cppReader_reserve (pfile, sizeof(define_directive) + macro_name_length);
2984   cppReader_putStrN (pfile, define_directive, sizeof(define_directive)-1);
2985   cppReader_putStrN (pfile, macro_name, macro_name_length);
2986   cppReader_putCharQ (pfile, ' ');
2987   cpp_expand_to_buffer (pfile, macro_name, macro_name_length);
2988   cppReader_putChar (pfile, '\n');
2989 }
2990
2991 /* Initialize the built-in macros.  */
2992
2993 static void
2994 cppReader_installBuiltin (/*@observer@*/ char *name, ctype ctyp,
2995                           int len, enum node_type type,
2996                           int ivalue, /*@null@*/ /*@only@*/ char *value,
2997                           int hash)
2998 {
2999   cstring sname = cstring_fromCharsNew (name);
3000
3001   llassert (usymtab_inGlobalScope ());
3002
3003   /*
3004   ** Be careful here: this is done before the ctype table has
3005   ** been initialized.
3006   */
3007
3008   if (!usymtab_exists (sname))
3009     {
3010       uentry ue = uentry_makeConstant (sname, ctyp, fileloc_createBuiltin ());
3011
3012       if (ctype_equal (ctyp, ctype_string))
3013         {
3014           qualList ql = qualList_new ();
3015           ql = qualList_add (ql, qual_createObserver ());
3016           uentry_reflectQualifiers (ue, ql);
3017           qualList_free (ql);
3018         }
3019       
3020       usymtab_addGlobalEntry (ue);
3021     }
3022   else
3023     {
3024       ;
3025     }
3026
3027   (void) cppReader_install (name, len, type, ivalue, value, hash);
3028   cstring_free (sname);
3029 }
3030
3031 static void
3032 cppReader_installBuiltinType (/*@observer@*/ char *name, ctype ctyp,
3033                               int len, enum node_type type,
3034                               int ivalue,
3035                               /*@only@*/ /*@null@*/ char *value, int hash)
3036 {
3037   cstring sname = cstring_fromChars (name);
3038   /* evs 2000 07 10 - removed a memory leak, detected by lclint */
3039
3040   llassert (usymtab_inGlobalScope ());
3041
3042   if (!usymtab_existsTypeEither (sname))
3043     {
3044       uentry ue = uentry_makeDatatype (sname, ctyp,
3045                                        NO, NO,
3046                                        fileloc_createBuiltin ());
3047       llassert (!usymtab_existsEither (sname));
3048       usymtab_addGlobalEntry (ue);
3049     }
3050
3051   (void) cppReader_install (name, len, type, ivalue, value, hash);
3052 }
3053
3054 static void
3055 initialize_builtins (cppReader *pfile)
3056 {
3057   cppReader_installBuiltin ("__LINE__", ctype_int, -1, T_SPECLINE, 0, NULL, -1);
3058   cppReader_installBuiltin ("__DATE__", ctype_string, -1, T_DATE, 0, NULL, -1);
3059   cppReader_installBuiltin ("__FILE__", ctype_string, -1, T_FILE, 0, NULL, -1);
3060   cppReader_installBuiltin ("__BASE_FILE__", ctype_string, -1, T_BASE_FILE, 0, NULL, -1);
3061   cppReader_installBuiltin ("__INCLUDE_LEVEL__", ctype_int, -1, T_INCLUDE_LEVEL, 0, NULL, -1);
3062   cppReader_installBuiltin ("__VERSION__", ctype_string, -1, T_VERSION, 0, NULL, -1);
3063 #ifndef NO_BUILTIN_SIZE_TYPE
3064   cppReader_installBuiltinType ("__SIZE_TYPE__", ctype_anyintegral, -1, T_SIZE_TYPE, 0, NULL, -1);
3065 #endif
3066 #ifndef NO_BUILTIN_PTRDIFF_TYPE
3067   cppReader_installBuiltinType ("__PTRDIFF_TYPE__", ctype_anyintegral, -1, T_PTRDIFF_TYPE, 0, NULL, -1);
3068 #endif
3069   cppReader_installBuiltinType ("__WCHAR_TYPE__", ctype_anyintegral, -1, T_WCHAR_TYPE, 0, NULL, -1);
3070   cppReader_installBuiltin ("__USER_LABEL_PREFIX__", ctype_string, -1, T_USER_LABEL_PREFIX_TYPE, 0, NULL, -1);
3071   cppReader_installBuiltin ("__REGISTER_PREFIX__", ctype_string, -1, T_REGISTER_PREFIX_TYPE, 0, NULL, -1);
3072   cppReader_installBuiltin ("__TIME__", ctype_string, -1, T_TIME, 0, NULL, -1);
3073
3074   /*
3075   ** No, don't define __STDC__
3076   **
3077
3078   if (!cppReader_isTraditional (pfile))
3079     {
3080       cppReader_installBuiltin ("__STDC__", ctype_int, -1, T_CONST, STDC_VALUE, NULL, -1);
3081     }
3082
3083   **
3084   */
3085
3086 # ifdef WIN32
3087     cppReader_installBuiltin ("_WIN32", ctype_int, -1, T_CONST, STDC_VALUE, NULL, -1);
3088 # endif
3089
3090   /*
3091   ** This is supplied using a -D by the compiler driver
3092   ** so that it is present only when truly compiling with GNU C.
3093   */
3094
3095   /*  cppReader_install ("__GNUC__", -1, T_CONST, 2, 0, -1);  */
3096
3097   cppReader_installBuiltin ("__LCLINT__", ctype_int, -1, T_CONST, 2, NULL, -1);
3098
3099   if (CPPOPTIONS (pfile)->debug_output)
3100     {
3101       dump_special_to_buffer (pfile, "__BASE_FILE__");
3102       dump_special_to_buffer (pfile, "__VERSION__");
3103 #ifndef NO_BUILTIN_SIZE_TYPE
3104       dump_special_to_buffer (pfile, "__SIZE_TYPE__");
3105 #endif
3106 #ifndef NO_BUILTIN_PTRDIFF_TYPE
3107       dump_special_to_buffer (pfile, "__PTRDIFF_TYPE__");
3108 #endif
3109       dump_special_to_buffer (pfile, "__WCHAR_TYPE__");
3110       dump_special_to_buffer (pfile, "__DATE__");
3111       dump_special_to_buffer (pfile, "__TIME__");
3112       if (!cppReader_isTraditional (pfile))
3113         dump_special_to_buffer (pfile, "__STDC__");
3114     }
3115 }
3116
3117
3118 /* Return 1 iff a token ending in C1 followed directly by a token C2
3119    could cause mis-tokenization.  */
3120
3121 static bool
3122 unsafe_chars (char c1, char c2)
3123 {
3124   switch (c1)
3125     {
3126     case '+': case '-':
3127       if (c2 == c1 || c2 == '=')
3128         return 1;
3129       goto letter;
3130     case '.':
3131     case '0': case '1': case '2': case '3': case '4':
3132     case '5': case '6': case '7': case '8': case '9':
3133     case 'e': case 'E': case 'p': case 'P':
3134       if (c2 == '-' || c2 == '+')
3135         return 1; /* could extend a pre-processing number */
3136       goto letter;
3137     case 'L':
3138       if (c2 == '\'' || c2 == '\"')
3139         return 1;   /* Could turn into L"xxx" or L'xxx'.  */
3140       goto letter;
3141     letter:
3142     case '_':
3143     case 'a': case 'b': case 'c': case 'd':           case 'f':
3144     case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
3145     case 'm': case 'n': case 'o':           case 'q': case 'r':
3146     case 's': case 't': case 'u': case 'v': case 'w': case 'x':
3147     case 'y': case 'z':
3148     case 'A': case 'B': case 'C': case 'D':           case 'F':
3149     case 'G': case 'H': case 'I': case 'J': case 'K':
3150     case 'M': case 'N': case 'O':           case 'Q': case 'R':
3151     case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
3152     case 'Y': case 'Z':
3153       /* We're in the middle of either a name or a pre-processing number.  */
3154       return (is_idchar[(int) c2] || c2 == '.');
3155     case '<': case '>': case '!': case '%': case '#': case ':':
3156     case '^': case '&': case '|': case '*': case '/': case '=':
3157       return (c2 == c1 || c2 == '=');
3158     }
3159   return 0;
3160 }
3161
3162 /* Expand a macro call.
3163    HP points to the symbol that is the macro being called.
3164    Put the result of expansion onto the input stack
3165    so that subsequent input by our caller will use it.
3166
3167    If macro wants arguments, caller has already verified that
3168    an argument list follows; arguments come from the input stack.  */
3169
3170 static void
3171 macroexpand (cppReader *pfile, /*@dependent@*/ hashNode hp)
3172 {
3173   int nargs;
3174   DEFINITION *defn = hp->value.defn;
3175   char *xbuf;
3176   char *oxbuf = NULL;
3177   int start_line;
3178   int start_column;
3179   size_t xbuf_len;
3180   size_t old_written = cppReader_getWritten (pfile);
3181   int rest_args;
3182   int rest_zero = 0;
3183   int i;
3184   struct argdata *args = NULL;
3185
3186   pfile->output_escapes++;
3187
3188   cppBuffer_lineAndColumn (cppReader_fileBuffer (pfile), &start_line, &start_column);
3189
3190   nargs = defn->nargs;
3191
3192   if (nargs >= 0)
3193     {
3194       enum cpp_token token = CPP_EOF;
3195
3196       args = (struct argdata *) dmalloc ((nargs + 1) * sizeof (*args));
3197
3198       for (i = 0; i < nargs; i++)
3199         {
3200           args[i].expanded = 0;
3201           args[i].raw = 0;
3202           args[i].raw_length = 0;
3203           args[i].expand_length = args[i].stringified_length = -1;
3204           args[i].use_count = 0;
3205         }
3206
3207       /*
3208       ** Parse all the macro args that are supplied.  I counts them.
3209       ** The first NARGS args are stored in ARGS.
3210       ** The rest are discarded.  If rest_args is set then we assume
3211       ** macarg absorbed the rest of the args.
3212       */
3213
3214       i = 0;
3215       rest_args = 0;
3216
3217       cppReader_forward (pfile, 1); /* Discard the open-parenthesis before the first arg.  */
3218       do
3219         {
3220           if (rest_args != 0)
3221             {
3222               continue;
3223             }
3224
3225           if (i < nargs || (nargs == 0 && i == 0))
3226             {
3227               /* if we are working on last arg which absorbs rest of args... */
3228               if (i == nargs - 1 && defn->rest_args)
3229                 {
3230                   rest_args = 1;
3231                 }
3232
3233               args[i].raw = size_toLong (cppReader_getWritten (pfile));
3234               token = macarg (pfile, rest_args);
3235               args[i].raw_length = cppReader_getWritten (pfile) - args[i].raw;
3236               args[i].newlines = FALSE; /* FIXME */
3237             }
3238           else
3239             {
3240               token = macarg (pfile, 0);
3241             }
3242
3243           if (token == CPP_EOF || token == CPP_POP)
3244             {
3245               cppReader_errorWithLine (pfile, start_line, start_column,
3246                                    cstring_fromCharsNew ("unterminated macro call"));
3247               sfree (args);
3248               return;
3249             }
3250           i++;
3251         } while (token == CPP_COMMA);
3252
3253       /* If we got one arg but it was just whitespace, call that 0 args.  */
3254       if (i == 1)
3255         {
3256           char *bp;
3257           char *lim;
3258
3259           assertSet (args);
3260
3261           bp = ARG_BASE + args[0].raw;
3262           lim = bp + args[0].raw_length;
3263
3264           /* cpp.texi says for foo ( ) we provide one argument.
3265              However, if foo wants just 0 arguments, treat this as 0.  */
3266
3267           if (nargs == 0)
3268             {
3269               while (bp != lim && is_space[(int) *bp])
3270                 {
3271                   bp++;
3272                 }
3273             }
3274
3275           if (bp == lim)
3276             i = 0;
3277         }
3278
3279       /* Don't output an error message if we have already output one for
3280          a parse error above.  */
3281       rest_zero = 0;
3282
3283       if (nargs == 0 && i > 0)
3284         {
3285           cppReader_error (pfile,
3286                      message ("arguments given to macro `%s'", hp->name));
3287         }
3288       else if (i < nargs)
3289         {
3290           /* traditional C allows foo() if foo wants one argument.  */
3291           if (nargs == 1 && i == 0 && cppReader_isTraditional (pfile))
3292             {
3293               ;
3294             }
3295           /* the rest args token is allowed to absorb 0 tokens */
3296           else if (i == nargs - 1 && defn->rest_args)
3297             rest_zero = 1;
3298           else if (i == 0)
3299             cppReader_error (pfile,
3300                        message ("macro `%s' used without args", hp->name));
3301           else if (i == 1)
3302             cppReader_error (pfile,
3303                        message ("macro `%s' used with just one arg", hp->name));
3304           else
3305             {
3306               cppReader_error (pfile,
3307                          message ("macro `%s' used with only %d args",
3308                                   hp->name, i));
3309             }
3310         }
3311       else if (i > nargs)
3312         {
3313           cppReader_error (pfile,
3314                      message ("macro `%s' used with too many (%d) args", hp->name, i));
3315         }
3316       else
3317         {
3318           ;
3319         }
3320     }
3321
3322   /* If macro wants zero args, we parsed the arglist for checking only.
3323      Read directly from the macro definition.  */
3324
3325   if (nargs <= 0)
3326     {
3327       xbuf = defn->expansion;
3328       xbuf_len = defn->length;
3329     }
3330   else
3331     {
3332       char *exp = defn->expansion;
3333       int offset;       /* offset in expansion,
3334                                    copied a piece at a time */
3335       size_t totlen;    /* total amount of exp buffer filled so far */
3336
3337       register struct reflist *ap, *last_ap;
3338       
3339       assertSet (args); /* args is defined since the nargs > 0 path was taken */
3340
3341       /* Macro really takes args.  Compute the expansion of this call.  */
3342
3343       /* Compute length in characters of the macro's expansion.
3344          Also count number of times each arg is used.  */
3345       xbuf_len = defn->length;
3346
3347       llassert (args != NULL);
3348
3349       for (ap = defn->pattern; ap != NULL; ap = ap->next)
3350         {
3351           if (ap->stringify)
3352             {
3353               struct argdata *arg = &args[ap->argno];
3354
3355               /* Stringify it it hasn't already been */
3356               assertSet (arg);
3357
3358               if (arg->stringified_length < 0)
3359                 {
3360                   int arglen = arg->raw_length;
3361                   bool escaped = FALSE;
3362                   char in_string = '\0';
3363                   char c;
3364
3365                   /* Initially need_space is -1.  Otherwise, 1 means the
3366                      previous character was a space, but we suppressed it;
3367                      0 means the previous character was a non-space.  */
3368                   int need_space = -1;
3369
3370                   i = 0;
3371                   arg->stringified = cppReader_getWritten (pfile);
3372                   if (!cppReader_isTraditional (pfile))
3373                     cppReader_putChar (pfile, '\"'); /* insert beginning quote */
3374                   for (; i < arglen; i++)
3375                     {
3376                       c = (ARG_BASE + arg->raw)[i];
3377
3378                       if (in_string == '\0')
3379                         {
3380                           /* Internal sequences of whitespace are replaced by
3381                              one space except within an string or char token.*/
3382                           if (is_space[(int) c])
3383                             {
3384                               if (cppReader_getWritten (pfile) > arg->stringified
3385                                   && (cppReader_getPWritten (pfile))[-1] == '@')
3386                                 {
3387                                   /* "@ " escape markers are removed */
3388                                   cppReader_adjustWritten (pfile, -1);
3389                                   /*@innercontinue@*/ continue;
3390                                 }
3391                               if (need_space == 0)
3392                                 need_space = 1;
3393                               /*@innercontinue@*/ continue;
3394                             }
3395                           else if (need_space > 0)
3396                             cppReader_putChar (pfile, ' ');
3397                           else
3398                             {
3399                               ;
3400                             }
3401
3402                           need_space = 0;
3403                         }
3404
3405                       if (escaped)
3406                         escaped = 0;
3407                       else
3408                         {
3409                           if (c == '\\')
3410                             escaped = 1;
3411
3412                           if (in_string != '\0')
3413                             {
3414                               if (c == in_string)
3415                                 in_string = '\0';
3416                             }
3417                           else if (c == '\"' || c == '\'')
3418                             {
3419                               in_string = c;
3420                             }
3421                           else
3422                             {
3423                               ;
3424                             }
3425                         }
3426
3427                       /* Escape these chars */
3428                       if (c == '\"' || (in_string != '\0' && c == '\\'))
3429                         cppReader_putChar (pfile, '\\');
3430                       if (isprint (c))
3431                         cppReader_putChar (pfile, c);
3432                       else
3433                         {
3434                           cppReader_reserve (pfile, 4);
3435                           sprintf (cppReader_getPWritten (pfile), "\\%03o",
3436                                    (unsigned int) c);
3437                           cppReader_adjustWritten (pfile, 4);
3438                         }
3439                     }
3440                   if (!cppReader_isTraditional (pfile))
3441                     cppReader_putChar (pfile, '\"'); /* insert ending quote */
3442                   arg->stringified_length
3443                     = size_toInt (cppReader_getWritten (pfile) - arg->stringified);
3444                 }
3445
3446               xbuf_len += args[ap->argno].stringified_length;
3447             }
3448           else if (ap->raw_before || ap->raw_after || cppReader_isTraditional (pfile))
3449             {
3450               /* Add 4 for two newline-space markers to prevent
3451                  token concatenation.  */
3452               assertSet (args); /*@i534 shouldn't need this */
3453               xbuf_len += args[ap->argno].raw_length + 4;
3454             }
3455           else
3456             {
3457               /* We have an ordinary (expanded) occurrence of the arg.
3458                  So compute its expansion, if we have not already.  */
3459
3460               assertSet (args); /*@i534 shouldn't need this */
3461
3462               if (args[ap->argno].expand_length < 0)
3463                 {
3464                   args[ap->argno].expanded = cppReader_getWritten (pfile);
3465                   cpp_expand_to_buffer (pfile,
3466                                         ARG_BASE + args[ap->argno].raw,
3467                                         size_fromInt (args[ap->argno].raw_length));
3468
3469                   args[ap->argno].expand_length
3470                     = size_toInt (cppReader_getWritten (pfile) - args[ap->argno].expanded);
3471                 }
3472
3473               /* Add 4 for two newline-space markers to prevent
3474                  token concatenation.  */
3475               xbuf_len += args[ap->argno].expand_length + 4;
3476            }
3477           if (args[ap->argno].use_count < 10)
3478             args[ap->argno].use_count++;
3479         }
3480
3481       xbuf = (char *) dmalloc (xbuf_len + 1);
3482       oxbuf = xbuf;
3483
3484       /*
3485       ** Generate in XBUF the complete expansion
3486       ** with arguments substituted in.
3487       ** TOTLEN is the total size generated so far.
3488       ** OFFSET is the index in the definition
3489       ** of where we are copying from.
3490       */
3491
3492       offset = 0;
3493       totlen = 0;
3494
3495       for (last_ap = NULL, ap = defn->pattern; ap != NULL;
3496            last_ap = ap, ap = ap->next)
3497         {
3498           register struct argdata *arg = &args[ap->argno];
3499           size_t count_before = totlen;
3500
3501           /* Add chars to XBUF.  */
3502           for (i = 0; i < ap->nchars; i++, offset++)
3503             {
3504               xbuf[totlen++] = exp[offset];
3505             }
3506
3507           /* If followed by an empty rest arg with concatenation,
3508              delete the last run of nonwhite chars.  */
3509           if (rest_zero && totlen > count_before
3510               && ((ap->rest_args && ap->raw_before)
3511                   || (last_ap != NULL && last_ap->rest_args
3512                       && last_ap->raw_after)))
3513             {
3514               /* Delete final whitespace.  */
3515               while (totlen > count_before && is_space[(int) xbuf[totlen - 1]])
3516                 {
3517                   totlen--;
3518                 }
3519
3520               /* Delete the nonwhites before them.  */
3521               while (totlen > count_before && ! is_space[(int) xbuf[totlen - 1]])
3522                 {
3523                   totlen--;
3524                 }
3525             }
3526
3527           if (ap->stringify != 0)
3528             {
3529               assertSet(arg);
3530               memcpy (xbuf + totlen,
3531                       ARG_BASE + arg->stringified,
3532                       size_fromInt (arg->stringified_length));
3533               totlen += arg->stringified_length;
3534             }
3535           else if (ap->raw_before || ap->raw_after || cppReader_isTraditional (pfile))
3536             {
3537               char *p1;
3538               char *l1;
3539
3540               assertSet (arg);
3541
3542               p1 = ARG_BASE + arg->raw;
3543               l1 = p1 + arg->raw_length;
3544
3545               if (ap->raw_before)
3546                 {
3547                   while (p1 != l1 && is_space[(int) *p1])
3548                     {
3549                       p1++;
3550                     }
3551
3552                   while (p1 != l1 && is_idchar[(int) *p1])
3553                     {
3554                       xbuf[totlen++] = *p1++;
3555                     }
3556
3557                   /* Delete any no-reexpansion marker that follows
3558                      an identifier at the beginning of the argument
3559                      if the argument is concatenated with what precedes it.  */
3560                   if (p1[0] == '@' && p1[1] == '-')
3561                     p1 += 2;
3562                 }
3563               if (ap->raw_after)
3564                 {
3565                   /* Arg is concatenated after: delete trailing whitespace,
3566                      whitespace markers, and no-reexpansion markers.  */
3567                   while (p1 != l1)
3568                     {
3569                       if (is_space[(int) l1[-1]]) l1--;
3570                       else if (l1[-1] == '-')
3571                         {
3572                           char *p2 = l1 - 1;
3573                           /* If a `-' is preceded by an odd number of newlines then it
3574                              and the last newline are a no-reexpansion marker.  */
3575                           while (p2 != p1 && p2[-1] == '\n')
3576                             {
3577                               p2--;
3578                             }
3579
3580                           if (((l1 - 1 - p2) & 1) != 0)
3581                             {
3582                               l1 -= 2;
3583                             }
3584                           else
3585                             {
3586                               /*@innerbreak@*/ break;
3587                             }
3588                         }
3589                       else
3590                         {
3591                           /*@innerbreak@*/ break;
3592                         }
3593                     }
3594                 }
3595
3596               memcpy (xbuf + totlen, p1, size_fromInt (l1 - p1));
3597               totlen += l1 - p1;
3598             }
3599           else
3600             {
3601               char *expanded;
3602
3603               assertSet (arg);
3604               expanded = ARG_BASE + arg->expanded;
3605
3606               if (!ap->raw_before && totlen > 0
3607                   && (arg->expand_length != 0)
3608                   && !cppReader_isTraditional(pfile)
3609                   && unsafe_chars (xbuf[totlen-1], expanded[0]))
3610                 {
3611                   xbuf[totlen++] = '@';
3612                   xbuf[totlen++] = ' ';
3613                 }
3614
3615               memcpy (xbuf + totlen, expanded,
3616                       size_fromInt (arg->expand_length));
3617               totlen += arg->expand_length;
3618
3619               if (!ap->raw_after && totlen > 0
3620                   && offset < size_toInt (defn->length)
3621                   && !cppReader_isTraditional(pfile)
3622                   && unsafe_chars (xbuf[totlen-1], exp[offset]))
3623                 {
3624                   xbuf[totlen++] = '@';
3625                   xbuf[totlen++] = ' ';
3626                 }
3627
3628               /* If a macro argument with newlines is used multiple times,
3629                  then only expand the newlines once.  This avoids creating
3630                  output lines which don't correspond to any input line,
3631                  which confuses gdb and gcov.  */
3632               if (arg->use_count > 1 && arg->newlines > 0)
3633                 {
3634                   /* Don't bother doing change_newlines for subsequent
3635                      uses of arg.  */
3636                   arg->use_count = 1;
3637                   arg->expand_length
3638                     = change_newlines (expanded, arg->expand_length);
3639                 }
3640             }
3641
3642           if (totlen > xbuf_len)
3643             abort ();
3644         }
3645
3646       /* if there is anything left of the definition
3647          after handling the arg list, copy that in too.  */
3648
3649       for (i = offset; i < size_toInt (defn->length); i++)
3650         {
3651           /* if we've reached the end of the macro */
3652           if (exp[i] == ')')
3653             rest_zero = 0;
3654           if (! (rest_zero && last_ap != NULL && last_ap->rest_args
3655                  && last_ap->raw_after))
3656             xbuf[totlen++] = exp[i];
3657         }
3658
3659       xbuf[totlen] = '\0';
3660       xbuf_len = totlen;
3661     }
3662
3663   pfile->output_escapes--;
3664
3665   /* Now put the expansion on the input stack
3666      so our caller will commence reading from it.  */
3667   push_macro_expansion (pfile, xbuf, xbuf_len, hp);
3668   cppReader_getBuffer (pfile)->has_escapes = 1;
3669
3670   /* Pop the space we've used in the token_buffer for argument expansion.  */
3671   cppReader_setWritten (pfile, old_written);
3672
3673   /* Recursive macro use sometimes works traditionally.
3674      #define foo(x,y) bar (x (y,0), y)
3675      foo (foo, baz)  */
3676
3677   if (!cppReader_isTraditional (pfile))
3678     hp->type = T_DISABLED;
3679
3680   sfree (args);
3681 }
3682
3683 static void
3684 push_macro_expansion (cppReader *pfile, char *xbuf, size_t xbuf_len,
3685                       /*@dependent@*/ hashNode hp)
3686 {
3687   cppBuffer *mbuf = cppReader_pushBuffer (pfile, xbuf, xbuf_len);
3688
3689   if (mbuf == NULL)
3690     {
3691       return;
3692     }
3693
3694   mbuf->cleanup = cppReader_macroCleanup;
3695
3696   llassert (mbuf->hnode == NULL);
3697   mbuf->hnode = hp;
3698
3699   /* The first chars of the expansion should be a "@ " added by
3700      collect_expansion.  This is to prevent accidental token-pasting
3701      between the text preceding the macro invocation, and the macro
3702      expansion text.
3703
3704      We would like to avoid adding unneeded spaces (for the sake of
3705      tools that use cpp, such as imake).  In some common cases we can
3706      tell that it is safe to omit the space.
3707
3708      The character before the macro invocation cannot have been an
3709      idchar (or else it would have been pasted with the idchars of
3710      the macro name).  Therefore, if the first non-space character
3711      of the expansion is an idchar, we do not need the extra space
3712      to prevent token pasting.
3713
3714      Also, we don't need the extra space if the first char is '(',
3715      or some other (less common) characters.  */
3716
3717   if (xbuf[0] == '@' && xbuf[1] == ' '
3718       && (is_idchar[(int) xbuf[2]] || xbuf[2] == '(' || xbuf[2] == '\''
3719           || xbuf[2] == '\"'))
3720   {
3721     llassert (mbuf->cur != NULL);
3722     mbuf->cur += 2;
3723   }
3724 }
3725
3726
3727 /* Like cppGetToken, except that it does not read past end-of-line.
3728    Also, horizontal space is skipped, and macros are popped.  */
3729
3730 static enum cpp_token
3731 get_directive_token (cppReader *pfile)
3732 {
3733   for (;;)
3734     {
3735       size_t old_written = cppReader_getWritten (pfile);
3736       enum cpp_token token;
3737       cppSkipHspace (pfile);
3738       if (cppReader_peekC (pfile) == '\n')
3739         {
3740           return CPP_VSPACE;
3741         }
3742
3743       token = cppGetToken (pfile);
3744
3745       switch (token)
3746         {
3747         case CPP_POP:
3748           if (!cppBuffer_isMacro (cppReader_getBuffer (pfile)))
3749             return token;
3750           /*@fallthrough@*/
3751         case CPP_HSPACE:
3752         case CPP_COMMENT:
3753           cppReader_setWritten (pfile, old_written);
3754           /*@switchbreak@*/ break;
3755         default:
3756           return token;
3757         }
3758     }
3759 }
3760
3761
3762 /* Handle #include and #import.
3763    This function expects to see "fname" or <fname> on the input.
3764
3765    The input is normally in part of the output_buffer following
3766    cppReader_getWritten, and will get overwritten by output_line_command.
3767    I.e. in input file specification has been popped by cppReader_handleDirective.
3768    This is safe.  */
3769
3770 # ifdef WIN32
3771 static void replace_unixdir_with_windir(char *filename)
3772 {
3773   int i=0;
3774   
3775   while(filename[i] != '\0')
3776     {
3777       if(filename[i] == '/')
3778         filename[i] = '\\';
3779       i++;
3780     }
3781 }
3782 # endif
3783
3784 static int
3785 do_include (cppReader *pfile, struct directive *keyword,
3786             /*@unused@*/ char *unused1, /*@unused@*/ char *unused2)
3787 {
3788   bool skip_dirs = (keyword->type == T_INCLUDE_NEXT);
3789   cstring fname;
3790   char *fbeg, *fend;            /* Beginning and end of fname */
3791   enum cpp_token token;
3792
3793   /* Chain of dirs to search */
3794   struct file_name_list *search_start = CPPOPTIONS (pfile)->include;
3795   struct file_name_list dsp[1]; /* First in chain, if #include "..." */
3796   struct file_name_list *searchptr = NULL;
3797   size_t old_written = cppReader_getWritten (pfile);
3798
3799   int flen;
3800
3801   int f;                        /* file number */
3802   int angle_brackets = 0;       /* 0 for "...", 1 for <...> */
3803   f= -1;                        /* JF we iz paranoid! */
3804
3805   pfile->parsing_include_directive++;
3806   token = get_directive_token (pfile);
3807   pfile->parsing_include_directive--;
3808
3809   if (token == CPP_STRING)
3810     {
3811       /* FIXME - check no trailing garbage */
3812       fbeg = pfile->token_buffer + old_written + 1;
3813       fend = cppReader_getPWritten (pfile) - 1;
3814       if (fbeg[-1] == '<')
3815         {
3816           angle_brackets = 1;
3817           /* If -I-, start with the first -I dir after the -I-.  */
3818           if (CPPOPTIONS (pfile)->first_bracket_include != NULL)
3819             search_start = CPPOPTIONS (pfile)->first_bracket_include;
3820         }
3821       /* If -I- was specified, don't search current dir, only spec'd ones.  */
3822       else if (!CPPOPTIONS (pfile)->ignore_srcdir)
3823         {
3824           cppBuffer *fp = CPPBUFFER (pfile);
3825           /* We have "filename".  Figure out directory this source
3826              file is coming from and put it on the front of the list.  */
3827
3828           for ( ; fp != cppReader_nullBuffer (pfile); fp = cppBuffer_prevBuffer (fp))
3829             {
3830               int n;
3831               char *ep,*nam;
3832
3833               llassert (fp != NULL);
3834
3835               nam = NULL;
3836
3837               if (cstring_isDefined (fp->nominal_fname))
3838                 {
3839                   nam = cstring_toCharsSafe (fp->nominal_fname);
3840
3841                   /* Found a named file.  Figure out dir of the file,
3842                      and put it in front of the search list.  */
3843                   dsp[0].next = search_start;
3844                   search_start = dsp;
3845
3846 #ifndef VMS
3847                   ep = strrchr (nam, CONNECTCHAR);
3848 #else                           /* VMS */
3849                   ep = strrchr (nam, ']');
3850                   if (ep == NULL) ep = strrchr (nam, '>');
3851                   if (ep == NULL) ep = strrchr (nam, ':');
3852                   if (ep != NULL) ep++;
3853 #endif                          /* VMS */
3854                   if (ep != NULL)
3855                     {
3856                       char save;
3857
3858                       n = ep - nam;
3859                       save = nam[n];
3860                       nam[n] = '\0';
3861
3862                       /*@-onlytrans@*/ /* This looks like a memory leak... */ 
3863                       dsp[0].fname = cstring_fromCharsNew (nam); /* evs 2000-07-20: was fromChars */
3864                       /*@=onlytrans@*/
3865                       nam[n] = save;
3866
3867                       if (n + INCLUDE_LEN_FUDGE > pfile->max_include_len)
3868                         pfile->max_include_len = n + INCLUDE_LEN_FUDGE;
3869                     }
3870                   else
3871                     {
3872                       dsp[0].fname = cstring_undefined; /* Current directory */
3873                     }
3874
3875                   dsp[0].got_name_map = 0;
3876                   break;
3877                 }
3878             }
3879         }
3880       else
3881         {
3882           ;
3883         }
3884     }
3885 #ifdef VMS
3886   else if (token == CPP_NAME)
3887     {
3888       /*
3889        * Support '#include xyz' like VAX-C to allow for easy use of all the
3890        * decwindow include files. It defaults to '#include <xyz.h>' (so the
3891        * code from case '<' is repeated here) and generates a warning.
3892        */
3893       cppReader_warning (pfile,
3894                    "VAX-C-style include specification found, use '#include <filename.h>' !");
3895       angle_brackets = 1;
3896       /* If -I-, start with the first -I dir after the -I-.  */
3897       if (CPPOPTIONS (pfile)->first_bracket_include)
3898         search_start = CPPOPTIONS (pfile)->first_bracket_include;
3899       fbeg = pfile->token_buffer + old_written;
3900       fend = cppReader_getPWritten (pfile);
3901     }
3902 #endif
3903   else
3904     {
3905       cppReader_error (pfile,
3906                  message ("Preprocessor command #%s expects \"FILENAME\" or <FILENAME>",
3907                           keyword->name));
3908
3909       cppReader_setWritten (pfile, old_written);
3910       cppReader_skipRestOfLine (pfile);
3911       return 0;
3912     }
3913
3914   *fend = 0;
3915
3916   token = get_directive_token (pfile);
3917   if (token != CPP_VSPACE)
3918     {
3919       cppReader_errorLit (pfile,
3920                     cstring_makeLiteralTemp ("Junk at end of #include"));
3921
3922       while (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP)
3923         {
3924           token = get_directive_token (pfile);
3925         }
3926     }
3927
3928   /*
3929   ** For #include_next, skip in the search path
3930   ** past the dir in which the containing file was found.
3931   */
3932
3933   if (skip_dirs)
3934     {
3935       cppBuffer *fp = CPPBUFFER (pfile);
3936
3937       for (; fp != cppReader_nullBuffer (pfile); fp = cppBuffer_prevBuffer (fp))
3938         {
3939           llassert (fp != NULL);
3940
3941           if (fp->fname != NULL)
3942             {
3943               /* fp->dir is null if the containing file was specified with
3944                  an absolute file name.  In that case, don't skip anything.  */
3945               if (fp->dir == SELF_DIR_DUMMY)
3946                 {
3947                   search_start = CPPOPTIONS (pfile)->include;
3948                 }
3949               else if (fp->dir != NULL)
3950                 {
3951                   search_start = fp->dir->next;
3952                 }
3953               else
3954                 {
3955                   ;
3956                 }
3957
3958               break;
3959             }
3960         }
3961     }
3962
3963   cppReader_setWritten (pfile, old_written);
3964
3965   flen = fend - fbeg;
3966
3967   DPRINTF (("fbeg: %s", fbeg));
3968
3969   if (flen == 0)
3970     {
3971       cppReader_error (pfile,
3972                  message ("Empty file name in #%s", keyword->name));
3973       return 0;
3974     }
3975
3976   /*
3977   ** Allocate this permanently, because it gets stored in the definitions
3978   ** of macros.
3979   */
3980
3981   fname = cstring_undefined;
3982
3983   /* + 2 above for slash and terminating null.  */
3984   /* + 2 added for '.h' on VMS (to support '#include filename') */
3985
3986   /* If specified file name is absolute, just open it.  */
3987
3988   if (osd_isConnectChar (*fbeg)
3989 # if defined (WIN32) || defined (OS2)
3990       || (*(fbeg + 1) == ':')
3991 # endif
3992       )
3993     {
3994       fname = cstring_copyLength (fbeg, flen);
3995       
3996       if (redundant_include_p (pfile, fname))
3997         {
3998           cstring_free (fname);
3999           return 0;
4000         }
4001       
4002       f = open_include_file (pfile, fname, NULL);
4003       
4004       if (f == IMPORT_FOUND)
4005         {
4006           return 0;             /* Already included this file */
4007         }
4008     } 
4009   else 
4010     {
4011       /* Search directory path, trying to open the file.
4012          Copy each filename tried into FNAME.  */
4013
4014       for (searchptr = search_start; searchptr != NULL;
4015            searchptr = searchptr->next)
4016         {
4017           if (!cstring_isEmpty (searchptr->fname))
4018             {
4019               /* The empty string in a search path is ignored.
4020                  This makes it possible to turn off entirely
4021                  a standard piece of the list.  */
4022               if (cstring_isEmpty (searchptr->fname))
4023                 continue;
4024               
4025               fname = cstring_copy (searchptr->fname);
4026               fname = cstring_appendChar (fname, CONNECTCHAR);
4027               DPRINTF (("Here: %s", fname));
4028             }
4029           else
4030             {
4031               ;
4032             }
4033           
4034           fname = cstring_concatLength (fname, fbeg, flen);
4035
4036           DPRINTF (("fname: %s", fname));
4037           
4038           /* Win32 directory fix from Kay Buschner. */
4039 #ifdef WIN32
4040           /* Fix all unixdir slashes to win dir slashes */
4041           if (searchptr->fname && (searchptr->fname[0] != 0)) 
4042             {
4043               replace_unixdir_with_windir(fname);
4044             }
4045 #endif /* WIN32 */
4046
4047 #ifdef VMS
4048           /* Change this 1/2 Unix 1/2 VMS file specification into a
4049              full VMS file specification */
4050           if (searchptr->fname && (searchptr->fname[0] != 0)) {
4051             /* Fix up the filename */
4052             hack_vms_include_specification (fname);
4053           } else {
4054             /* This is a normal VMS filespec, so use it unchanged.  */
4055             strncpy (fname, fbeg, flen);
4056             fname[flen] = 0;
4057             /* if it's '#include filename', add the missing .h */
4058             if (strchr (fname,'.') == NULL) {
4059               strcat (fname, ".h");
4060             }
4061           }
4062 #endif /* VMS */
4063           /* ??? There are currently 3 separate mechanisms for avoiding processing
4064              of redundant include files: #import, #pragma once, and
4065              redundant_include_p.  It would be nice if they were unified.  */
4066           
4067           if (redundant_include_p (pfile, fname))
4068             {
4069               cstring_free (fname);
4070               return 0;
4071             }
4072
4073           DPRINTF (("Trying: %s", fname));
4074
4075           f = open_include_file (pfile, fname, searchptr);
4076           
4077           if (f == IMPORT_FOUND)
4078             {
4079               return 0;                 /* Already included this file */
4080             }
4081 #ifdef EACCES
4082           else if (f == IMPORT_NOT_FOUND && errno == EACCES)
4083             {
4084               cppReader_warning (pfile,
4085                                  message ("Header file %s exists, but is not readable", fname));
4086             }
4087 #endif
4088           
4089           if (f >= 0)
4090             {
4091               break;
4092             }
4093         }
4094     }
4095   
4096   if (f < 0)
4097     {
4098       /* A file that was not found.  */
4099       fname = cstring_copyLength (fbeg, flen);
4100
4101       if (search_start != NULL)
4102         {
4103           cppReader_error (pfile,
4104                            message ("Cannot find include file %s on search path: %x", 
4105                                     fname,
4106                                     searchPath_unparse (search_start)));
4107         }
4108       else
4109         {
4110           cppReader_error (pfile,
4111                            message ("No include path in which to find %s", fname));
4112         }
4113     }
4114   else {
4115     /*
4116     ** Check to see if this include file is a once-only include file.
4117     ** If so, give up.
4118     */
4119
4120     struct file_name_list *ptr;
4121
4122     for (ptr = pfile->all_include_files; ptr != NULL; ptr = ptr->next)
4123       {
4124         if (cstring_equal (ptr->fname, fname))
4125           {
4126             /* This file was included before.  */
4127             break;
4128           }
4129       }
4130
4131     if (ptr == NULL)
4132       {
4133         /* This is the first time for this file.  */
4134         /* Add it to list of files included.  */
4135
4136         ptr = (struct file_name_list *) dmalloc (sizeof (*ptr));
4137         ptr->control_macro = NULL;
4138         ptr->c_system_include_path = NULL;
4139         ptr->next = pfile->all_include_files;
4140         ptr->fname = fname;
4141         ptr->got_name_map = NULL;
4142
4143         DPRINTF (("Including file: %s", fname));
4144         pfile->all_include_files = ptr;
4145         assertSet (pfile->all_include_files);
4146       }
4147
4148     if (angle_brackets != 0)
4149       {
4150         pfile->system_include_depth++;
4151       }
4152
4153     /* Actually process the file */
4154     if (cppReader_pushBuffer (pfile, NULL, 0) == NULL)
4155       {
4156         cstring_free (fname);
4157         return 0;
4158       }
4159
4160     if (finclude (pfile, f, fname, is_system_include (pfile, fname),
4161                   searchptr != dsp ? searchptr : SELF_DIR_DUMMY))
4162       {
4163         output_line_command (pfile, 0, enter_file);
4164         pfile->only_seen_white = 2;
4165       }
4166
4167     if (angle_brackets)
4168       {
4169         pfile->system_include_depth--;
4170       }
4171     /*@-branchstate@*/
4172   } /*@=branchstate@*/ 
4173
4174   return 0;
4175 }
4176
4177 /* Return nonzero if there is no need to include file NAME
4178    because it has already been included and it contains a conditional
4179    to make a repeated include do nothing.  */
4180
4181 static bool
4182 redundant_include_p (cppReader *pfile, cstring name)
4183 {
4184   struct file_name_list *l = pfile->all_include_files;
4185
4186   for (; l != NULL; l = l->next)
4187     {
4188       if (cstring_equal (name, l->fname)
4189           && (l->control_macro != NULL)
4190           && (cppReader_lookup (l->control_macro, -1, -1) != NULL))
4191         {
4192           return TRUE;
4193         }
4194     }
4195
4196   return FALSE;
4197 }
4198
4199 /* Return nonzero if the given FILENAME is an absolute pathname which
4200    designates a file within one of the known "system" include file
4201    directories.  We assume here that if the given FILENAME looks like
4202    it is the name of a file which resides either directly in a "system"
4203    include file directory, or within any subdirectory thereof, then the
4204    given file must be a "system" include file.  This function tells us
4205    if we should suppress pedantic errors/warnings for the given FILENAME.
4206
4207    The value is 2 if the file is a C-language system header file
4208    for which C++ should (on most systems) assume `extern "C"'.  */
4209
4210 static bool
4211 is_system_include (cppReader *pfile, cstring filename)
4212 {
4213   struct file_name_list *searchptr;
4214
4215   for (searchptr = CPPOPTIONS (pfile)->first_system_include;
4216        searchptr != NULL;
4217        searchptr = searchptr->next)
4218     {
4219       if (!cstring_isEmpty (searchptr->fname)) {
4220         cstring sys_dir = searchptr->fname;
4221         int length = cstring_length (sys_dir);
4222
4223         if (cstring_equalLen (sys_dir, filename, length)
4224             && osd_isConnectChar (cstring_getChar (filename, length)))
4225           {
4226             if (searchptr->c_system_include_path)
4227               return 2;
4228             else
4229               return 1;
4230           }
4231       }
4232     }
4233
4234   return 0;
4235 }
4236
4237 /* Convert a character string literal into a nul-terminated string.
4238    The input string is [IN ... LIMIT).
4239    The result is placed in RESULT.  RESULT can be the same as IN.
4240    The value returned in the end of the string written to RESULT,
4241    or NULL on error.  */
4242
4243 static /*@null@*/ char *
4244 convert_string (cppReader *pfile, /*@returned@*/ char *result,
4245                 char *in, char *limit, int handle_escapes)
4246 {
4247   char c;
4248   c = *in++;
4249
4250   if (c != '\"')
4251     {
4252       return NULL;
4253     }
4254
4255   while (in < limit)
4256     {
4257       c = *in++;
4258
4259       switch (c)
4260         {
4261         case '\0':
4262           return NULL;
4263         case '\"':
4264           limit = in;
4265           /*@switchbreak@*/ break;
4266         case '\\':
4267           if (handle_escapes)
4268             {
4269               char *bpc = (char *) in;
4270               int i = (char) cppReader_parseEscape (pfile, &bpc);
4271               in = (char *) bpc;
4272               if (i >= 0)
4273                 *result++ = (char) c;
4274               /*@switchbreak@*/ break;
4275             }
4276
4277           /*@fallthrough@*/
4278         default:
4279           *result++ = c;
4280         }
4281     }
4282
4283   *result = 0;
4284   return result;
4285 }
4286
4287 /*
4288  * interpret #line command.  Remembers previously seen fnames
4289  * in its very own hash table.
4290  */
4291
4292 /*@constant int FNAME_HASHSIZE@*/
4293 #define FNAME_HASHSIZE 37
4294
4295 static int
4296 do_line (cppReader *pfile, /*@unused@*/ struct directive *keyword)
4297 {
4298   cppBuffer *ip = cppReader_getBuffer (pfile);
4299   int new_lineno;
4300   size_t old_written = cppReader_getWritten (pfile);
4301   enum file_change_code file_change = same_file;
4302   enum cpp_token token;
4303
4304   token = get_directive_token (pfile);
4305
4306   if (token != CPP_NUMBER
4307       || !isdigit(pfile->token_buffer[old_written]))
4308     {
4309       cppReader_errorLit (pfile,
4310                     cstring_makeLiteralTemp ("invalid format `#line' command"));
4311
4312       goto bad_line_directive;
4313     }
4314
4315   /* The Newline at the end of this line remains to be processed.
4316      To put the next line at the specified line number,
4317      we must store a line number now that is one less.  */
4318   new_lineno = atoi (pfile->token_buffer + old_written) - 1;
4319   cppReader_setWritten (pfile, old_written);
4320
4321   /* NEW_LINENO is one less than the actual line number here.  */
4322   if (cppReader_isPedantic (pfile) && new_lineno < 0)
4323     cppReader_pedwarnLit (pfile,
4324                     cstring_makeLiteralTemp ("line number out of range in `#line' command"));
4325
4326   token = get_directive_token (pfile);
4327
4328   if (token == CPP_STRING) {
4329     char *fname = pfile->token_buffer + old_written;
4330     char *end_name;
4331     static hashNode fname_table[FNAME_HASHSIZE];
4332     hashNode hp; 
4333     hashNode *hash_bucket;
4334     char *p;
4335     size_t num_start;
4336     int fname_length;
4337
4338     /* Turn the file name, which is a character string literal,
4339        into a null-terminated string.  Do this in place.  */
4340     end_name = convert_string (pfile, fname, fname, cppReader_getPWritten (pfile), 1);
4341     if (end_name == NULL)
4342       {
4343         cppReader_errorLit (pfile,
4344                       cstring_makeLiteralTemp ("invalid format `#line' command"));
4345         goto bad_line_directive;
4346       }
4347
4348     fname_length = end_name - fname;
4349     num_start = cppReader_getWritten (pfile);
4350
4351     token = get_directive_token (pfile);
4352     if (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP) {
4353       p = pfile->token_buffer + num_start;
4354       if (cppReader_isPedantic (pfile))
4355         cppReader_pedwarnLit (pfile,
4356                         cstring_makeLiteralTemp ("garbage at end of `#line' command"));
4357
4358       if (token != CPP_NUMBER || *p < '0' || *p > '4' || p[1] != '\0')
4359         {
4360           cppReader_errorLit (pfile,
4361                         cstring_makeLiteralTemp ("invalid format `#line' command"));
4362           goto bad_line_directive;
4363         }
4364       if (*p == '1')
4365         file_change = enter_file;
4366       else if (*p == 2)
4367         file_change = leave_file;
4368       else if (*p == 3)
4369         ip->system_header_p = 1;
4370       else /* if (*p == 4) */
4371         ip->system_header_p = 2;
4372
4373       cppReader_setWritten (pfile, num_start);
4374       token = get_directive_token (pfile);
4375       p = pfile->token_buffer + num_start;
4376       if (token == CPP_NUMBER && p[1] == '\0' && (*p == '3' || *p== '4')) {
4377         ip->system_header_p = *p == 3 ? 1 : 2;
4378         token = get_directive_token (pfile);
4379       }
4380       if (token != CPP_VSPACE) {
4381         cppReader_errorLit (pfile,
4382                       cstring_makeLiteralTemp ("invalid format `#line' command"));
4383
4384         goto bad_line_directive;
4385       }
4386     }
4387
4388     hash_bucket =
4389       &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
4390     for (hp = *hash_bucket; hp != NULL; hp = hp->next)
4391       {
4392         if (hp->length == fname_length &&
4393             strncmp (hp->value.cpval, fname, size_fromInt (fname_length)) == 0) {
4394           ip->nominal_fname = cstring_fromChars (hp->value.cpval);
4395           break;
4396         }
4397       }
4398
4399     if (hp == 0) {
4400       /* Didn't find it; cons up a new one.  */
4401       hp = (hashNode) dmalloc (sizeof (*hp));
4402
4403       hp->prev = NULL;
4404       hp->bucket_hdr = NULL;
4405       hp->type = T_NONE;
4406       hp->name = cstring_undefined;
4407       hp->next = *hash_bucket;
4408
4409       *hash_bucket = hp;
4410
4411       hp->length = fname_length;
4412       hp->value.cpval = dmalloc (sizeof (*hp->value.cpval) * (fname_length + 1));
4413       memcpy (hp->value.cpval, fname, size_fromInt (fname_length));
4414       hp->value.cpval[fname_length] = '\0';
4415       ip->nominal_fname = cstring_fromChars (hp->value.cpval);
4416     }
4417   }
4418   else if (token != CPP_VSPACE && token != CPP_EOF)
4419     {
4420       cppReader_errorLit (pfile,
4421                     cstring_makeLiteralTemp ("invalid format `#line' command"));
4422       goto bad_line_directive;
4423     }
4424   else
4425     {
4426       ;
4427     }
4428
4429   ip->lineno = new_lineno;
4430 bad_line_directive:
4431   cppReader_skipRestOfLine (pfile);
4432   cppReader_setWritten (pfile, old_written);
4433   output_line_command (pfile, 0, file_change);
4434   return 0;
4435 }
4436
4437 /*
4438  * remove the definition of a symbol from the symbol table.
4439  * according to un*x /lib/cpp, it is not an error to undef
4440  * something that has no definitions, so it isn't one here either.
4441  */
4442
4443 static int
4444 do_undef (cppReader *pfile, struct directive *keyword, char *buf, char *limit)
4445 {
4446
4447   int sym_length;
4448   hashNode hp;
4449   char *orig_buf = buf;
4450
4451   SKIP_WHITE_SPACE (buf);
4452
4453   sym_length = cppReader_checkMacroName (pfile, buf, cstring_makeLiteralTemp ("macro"));
4454
4455   while ((hp = cppReader_lookup (buf, sym_length, -1)) != NULL)
4456     {
4457       /* If we are generating additional info for debugging (with -g) we
4458          need to pass through all effective #undef commands.  */
4459       if (CPPOPTIONS (pfile)->debug_output && (keyword != NULL))
4460         {
4461           pass_thru_directive (orig_buf, limit, pfile, keyword);
4462         }
4463
4464       if (hp->type != T_MACRO)
4465         {
4466           cppReader_warning (pfile,
4467                        message ("Undefining preprocessor builtin: %s",
4468                                 hp->name));
4469         }
4470
4471       cppReader_deleteMacro (hp);
4472     }
4473
4474   if (cppReader_isPedantic (pfile)) {
4475     buf += sym_length;
4476     SKIP_WHITE_SPACE (buf);
4477     if (buf != limit)
4478       {
4479         cppReader_pedwarnLit (pfile,
4480                         cstring_makeLiteralTemp ("garbage after `#undef' directive"));
4481       }
4482   }
4483
4484   return 0;
4485 }
4486
4487
4488 /*
4489  * Report an error detected by the program we are processing.
4490  * Use the text of the line in the error message.
4491  * (We use error because it prints the filename & line#.)
4492  */
4493
4494 static int
4495 do_error (cppReader *pfile, /*@unused@*/ struct directive *keyword,
4496           char *buf, char *limit)
4497 {
4498   int length = limit - buf;
4499   cstring copy = cstring_copyLength (buf, length);
4500   cstring adv = cstring_advanceWhiteSpace (copy);
4501
4502   cppReader_error (pfile, message ("#error %s", adv));
4503   cstring_free (copy);
4504   return 0;
4505 }
4506
4507 /*
4508  * Report a warning detected by the program we are processing.
4509  * Use the text of the line in the warning message, then continue.
4510  * (We use error because it prints the filename & line#.)
4511  */
4512
4513 static int
4514 do_warning (cppReader *pfile, /*@unused@*/ struct directive *keyword,
4515             char *buf, char *limit)
4516 {
4517   int length = limit - buf;
4518   cstring copy = cstring_copyLength (buf, length);
4519   cstring adv = cstring_advanceWhiteSpace (copy);
4520   cppReader_warning (pfile, message ("#warning %s", adv));
4521   cstring_free (copy);
4522   return 0;
4523 }
4524
4525
4526 /* #ident has already been copied to the output file, so just ignore it.  */
4527
4528 static int
4529 do_ident (cppReader *pfile, /*@unused@*/ struct directive *keyword,
4530           /*@unused@*/ char *buf, /*@unused@*/ char *limit)
4531 {
4532   /* Allow #ident in system headers, since that's not user's fault.  */
4533   if (cppReader_isPedantic (pfile) && !cppReader_getBuffer (pfile)->system_header_p)
4534     cppReader_pedwarnLit (pfile,
4535                     cstring_makeLiteralTemp ("ANSI C does not allow `#ident'"));
4536
4537   /* Leave rest of line to be read by later calls to cppGetToken.  */
4538
4539   return 0;
4540 }
4541
4542 /* #pragma and its argument line have already been copied to the output file.
4543    Just check for some recognized pragmas that need validation here.  */
4544
4545 static int
4546 do_pragma (cppReader *pfile, /*@unused@*/ struct directive *keyword,
4547            /*@unused@*/ char *buf, /*@unused@*/ char *limit)
4548 {
4549   while (*buf == ' ' || *buf == '\t')
4550     {
4551       buf++;
4552     }
4553
4554   if (!strncmp (buf, "implementation", 14)) {
4555     /* Be quiet about `#pragma implementation' for a file only if it hasn't
4556        been included yet.  */
4557     struct file_name_list *ptr;
4558     char *p = buf + 14, *fname, *inc_fname;
4559     int fname_len;
4560     SKIP_WHITE_SPACE (p);
4561     if (*p == '\n' || *p != '\"')
4562       return 0;
4563
4564     fname = p + 1;
4565     p = (char *) strchr (fname, '\"');
4566     fname_len = p != NULL ? p - fname : mstring_length (fname);
4567
4568     for (ptr = pfile->all_include_files; ptr != NULL; ptr = ptr->next)
4569       {
4570         inc_fname = (char *) strrchr (cstring_toCharsSafe (ptr->fname), CONNECTCHAR);
4571         inc_fname = (inc_fname != NULL)
4572           ? inc_fname + 1 : cstring_toCharsSafe (ptr->fname);
4573
4574         if ((inc_fname != NULL)
4575             && (strncmp (inc_fname, fname, size_fromInt (fname_len)) == 0))
4576           {
4577             cpp_setLocation (pfile);
4578
4579             ppllerror (message ("`#pragma implementation' for `%s' appears "
4580                                 "after file is included",
4581                                 cstring_fromChars (fname)));
4582           }
4583       }
4584   }
4585
4586   return 0;
4587 }
4588
4589 /*
4590  * handle #if command by
4591  *   1) inserting special `defined' keyword into the hash table
4592  *      that gets turned into 0 or 1 by special_symbol (thus,
4593  *      if the luser has a symbol called `defined' already, it won't
4594  *      work inside the #if command)
4595  *   2) rescan the input into a temporary output buffer
4596  *   3) pass the output buffer to the yacc parser and collect a value
4597  *   4) clean up the mess left from steps 1 and 2.
4598  *   5) call conditional_skip to skip til the next #endif (etc.),
4599  *      or not, depending on the value from step 3.
4600  */
4601
4602 static int
4603 do_if (cppReader *pfile, /*@unused@*/ struct directive *keyword,
4604        char *buf, char *limit)
4605 {
4606   HOST_WIDE_INT value = eval_if_expression (pfile, buf, limit - buf);
4607   conditional_skip (pfile, value == 0, T_IF, NULL);
4608   return 0;
4609 }
4610
4611 /*
4612  * handle a #elif directive by not changing  if_stack  either.
4613  * see the comment above do_else.
4614  */
4615
4616 static int do_elif (cppReader *pfile, /*@unused@*/ struct directive *keyword,
4617                     char *buf, char *limit)
4618 {
4619   if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack)
4620     {
4621       cppReader_errorLit (pfile,
4622                     cstring_makeLiteralTemp ("Preprocessor command #elif is not within a conditional"));
4623       return 0;
4624     }
4625   else
4626     {
4627       llassert (pfile->if_stack != NULL);
4628
4629       if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF)
4630         {
4631           cppReader_errorLit (pfile,
4632                         cstring_makeLiteralTemp ("`#elif' after `#else'"));
4633
4634           if (pfile->if_stack->fname != NULL
4635               && cppReader_getBuffer (pfile)->fname != NULL
4636               && !cstring_equal (pfile->if_stack->fname,
4637                                  cppReader_getBuffer (pfile)->nominal_fname))
4638             fprintf (stderr, ", file %s", cstring_toCharsSafe (pfile->if_stack->fname));
4639           fprintf (stderr, ")\n");
4640         }
4641       pfile->if_stack->type = T_ELIF;
4642     }
4643
4644   if (pfile->if_stack->if_succeeded)
4645     {
4646       skip_if_group (pfile, 0);
4647     }
4648   else
4649     {
4650       HOST_WIDE_INT value = eval_if_expression (pfile, buf, limit - buf);
4651       if (value == 0)
4652         skip_if_group (pfile, 0);
4653       else
4654         {
4655           ++pfile->if_stack->if_succeeded;      /* continue processing input */
4656           output_line_command (pfile, 1, same_file);
4657         }
4658     }
4659
4660   return 0;
4661 }
4662
4663 /*
4664  * evaluate a #if expression in BUF, of length LENGTH,
4665  * then parse the result as a C expression and return the value as an int.
4666  */
4667
4668 static HOST_WIDE_INT
4669 eval_if_expression (cppReader *pfile,
4670                     /*@unused@*/ char *buf,
4671                     /*@unused@*/ int length)
4672 {
4673   hashNode save_defined;
4674   HOST_WIDE_INT value;
4675   size_t old_written = cppReader_getWritten (pfile);
4676
4677   save_defined = cppReader_install ("defined", -1, T_SPEC_DEFINED, 0, 0, -1);
4678   pfile->pcp_inside_if = 1;
4679
4680   value = cppReader_parseExpression (pfile);
4681   pfile->pcp_inside_if = 0;
4682
4683   /* Clean up special symbol */
4684   cppReader_deleteMacro (save_defined);
4685
4686   cppReader_setWritten (pfile, old_written); /* Pop */
4687
4688   return value;
4689 }
4690
4691 /*
4692  * routine to handle ifdef/ifndef.  Try to look up the symbol,
4693  * then do or don't skip to the #endif/#else/#elif depending
4694  * on what directive is actually being processed.
4695  */
4696
4697 static int
4698 do_xifdef (cppReader *pfile, struct directive *keyword,
4699            /*@unused@*/ char *unused1, /*@unused@*/ char *unused2)
4700 {
4701   int skip;
4702   cppBuffer *ip = cppReader_getBuffer (pfile);
4703   char *ident;
4704   int ident_length;
4705   enum cpp_token token;
4706   int start_of_file = 0;
4707   char *control_macro = 0;
4708   size_t old_written = cppReader_getWritten (pfile);
4709
4710   DPRINTF (("do xifdef: %d",
4711             keyword->type == T_IFNDEF));
4712
4713   /* Detect a #ifndef at start of file (not counting comments).  */
4714   if (cstring_isDefined (ip->fname) && keyword->type == T_IFNDEF)
4715     {
4716       start_of_file = pfile->only_seen_white == 2;
4717     }
4718
4719   pfile->no_macro_expand++;
4720   token = get_directive_token (pfile);
4721   pfile->no_macro_expand--;
4722
4723   ident = pfile->token_buffer + old_written;
4724   ident_length = size_toInt (cppReader_getWritten (pfile) - old_written);
4725   cppReader_setWritten (pfile, old_written); /* Pop */
4726
4727   if (token == CPP_VSPACE || token == CPP_POP || token == CPP_EOF)
4728     {
4729       skip = (keyword->type == T_IFDEF);
4730       if (! cppReader_isTraditional (pfile))
4731         {
4732           cppReader_pedwarn (pfile,
4733                        message ("`#%s' with no argument", keyword->name));
4734         }
4735     }
4736   else if (token == CPP_NAME)
4737     {
4738       hashNode hp = cppReader_lookup (ident, ident_length, -1);
4739       skip = (keyword->type == T_IFDEF) 
4740         ? (hp == NULL) : (hp != NULL);
4741
4742       DPRINTF (("hp null: %d / %d / %d",
4743                 (hp == NULL),
4744                 (keyword->type == T_IFNDEF),
4745                 skip));
4746                 
4747       if (start_of_file && !skip)
4748         {
4749           DPRINTF (("Not skipping!"));
4750           control_macro = (char *) dmalloc (size_fromInt (ident_length + 1));
4751           memcpy (control_macro, ident, size_fromInt (ident_length + 1));
4752         }
4753     }
4754   else
4755     {
4756       skip = (keyword->type == T_IFDEF);
4757       if (! cppReader_isTraditional (pfile))
4758         {
4759           cppReader_error (pfile,
4760                      message ("`#%s' with invalid argument", keyword->name));
4761         }
4762     }
4763
4764   if (!cppReader_isTraditional (pfile))
4765     {
4766       int c;
4767       cppSkipHspace (pfile);
4768       c = cppReader_peekC (pfile);
4769       if (c != EOF && c != '\n')
4770         {
4771           cppReader_pedwarn (pfile,
4772                              message ("garbage at end of `#%s' argument", keyword->name));
4773         }
4774     }
4775
4776   cppReader_skipRestOfLine (pfile);
4777
4778   DPRINTF (("Conditional skip: %d", skip));
4779   conditional_skip (pfile, skip, T_IF, control_macro);
4780   return 0;
4781 }
4782
4783 /* Push TYPE on stack; then, if SKIP is nonzero, skip ahead.
4784    If this is a #ifndef starting at the beginning of a file,
4785    CONTROL_MACRO is the macro name tested by the #ifndef.
4786    Otherwise, CONTROL_MACRO is 0.  */
4787
4788 static void
4789 conditional_skip (cppReader *pfile, int skip,
4790                   enum node_type type,
4791                   /*@dependent@*/ char *control_macro)
4792 {
4793   cppIfStackFrame *temp = (cppIfStackFrame *) dmalloc (sizeof (*temp));
4794
4795   temp->fname = cppReader_getBuffer (pfile)->nominal_fname;
4796   temp->next = pfile->if_stack;
4797   temp->control_macro = control_macro;
4798   temp->lineno = 0;
4799   temp->if_succeeded = 0;
4800
4801   pfile->if_stack = temp;
4802   pfile->if_stack->type = type;
4803
4804   if (skip != 0)
4805     {
4806       skip_if_group (pfile, 0);
4807       return;
4808     }
4809   else
4810     {
4811       ++pfile->if_stack->if_succeeded;
4812       output_line_command (pfile, 1, same_file);
4813     }
4814 }
4815
4816 /*
4817  * skip to #endif, #else, or #elif.  adjust line numbers, etc.
4818  * leaves input ptr at the sharp sign found.
4819  * If ANY is nonzero, return at next directive of any sort.
4820  */
4821
4822 static void
4823 skip_if_group (cppReader *pfile, int any)
4824 {
4825   int c;
4826   struct directive *kt;
4827   cppIfStackFrame *save_if_stack = pfile->if_stack; /* don't pop past here */
4828   register int ident_length;
4829   char *ident;
4830   struct parse_marker line_start_mark;
4831
4832   parseSetMark (&line_start_mark, pfile);
4833
4834   if (CPPOPTIONS (pfile)->output_conditionals) {
4835     static char failed[] = "#failed\n";
4836     cppReader_puts (pfile, failed, sizeof(failed)-1);
4837     pfile->lineno++;
4838     output_line_command (pfile, 1, same_file);
4839   }
4840
4841 beg_of_line:
4842   if (CPPOPTIONS (pfile)->output_conditionals)
4843     {
4844       cppBuffer *pbuf = cppReader_getBuffer (pfile);
4845       char *start_line;
4846
4847       llassert (pbuf->buf != NULL);
4848
4849       start_line = pbuf->buf + line_start_mark.position;
4850       cppReader_puts (pfile, start_line, size_fromInt (pbuf->cur - start_line));
4851     }
4852
4853   parseMoveMark (&line_start_mark, pfile);
4854
4855   if (!cppReader_isTraditional (pfile))
4856     {
4857       cppSkipHspace (pfile);
4858     }
4859
4860   c  = cppReader_getC (pfile);
4861   if (c == '#')
4862     {
4863       size_t old_written = cppReader_getWritten (pfile);
4864       cppSkipHspace (pfile);
4865
4866       parse_name (pfile, cppReader_getC (pfile));
4867       ident_length = size_toInt (cppReader_getWritten (pfile) - old_written);
4868       ident = pfile->token_buffer + old_written;
4869       pfile->limit = ident;
4870
4871       for (kt = directive_table; kt->length >= 0; kt++)
4872         {
4873           cppIfStackFrame *temp;
4874           if (ident_length == kt->length
4875               && cstring_equalPrefix (kt->name, ident))
4876             {
4877               /* If we are asked to return on next directive, do so now.  */
4878               if (any)
4879                 {
4880                   goto done;
4881                 }
4882
4883               switch (kt->type)
4884                 {
4885                 case T_IF:
4886                 case T_IFDEF:
4887                 case T_IFNDEF:
4888                   temp = (cppIfStackFrame *) dmalloc (sizeof (*temp));
4889                   temp->next = pfile->if_stack;
4890                   temp->fname = cppReader_getBuffer (pfile)->nominal_fname;
4891                   temp->type = kt->type;
4892                   temp->lineno = 0;
4893                   temp->if_succeeded = 0;
4894                   temp->control_macro = NULL;
4895
4896                   pfile->if_stack = temp;
4897                   /*@switchbreak@*/ break;
4898                 case T_ELSE:
4899                 case T_ENDIF:
4900                   if (cppReader_isPedantic (pfile) && pfile->if_stack != save_if_stack)
4901                     validate_else (pfile,
4902                                    cstring_makeLiteralTemp (kt->type == T_ELSE ? "#else" : "#endif"));
4903                   /*@fallthrough@*/
4904                 case T_ELIF:
4905                   if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack)
4906                     {
4907                       cppReader_error (pfile,
4908                                  message ("Preprocessor command #%s is not within a conditional", kt->name));
4909                       /*@switchbreak@*/ break;
4910                     }
4911                   else if (pfile->if_stack == save_if_stack)
4912                     {
4913                       goto done;                /* found what we came for */
4914                     }
4915                   else
4916                     {
4917                       ;
4918                     }
4919
4920                   if (kt->type != T_ENDIF)
4921                     {
4922                       llassert (pfile->if_stack != NULL);
4923
4924                       if (pfile->if_stack->type == T_ELSE)
4925                         {
4926                           cppReader_errorLit (pfile,
4927                                         cstring_makeLiteralTemp ("`#else' or `#elif' after `#else'"));
4928                         }
4929
4930                       pfile->if_stack->type = kt->type;
4931                       /*@switchbreak@*/ break;
4932                     }
4933
4934                   temp = pfile->if_stack;
4935                   llassert (temp != NULL);
4936                   pfile->if_stack = temp->next;
4937                   sfree (temp);
4938                   /*@switchbreak@*/ break;
4939                 default: ;
4940                   /*@-branchstate@*/ 
4941                 }
4942               /*@=branchstate@*/
4943               break;
4944             }
4945           
4946           /* Don't let erroneous code go by.  */
4947           
4948           if (kt->length < 0 && !CPPOPTIONS (pfile)->lang_asm
4949               && cppReader_isPedantic (pfile))
4950             {
4951               cppReader_pedwarnLit (pfile,
4952                                     cstring_makeLiteralTemp ("Invalid preprocessor directive name"));
4953             }
4954         }
4955
4956       c = cppReader_getC (pfile);
4957     }
4958   /* We're in the middle of a line.  Skip the rest of it.  */
4959   for (;;) {
4960     size_t old;
4961
4962     switch (c)
4963       {
4964       case EOF:
4965         goto done;
4966       case '/':                 /* possible comment */
4967         c = skip_comment (pfile, NULL);
4968         if (c == EOF)
4969           goto done;
4970         /*@switchbreak@*/ break;
4971       case '\"':
4972       case '\'':
4973         cppReader_forward (pfile, -1);
4974         old = cppReader_getWritten (pfile);
4975         (void) cppGetToken (pfile);
4976         cppReader_setWritten (pfile, old);
4977         /*@switchbreak@*/ break;
4978       case '\\':
4979         /* Char after backslash loses its special meaning.  */
4980         if (cppReader_peekC (pfile) == '\n')
4981           {
4982             cppReader_forward (pfile, 1);
4983           }
4984
4985         /*@switchbreak@*/ break;
4986       case '\n':
4987         goto beg_of_line;
4988       }
4989     c = cppReader_getC (pfile);
4990   }
4991 done:
4992   if (CPPOPTIONS (pfile)->output_conditionals) {
4993     static char end_failed[] = "#endfailed\n";
4994     cppReader_puts (pfile, end_failed, sizeof(end_failed)-1);
4995     pfile->lineno++;
4996   }
4997   pfile->only_seen_white = 1;
4998
4999   parseGotoMark (&line_start_mark, pfile);
5000   parseClearMark (&line_start_mark);
5001 }
5002
5003 /*
5004  * handle a #else directive.  Do this by just continuing processing
5005  * without changing  if_stack ;  this is so that the error message
5006  * for missing #endif's etc. will point to the original #if.  It
5007  * is possible that something different would be better.
5008  */
5009
5010 static int
5011 do_else (cppReader *pfile, /*@unused@*/ struct directive *keyword,
5012         /*@unused@*/ char *buf, /*@unused@*/ char *limit)
5013 {
5014   if (cppReader_isPedantic (pfile))
5015     {
5016       validate_else (pfile, cstring_makeLiteralTemp ("#else"));
5017     }
5018
5019   cppReader_skipRestOfLine (pfile);
5020
5021   if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack) {
5022     cppReader_errorLit (pfile,
5023                   cstring_makeLiteralTemp ("Preprocessor command #else is not within a conditional"));
5024     return 0;
5025   } else {
5026     /* #ifndef can't have its special treatment for containing the whole file
5027        if it has a #else clause.  */
5028
5029     llassert (pfile->if_stack != NULL);
5030
5031     pfile->if_stack->control_macro = 0;
5032
5033     if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF)
5034       {
5035         cpp_setLocation (pfile);
5036         genppllerrorhint (FLG_PREPROC,
5037                           message ("Pre-processor directive #else after #else"),
5038                           message ("%q: Location of match",
5039                                    fileloc_unparseRaw (pfile->if_stack->fname,
5040                                                        pfile->if_stack->lineno)));
5041       }
5042
5043     pfile->if_stack->type = T_ELSE;
5044   }
5045
5046   if (pfile->if_stack->if_succeeded)
5047     skip_if_group (pfile, 0);
5048   else {
5049     ++pfile->if_stack->if_succeeded;    /* continue processing input */
5050     output_line_command (pfile, 1, same_file);
5051   }
5052
5053   return 0;
5054 }
5055
5056 /*
5057  * unstack after #endif command
5058  */
5059
5060 static int
5061 do_endif (cppReader *pfile, /*@unused@*/ struct directive *keyword,
5062           /*@unused@*/ char *buf, /*@unused@*/ char *limit)
5063 {
5064   if (cppReader_isPedantic (pfile))
5065     {
5066       validate_else (pfile, cstring_makeLiteralTemp ("#endif"));
5067     }
5068
5069   cppReader_skipRestOfLine (pfile);
5070
5071   if (pfile->if_stack == cppReader_getBuffer (pfile)->if_stack)
5072     {
5073       cppReader_errorLit (pfile, cstring_makeLiteralTemp ("Unbalanced #endif"));
5074     }
5075   else
5076     {
5077       cppIfStackFrame *temp = pfile->if_stack;
5078
5079       llassert (temp != NULL);
5080
5081       pfile->if_stack = temp->next;
5082       if (temp->control_macro != 0)
5083         {
5084           /* This #endif matched a #ifndef at the start of the file.
5085              See if it is at the end of the file.  */
5086           struct parse_marker start_mark;
5087           int c;
5088
5089           parseSetMark (&start_mark, pfile);
5090
5091           for (;;)
5092             {
5093               cppSkipHspace (pfile);
5094               c = cppReader_getC (pfile);
5095
5096               if (c != '\n')
5097                 break;
5098             }
5099
5100           parseGotoMark (&start_mark, pfile);
5101           parseClearMark (&start_mark);
5102
5103           if (c == EOF)
5104             {
5105               /* If we get here, this #endif ends a #ifndef
5106                  that contains all of the file (aside from whitespace).
5107                  Arrange not to include the file again
5108                  if the macro that was tested is defined.
5109
5110                  Do not do this for the top-level file in a -include or any
5111                  file in a -imacros.  */
5112               struct file_name_list *ifile = pfile->all_include_files;
5113
5114               for ( ; ifile != NULL; ifile = ifile->next)
5115                 {
5116                   if (cstring_equal (ifile->fname, cppReader_getBuffer (pfile)->fname))
5117                     {
5118                       ifile->control_macro = temp->control_macro;
5119                       break;
5120                     }
5121                 }
5122             }
5123         }
5124
5125       sfree (temp);
5126       output_line_command (pfile, 1, same_file);
5127     }
5128   return 0;
5129 }
5130
5131 /* When an #else or #endif is found while skipping failed conditional,
5132    if -pedantic was specified, this is called to warn about text after
5133    the command name.  P points to the first char after the command name.  */
5134
5135 static void
5136 validate_else (cppReader *pfile, cstring directive)
5137 {
5138   int c;
5139   cppSkipHspace (pfile);
5140   c = cppReader_peekC (pfile);
5141   if (c != EOF && c != '\n')
5142     {
5143       cppReader_pedwarn (pfile,
5144                    message ("text following `%s' violates ANSI standard", directive));
5145     }
5146 }
5147
5148 /*
5149 ** Get the next token, and add it to the text in pfile->token_buffer.
5150 ** Return the kind of token we got.
5151 */
5152
5153 enum cpp_token
5154 cppGetToken (cppReader *pfile)
5155 {
5156   int c, c2, c3;
5157   size_t old_written = 0;
5158   int start_line, start_column;
5159   enum cpp_token token;
5160   struct cppOptions *opts = CPPOPTIONS (pfile);
5161   cppReader_getBuffer (pfile)->prev = cppReader_getBuffer (pfile)->cur;
5162
5163 get_next:
5164   c = cppReader_getC (pfile);
5165
5166   if (c == EOF)
5167     {
5168     handle_eof:
5169       if (cppReader_getBuffer (pfile)->seen_eof)
5170         {
5171           cppBuffer *buf = cppReader_popBuffer (pfile);
5172
5173           if (buf != cppReader_nullBuffer (pfile))
5174             {
5175               goto get_next;
5176             }
5177           else
5178             {
5179               return CPP_EOF;
5180             }
5181         }
5182       else
5183         {
5184           cppBuffer *next_buf = cppBuffer_prevBuffer (cppReader_getBuffer (pfile));
5185           cppReader_getBuffer (pfile)->seen_eof = 1;
5186
5187           if (cstring_isDefined (cppReader_getBuffer (pfile)->nominal_fname)
5188               && next_buf != cppReader_nullBuffer (pfile))
5189             {
5190               /* We're about to return from an #include file.
5191                  Emit #line information now (as part of the CPP_POP) result.
5192                  But the #line refers to the file we will pop to.  */
5193               cppBuffer *cur_buffer = CPPBUFFER (pfile);
5194               CPPBUFFER (pfile) = next_buf;
5195               pfile->input_stack_listing_current = 0;
5196               output_line_command (pfile, 0, leave_file);
5197               CPPBUFFER (pfile) = cur_buffer;
5198             }
5199           return CPP_POP;
5200         }
5201     }
5202   else
5203     {
5204       long newlines;
5205       struct parse_marker start_mark;
5206
5207       switch (c)
5208         {
5209         case '/':
5210           if (cppReader_peekC (pfile) == '=')
5211             {
5212               goto op2;
5213             }
5214
5215           if (opts->put_out_comments)
5216             {
5217               parseSetMark (&start_mark, pfile);
5218             }
5219
5220           newlines = 0;
5221           cppBuffer_lineAndColumn (cppReader_fileBuffer (pfile),
5222                                    &start_line, &start_column);
5223           c = skip_comment (pfile, &newlines);
5224
5225           if (opts->put_out_comments && (c == '/' || c == EOF))
5226             {
5227               assertSet (&start_mark);
5228               parseClearMark (&start_mark);
5229             }
5230
5231           if (c == '/')
5232             goto randomchar;
5233           if (c == EOF)
5234             {
5235               cppReader_errorWithLine (pfile, start_line, start_column,
5236                                        cstring_makeLiteral ("Unterminated comment"));
5237               goto handle_eof;
5238             }
5239           c = '/';  /* Initial letter of comment.  */
5240         return_comment:
5241           /* Comments are equivalent to spaces.
5242              For -traditional, a comment is equivalent to nothing.  */
5243
5244           if (opts->put_out_comments)
5245             {
5246               enum cpp_token res;
5247
5248               assertSet (&start_mark);
5249               res = cpp_handleComment (pfile, &start_mark);
5250               pfile->lineno += newlines;
5251               return res;
5252             }
5253           else if (cppReader_isTraditional (pfile))
5254             {
5255               return CPP_COMMENT;
5256             }
5257           else
5258             {
5259               cppReader_reserve(pfile, 1);
5260               cppReader_putCharQ (pfile, ' ');
5261               return CPP_HSPACE;
5262             }
5263
5264         case '#':
5265           if (!pfile->only_seen_white)
5266             {
5267               goto randomchar;
5268             }
5269
5270           if (cppReader_handleDirective (pfile))
5271             {
5272               return CPP_DIRECTIVE;
5273             }
5274
5275           pfile->only_seen_white = 0;
5276           return CPP_OTHER;
5277
5278         case '\"':
5279         case '\'':
5280           /* A single quoted string is treated like a double -- some
5281              programs (e.g., troff) are perverse this way */
5282           cppBuffer_lineAndColumn (cppReader_fileBuffer (pfile),
5283                                    &start_line, &start_column);
5284           old_written = cppReader_getWritten (pfile);
5285         string:
5286           cppReader_putChar (pfile, c);
5287           while (TRUE)
5288             {
5289               int cc = cppReader_getC (pfile);
5290               if (cc == EOF)
5291                 {
5292                   if (cppBuffer_isMacro (CPPBUFFER (pfile)))
5293                     {
5294                       /* try harder: this string crosses a macro expansion
5295                          boundary.  This can happen naturally if -traditional.
5296                          Otherwise, only -D can make a macro with an unmatched
5297                          quote.  */
5298                       cppBuffer *next_buf
5299                         = cppBuffer_prevBuffer (cppReader_getBuffer (pfile));
5300                       (*cppReader_getBuffer (pfile)->cleanup)
5301                         (cppReader_getBuffer (pfile), pfile);
5302                       CPPBUFFER (pfile) = next_buf;
5303                       continue;
5304                     }
5305                   if (!cppReader_isTraditional (pfile))
5306                     {
5307                       cpp_setLocation (pfile);
5308
5309                       setLine (long_toInt (start_line));
5310                       setColumn (long_toInt (start_column));
5311
5312                       if (pfile->multiline_string_line != long_toInt (start_line)
5313                           && pfile->multiline_string_line != 0)
5314                         {
5315                           genppllerrorhint
5316                             (FLG_PREPROC,
5317                              message ("Unterminated string or character constant"),
5318                              message ("%q: Possible real start of unterminated constant",
5319                                       fileloc_unparseRaw 
5320                                       (fileloc_filename (g_currentloc),
5321                                        pfile->multiline_string_line)));
5322                           pfile->multiline_string_line = 0;
5323                         }
5324                       else
5325                         {
5326                           genppllerror
5327                             (FLG_PREPROC,
5328                              message ("Unterminated string or character constant"));
5329                         }
5330                     }
5331                   /*@loopbreak@*/ break;
5332                 }
5333               cppReader_putChar (pfile, cc);
5334               switch (cc)
5335                 {
5336                 case '\n':
5337                   /* Traditionally, end of line ends a string constant with
5338                      no error.  So exit the loop and record the new line.  */
5339                   if (cppReader_isTraditional (pfile))
5340                     goto while2end;
5341                   if (c == '\'')
5342                     {
5343                       goto while2end;
5344                     }
5345                   if (cppReader_isPedantic (pfile)
5346                       && pfile->multiline_string_line == 0)
5347                     {
5348                       cppReader_pedwarnWithLine
5349                         (pfile, long_toInt (start_line),
5350                          long_toInt (start_column),
5351                          cstring_makeLiteral ("String constant runs past end of line"));
5352                     }
5353                   if (pfile->multiline_string_line == 0)
5354                     {
5355                       pfile->multiline_string_line = start_line;
5356                     }
5357
5358                   /*@switchbreak@*/ break;
5359
5360                 case '\\':
5361                   cc = cppReader_getC (pfile);
5362                   if (cc == '\n')
5363                     {
5364                       /* Backslash newline is replaced by nothing at all.  */
5365                       cppReader_adjustWritten (pfile, -1);
5366                       pfile->lineno++;
5367                     }
5368                   else
5369                     {
5370                       /* ANSI stupidly requires that in \\ the second \
5371                          is *not* prevented from combining with a newline.  */
5372                       NEWLINE_FIX1(cc);
5373                       if (cc != EOF)
5374                         cppReader_putChar (pfile, cc);
5375                     }
5376                   /*@switchbreak@*/ break;
5377
5378                 case '\"':
5379                 case '\'':
5380                   if (cc == c)
5381                     goto while2end;
5382                   /*@switchbreak@*/ break;
5383                 }
5384             }
5385         while2end:
5386           pfile->lineno += count_newlines (pfile->token_buffer + old_written,
5387                                            cppReader_getPWritten (pfile));
5388           pfile->only_seen_white = 0;
5389           return c == '\'' ? CPP_CHAR : CPP_STRING;
5390
5391         case '$':
5392           if (!opts->dollars_in_ident)
5393             goto randomchar;
5394           goto letter;
5395
5396         case ':':
5397           if (opts->cplusplus && cppReader_peekC (pfile) == ':')
5398             goto op2;
5399           goto randomchar;
5400
5401         case '&':
5402         case '+':
5403         case '|':
5404           NEWLINE_FIX;
5405           c2 = cppReader_peekC (pfile);
5406           if (c2 == c || c2 == '=')
5407             goto op2;
5408           goto randomchar;
5409
5410         case '*':
5411         case '!':
5412         case '%':
5413         case '=':
5414         case '^':
5415           NEWLINE_FIX;
5416           if (cppReader_peekC (pfile) == '=')
5417             goto op2;
5418           goto randomchar;
5419
5420         case '-':
5421           NEWLINE_FIX;
5422           c2 = cppReader_peekC (pfile);
5423           if (c2 == '-' && opts->chill)
5424             {
5425               /* Chill style comment */
5426               if (opts->put_out_comments)
5427                 {
5428                   parseSetMark (&start_mark, pfile);
5429                 }
5430
5431               cppReader_forward (pfile, 1);  /* Skip second '-'.  */
5432
5433               for (;;)
5434                 {
5435                   c = cppReader_getC (pfile);
5436                   if (c == EOF)
5437                     /*@loopbreak@*/ break;
5438                   if (c == '\n')
5439                     {
5440                       /* Don't consider final '\n' to be part of comment.  */
5441                       cppReader_forward (pfile, -1);
5442                       /*@loopbreak@*/ break;
5443                     }
5444                 }
5445               c = '-';
5446               goto return_comment;
5447             }
5448           if (c2 == '-' || c2 == '=' || c2 == '>')
5449             goto op2;
5450           goto randomchar;
5451
5452         case '<':
5453           if (pfile->parsing_include_directive)
5454             {
5455               for (;;)
5456                 {
5457                   cppReader_putChar (pfile, c);
5458                   if (c == '>')
5459                     /*@loopbreak@*/ break;
5460                   c = cppReader_getC (pfile);
5461                   NEWLINE_FIX1 (c);
5462                   if (c == '\n' || c == EOF)
5463                     {
5464                       cppReader_errorLit (pfile,
5465                                     cstring_makeLiteralTemp ("Missing '>' in \"#include <FILENAME>\""));
5466                       /*@loopbreak@*/ break;
5467                     }
5468                 }
5469               return CPP_STRING;
5470             }
5471           /*@fallthrough@*/
5472         case '>':
5473           NEWLINE_FIX;
5474           c2 = cppReader_peekC (pfile);
5475           if (c2 == '=')
5476             goto op2;
5477           if (c2 != c)
5478             goto randomchar;
5479           cppReader_forward (pfile, 1);
5480           cppReader_reserve (pfile, 4);
5481           cppReader_putChar (pfile, c);
5482           cppReader_putChar (pfile, c2);
5483           NEWLINE_FIX;
5484           c3 = cppReader_peekC (pfile);
5485           if (c3 == '=')
5486             cppReader_putCharQ (pfile, cppReader_getC (pfile));
5487           cppReader_nullTerminateQ (pfile);
5488           pfile->only_seen_white = 0;
5489           return CPP_OTHER;
5490
5491         case '@':
5492           if (cppReader_getBuffer (pfile)->has_escapes)
5493             {
5494               c = cppReader_getC (pfile);
5495               if (c == '-')
5496                 {
5497                   if (pfile->output_escapes)
5498                     cppReader_puts (pfile, "@-", 2);
5499                   parse_name (pfile, cppReader_getC (pfile));
5500                   return CPP_NAME;
5501                 }
5502               else if (is_space [c])
5503                 {
5504                   cppReader_reserve (pfile, 2);
5505                   if (pfile->output_escapes)
5506                     cppReader_putCharQ (pfile, '@');
5507                   cppReader_putCharQ (pfile, c);
5508                   return CPP_HSPACE;
5509                 }
5510               else
5511                 {
5512                   ;
5513                 }
5514             }
5515           if (pfile->output_escapes)
5516             {
5517               cppReader_puts (pfile, "@@", 2);
5518               return CPP_OTHER;
5519             }
5520           goto randomchar;
5521         case '.':
5522           NEWLINE_FIX;
5523           c2 = cppReader_peekC (pfile);
5524           if (isdigit(c2))
5525             {
5526               cppReader_reserve(pfile, 2);
5527               cppReader_putCharQ (pfile, '.');
5528               c = cppReader_getC (pfile);
5529               goto number;
5530             }
5531
5532           /* FIXME - misses the case "..\\\n." */
5533           if (c2 == '.' && cpp_peekN (pfile, 1) == '.')
5534             {
5535               cppReader_reserve(pfile, 4);
5536               cppReader_putCharQ (pfile, '.');
5537               cppReader_putCharQ (pfile, '.');
5538               cppReader_putCharQ (pfile, '.');
5539               cppReader_forward (pfile, 2);
5540               cppReader_nullTerminateQ (pfile);
5541               pfile->only_seen_white = 0;
5542               return CPP_3DOTS;
5543             }
5544           goto randomchar;
5545         op2:
5546           token = CPP_OTHER;
5547           pfile->only_seen_white = 0;
5548         op2any:
5549           cppReader_reserve(pfile, 3);
5550           cppReader_putCharQ (pfile, c);
5551           cppReader_putCharQ (pfile, cppReader_getC (pfile));
5552           cppReader_nullTerminateQ (pfile);
5553           return token;
5554
5555         case 'L':
5556           NEWLINE_FIX;
5557           c2 = cppReader_peekC (pfile);
5558           if ((c2 == '\'' || c2 == '\"') && !cppReader_isTraditional (pfile))
5559             {
5560               cppReader_putChar (pfile, c);
5561               c = cppReader_getC (pfile);
5562               goto string;
5563             }
5564           goto letter;
5565
5566         case '0': case '1': case '2': case '3': case '4':
5567         case '5': case '6': case '7': case '8': case '9':
5568         number:
5569           c2  = '.';
5570           for (;;)
5571             {
5572               cppReader_reserve (pfile, 2);
5573               cppReader_putCharQ (pfile, c);
5574               NEWLINE_FIX;
5575               c = cppReader_peekC (pfile);
5576               if (c == EOF)
5577                 /*@loopbreak@*/ break;
5578               if (!is_idchar[c] && c != '.'
5579                   && ((c2 != 'e' && c2 != 'E'
5580                        && ((c2 != 'p' && c2 != 'P') || cppReader_isC89 (pfile)))
5581                       || (c != '+' && c != '-')))
5582                 /*@loopbreak@*/ break;
5583               cppReader_forward (pfile, 1);
5584               c2= c;
5585             }
5586
5587           cppReader_nullTerminateQ (pfile);
5588           pfile->only_seen_white = 0;
5589           return CPP_NUMBER;
5590
5591         case 'b': case 'c': case 'd': case 'h': case 'o':
5592         case 'B': case 'C': case 'D': case 'H': case 'O':
5593           if (opts->chill && cppReader_peekC (pfile) == '\'')
5594             {
5595               pfile->only_seen_white = 0;
5596               cppReader_reserve (pfile, 2);
5597               cppReader_putCharQ (pfile, c);
5598               cppReader_putCharQ (pfile, '\'');
5599               cppReader_forward (pfile, 1);
5600               for (;;)
5601                 {
5602                   c = cppReader_getC (pfile);
5603                   if (c == EOF)
5604                     goto chill_number_eof;
5605                   if (!is_idchar[c])
5606                     {
5607                       if (c == '\\' && cppReader_peekC (pfile) == '\n')
5608                         {
5609                           cppReader_forward (pfile, 2);
5610                           continue;
5611                         }
5612                       /*@loopbreak@*/ break;
5613                     }
5614                   cppReader_putChar (pfile, c);
5615                 }
5616               if (c == '\'')
5617                 {
5618                   cppReader_reserve (pfile, 2);
5619                   cppReader_putCharQ (pfile, c);
5620                   cppReader_nullTerminateQ (pfile);
5621                   return CPP_STRING;
5622                 }
5623               else
5624                 {
5625                   cppReader_forward (pfile, -1);
5626                 chill_number_eof:
5627                   cppReader_nullTerminate (pfile);
5628                   return CPP_NUMBER;
5629                 }
5630             }
5631           else
5632             goto letter;
5633         case '_':
5634         case 'a': case 'e': case 'f': case 'g': case 'i': case 'j':
5635         case 'k': case 'l': case 'm': case 'n': case 'p': case 'q':
5636         case 'r': case 's': case 't': case 'u': case 'v': case 'w':
5637         case 'x': case 'y': case 'z':
5638         case 'A': case 'E': case 'F': case 'G': case 'I': case 'J':
5639         case 'K': case 'M': case 'N': case 'P': case 'Q': case 'R':
5640         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
5641         case 'Y': case 'Z':
5642         letter:
5643           {
5644             hashNode hp;
5645             char *ident;
5646             size_t before_name_written = cppReader_getWritten (pfile);
5647             int ident_len;
5648             parse_name (pfile, c);
5649             pfile->only_seen_white = 0;
5650             if (pfile->no_macro_expand)
5651               {
5652                 return CPP_NAME;
5653               }
5654
5655             ident = pfile->token_buffer + before_name_written;
5656             ident_len = (cppReader_getPWritten (pfile)) - ident;
5657
5658             hp = cppReader_lookupExpand (ident, ident_len, -1);
5659
5660             if (hp == NULL)
5661               {
5662                 return CPP_NAME;
5663               }
5664
5665             if (hp->type == T_DISABLED)
5666               {
5667                 if (pfile->output_escapes)
5668                   { /* Return "@-IDENT", followed by '\0'.  */
5669                     int i;
5670                     cppReader_reserve (pfile, 3);
5671                     ident = pfile->token_buffer + before_name_written;
5672                     cppReader_adjustWritten (pfile, 2);
5673
5674                     for (i = ident_len; i >= 0; i--)
5675                       {
5676                         ident[i+2] = ident[i];
5677                       }
5678
5679                     ident[0] = '@';
5680                     ident[1] = '-';
5681                   }
5682                 return CPP_NAME;
5683               }
5684
5685             /* If macro wants an arglist, verify that a '(' follows.
5686                first skip all whitespace, copying it to the output
5687                after the macro name.  Then, if there is no '(',
5688                decide this is not a macro call and leave things that way.  */
5689
5690             if (hp->type == T_MACRO && hp->value.defn->nargs >= 0)
5691               {
5692                 struct parse_marker macro_mark;
5693                 int is_macro_call;
5694
5695                 while (cppBuffer_isMacro (CPPBUFFER (pfile)))
5696                   {
5697                     cppBuffer *next_buf;
5698                     cppSkipHspace (pfile);
5699                     if (cppReader_peekC (pfile) != EOF)
5700                       {
5701                         /*@loopbreak@*/ break;
5702                       }
5703
5704                   next_buf = cppBuffer_prevBuffer (cppReader_getBuffer (pfile));
5705                   (*cppReader_getBuffer (pfile)->cleanup) (cppReader_getBuffer (pfile), pfile);
5706                   CPPBUFFER (pfile) = next_buf;
5707                   }
5708
5709                 parseSetMark (&macro_mark, pfile);
5710
5711                 for (;;)
5712                   {
5713                     cppSkipHspace (pfile);
5714                     c = cppReader_peekC (pfile);
5715                     is_macro_call = c == '(';
5716                     if (c != '\n')
5717                       /*@loopbreak@*/ break;
5718                     cppReader_forward (pfile, 1);
5719                   }
5720
5721                 if (!is_macro_call)
5722                   {
5723                     parseGotoMark (&macro_mark, pfile);
5724                   }
5725
5726                 parseClearMark (&macro_mark);
5727
5728                 if (!is_macro_call)
5729                   {
5730                     return CPP_NAME;
5731                   }
5732               }
5733             /* This is now known to be a macro call.  */
5734
5735             /* it might not actually be a macro.  */
5736             if (hp->type != T_MACRO)
5737               {
5738                 size_t xbuf_len;
5739                 char *xbuf;
5740
5741                 cppReader_setWritten (pfile, before_name_written);
5742                 special_symbol (hp, pfile);
5743                 xbuf_len = cppReader_getWritten (pfile) - before_name_written;
5744                 xbuf = (char *) dmalloc (xbuf_len + 1);
5745                 cppReader_setWritten (pfile, before_name_written);
5746                 memcpy (xbuf, cppReader_getPWritten (pfile), xbuf_len + 1);
5747                 push_macro_expansion (pfile, xbuf, xbuf_len, hp);
5748               }
5749             else
5750               {
5751                 /* Expand the macro, reading arguments as needed,
5752                    and push the expansion on the input stack.  */
5753                                 macroexpand (pfile, hp);
5754                 cppReader_setWritten (pfile, before_name_written);
5755               }
5756
5757             /* An extra "@ " is added to the end of a macro expansion
5758                to prevent accidental token pasting.  We prefer to avoid
5759                unneeded extra spaces (for the sake of cpp-using tools like
5760                imake).  Here we remove the space if it is safe to do so.  */
5761
5762             llassert (pfile->buffer->rlimit != NULL);
5763
5764             if (pfile->buffer->rlimit - pfile->buffer->cur >= 3
5765                 && pfile->buffer->rlimit[-2] == '@'
5766                 && pfile->buffer->rlimit[-1] == ' ')
5767               {
5768                 int c1 = pfile->buffer->rlimit[-3];
5769                 int cl2 = cppBufPeek (cppBuffer_prevBuffer (CPPBUFFER (pfile)));
5770
5771                 if (cl2 == EOF || !unsafe_chars ((char) c1, (char) cl2))
5772                   pfile->buffer->rlimit -= 2;
5773               }
5774           }
5775           goto get_next;
5776
5777
5778         case ' ':  case '\t':  case '\v':  case '\r':
5779           for (;;)
5780             {
5781               cppReader_putChar (pfile, c);
5782               c = cppReader_peekC (pfile);
5783               if (c == EOF || !is_hor_space[c])
5784                 /*@loopbreak@*/ break;
5785               cppReader_forward (pfile, 1);
5786             }
5787           return CPP_HSPACE;
5788
5789         case '\\':
5790           c2 = cppReader_peekC (pfile);
5791           if (c2 != '\n')
5792             goto randomchar;
5793           token = CPP_HSPACE;
5794           goto op2any;
5795
5796         case '\n':
5797           cppReader_putChar (pfile, c);
5798           if (pfile->only_seen_white == 0)
5799             pfile->only_seen_white = 1;
5800           pfile->lineno++;
5801           output_line_command (pfile, 1, same_file);
5802           return CPP_VSPACE;
5803
5804         case '(': token = CPP_LPAREN;    goto char1;
5805         case ')': token = CPP_RPAREN;    goto char1;
5806         case '{': token = CPP_LBRACE;    goto char1;
5807         case '}': token = CPP_RBRACE;    goto char1;
5808         case ',': token = CPP_COMMA;     goto char1;
5809         case ';': token = CPP_SEMICOLON; goto char1;
5810
5811         randomchar:
5812         default:
5813           token = CPP_OTHER;
5814         char1:
5815           pfile->only_seen_white = 0;
5816           cppReader_putChar (pfile, c);
5817           return token;
5818         }
5819     }
5820
5821   BADBRANCH;
5822   /*@notreached@*/
5823 }
5824
5825 /* Parse an identifier starting with C.  */
5826
5827 void
5828 parse_name (cppReader *pfile, int c)
5829 {
5830   for (;;)
5831     {
5832       if (!is_idchar[c])
5833         {
5834           if (c == '\\' && cppReader_peekC (pfile) == '\n')
5835             {
5836               cppReader_forward (pfile, 2);
5837               continue;
5838             }
5839
5840           cppReader_forward (pfile, -1);
5841           break;
5842         }
5843
5844       if (c == '$' && cppReader_isPedantic (pfile))
5845         {
5846           cppReader_pedwarnLit (pfile,
5847                           cstring_makeLiteralTemp ("`$' in identifier"));
5848         }
5849
5850       cppReader_reserve(pfile, 2); /* One more for final NUL.  */
5851       cppReader_putCharQ (pfile, c);
5852       c = cppReader_getC (pfile);
5853
5854       if (c == EOF)
5855         break;
5856     }
5857
5858   cppReader_nullTerminateQ (pfile);
5859 }
5860
5861 /* The file_name_map structure holds a mapping of file names for a
5862    particular directory.  This mapping is read from the file named
5863    FILE_NAME_MAP_FILE in that directory.  Such a file can be used to
5864    map filenames on a file system with severe filename restrictions,
5865    such as DOS.  The format of the file name map file is just a series
5866    of lines with two tokens on each line.  The first token is the name
5867    to map, and the second token is the actual name to use.  */
5868
5869 struct file_name_map
5870 {
5871   struct file_name_map *map_next;
5872   cstring map_from;
5873   cstring map_to;
5874 };
5875
5876 /*@constant observer char *FILE_NAME_MAP_FILE*/
5877 #define FILE_NAME_MAP_FILE "header.gcc"
5878
5879 /* Read a space delimited string of unlimited length from a stdio
5880    file.  */
5881
5882 static cstring read_filename_string (int ch, /*:open:*/ FILE *f)
5883 {
5884   char *alloc, *set;
5885   size_t len;
5886
5887   len = 20;
5888   set = alloc = dmalloc (len + 1);
5889
5890   if (!is_space[ch])
5891     {
5892       *set++ = ch;
5893       while ((ch = getc (f)) != EOF && ! is_space[ch])
5894         {
5895           if (set - alloc == size_toInt (len))
5896             {
5897               len *= 2;
5898               alloc = drealloc (alloc, len + 1);
5899               set = alloc + len / 2;
5900               /*@-branchstate@*/ }
5901
5902           *set++ = ch;
5903         } /*@=branchstate@*/
5904     }
5905   *set = '\0';
5906   check (ungetc (ch, f) != EOF);
5907
5908   return cstring_fromChars (alloc);
5909 }
5910
5911 /* This structure holds a linked list of file name maps, one per directory.  */
5912
5913 struct file_name_map_list
5914 {
5915   struct file_name_map_list *map_list_next;
5916   cstring map_list_name;
5917   struct file_name_map *map_list_map;
5918 };
5919
5920 /* Read the file name map file for DIRNAME.  */
5921
5922 static struct file_name_map *
5923 read_name_map (cppReader *pfile, cstring dirname)
5924 {
5925   struct file_name_map_list *map_list_ptr;
5926   cstring name;
5927   FILE *f;
5928
5929   for (map_list_ptr = CPPOPTIONS (pfile)->map_list;
5930        map_list_ptr != NULL;
5931        map_list_ptr = map_list_ptr->map_list_next)
5932     {
5933       if (cstring_equal (map_list_ptr->map_list_name, dirname))
5934         {
5935           return map_list_ptr->map_list_map;
5936         }
5937     }
5938
5939   map_list_ptr = (struct file_name_map_list *) dmalloc (sizeof (*map_list_ptr));
5940   map_list_ptr->map_list_name = cstring_copy (dirname);
5941   map_list_ptr->map_list_map = NULL;
5942
5943   name = cstring_copy (dirname);
5944
5945   if (cstring_length (dirname) > 0)
5946     {
5947       name = cstring_appendChar (name, CONNECTCHAR);
5948     }
5949
5950   name = cstring_concatFree1 (name, cstring_makeLiteralTemp (FILE_NAME_MAP_FILE));
5951
5952   f = fopen (cstring_toCharsSafe (name), "r");
5953   cstring_free (name);
5954
5955   if (f == NULL)
5956     {
5957       map_list_ptr->map_list_map = NULL;
5958     }
5959   else
5960     {
5961       int ch;
5962
5963       while ((ch = getc (f)) != EOF)
5964         {
5965           cstring from, to;
5966           struct file_name_map *ptr;
5967
5968           if (is_space[ch])
5969             {
5970               continue;
5971             }
5972
5973           from = read_filename_string (ch, f);
5974           while ((ch = getc (f)) != EOF && is_hor_space[ch])
5975             {
5976               ;
5977             }
5978
5979           to = read_filename_string (ch, f);
5980
5981           ptr = (struct file_name_map *) dmalloc (sizeof (*ptr));
5982           ptr->map_from = from;
5983
5984           /* Make the real filename absolute.  */
5985           if (cstring_length (to) > 1 
5986               && osd_isConnectChar (cstring_firstChar (to)))
5987             {
5988               ptr->map_to = to;
5989             }
5990           else
5991             {
5992               ptr->map_to = cstring_copy (dirname);
5993               ptr->map_to = cstring_appendChar (ptr->map_to, CONNECTCHAR);
5994               ptr->map_to = cstring_concatFree (ptr->map_to, to);
5995             }
5996
5997           ptr->map_next = map_list_ptr->map_list_map;
5998           map_list_ptr->map_list_map = ptr;
5999
6000           while ((ch = getc (f)) != '\n')
6001             {
6002               if (ch == EOF)
6003                 {
6004                   /*@innerbreak@*/ break;
6005                 }
6006             }
6007         }
6008
6009       assertSet (map_list_ptr->map_list_map);
6010       check (fclose (f) == 0);
6011     }
6012
6013   map_list_ptr->map_list_next = pfile->opts->map_list;
6014   pfile->opts->map_list = map_list_ptr;
6015
6016   return map_list_ptr->map_list_map;
6017 }
6018
6019 /* Try to open include file FILENAME.  SEARCHPTR is the directory
6020    being tried from the include file search path.  This function maps
6021    filenames on file systems based on information read by
6022    read_name_map.  */
6023
6024 static int
6025 open_include_file (cppReader *pfile,
6026                    cstring fname,
6027                    struct file_name_list *searchptr)
6028 {
6029   char *filename = cstring_toCharsSafe (fname);
6030   struct file_name_map *map;
6031   char *from;
6032   char *p, *dir;
6033
6034   cstring_markOwned (fname);
6035
6036   cpp_setLocation (pfile);
6037
6038   if (context_getFlag (FLG_NEVERINCLUDE))
6039     {
6040       if (isHeaderFile (fname))
6041         {
6042           return SKIP_INCLUDE;
6043         }
6044     }
6045
6046   if ((searchptr != NULL) && ! searchptr->got_name_map)
6047     {
6048       searchptr->name_map = read_name_map (pfile,
6049                                            !cstring_isEmpty (searchptr->fname)
6050                                            ? searchptr->fname :
6051                                            cstring_makeLiteralTemp ("."));
6052       searchptr->got_name_map = 1;
6053     }
6054
6055   /* First check the mapping for the directory we are using.  */
6056
6057   if ((searchptr != NULL)
6058       && (searchptr->name_map != NULL))
6059     {
6060       from = filename;
6061
6062       if (!cstring_isEmpty (searchptr->fname))
6063         {
6064           from += cstring_length (searchptr->fname) + 1;
6065         }
6066
6067       for (map = searchptr->name_map;
6068            map != NULL;
6069            map = map->map_next)
6070         {
6071           if (cstring_equal (map->map_from, cstring_fromChars (from)))
6072             {
6073               /*
6074               ** Found a match.  Check if the file should be skipped
6075               */
6076               
6077               if (cpp_skipIncludeFile (map->map_to))
6078                 {
6079                   return SKIP_INCLUDE;
6080                 }
6081               else
6082                 {
6083                   return cpp_openIncludeFile (cstring_toCharsSafe (map->map_to));
6084                 }
6085             }
6086         }
6087     }
6088
6089   /*
6090   ** Try to find a mapping file for the particular directory we are
6091   ** looking in.  Thus #include <sys/types.h> will look up sys/types.h
6092   ** in /usr/include/header.gcc and look up types.h in
6093   ** /usr/include/sys/header.gcc.
6094   */
6095
6096   p = strrchr (filename, CONNECTCHAR);
6097
6098   if (p == NULL)
6099     {
6100       p = filename;
6101     }
6102
6103   if ((searchptr != NULL)
6104       && (cstring_isDefined (searchptr->fname))
6105       && (cstring_length (searchptr->fname) == p - filename)
6106       && !strncmp (cstring_toCharsSafe (searchptr->fname),
6107                    filename,
6108                    size_fromInt (p - filename)))
6109     {
6110       /* filename is in SEARCHPTR, which we've already checked.  */
6111
6112       if (cpp_skipIncludeFile (cstring_fromChars (filename)))
6113         {
6114           return SKIP_INCLUDE;
6115         }
6116       else
6117         {
6118           return cpp_openIncludeFile (filename);
6119         }
6120     }
6121
6122   if (p == filename)
6123     {
6124       dir = mstring_copy (".");
6125       from = filename;
6126     }
6127   else
6128     {
6129       dir = (char *) dmalloc (size_fromInt (p - filename + 1));
6130       memcpy (dir, filename, size_fromInt (p - filename));
6131       dir[p - filename] = '\0';
6132       from = p + 1;
6133     }
6134
6135   for (map = read_name_map (pfile, cstring_fromChars (dir));
6136        map != NULL;
6137        map = map->map_next)
6138     {
6139       if (cstring_equal (map->map_from, cstring_fromChars (from)))
6140         {
6141           sfree (dir);
6142
6143           if (cpp_skipIncludeFile (map->map_to))
6144             {
6145               return SKIP_INCLUDE;
6146             }
6147           else
6148             {
6149               return cpp_openIncludeFile (cstring_toCharsSafe (map->map_to));
6150             }
6151         }
6152     }
6153
6154   sfree (dir);
6155
6156   if (cpp_skipIncludeFile (cstring_fromChars (filename)))
6157     {
6158       return SKIP_INCLUDE;
6159     }
6160   else
6161     {
6162       return cpp_openIncludeFile (filename);
6163     }
6164 }
6165
6166 /* Process the contents of include file FNAME, already open on descriptor F,
6167    with output to OP.
6168    SYSTEM_HEADER_P is 1 if this file resides in any one of the known
6169    "system" include directories (as decided by the `is_system_include'
6170    function above).
6171    DIRPTR is the link in the dir path through which this file was found,
6172    or 0 if the file name was absolute or via the current directory.
6173    Return 1 on success, 0 on failure.
6174
6175    The caller is responsible for the cppReader_pushBuffer.  */
6176
6177 static int
6178 finclude (cppReader *pfile, int f,
6179           cstring fname,
6180           bool system_header_p,
6181           /*@dependent@*/ struct file_name_list *dirptr)
6182 {
6183   mode_t st_mode;
6184   size_t st_size;
6185   long i;
6186   int length = 0;
6187   cppBuffer *fp;                        /* For input stack frame */
6188
6189   if (file_size_and_mode (f, &st_mode, &st_size) < 0)
6190     {
6191       cppReader_perrorWithName (pfile, fname);
6192       check (close (f) == 0);
6193       (void) cppReader_popBuffer (pfile);
6194       /*@-mustfree@*/
6195       return 0;
6196       /*@=mustfree@*/
6197     }
6198
6199   fp = cppReader_getBuffer (pfile);
6200
6201   /*@-temptrans@*/ /* fname shouldn't really be temp */
6202   fp->nominal_fname = fp->fname = fname;
6203   /*@=temptrans@*/
6204
6205   fp->dir = dirptr;
6206   fp->system_header_p = system_header_p;
6207   fp->lineno = 1;
6208   fp->colno = 1;
6209   fp->cleanup = cppReader_fileCleanup;
6210
6211   if (S_ISREG (st_mode))
6212     {
6213       sfree (fp->buf);
6214       fp->buf = (char *) dmalloc (st_size + 2);
6215       fp->alimit = fp->buf + st_size + 2;
6216       fp->cur = fp->buf;
6217
6218       /* Read the file contents, knowing that st_size is an upper bound
6219          on the number of bytes we can read.  */
6220       length = safe_read (f, fp->buf, size_toInt (st_size));
6221       fp->rlimit = fp->buf + length;
6222       if (length < 0) goto nope;
6223     }
6224   else if (S_ISDIR (st_mode))
6225     {
6226       cppReader_error (pfile,
6227                        message ("Directory specified in #include: %s", fname));
6228       check (close (f) == 0);
6229       return 0;
6230     }
6231   else
6232     {
6233       /*
6234       ** Cannot count its file size before reading.
6235       ** First read the entire file into heap and
6236       ** copy them into buffer on stack.
6237       */
6238
6239       size_t bsize = 2000;
6240
6241       st_size = 0;
6242
6243       sfree (fp->buf);
6244       fp->buf = (char *) dmalloc (bsize + 2);
6245
6246       for (;;) {
6247         i = safe_read (f, fp->buf + st_size, size_toInt (bsize - st_size));
6248
6249         if (i < 0)
6250           goto nope;      /* error! */
6251         st_size += i;
6252
6253         if (st_size != bsize)
6254           {
6255             break;      /* End of file */
6256           }
6257
6258         bsize *= 2;
6259         fp->buf = (char *) drealloc (fp->buf, bsize + 2);
6260       }
6261
6262       fp->cur = fp->buf;
6263       length = size_toInt (st_size);
6264     }
6265
6266   if ((length > 0 && fp->buf[length - 1] != '\n')
6267       /* Backslash-newline at end is not good enough.  */
6268       || (length > 1 && fp->buf[length - 2] == '\\')) {
6269     fp->buf[length++] = '\n';
6270   }
6271
6272   fp->buf[length] = '\0';
6273   fp->rlimit = fp->buf + length;
6274
6275   /* Close descriptor now, so nesting does not use lots of descriptors.  */
6276   check (close (f) == 0);
6277
6278   /* Must do this before calling trigraph_pcp, so that the correct file name
6279      will be printed in warning messages.  */
6280
6281   pfile->input_stack_listing_current = 0;
6282   return 1;
6283
6284  nope:
6285
6286   cppReader_perrorWithName (pfile, fname);
6287   check (close (f) == 0);
6288   sfree (fp->buf);
6289   return 1;
6290 }
6291
6292 void
6293 cppReader_init (cppReader *pfile)
6294 {
6295   memset ((char *) pfile, 0, sizeof (*pfile));
6296
6297   pfile->get_token = cppGetToken;
6298   pfile->token_buffer_size = 200;
6299   pfile->token_buffer = (char *) dmalloc (pfile->token_buffer_size);
6300   pfile->all_include_files = NULL;
6301
6302   assertSet (pfile);
6303
6304   cppReader_setWritten (pfile, 0);
6305
6306   pfile->system_include_depth = 0;
6307   pfile->max_include_len = 0;
6308   pfile->timebuf = NULL;
6309   pfile->only_seen_white = 1;
6310
6311   pfile->buffer = cppReader_nullBuffer (pfile);
6312 }
6313
6314 void
6315 cppReader_finish (/*@unused@*/ cppReader *pfile)
6316 {
6317   ;
6318 }
6319
6320 /* Free resources used by PFILE.
6321    This is the cppReader 'finalizer' or 'destructor' (in C++ terminology).  */
6322
6323 void
6324 cppCleanup (cppReader *pfile)
6325 {
6326   while (CPPBUFFER (pfile) != cppReader_nullBuffer (pfile))
6327     {
6328       (void) cppReader_popBuffer (pfile);
6329     }
6330
6331   if (pfile->token_buffer != NULL)
6332     {
6333       sfree (pfile->token_buffer);
6334       pfile->token_buffer = NULL;
6335     }
6336
6337   while (pfile->if_stack != NULL)
6338     {
6339       cppIfStackFrame *temp = pfile->if_stack;
6340       pfile->if_stack = temp->next;
6341       sfree (temp);
6342     }
6343
6344   while (pfile->all_include_files != NULL)
6345     {
6346       struct file_name_list *temp = pfile->all_include_files;
6347       pfile->all_include_files = temp->next;
6348       /*@-dependenttrans@*/
6349       cstring_free (temp->fname);
6350       /*@=dependenttrans@*/
6351       sfree (temp);
6352     }
6353
6354   cppReader_hashCleanup ();
6355 }
6356
6357 /*
6358 ** Get the file-mode and data size of the file open on FD
6359 ** and store them in *MODE_POINTER and *SIZE_POINTER.
6360 */
6361
6362 static int
6363 file_size_and_mode (int fd, mode_t *mode_pointer, size_t *size_pointer)
6364 {
6365   struct stat sbuf;
6366
6367   if (fstat (fd, &sbuf) < 0) {
6368     return (-1);
6369   }
6370
6371   if (mode_pointer != NULL)
6372     {
6373       *mode_pointer = sbuf.st_mode;
6374     }
6375
6376   if (size_pointer != NULL)
6377     {
6378       *size_pointer = (size_t) sbuf.st_size;
6379     }
6380
6381   return 0;
6382 }
6383
6384 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
6385    retrying if necessary.  Return a negative value if an error occurs,
6386    otherwise return the actual number of bytes read,
6387    which must be LEN unless end-of-file was reached.  */
6388
6389 static int safe_read (int desc, char *ptr, int len)
6390 {
6391   int left = len;
6392
6393   while (left > 0)
6394     {
6395 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
6396           /*@-compdef@*/ /* ptr is an out parameter */
6397       int nchars = _read (desc, ptr, (unsigned) left);
6398           /*@=compdef@*/
6399 # else
6400       ssize_t nchars = read (desc, ptr, size_fromInt (left));
6401 # endif
6402
6403       if (nchars < 0)
6404         {
6405 #ifdef EINTR
6406           if (errno == EINTR)
6407             continue;
6408 #endif
6409           return (int) nchars;
6410         }
6411
6412       if (nchars == 0) {
6413         break;
6414       }
6415
6416       ptr += nchars;
6417       left -= nchars;
6418     }
6419
6420   return len - left;
6421 }
6422
6423 /* Initialize PMARK to remember the current position of PFILE.  */
6424
6425 void
6426 parseSetMark (struct parse_marker *pmark, cppReader *pfile)
6427 {
6428   cppBuffer *pbuf = cppReader_getBuffer (pfile);
6429
6430   pmark->next = pbuf->marks;
6431   /*@-temptrans@*/
6432   pbuf->marks = pmark;
6433   /*@=temptrans@*/
6434
6435   pmark->buf = pbuf;
6436   pmark->position = pbuf->cur - pbuf->buf;
6437 }
6438
6439 /* Cleanup PMARK - we no longer need it.  */
6440
6441 void parseClearMark (struct parse_marker *pmark)
6442 {
6443   struct parse_marker **pp = &pmark->buf->marks;
6444
6445   for (; ; pp = &(*pp)->next)
6446     {
6447       llassert (*pp != NULL);
6448       if (*pp == pmark) break;
6449     }
6450
6451   *pp = pmark->next;
6452 }
6453
6454 /* Backup the current position of PFILE to that saved in PMARK.  */
6455
6456 void
6457 parseGotoMark (struct parse_marker *pmark, cppReader *pfile)
6458 {
6459   cppBuffer *pbuf = cppReader_getBuffer (pfile);
6460
6461   if (pbuf != pmark->buf)
6462     {
6463       cpp_setLocation (pfile);
6464       llfatalbug (cstring_makeLiteral ("Internal error parseGotoMark"));
6465     }
6466
6467   llassert (pbuf->buf != NULL);
6468   pbuf->cur = pbuf->buf + pmark->position;
6469 }
6470
6471 /* Reset PMARK to point to the current position of PFILE.  (Same
6472    as parseClearMark (PMARK), parseSetMark (PMARK, PFILE) but faster.  */
6473
6474 void
6475 parseMoveMark (struct parse_marker *pmark, cppReader *pfile)
6476 {
6477   cppBuffer *pbuf = cppReader_getBuffer (pfile);
6478
6479   if (pbuf != pmark->buf)
6480     {
6481       cpp_setLocation (pfile);
6482       llfatalerror (cstring_makeLiteral ("Internal error parseMoveMark"));
6483     }
6484
6485   pmark->position = pbuf->cur - pbuf->buf;
6486 }
6487
6488 void cppReader_initializeReader (cppReader *pfile) /* Must be done after library is loaded. */
6489 {
6490   struct cppOptions *opts = CPPOPTIONS (pfile);
6491   cstring xp;
6492
6493   /* The code looks at the defaults through this pointer, rather than through
6494      the constant structure above.  This pointer gets changed if an environment
6495      variable specifies other defaults.  */
6496
6497   struct default_include *include_defaults = include_defaults_array;
6498
6499   /* Add dirs from CPATH after dirs from -I.  */
6500   /* There seems to be confusion about what CPATH should do,
6501      so for the moment it is not documented.  */
6502   /* Some people say that CPATH should replace the standard include dirs,
6503      but that seems pointless: it comes before them, so it overrides them
6504      anyway.  */
6505
6506   xp = osd_getEnvironmentVariable (INCLUDEPATH_VAR);
6507
6508   if (cstring_isDefined (xp) && !opts->no_standard_includes)
6509     {
6510       path_include (pfile, cstring_toCharsSafe (xp));
6511     }
6512
6513   /* Now that dollars_in_ident is known, initialize is_idchar.  */
6514   initialize_char_syntax (opts);
6515
6516   /* CppReader_Install __LINE__, etc.  Must follow initialize_char_syntax
6517      and option processing.  */
6518
6519   initialize_builtins (pfile);
6520
6521   /* Do standard #defines and assertions
6522      that identify system and machine type.  */
6523
6524   if (!opts->inhibit_predefs) {
6525     char *p = (char *) dmalloc (strlen (predefs) + 1);
6526     strcpy (p, predefs);
6527
6528     while (*p)
6529       {
6530         char *q;
6531
6532         while (*p == ' ' || *p == '\t')
6533           {
6534             p++;
6535           }
6536
6537         /* Handle -D options.  */
6538         if (p[0] == '-' && p[1] == 'D')
6539           {
6540             q = &p[2];
6541
6542             while (*p && *p != ' ' && *p != '\t')
6543               {
6544                 p++;
6545               }
6546
6547             if (*p != 0)
6548               {
6549                 *p++= 0;
6550               }
6551
6552             if (opts->debug_output)
6553               {
6554                 output_line_command (pfile, 0, same_file);
6555               }
6556
6557             cppReader_define (pfile, q);
6558
6559             while (*p == ' ' || *p == '\t')
6560               {
6561                 p++;
6562               }
6563           }
6564         else
6565           {
6566             abort ();
6567           }
6568       }
6569
6570     sfree (p);
6571   }
6572
6573   opts->done_initializing = 1;
6574
6575   { /* Read the appropriate environment variable and if it exists
6576        replace include_defaults with the listed path.  */
6577     char *epath = 0;
6578 #ifdef __CYGWIN32__
6579   char *win32epath;
6580   int win32_buf_size = 0; /* memory we need to allocate */
6581 #endif
6582
6583   if (opts->cplusplus)
6584     {
6585       epath = getenv ("CPLUS_INCLUDE_PATH");
6586     }
6587   else
6588     {
6589       epath = getenv ("C_INCLUDE_PATH");
6590     }
6591
6592   /*
6593   ** If the environment var for this language is set,
6594   ** add to the default list of include directories.
6595   */
6596
6597     if (epath != NULL) {
6598       char *nstore = (char *) dmalloc (strlen (epath) + 2);
6599       int num_dirs;
6600       char *startp, *endp;
6601
6602 #ifdef __CYGWIN32__
6603       /* if we have a posix path list, convert to win32 path list */
6604       if (cygwin32_posix_path_list_p (epath))
6605         {
6606           win32_buf_size = cygwin32_posix_to_win32_path_list_buf_size (epath);
6607           win32epath = (char *) dmalloc /*@i4@*/ (win32_buf_size);
6608           cygwin32_posix_to_win32_path_list (epath, win32epath);
6609           epath = win32epath;
6610         }
6611 #endif
6612       for (num_dirs = 1, startp = epath; *startp; startp++)
6613         {
6614           if (*startp == PATH_SEPARATOR)
6615             num_dirs++;
6616         }
6617
6618       /*@-sizeoftype@*/
6619       include_defaults
6620         = (struct default_include *) dmalloc ((num_dirs
6621                                                * sizeof (struct default_include))
6622                                               + sizeof (include_defaults_array));
6623       /*@=sizeoftype@*/
6624
6625       startp = endp = epath;
6626       num_dirs = 0;
6627       while (1) {
6628         /* Handle cases like c:/usr/lib:d:/gcc/lib */
6629         if ((*endp == PATH_SEPARATOR) || *endp == 0)
6630           {
6631             strncpy (nstore, startp, size_fromInt (endp - startp));
6632             if (endp == startp)
6633               {
6634                 strcpy (nstore, ".");
6635               }
6636             else
6637               {
6638                 nstore[endp-startp] = '\0';
6639               }
6640
6641             include_defaults[num_dirs].fname = cstring_fromCharsNew (nstore);
6642             include_defaults[num_dirs].cplusplus = opts->cplusplus;
6643             include_defaults[num_dirs].cxx_aware = 1;
6644             num_dirs++;
6645
6646             if (*endp == '\0')
6647               {
6648                 break;
6649               }
6650             endp = startp = endp + 1;
6651           }
6652         else
6653           {
6654             endp++;
6655           }
6656       }
6657       /* Put the usual defaults back in at the end.  */
6658       memcpy ((char *) &include_defaults[num_dirs],
6659               (char *) include_defaults_array,
6660               sizeof (include_defaults_array));
6661
6662       sfree (nstore);
6663       /*@-branchstate@*/ } /*@=branchstate@*/
6664   }
6665
6666   cppReader_appendIncludeChain (pfile, opts->before_system,
6667                                 opts->last_before_system);
6668   opts->first_system_include = opts->before_system;
6669
6670   /* Unless -fnostdinc,
6671      tack on the standard include file dirs to the specified list */
6672   if (!opts->no_standard_includes) {
6673     struct default_include *p = include_defaults;
6674     char *specd_prefix = opts->include_prefix;
6675     char *default_prefix = mstring_copy (GCC_INCLUDE_DIR);
6676     int default_len = 0;
6677
6678         /* Remove the `include' from /usr/local/lib/gcc.../include.  */
6679         if (default_prefix != NULL) {
6680     if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) {
6681       default_len = strlen (default_prefix) - 7;
6682       default_prefix[default_len] = 0;
6683     }
6684         }
6685
6686     /* Search "translated" versions of GNU directories.
6687        These have /usr/local/lib/gcc... replaced by specd_prefix.  */
6688     if (specd_prefix != 0 && default_len != 0)
6689       for (p = include_defaults; p->fname != NULL; p++) {
6690         /* Some standard dirs are only for C++.  */
6691         if (!p->cplusplus
6692             || (opts->cplusplus && !opts->no_standard_cplusplus_includes)) {
6693           /* Does this dir start with the prefix?  */
6694           if (!strncmp (cstring_toCharsSafe (p->fname), default_prefix,
6695                         size_fromInt (default_len)))
6696             {
6697               /* Yes; change prefix and add to search list.  */
6698               struct file_name_list *nlist
6699                 = (struct file_name_list *) dmalloc (sizeof (*nlist));
6700               size_t this_len = strlen (specd_prefix) + cstring_length (p->fname) - default_len;
6701               char *str = (char *) dmalloc (this_len + 1);
6702               strcpy (str, specd_prefix);
6703               strcat (str, cstring_toCharsSafe (p->fname) + default_len);
6704
6705               nlist->next = NULL;
6706               nlist->fname = cstring_fromChars (str);
6707               nlist->control_macro = 0;
6708               nlist->c_system_include_path = !p->cxx_aware;
6709               nlist->got_name_map = 0;
6710
6711               cppReader_addIncludeChain (pfile, nlist);
6712               if (opts->first_system_include == 0)
6713                 {
6714                   opts->first_system_include = nlist;
6715                 }
6716             }
6717         }
6718       }
6719
6720     /* Search ordinary names for GNU include directories.  */
6721
6722     for (p = include_defaults; p->fname != NULL; p++)
6723       {
6724         /* Some standard dirs are only for C++.  */
6725         if (!p->cplusplus
6726             || (opts->cplusplus && !opts->no_standard_cplusplus_includes))
6727           {
6728             struct file_name_list *nlist
6729               = (struct file_name_list *) dmalloc (sizeof (*nlist));
6730             nlist->control_macro = 0;
6731             nlist->c_system_include_path = !p->cxx_aware;
6732             nlist->fname = p->fname;
6733             nlist->got_name_map = 0;
6734             nlist->next = NULL;
6735
6736             cppReader_addIncludeChain (pfile, nlist);
6737
6738             if (opts->first_system_include == 0)
6739               {
6740                 opts->first_system_include = nlist;
6741               }
6742           }
6743       }
6744     sfree (default_prefix);
6745   }
6746
6747   /* Tack the after_include chain at the end of the include chain.  */
6748   cppReader_appendIncludeChain (pfile, opts->after_include,
6749                                 opts->last_after_include);
6750
6751   if (opts->first_system_include == 0)
6752     {
6753       opts->first_system_include = opts->after_include;
6754     }
6755
6756   /* With -v, print the list of dirs to search.  */
6757   if (opts->verbose) {
6758     struct file_name_list *p;
6759     fprintf (stderr, "#include \"...\" search starts here:\n");
6760
6761     for (p = opts->include; p != NULL; p = p->next) {
6762       if (p == opts->first_bracket_include)
6763         fprintf (stderr, "#include <...> search starts here:\n");
6764
6765       fprintf (stderr, " %s\n", cstring_toCharsSafe (p->fname));
6766     }
6767     fprintf (stderr, "End of search list.\n");
6768   }
6769 }
6770
6771 int cppReader_startProcess (cppReader *pfile, cstring fname)
6772 {
6773   cppBuffer *fp;
6774   int f;
6775   struct cppOptions *opts = CPPOPTIONS (pfile);
6776
6777   fp = cppReader_pushBuffer (pfile, NULL, 0);
6778
6779   if (fp == NULL)
6780     {
6781       return 0;
6782     }
6783
6784   if (opts->in_fname == NULL)
6785     {
6786       opts->in_fname = cstring_makeLiteralTemp ("");
6787     }
6788
6789   fp->fname = opts->in_fname;
6790   fp->nominal_fname = fp->fname;
6791   fp->lineno = 0;
6792
6793   /* Copy the entire contents of the main input file into
6794      the stacked input buffer previously allocated for it.  */
6795
6796   if (cstring_isEmpty (fname))
6797     {
6798       fname = cstring_makeLiteralTemp ("");
6799       f = 0;
6800     }
6801   else if ((f = open (cstring_toCharsSafe (fname), O_RDONLY, 0666)) < 0)
6802     {
6803       cppReader_error (pfile,
6804                        message ("Error opening %s for reading: %s",
6805                                 fname, lldecodeerror (errno)));
6806
6807       return 0;
6808     }
6809   else
6810     {
6811       ;
6812     }
6813
6814   if (finclude (pfile, f, fname, 0, NULL))
6815     {
6816       output_line_command (pfile, 0, same_file);
6817     }
6818
6819   return 1;
6820 }
6821
6822 static /*@exposed@*/ /*@null@*/ cppBuffer *cppReader_getBuffer (cppReader *pfile)
6823 {
6824   return pfile->buffer;
6825 }
6826
6827 /*@exposed@*/ cppBuffer *cppReader_getBufferSafe (cppReader *pfile)
6828 {
6829   llassert (pfile->buffer != NULL);
6830   return pfile->buffer;
6831 }
6832
6833 /*@exposed@*/ char *cppLineBase (cppBuffer *buf)
6834 {
6835   llassert (buf->buf != NULL);
6836   return (buf->buf + buf->line_base);
6837 }
6838
6839 int cppBufPeek (cppBuffer *buf)
6840 {
6841   if (buf->cur == NULL || buf->rlimit == NULL) {
6842     return EOF;
6843   }
6844
6845   if (buf->cur < buf->rlimit) {
6846     return *(buf->cur);
6847   }
6848
6849   return EOF;
6850 }
6851
6852 bool cppBuffer_isMacro (cppBuffer *buf)
6853 {
6854   if (buf != NULL)
6855     {
6856       return (buf->cleanup == cppReader_macroCleanup);
6857     }
6858
6859   return FALSE;
6860 }
6861
6862 /*
6863 ** Returns true if the macro should be checked, false
6864 ** if it should be expanded normally.
6865 */
6866
6867 static bool notparseable = FALSE;  /* preceeded by @notparseable@ */
6868 static bool notfunction = FALSE;   /* preceeded by @notfunction@ */
6869 static bool expectiter = FALSE;    /* preceeded by @iter@ */
6870 static bool expectenditer = FALSE; /* second after @iter@ */
6871 static bool expectfunction = FALSE;    /* preceeded by @function@ */
6872 static bool expectconstant = FALSE;   /* preceeded by @constant@ */
6873 static bool expectmacro = FALSE;   /* preceeded by notfunction or notparseable */
6874
6875 static void cpp_setLocation (cppReader *pfile)
6876 {
6877   fileId fid;
6878   int line;
6879
6880   if (pfile->buffer != NULL)
6881     {
6882       if (cstring_isDefined (cppReader_getBuffer (pfile)->nominal_fname))
6883         {
6884           cstring fname = cppReader_getBuffer (pfile)->nominal_fname;
6885           
6886           DPRINTF (("Looking up: %s", fname));
6887           
6888           if (fileTable_exists (context_fileTable (), fname))
6889             {
6890               fid = fileTable_lookup (context_fileTable (), fname);
6891             }
6892           else
6893             {
6894               DPRINTF (("Trying %s", cppReader_getBuffer (pfile)->fname));
6895
6896               fid = fileTable_lookup (context_fileTable (),
6897                                       cppReader_getBuffer (pfile)->fname);
6898             }
6899         }
6900       else
6901         {
6902           fid = fileTable_lookup (context_fileTable (),
6903                                   cppReader_getBuffer (pfile)->fname);
6904         }
6905       
6906       line = cppReader_getBuffer (pfile)->lineno;
6907       fileloc_free (g_currentloc);
6908
6909       if (fileId_isValid (fid))
6910         {
6911           g_currentloc = fileloc_create (fid, line, 1);
6912         }
6913       else
6914         {
6915           g_currentloc = fileloc_createBuiltin ();
6916         }
6917     }
6918   else
6919     {
6920       fileloc_free (g_currentloc);
6921       g_currentloc = fileloc_createBuiltin ();
6922     }
6923 }
6924
6925 static bool cpp_shouldCheckMacro (cppReader *pfile, char *p) /*@*/
6926 {
6927   bool checkmacro = FALSE;
6928   bool hasParams = FALSE;
6929   bool noexpand = FALSE;
6930   cstring sname;
6931   char c;
6932
6933   cpp_setLocation (pfile);
6934
6935   DPRINTF (("Should check macro? %s", p));
6936
6937   if (expectiter || expectconstant || expectenditer)
6938     {
6939       if (expectiter)
6940         {
6941           expectiter = FALSE;
6942           expectenditer = TRUE;
6943         }
6944       else
6945         {
6946           expectiter = FALSE;
6947           expectconstant = FALSE;
6948           expectenditer = FALSE;
6949         }
6950
6951       if (notfunction || notparseable)
6952         {
6953           notfunction = FALSE;
6954           notparseable = FALSE;
6955           return FALSE;
6956         }
6957       else
6958         {
6959           return TRUE;
6960         }
6961     }
6962
6963   llassert (*p == '#');
6964   p++;
6965
6966   while (*p == ' ' || *p == '\t')
6967     {
6968       p++;
6969     }
6970
6971   llassert (*p == 'd'); /* define starts */
6972
6973   p += 6;
6974
6975   while (*p == ' ' || *p == '\t')
6976     {
6977       p++;
6978     }
6979
6980   sname = cstring_fromChars (p);
6981   DPRINTF (("Check macro: %s", sname));
6982
6983   while (((c = *p) != ' ')
6984          && c != '\0' && c != '('
6985          && c != '\t' && c != '\\' && c != '\n'
6986          && !iscntrl (c))
6987     {
6988       p++;
6989     }
6990
6991   hasParams = (c == '(');
6992   *p = '\0';
6993
6994
6995   if (notparseable)
6996     {
6997       notparseable = FALSE;
6998     }
6999   else if (notfunction || fileloc_isStandardLib (g_currentloc))
7000     {
7001       DPRINTF (("Clear notfunction"));
7002       notfunction = FALSE;
7003     }
7004   else
7005     {
7006       if (noexpand)
7007         {
7008           checkmacro = TRUE;
7009
7010           if (!expectenditer)
7011             {
7012               noexpand = FALSE;
7013             }
7014         }
7015       else
7016         {
7017           if (usymtab_existsReal (sname))
7018             {
7019               uentry ue = usymtab_lookup (sname);
7020
7021               DPRINTF (("Lookup macro: %s", uentry_unparse (ue)));
7022
7023               if (fileloc_isPreproc (uentry_whereLast (ue)))
7024                 {
7025                   goto macroDne;
7026                 }
7027               else
7028                 {
7029                   if (uentry_isSpecified (ue))
7030                     {
7031                       checkmacro = context_getFlag (FLG_SPECMACROS);
7032                     }
7033                   else
7034                     {
7035                       if (hasParams)
7036                         {
7037                           checkmacro = context_getFlag (FLG_LIBMACROS)
7038                             || context_getFlag (FLG_FCNMACROS);
7039                         }
7040                     }
7041                 }
7042             }
7043           else
7044             {
7045             macroDne:
7046               DPRINTF (("Macro doesn't exist: %s", bool_unparse (checkmacro)));
7047
7048               if (fileloc_isSystemFile (g_currentloc)
7049                   && context_getFlag (FLG_SYSTEMDIREXPAND))
7050                 {
7051                   ; /* don't check this macro */
7052                   DPRINTF (("Don't check 1"));
7053                 }
7054               else
7055                 {
7056                   uentry le;
7057                   
7058                   if (hasParams)
7059                     {
7060                       DPRINTF (("Has params..."));
7061
7062                       if (context_getFlag (FLG_FCNMACROS))
7063                         {
7064                           if (usymtab_exists (sname))
7065                             {
7066                               /*
7067                               ** only get here is macro is redefined
7068                               ** error reported elsewhere
7069                               */
7070
7071                               DPRINTF (("It exists!"));
7072                             }
7073                           else
7074                             {
7075                               /*
7076                               ** We make it a forward function, since it might be declared elsewhere.
7077                               ** After all headers have been processed, we should check the forward
7078                               ** functions.
7079                               */
7080
7081                               fileloc loc = fileloc_makePreproc (g_currentloc);
7082
7083                               /* the line is off-by-one, since the newline was already read */
7084                               decLine ();
7085
7086                               if (expectfunction)
7087                                 {
7088                                   expectfunction = FALSE;
7089                                 }
7090
7091                               le = uentry_makeForwardFunction (sname,
7092                                                                typeId_invalid, loc);
7093
7094                               fileloc_free (loc);
7095
7096                               incLine ();
7097
7098                               /* Do not define here! */
7099
7100                               (void) usymtab_addEntry (le);
7101                             }
7102
7103                           checkmacro = TRUE;
7104                           DPRINTF (("Check: TRUE"));
7105                         }
7106                       else 
7107                         {
7108                           DPRINTF (("Flag FCN_MACROS not set!"));
7109                         }
7110                     }
7111                   else
7112                     {
7113                       DPRINTF (("No params"));
7114
7115                       if (context_getFlag (FLG_CONSTMACROS))
7116                         {
7117                           bool nocontent = FALSE;
7118
7119                           if (c == '\0')
7120                             {
7121                               nocontent = TRUE;
7122                             }
7123                           else
7124                             {
7125                               if (isspace (c))
7126                                 {
7127                                   char *rest = p + 1;
7128
7129                                   /*
7130                                   ** Check if there is nothing after the define.
7131                                   */
7132
7133                                   while ((*rest) != '\0' && isspace (*rest))
7134                                     {
7135                                       rest++;
7136                                     }
7137
7138                                   if (*rest == '\0')
7139                                     {
7140                                       nocontent = TRUE; /* empty macro, don't check */
7141                                     }
7142                                 }
7143                             }
7144
7145                           if (usymtab_exists (sname))
7146                             {
7147                               ;
7148                             }
7149                           else
7150                             {
7151                               fileloc loc = fileloc_makePreproc (g_currentloc);
7152                               DPRINTF (("Make constant: %s", sname));
7153                               le = uentry_makeConstant (sname,
7154                                                         ctype_unknown, loc);
7155                               (void) usymtab_addEntry (le);
7156                             }
7157
7158                           checkmacro = !nocontent;
7159                         }
7160                     }
7161                 }
7162
7163               if (checkmacro && usymtab_existsType (sname))
7164                 {
7165                   DPRINTF (("Making false..."));
7166                   decLine ();
7167                   ppllerror (message ("Specified type implemented as macro: %s", sname));
7168                   checkmacro = FALSE;
7169                   incLine ();
7170                 }
7171             }
7172         }
7173     }
7174
7175   if (!checkmacro)
7176     {
7177       if (usymtab_exists (sname))
7178         {
7179           uentry ue = usymtab_lookupExpose (sname);
7180           fileloc tloc = fileloc_makePreproc (g_currentloc);
7181
7182           uentry_setDefined (ue, tloc);
7183           fileloc_free (tloc);
7184           uentry_setUsed (ue, fileloc_undefined);
7185         }
7186       else
7187         {
7188           fileloc tloc = fileloc_makePreproc (g_currentloc);
7189           uentry ue = uentry_makeExpandedMacro (sname, tloc);
7190           DPRINTF (("Make expanded macro: %s", sname));
7191           DPRINTF (("Not in symbol table: %s", sname));
7192           
7193           (void) usymtab_addGlobalEntry (ue);
7194           fileloc_free (tloc);
7195         }
7196     }
7197
7198   *p = c;
7199   DPRINTF (("Returning: %s", bool_unparse (checkmacro)));
7200   return checkmacro;
7201 }
7202
7203 static enum cpp_token
7204 cpp_handleComment (cppReader *pfile, struct parse_marker *smark)
7205 {
7206   cppBuffer *pbuf = cppReader_getBuffer (pfile);
7207   char *start;
7208   int len;
7209   bool eliminateComment = FALSE;
7210
7211   llassert (pbuf->buf != NULL);
7212
7213   start = pbuf->buf + smark->position;
7214
7215   llassert (pbuf->cur != NULL);
7216   len = pbuf->cur - start;
7217
7218   if (start[0] == '*'
7219       && start[1] == context_getCommentMarkerChar ())
7220     {
7221       int i;
7222       char c = ' ';
7223       char *scomment = start + 2;
7224
7225       start[0] = BEFORE_COMMENT_MARKER[0];
7226       start[1] = BEFORE_COMMENT_MARKER[1];
7227
7228       llassert (start[len - 2] == '*');
7229       start[len - 2] = AFTER_COMMENT_MARKER[0];
7230
7231       llassert (start[len - 1] == '/');
7232       start[len - 1] = AFTER_COMMENT_MARKER[1];
7233
7234       cppReader_reserve(pfile, size_fromInt (1 + len));
7235       cppReader_putCharQ (pfile, c);
7236
7237       cpp_setLocation (pfile);
7238
7239       if (mstring_equalPrefix (scomment, "ignore"))
7240         {
7241           if (!context_getFlag (FLG_NOCOMMENTS))
7242             {
7243               context_enterSuppressRegion ();
7244             }
7245         }
7246       else if (mstring_equalPrefix (scomment, "end"))
7247         {
7248           if (!context_getFlag (FLG_NOCOMMENTS))
7249             {
7250               context_exitSuppressRegion ();
7251             }
7252         }
7253       else if (mstring_equalPrefix (scomment, "notparseable"))
7254         {
7255           notparseable = TRUE;
7256           expectmacro = TRUE;
7257           eliminateComment = TRUE;
7258         }
7259       else if (mstring_equalPrefix (scomment, "notfunction"))
7260         {
7261           notfunction = TRUE;
7262           expectmacro = TRUE;
7263           eliminateComment = TRUE;
7264         }
7265       else if (mstring_equalPrefix (scomment, "iter"))
7266         {
7267           expectiter = TRUE;
7268         }
7269       else if (mstring_equalPrefix (scomment, "function"))
7270         {
7271           expectfunction = TRUE;
7272         }
7273       else if (mstring_equalPrefix (scomment, "constant"))
7274         {
7275           expectconstant = TRUE;
7276         }
7277       else
7278         {
7279           char sChar = *scomment;
7280
7281           if (sChar == '='
7282               || sChar == '-'
7283               || sChar == '+')
7284             {
7285               char *rest = scomment + 1;
7286
7287               if (mstring_equalPrefix (rest, "commentchar"))
7288                 {
7289                   eliminateComment = TRUE;
7290
7291                   if (sChar == '=')
7292                     {
7293                       ppllerror (cstring_makeLiteral
7294                                  ("Cannot restore commentchar"));
7295                     }
7296                   else
7297                     {
7298                       char *next = scomment + 12; /* strlen commentchar = 12 */
7299
7300                       if (*next != ' ' && *next != '\t' && *next != '\n')
7301                         {
7302                           ppllerror
7303                             (message
7304                              ("Syntactic commentchar comment is not followed by a "
7305                               "whitespace character: %c",
7306                               *next));
7307                         }
7308                       else
7309                         {
7310                           char cchar = *(next + 1);
7311
7312                           if (cchar == '\0')
7313                             {
7314                               ppllerror
7315                                 (cstring_makeLiteral
7316                                  ("Cannot set commentchar to NUL"));
7317                             }
7318                           else
7319                             {
7320                               context_setCommentMarkerChar (cchar);
7321                               /* setComment = TRUE; */
7322                             }
7323                         }
7324                     }
7325                 }
7326               else if (mstring_equalPrefix (scomment, "nestcomment"))
7327                 {
7328                   /* fix from Mike Miller <MikeM@xata.com> */
7329                   context_fileSetFlag (FLG_NESTCOMMENT,
7330                                        ynm_fromCodeChar (sChar));
7331                 }
7332               else if (mstring_equalPrefix (rest, "namechecks"))
7333                 {
7334                   context_fileSetFlag (FLG_NAMECHECKS,
7335                                        ynm_fromCodeChar (sChar));
7336                 }
7337               else if (mstring_equalPrefix (rest, "macroredef"))
7338                 {
7339                   context_fileSetFlag (FLG_MACROREDEF,
7340                                        ynm_fromCodeChar (sChar));
7341                 }
7342               else if (mstring_equalPrefix (rest, "usevarargs"))
7343                 {
7344                   context_fileSetFlag (FLG_USEVARARGS,
7345                                        ynm_fromCodeChar (sChar));
7346                 }
7347               else if (mstring_equalPrefix (rest, "nextlinemacros"))
7348                 {
7349                   context_fileSetFlag (FLG_MACRONEXTLINE,
7350                                        ynm_fromCodeChar (sChar));
7351                 }
7352               else if (mstring_equalPrefix (rest, "allmacros")
7353                        || mstring_equalPrefix (rest, "fcnmacros")
7354                        || mstring_equalPrefix (rest, "constmacros"))
7355                 {
7356                   flagcode fl;
7357
7358                   if (mstring_equalPrefix (rest, "allmacros"))
7359                     {
7360                       fl = FLG_ALLMACROS;
7361                     }
7362                   else if (mstring_equalPrefix (rest, "fcnmacros"))
7363                     {
7364                       fl = FLG_FCNMACROS;
7365                     }
7366                   else
7367                     {
7368                       llassert (mstring_equalPrefix (rest, "constmacros"));
7369                       fl = FLG_CONSTMACROS;
7370                     }
7371
7372
7373                   context_fileSetFlag (fl, ynm_fromCodeChar (sChar));
7374                   notfunction = FALSE;
7375                 }
7376               else
7377                 {
7378                   ;
7379                 }
7380             }
7381           else
7382             {
7383               ;
7384             }
7385         }
7386
7387       if (eliminateComment)
7388         {
7389           goto removeComment;
7390         }
7391
7392       /* Replaces comment char's in start with spaces */
7393
7394       for (i = 2; i < len - 2; i++)
7395         {
7396           if (start[i] == BEFORE_COMMENT_MARKER[0]
7397               || start[i] == BEFORE_COMMENT_MARKER[1]
7398               || start[i] == context_getCommentMarkerChar ())
7399             {
7400               start[i] = ' ';
7401             }
7402         }
7403
7404       cppReader_putStrN (pfile, start, size_fromInt (len));
7405       parseClearMark (smark);
7406       return CPP_COMMENT;
7407     }
7408   else
7409     {
7410     removeComment:
7411       {
7412         int i;
7413
7414         /*
7415         ** Output the comment as all spaces so line/column
7416         ** in output file is still correct.
7417         */
7418
7419         char c = ' ';
7420         cstring lintcomment = cstring_undefined;
7421
7422         if (context_getFlag (FLG_LINTCOMMENTS))
7423           {
7424             if (mstring_equalPrefix (start, "*NOTREACHED*/"))
7425               {
7426                 lintcomment = cstring_makeLiteralTemp ("l_notreach");
7427               }
7428             else if (mstring_equalPrefix (start, "*PRINTFLIKE*/"))
7429               {
7430                 lintcomment = cstring_makeLiteralTemp ("l_printfli");
7431               }
7432             else if (mstring_equalPrefix (start, "*FALLTHROUGH*/"))
7433               {
7434                 lintcomment = cstring_makeLiteralTemp ("l_fallthrou");
7435               }
7436             else if (mstring_equalPrefix (start, "*ARGSUSED*/"))
7437               {
7438                 lintcomment = cstring_makeLiteralTemp ("l_argsus");
7439               }
7440             else if (mstring_equalPrefix (start, "*FALLTHRU*/"))
7441               {
7442                 lintcomment = cstring_makeLiteralTemp ("l_fallth");
7443               }
7444             else
7445               {
7446                 lintcomment = cstring_undefined;
7447               }
7448           }
7449         else
7450           {
7451             lintcomment = cstring_undefined;
7452           }
7453
7454         if (cstring_isDefined (lintcomment))
7455           {
7456             c = BEFORE_COMMENT_MARKER[0];
7457             start[0] = BEFORE_COMMENT_MARKER[1];
7458
7459             llassert (cstring_length (lintcomment) == len - 3);
7460
7461             for (i = 1; i < len - 2; i++)
7462               {
7463                 start[i] = cstring_getChar (lintcomment, i);
7464               }
7465             
7466             start[len - 2] = AFTER_COMMENT_MARKER[0];
7467             start[len - 1] = AFTER_COMMENT_MARKER[1];
7468           }
7469         else
7470           {
7471             /* Replaces  char's in start with spaces */
7472             for (i = 0; i < len; i++)
7473               {
7474                 if (start[i] == '/'
7475                     && i < len - 1
7476                     && start[i + 1] == '*') {
7477                   (void) cppoptgenerror (FLG_NESTCOMMENT,
7478                                          message ("Comment starts inside comment"),
7479                                          pfile);
7480                 }
7481                 
7482                 if (start[i] != '\n')
7483                   {
7484                     start[i] = ' ';
7485                   }
7486               }
7487           }
7488
7489         cppReader_reserve (pfile, size_fromInt (1 + len));
7490         cppReader_putCharQ (pfile, c);
7491         cppReader_putStrN (pfile, start, size_fromInt (len));
7492         parseClearMark (smark);
7493         return CPP_COMMENT;
7494       }
7495     }
7496 }
7497
7498 static int cpp_openIncludeFile (char *filename)
7499 {
7500   int res = open (filename, O_RDONLY, 0666);
7501
7502   if (res) 
7503     {
7504       if (!fileTable_exists (context_fileTable (),
7505                              cstring_fromChars (filename)))
7506         {
7507           (void) fileTable_addHeaderFile (context_fileTable (),
7508                                           cstring_fromChars (filename));
7509         }
7510       else
7511         {
7512           DPRINTF (("File already exists: %s", filename));
7513         }
7514     }
7515                 
7516
7517   return res;
7518 }
7519
7520 static bool cpp_skipIncludeFile (cstring fname)
7521 {
7522   if (context_isSystemDir (fname))
7523     {
7524       DPRINTF (("System dir: %s", fname));
7525
7526       if (lcllib_isSkipHeader (fname))
7527         {
7528           DPRINTF (("Skip include TRUE: %s", fname));
7529           return TRUE;
7530         }
7531       
7532       if (context_getFlag (FLG_SKIPSYSHEADERS))
7533         {
7534           DPRINTF (("Skip include TRUE: %s", fname));
7535           return TRUE;
7536         }
7537     }
7538
7539   if (context_getFlag (FLG_SINGLEINCLUDE))
7540     {
7541       fname = removePreDirs (fname);
7542
7543 # if defined (WIN32) || defined (OS2)
7544       cstring_replaceAll (fname, '\\', '/');
7545 # endif
7546
7547       if (fileTable_exists (context_fileTable (), fname))
7548         {
7549           DPRINTF (("Skip include TRUE: %s", fname));
7550           return TRUE;
7551         }
7552     }
7553
7554   DPRINTF (("Skip include FALSE: %s", fname));
7555   return FALSE;
7556 }
7557
7558 static int cpp_peekN (cppReader *pfile, int n)
7559 {
7560   cppBuffer *buf = cppReader_getBuffer (pfile);
7561
7562   llassert (buf->cur != NULL);
7563
7564   return (buf->rlimit - buf->cur >= (n)
7565           ? buf->cur[n]
7566           : EOF);
7567 }
7568
7569 cppBuffer *cppBuffer_prevBuffer (cppBuffer *buf)
7570 {
7571   return buf + 1;
7572 }
7573
7574 void cppBuffer_forward (cppBuffer *buf, int n)
7575 {
7576   llassert (buf->cur != NULL);
7577   buf->cur += n;
7578 }
This page took 0.673531 seconds and 5 git commands to generate.