]> andersk Git - splint.git/blame - src/cpplib.c
Small additions to library
[splint.git] / src / cpplib.c
CommitLineData
fbace05a 1/*\r
2See\r
3http://src.openresources.com/debian/src/devel/HTML/S/altgcc_2.7.2.2.orig%20altgcc-2.7.2.2.orig%20protoize.c.html\r
4static char *\r
5abspath (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
33Carl 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
68This program is free software; you can redistribute it and/or modify it\r
69under the terms of the GNU General Public License as published by the\r
70Free Software Foundation; either version 2, or (at your option) any\r
71later version.\r
72\r
73This program is distributed in the hope that it will be useful,\r
74but WITHOUT ANY WARRANTY; without even the implied warranty of\r
75MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
76GNU General Public License for more details.\r
77\r
78You should have received a copy of the GNU General Public License\r
79along with this program; if not, write to the Free Software\r
80Foundation, 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
176static void parse_name (cppReader *, int);\r
177\r
178static int cpp_openIncludeFile (char *p_filename)\r
179 /*@modifies fileSystem @*/ ;\r
180\r
181static void cpp_setLocation (cppReader *p_pfile)\r
182 /*@modifies g_currentloc@*/ ;\r
183\r
184static 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
188static bool cpp_shouldCheckMacro (cppReader *p_pfile, char *p_p) /*@*/ ;\r
189\r
190static 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
199static /*@observer@*/ char *predefs = CPP_PREDEFINES;\r
200#else\r
201static /*@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
246static bool is_idchar[256];\r
247/* table to tell if char can be first char of a c identifier. */\r
248static bool is_idstart[256];\r
249/* table to tell if c is horizontal space. */\r
250static bool is_hor_space[256];\r
251/* table to tell if c is horizontal or vertical space. */\r
252static bool is_space[256];\r
253\r
254static /*@exposed@*/ /*@null@*/ cppBuffer *\r
255cppReader_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
265static 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
313static 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
342static void parseSetMark (/*@out@*/ struct parse_marker *,\r
343 cppReader *);\r
344static void parseClearMark (struct parse_marker *);\r
345static void parseGotoMark (struct parse_marker *, cppReader *);\r
346static void parseMoveMark (struct parse_marker *, cppReader *);\r
347\r
348/* If we have a huge buffer, may need to cache more recent counts */\r
349static /*@exposed@*/ char *cppLineBase (/*@sef@*/ cppBuffer *);\r
350\r
351static /*@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
356static 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
361static void cppReader_macroCleanup (cppBuffer *p_pbuf, cppReader *p_pfile);\r
362static enum cpp_token cppReader_nullUnderflow (/*@unused@*/ cppReader *p_pfile);\r
363\r
364static void cppReader_nullCleanup (/*@unused@*/ cppBuffer *p_pbuf,\r
365 /*@unused@*/ cppReader *p_pfile);\r
366\r
367static void cppReader_fileCleanup (cppBuffer *p_pbuf,\r
368 /*@unused@*/ cppReader *p_pfile);\r
369\r
370static int cppReader_handleDirective (cppReader *p_pfile);\r
371\r
372static 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
381typedef unsigned int mode_t;\r
382/*@=incondefs@*/ /*@=czechtypes@*/\r
383\r
384# endif\r
385\r
386static int file_size_and_mode (int p_fd, /*@out@*/ mode_t *p_mode_pointer,\r
387 /*@out@*/ size_t *p_size_pointer);\r
388static 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
396static bool cppBuffer_isMacro (/*@null@*/ cppBuffer *) /*@*/ ;\r
397\r
398static void path_include (cppReader *p_pfile, char *p_path)\r
399 /*@modifies p_pfile@*/ ;\r
400\r
401static void initialize_builtins (cppReader *p_pfile)\r
402 /*@modifies p_pfile@*/ ;\r
403\r
404static void initialize_char_syntax (struct cppOptions *p_opts) ;\r
405\r
406static 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
411static void validate_else (cppReader *p_pfile, cstring p_directive);\r
412\r
413static 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
417static HOST_WIDE_INT eval_if_expression (cppReader *p_pfile,\r
418 char *p_buf,\r
419 int p_length);\r
420\r
421static void skip_if_group (cppReader *p_pfile, int p_any);\r
422\r
423static 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
427extern void fancy_abort ();\r
428#endif\r
429\r
430static bool redundant_include_p (cppReader *p_pfile, /*@null@*/ cstring p_name);\r
431static bool is_system_include (cppReader *p_pfile, cstring p_filename);\r
432\r
433static /*@observer@*/ /*@null@*/ struct file_name_map *\r
434read_name_map (cppReader *p_pfile, cstring p_dirname);\r
435\r
436static cstring read_filename_string (int p_ch, /*:open:*/ FILE *p_f);\r
437\r
438static 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
442static 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
447enum 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
453struct 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
467static int do_define (cppReader *, /*@null@*/ struct directive *, \r
468 char *, char *);\r
469static int do_defineAux (cppReader *, /*@null@*/ struct directive *,\r
470 char *, char *, bool);\r
471 \r
472static int do_line (cppReader *, /*@null@*/ struct directive *);\r
473static int do_include (cppReader *, struct directive *, char *, char *);\r
474static int do_undef (cppReader *, struct directive *, char *, char *);\r
475static int do_error (cppReader *, struct directive *, char *, char *);\r
476static int do_pragma (cppReader *, struct directive *, char *, char *);\r
477static int do_ident (cppReader *, struct directive *, char *, char *);\r
478static int do_if (cppReader *, struct directive *, char *, char *);\r
479static int do_xifdef (cppReader *, struct directive *, char *, char *);\r
480static int do_else (cppReader *, struct directive *, char *, char *);\r
481static int do_elif (cppReader *, struct directive *, char *, char *);\r
482static int do_endif (cppReader *, struct directive *, char *, char *);\r
483static 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
497static 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
519static 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
539static 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
559static void\r
560initialize_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
603bool 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
611static void\r
612quote_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
648void\r
649cppReader_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
665void\r
666cppReader_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
761void\r
762cppReader_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
803static /*@unused@*/ void \r
804cppReader_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
825cstring \r
826cppReader_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
848void\r
849cppReader_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
886static void\r
887path_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
947void\r
948cppOptions_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
979enum cpp_token\r
980cppReader_nullUnderflow (/*@unused@*/ cppReader *pfile)\r
981{\r
982 return CPP_EOF;\r
983}\r
984\r
985void\r
986cppReader_nullCleanup (/*@unused@*/ cppBuffer *pbuf,\r
987 /*@unused@*/ cppReader *pfile)\r
988{\r
989 ;\r
990}\r
991\r
992void\r
993cppReader_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
1009void\r
1010cppReader_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
1025static int\r
1026skip_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
1119int /*@alt void@*/\r
1120cppSkipHspace (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
1183static void\r
1184copy_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
1244end_directive: ;\r
1245 cppReader_nullTerminate (pfile);\r
1246}\r
1247\r
1248void\r
1249cppReader_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
1259int\r
1260cppReader_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
1436done_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
1451static void\r
1452pass_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
1487static DEFINITION *\r
1488collect_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
1826static 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
1835static /*@null@*/ MACRODEF\r
1836create_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
2036nope:\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
2045int 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
2084static bool\r
2085compare_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
2139static bool\r
2140comp_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
2170static int\r
2171do_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
2279nope:\r
2280\r
2281 return 1;\r
2282}\r
2283\r
2284static int\r
2285do_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
2306struct 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
2324cppReader_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
2364cppBuffer *\r
2365cppReader_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
2378void\r
2379cppReader_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
2410static void\r
2411cpp_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
2451static void\r
2452adjust_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
2466static void\r
2467update_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
2489void\r
2490cppBuffer_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
2537static long\r
2538count_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
2559static void\r
2560output_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
2656static enum cpp_token\r
2657macarg (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
2707done:\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
2719static int\r
2720change_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
2755static /*@observer@*/ struct tm *\r
2756timestamp (/*@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
2769static 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
2779static void\r
2780special_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
2984static void\r
2985dump_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
3000static void\r
3001cppReader_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
3038static void\r
3039cppReader_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
3061static void\r
3062initialize_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
3128static bool\r
3129unsafe_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
3177static void\r
3178macroexpand (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
3690static void\r
3691push_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
3737static enum cpp_token\r
3738get_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
3777static int\r
3778do_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
4174static bool\r
4175redundant_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
4203static bool\r
4204is_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
4236static /*@null@*/ char *\r
4237convert_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
4288static int\r
4289do_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
4423bad_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
4436static int\r
4437do_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
4487static int\r
4488do_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
4506static int\r
4507do_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
4521static int\r
4522do_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
4538static int\r
4539do_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
4595static int\r
4596do_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
4609static 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
4661static HOST_WIDE_INT\r
4662eval_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
4690static int\r
4691do_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
4781static void\r
4782conditional_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
4815static void\r
4816skip_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
4834beg_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
4984done:\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
5003static int\r
5004do_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
5053static int\r
5054do_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
5128static void\r
5129validate_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
5146enum cpp_token\r
5147cppGetToken (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
5156get_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
5820void\r
5821parse_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
5862struct 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
5875static 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
5906struct 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
5915static struct file_name_map *\r
5916read_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
6017static int\r
6018open_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
6170static int\r
6171finclude (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
6285void\r
6286cppReader_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
6307void\r
6308cppReader_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
6316void\r
6317cppCleanup (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
6355static int\r
6356file_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
6382static 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
6418void\r
6419parseSetMark (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
6434void 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
6449void\r
6450parseGotoMark (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
6467void\r
6468parseMoveMark (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
6481void 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
6764int 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
6815static /*@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
6832int 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
6845bool 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
6860static bool notparseable = FALSE; /* preceeded by @notparseable@ */\r
6861static bool notfunction = FALSE; /* preceeded by @notfunction@ */\r
6862static bool expectiter = FALSE; /* preceeded by @iter@ */\r
6863static bool expectenditer = FALSE; /* second after @iter@ */\r
6864static bool expectfunction = FALSE; /* preceeded by @function@ */\r
6865static bool expectconstant = FALSE; /* preceeded by @constant@ */\r
6866static bool expectmacro = FALSE; /* preceeded by notfunction or notparseable */\r
6867\r
6868static 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
6918static 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
7196static enum cpp_token\r
7197cpp_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
7505static 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
7527static 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
7565static 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
7576cppBuffer *cppBuffer_prevBuffer (cppBuffer *buf)\r
7577{\r
7578 return buf + 1;\r
7579}\r
7580\r
7581void 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 1.192686 seconds and 5 git commands to generate.