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