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