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