File: | workdir/unxlngi6.pro/CustomTarget/ucpp/source/cpp.c |
Location: | line 813, column 3 |
Description: | Value stored to 'nffa' is never read |
1 | /* |
2 | * C and T preprocessor, and integrated lexer |
3 | * (c) Thomas Pornin 1999 - 2002 |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
8 | * 1. Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions and the following disclaimer. |
10 | * 2. Redistributions in binary form must reproduce the above copyright |
11 | * notice, this list of conditions and the following disclaimer in the |
12 | * documentation and/or other materials provided with the distribution. |
13 | * 4. The name of the authors may not be used to endorse or promote |
14 | * products derived from this software without specific prior written |
15 | * permission. |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE |
21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
23 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
27 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | * |
29 | */ |
30 | |
31 | #define VERS_MAJ1 1 |
32 | #define VERS_MIN3 3 |
33 | /* uncomment the following if you cannot set it with a compiler flag */ |
34 | /* #define STAND_ALONE */ |
35 | |
36 | #include "tune.h" |
37 | #include <stdio.h> |
38 | #include <string.h> |
39 | #include <stdarg.h> |
40 | #include <setjmp.h> |
41 | #include <stddef.h> |
42 | #include <limits.h> |
43 | #include <time.h> |
44 | #include "ucppi.h" |
45 | #include "mem.h" |
46 | #include "nhash.h" |
47 | #ifdef UCPP_MMAP |
48 | #include <unistd.h> |
49 | #include <sys/types.h> |
50 | #include <sys/mman.h> |
51 | #include <fcntl.h> |
52 | #endif |
53 | |
54 | /* |
55 | * The standard path where includes are looked for. |
56 | */ |
57 | #ifdef STAND_ALONE1 |
58 | static char *include_path_std[] = { STD_INCLUDE_PATH"/usr/local/include", "/usr/include", 0 }; |
59 | #endif |
60 | static char **include_path; |
61 | static size_t include_path_nb = 0; |
62 | |
63 | int no_special_macros = 0; |
64 | int emit_dependencies = 0, emit_defines = 0, emit_assertions = 0; |
65 | FILE *emit_output; |
66 | |
67 | #ifdef STAND_ALONE1 |
68 | static char *system_macros_def[] = { STD_MACROS0, 0 }; |
69 | static char *system_assertions_def[] = { STD_ASSERT0, 0 }; |
70 | #endif |
71 | |
72 | char *current_filename = 0, *current_long_filename = 0; |
73 | static int current_incdir = -1; |
74 | |
75 | #ifndef NO_UCPP_ERROR_FUNCTIONS |
76 | /* |
77 | * "ouch" is the name for an internal ucpp error. If AUDIT is not defined, |
78 | * no code calling this function will be generated; a "ouch" may still be |
79 | * emitted by getmem() (in mem.c) if MEM_CHECK is defined, but this "ouch" |
80 | * does not use this function. |
81 | */ |
82 | void ucpp_ouch(char *fmt, ...) |
83 | { |
84 | va_list ap; |
85 | |
86 | va_start(ap, fmt)__builtin_va_start(ap, fmt); |
87 | fprintf(stderrstderr, "%s: ouch, ", current_filename); |
88 | vfprintf(stderrstderr, fmt, ap); |
89 | fprintf(stderrstderr, "\n"); |
90 | va_end(ap)__builtin_va_end(ap); |
91 | die(); |
92 | } |
93 | |
94 | /* |
95 | * report an error, with current_filename, line, and printf-like syntax |
96 | */ |
97 | void ucpp_error(long line, char *fmt, ...) |
98 | { |
99 | va_list ap; |
100 | |
101 | va_start(ap, fmt)__builtin_va_start(ap, fmt); |
102 | if (line > 0) |
103 | fprintf(stderrstderr, "%s: line %ld: ", current_filename, line); |
104 | else if (line == 0) fprintf(stderrstderr, "%s: ", current_filename); |
105 | vfprintf(stderrstderr, fmt, ap); |
106 | fprintf(stderrstderr, "\n"); |
107 | if (line >= 0) { |
108 | struct stack_context *sc = report_context(); |
109 | size_t i; |
110 | |
111 | for (i = 0; sc[i].line >= 0; i ++) |
112 | fprintf(stderrstderr, "\tincluded from %s:%ld\n", |
113 | sc[i].long_name ? sc[i].long_name : sc[i].name, |
114 | sc[i].line); |
115 | freememfree(sc); |
116 | } |
117 | va_end(ap)__builtin_va_end(ap); |
118 | } |
119 | |
120 | /* |
121 | * like error(), with the mention "warning" |
122 | */ |
123 | void ucpp_warning(long line, char *fmt, ...) |
124 | { |
125 | va_list ap; |
126 | |
127 | va_start(ap, fmt)__builtin_va_start(ap, fmt); |
128 | if (line > 0) |
129 | fprintf(stderrstderr, "%s: warning: line %ld: ", |
130 | current_filename, line); |
131 | else if (line == 0) |
132 | fprintf(stderrstderr, "%s: warning: ", current_filename); |
133 | else fprintf(stderrstderr, "warning: "); |
134 | vfprintf(stderrstderr, fmt, ap); |
135 | fprintf(stderrstderr, "\n"); |
136 | if (line >= 0) { |
137 | struct stack_context *sc = report_context(); |
138 | size_t i; |
139 | |
140 | for (i = 0; sc[i].line >= 0; i ++) |
141 | fprintf(stderrstderr, "\tincluded from %s:%ld\n", |
142 | sc[i].long_name ? sc[i].long_name : sc[i].name, |
143 | sc[i].line); |
144 | freememfree(sc); |
145 | } |
146 | va_end(ap)__builtin_va_end(ap); |
147 | } |
148 | #endif /* NO_UCPP_ERROR_FUNCTIONS */ |
149 | |
150 | /* |
151 | * Some memory allocations are manually garbage-collected; essentially, |
152 | * strings duplicated in the process of macro replacement. Each such |
153 | * string is referenced in the garbage_fifo, which is cleared when all |
154 | * nested macros have been resolved. |
155 | */ |
156 | |
157 | struct garbage_fifo { |
158 | char **garbage; |
159 | size_t ngarb, memgarb; |
160 | }; |
161 | |
162 | /* |
163 | * throw_away() marks a string to be collected later |
164 | */ |
165 | void throw_awayucpp_throw_away(struct garbage_fifo *gf, char *n) |
166 | { |
167 | wan(gf->garbage, gf->ngarb, n, gf->memgarb)do { if ((gf->ngarb) == (gf->memgarb)) { (gf->memgarb ) += (gf->memgarb); (gf->garbage) = incmem((gf->garbage ), (gf->ngarb) * sizeof(n), (gf->memgarb) * sizeof(n)); } (gf->garbage)[(gf->ngarb) ++] = (n); } while (0); |
168 | } |
169 | |
170 | /* |
171 | * free marked strings |
172 | */ |
173 | void garbage_collectucpp_garbage_collect(struct garbage_fifo *gf) |
174 | { |
175 | size_t i; |
176 | |
177 | for (i = 0; i < gf->ngarb; i ++) freememfree(gf->garbage[i]); |
178 | gf->ngarb = 0; |
179 | } |
180 | |
181 | static void init_garbage_fifo(struct garbage_fifo *gf) |
182 | { |
183 | gf->garbage = getmemmalloc((gf->memgarb = GARBAGE_LIST_MEMG32) |
184 | * sizeof(char *)); |
185 | gf->ngarb = 0; |
186 | } |
187 | |
188 | static void free_garbage_fifo(struct garbage_fifo *gf) |
189 | { |
190 | garbage_collectucpp_garbage_collect(gf); |
191 | freememfree(gf->garbage); |
192 | freememfree(gf); |
193 | } |
194 | |
195 | /* |
196 | * order is important: it must match the token-constants declared as an |
197 | * enum in the header file. |
198 | */ |
199 | char *operators_name[] = { |
200 | " ", "\n", " ", |
201 | "0000", "name", "bunch", "pragma", "context", |
202 | "\"dummy string\"", "'dummy char'", |
203 | "/", "/=", "-", "--", "-=", "->", "+", "++", "+=", "<", "<=", "<<", |
204 | "<<=", ">", ">=", ">>", ">>=", "=", "==", |
205 | #ifdef CAST_OP |
206 | "=>", |
207 | #endif |
208 | "~", "!=", "&", "&&", "&=", "|", "||", "|=", "%", "%=", "*", "*=", |
209 | "^", "^=", "!", |
210 | "{", "}", "[", "]", "(", ")", ",", "?", ";", |
211 | ":", ".", "...", "#", "##", " ", "ouch", "<:", ":>", "<%", "%>", |
212 | "%:", "%:%:" |
213 | }; |
214 | |
215 | /* the ascii representation of a token */ |
216 | #ifdef SEMPER_FIDELIS |
217 | #define tname(x)((((x).type) >= NUMBER && ((x).type) <= CHAR) ? (x).name : operators_name[(x).type]) (ttWHI((x).type)((((x).type) == NONE || ((x).type) == COMMENT || ((x).type) == OPT_NONE) || ((x).type) == NEWLINE) ? " " : S_TOKEN((x).type)(((x).type) >= NUMBER && ((x).type) <= CHAR) \ |
218 | ? (x).name : operators_name[(x).type]) |
219 | #else |
220 | #define tname(x)((((x).type) >= NUMBER && ((x).type) <= CHAR) ? (x).name : operators_name[(x).type]) (S_TOKEN((x).type)(((x).type) >= NUMBER && ((x).type) <= CHAR) ? (x).name \ |
221 | : operators_name[(x).type]) |
222 | #endif |
223 | |
224 | char *token_nameucpp_token_name(struct token *t) |
225 | { |
226 | return tname(*t)((((*t).type) >= NUMBER && ((*t).type) <= CHAR) ? (*t).name : operators_name[(*t).type]); |
227 | } |
228 | |
229 | /* |
230 | * To speed up deeply nested and repeated inclusions, we: |
231 | * -- use a hash table to remember where we found each file |
232 | * -- remember when the file is protected by a #ifndef/#define/#endif |
233 | * construction; we can then avoid including several times a file |
234 | * when this is not necessary. |
235 | * -- remember in which directory, in the include path, the file was found. |
236 | */ |
237 | struct found_file { |
238 | hash_item_header head; /* first field */ |
239 | char *name; |
240 | char *protect; |
241 | }; |
242 | |
243 | /* |
244 | * For files from system include path. |
245 | */ |
246 | struct found_file_sys { |
247 | hash_item_header head; /* first field */ |
248 | struct found_file *rff; |
249 | int incdir; |
250 | }; |
251 | |
252 | static HTT found_files, found_files_sys; |
253 | static int found_files_init_done = 0, found_files_sys_init_done = 0; |
254 | |
255 | static struct found_file *new_found_file(void) |
256 | { |
257 | struct found_file *ff = getmemmalloc(sizeof(struct found_file)); |
258 | |
259 | ff->name = 0; |
260 | ff->protect = 0; |
261 | return ff; |
262 | } |
263 | |
264 | static void del_found_file(void *m) |
265 | { |
266 | struct found_file *ff = (struct found_file *)m; |
267 | |
268 | if (ff->name) freememfree(ff->name); |
269 | if (ff->protect) freememfree(ff->protect); |
270 | freememfree(ff); |
271 | } |
272 | |
273 | static struct found_file_sys *new_found_file_sys(void) |
274 | { |
275 | struct found_file_sys *ffs = getmemmalloc(sizeof(struct found_file_sys)); |
276 | |
277 | ffs->rff = 0; |
278 | ffs->incdir = -1; |
279 | return ffs; |
280 | } |
281 | |
282 | static void del_found_file_sys(void *m) |
283 | { |
284 | struct found_file_sys *ffs = (struct found_file_sys *)m; |
285 | |
286 | freememfree(ffs); |
287 | } |
288 | |
289 | /* |
290 | * To keep up with the #ifndef/#define/#endif protection mechanism |
291 | * detection. |
292 | */ |
293 | struct protect protect_detect; |
294 | static struct protect *protect_detect_stack = 0; |
295 | |
296 | void set_init_filename(char *x, int real_file) |
297 | { |
298 | if (current_filename) freememfree(current_filename); |
299 | current_filename = sdup(x); |
300 | current_long_filename = 0; |
301 | current_incdir = -1; |
302 | if (real_file) { |
303 | protect_detect.macro = 0; |
304 | protect_detect.state = 1; |
305 | protect_detect.ff = new_found_file(); |
306 | protect_detect.ff->name = sdup(x); |
307 | HTT_put(&found_files, protect_detect.ff, x); |
308 | } else { |
309 | protect_detect.state = 0; |
310 | } |
311 | } |
312 | |
313 | static void init_found_files(void) |
314 | { |
315 | if (found_files_init_done) HTT_kill(&found_files); |
316 | HTT_init(&found_files, del_found_file); |
317 | found_files_init_done = 1; |
318 | if (found_files_sys_init_done) HTT_kill(&found_files_sys); |
319 | HTT_init(&found_files_sys, del_found_file_sys); |
320 | found_files_sys_init_done = 1; |
321 | } |
322 | |
323 | /* |
324 | * Set the lexer state at the beginning of a file. |
325 | */ |
326 | static void reinit_lexer_state(struct lexer_state *ls, int wb) |
327 | { |
328 | #ifndef NO_UCPP_BUF1 |
329 | ls->input_buf = wb ? getmemmalloc(INPUT_BUF_MEMG8192) : 0; |
330 | #ifdef UCPP_MMAP |
331 | ls->from_mmap = 0; |
332 | #endif |
333 | #endif |
334 | ls->input = 0; |
335 | ls->ebuf = ls->pbuf = 0; |
336 | ls->nlka = 0; |
337 | ls->macfile = 0; |
338 | ls->discard = 1; |
339 | ls->last = 0; /* we suppose '\n' is not 0 */ |
340 | ls->line = 1; |
341 | ls->ltwnl = 1; |
342 | ls->oline = 1; |
343 | ls->pending_token = 0; |
344 | ls->cli = 0; |
345 | ls->copy_line[COPY_LINE_LENGTH80 - 1] = 0; |
346 | ls->ifnest = 0; |
347 | ls->condf[0] = ls->condf[1] = 0; |
348 | } |
349 | |
350 | /* |
351 | * Initialize the struct lexer_state, with optional input and output buffers. |
352 | */ |
353 | void init_buf_lexer_stateucpp_init_buf_lexer_state(struct lexer_state *ls, int wb) |
354 | { |
355 | reinit_lexer_state(ls, wb); |
356 | #ifndef NO_UCPP_BUF1 |
357 | ls->output_buf = wb ? getmemmalloc(OUTPUT_BUF_MEMG8192) : 0; |
358 | #endif |
359 | ls->sbuf = 0; |
360 | ls->output_fifo = 0; |
361 | |
362 | ls->ctok = getmemmalloc(sizeof(struct token)); |
363 | ls->ctok->name = getmemmalloc(ls->tknl = TOKEN_NAME_MEMG64); |
364 | ls->pending_token = 0; |
365 | |
366 | ls->flags = 0; |
367 | ls->count_trigraphs = 0; |
368 | ls->gf = getmemmalloc(sizeof(struct garbage_fifo)); |
369 | init_garbage_fifo(ls->gf); |
370 | ls->condcomp = 1; |
371 | ls->condnest = 0; |
372 | #ifdef INMACRO_FLAG |
373 | ls->inmacro = 0; |
374 | ls->macro_count = 0; |
375 | #endif |
376 | } |
377 | |
378 | /* |
379 | * Initialize the (complex) struct lexer_state. |
380 | */ |
381 | void init_lexer_state(struct lexer_state *ls) |
382 | { |
383 | init_buf_lexer_stateucpp_init_buf_lexer_state(ls, 1); |
384 | ls->input = 0; |
385 | } |
386 | |
387 | /* |
388 | * Restore what is needed from a lexer_state. This is used for #include. |
389 | */ |
390 | static void restore_lexer_state(struct lexer_state *ls, |
391 | struct lexer_state *lsbak) |
392 | { |
393 | #ifndef NO_UCPP_BUF1 |
394 | freememfree(ls->input_buf); |
395 | ls->input_buf = lsbak->input_buf; |
396 | #ifdef UCPP_MMAP |
397 | ls->from_mmap = lsbak->from_mmap; |
398 | ls->input_buf_sav = lsbak->input_buf_sav; |
399 | #endif |
400 | #endif |
401 | ls->input = lsbak->input; |
402 | ls->ebuf = lsbak->ebuf; |
403 | ls->pbuf = lsbak->pbuf; |
404 | ls->nlka = lsbak->nlka; |
405 | ls->discard = lsbak->discard; |
406 | ls->line = lsbak->line; |
407 | ls->oline = lsbak->oline; |
408 | ls->ifnest = lsbak->ifnest; |
409 | ls->condf[0] = lsbak->condf[0]; |
410 | ls->condf[1] = lsbak->condf[1]; |
411 | } |
412 | |
413 | /* |
414 | * close input file operations on a struct lexer_state |
415 | */ |
416 | static void close_input(struct lexer_state *ls) |
417 | { |
418 | #ifdef UCPP_MMAP |
419 | if (ls->from_mmap) { |
420 | munmap((void *)ls->input_buf, ls->ebuf); |
421 | ls->from_mmap = 0; |
422 | ls->input_buf = ls->input_buf_sav; |
423 | } |
424 | #endif |
425 | if (ls->input) { |
426 | fclose(ls->input); |
427 | ls->input = 0; |
428 | } |
429 | } |
430 | |
431 | /* |
432 | * file_context (and the two functions push_ and pop_) are used to save |
433 | * all that is needed when including a file. |
434 | */ |
435 | static struct file_context { |
436 | struct lexer_state ls; |
437 | char *name, *long_name; |
438 | int incdir; |
439 | } *ls_stack; |
440 | static size_t ls_depth = 0; |
441 | |
442 | static void push_file_context(struct lexer_state *ls) |
443 | { |
444 | struct file_context fc; |
445 | |
446 | fc.name = current_filename; |
447 | fc.long_name = current_long_filename; |
448 | fc.incdir = current_incdir; |
449 | mmvmemcpy(&(fc.ls), ls, sizeof(struct lexer_state)); |
450 | aol(ls_stack, ls_depth, fc, LS_STACK_MEMG)do { if (((ls_depth) % (4)) == 0) { if ((ls_depth) != 0) { (ls_stack ) = incmem((ls_stack), (ls_depth) * sizeof(fc), ((ls_depth) + (4)) * sizeof(fc)); } else { (ls_stack) = malloc((4) * sizeof (fc)); } } (ls_stack)[(ls_depth) ++] = (fc); } while (0); |
451 | ls_depth --; |
452 | aol(protect_detect_stack, ls_depth, protect_detect, LS_STACK_MEMG)do { if (((ls_depth) % (4)) == 0) { if ((ls_depth) != 0) { (protect_detect_stack ) = incmem((protect_detect_stack), (ls_depth) * sizeof(protect_detect ), ((ls_depth) + (4)) * sizeof(protect_detect)); } else { (protect_detect_stack ) = malloc((4) * sizeof(protect_detect)); } } (protect_detect_stack )[(ls_depth) ++] = (protect_detect); } while (0); |
453 | protect_detect.macro = 0; |
454 | } |
455 | |
456 | static void pop_file_context(struct lexer_state *ls) |
457 | { |
458 | #ifdef AUDIT |
459 | if (ls_depth <= 0) ouchucpp_ouch("prepare to meet thy creator"); |
460 | #endif |
461 | close_input(ls); |
462 | restore_lexer_state(ls, &(ls_stack[-- ls_depth].ls)); |
463 | if (protect_detect.macro) freememfree(protect_detect.macro); |
464 | protect_detect = protect_detect_stack[ls_depth]; |
465 | if (current_filename) freememfree(current_filename); |
466 | current_filename = ls_stack[ls_depth].name; |
467 | current_long_filename = ls_stack[ls_depth].long_name; |
468 | current_incdir = ls_stack[ls_depth].incdir; |
469 | if (ls_depth == 0) { |
470 | freememfree(ls_stack); |
471 | freememfree(protect_detect_stack); |
472 | } |
473 | } |
474 | |
475 | /* |
476 | * report_context() returns the list of successive includers of the |
477 | * current file, ending with a dummy entry with a negative line number. |
478 | * The caller is responsible for freeing the returned pointer. |
479 | */ |
480 | struct stack_context *report_context(void) |
481 | { |
482 | struct stack_context *sc; |
483 | size_t i; |
484 | |
485 | sc = getmemmalloc((ls_depth + 1) * sizeof(struct stack_context)); |
486 | for (i = 0; i < ls_depth; i ++) { |
487 | sc[i].name = ls_stack[ls_depth - i - 1].name; |
488 | sc[i].long_name = ls_stack[ls_depth - i - 1].long_name; |
489 | sc[i].line = ls_stack[ls_depth - i - 1].ls.line - 1; |
490 | } |
491 | sc[ls_depth].line = -1; |
492 | return sc; |
493 | } |
494 | |
495 | /* |
496 | * init_lexer_mode() is used to end initialization of a struct lexer_state |
497 | * if it must be used for a lexer |
498 | */ |
499 | void init_lexer_mode(struct lexer_state *ls) |
500 | { |
501 | ls->flags = DEFAULT_LEXER_FLAGS(0x000080UL | 0x000001UL | 0x000020UL | 0x002000UL | 0x000100UL | 0x010000UL | 0x008000UL | 0x000800UL); |
502 | ls->output_fifo = getmemmalloc(sizeof(struct token_fifo)); |
503 | ls->output_fifo->art = ls->output_fifo->nt = 0; |
504 | ls->toplevel_of = ls->output_fifo; |
505 | ls->save_ctok = ls->ctok; |
506 | } |
507 | |
508 | /* |
509 | * release memory used by a struct lexer_state; this implies closing |
510 | * any input stream held by this structure. |
511 | */ |
512 | void free_lexer_state(struct lexer_state *ls) |
513 | { |
514 | close_input(ls); |
515 | #ifndef NO_UCPP_BUF1 |
516 | if (ls->input_buf) { |
517 | freememfree(ls->input_buf); |
518 | ls->input_buf = 0; |
519 | } |
520 | if (ls->output_buf) { |
521 | freememfree(ls->output_buf); |
522 | ls->output_buf = 0; |
523 | } |
524 | #endif |
525 | if (ls->ctok && (!ls->output_fifo || ls->output_fifo->nt == 0)) { |
526 | freememfree(ls->ctok->name); |
527 | freememfree(ls->ctok); |
528 | ls->ctok = 0; |
529 | } |
530 | if (ls->gf) { |
531 | free_garbage_fifo(ls->gf); |
532 | ls->gf = 0; |
533 | } |
534 | if (ls->output_fifo) { |
535 | freememfree(ls->output_fifo); |
536 | ls->output_fifo = 0; |
537 | } |
538 | } |
539 | |
540 | /* |
541 | * Print line information. |
542 | */ |
543 | static void print_line_info(struct lexer_state *ls, unsigned long flags) |
544 | { |
545 | char *fn = current_long_filename ? |
546 | current_long_filename : current_filename; |
547 | char *b, *d; |
548 | |
549 | b = getmemmalloc(50 + strlen(fn)); |
550 | if (flags & GCC_LINE_NUM0x000400UL) { |
551 | sprintf(b, "# %ld \"%s\"\n", ls->line, fn); |
552 | } else { |
553 | sprintf(b, "#line %ld \"%s\"\n", ls->line, fn); |
554 | } |
555 | for (d = b; *d; d ++) put_charucpp_put_char(ls, (unsigned char)(*d)); |
556 | freememfree(b); |
557 | } |
558 | |
559 | /* |
560 | * Enter a file; this implies the possible emission of a #line directive. |
561 | * The flags used are passed as second parameter instead of being |
562 | * extracted from the struct lexer_state. |
563 | * |
564 | * As a command-line option, gcc-like directives (with only a '#', |
565 | * without 'line') may be produced. |
566 | * |
567 | * enter_file() returns 1 if a (CONTEXT) token was produced, 0 otherwise. |
568 | */ |
569 | int enter_file(struct lexer_state *ls, unsigned long flags) |
570 | { |
571 | char *fn = current_long_filename ? |
572 | current_long_filename : current_filename; |
573 | |
574 | if (!(flags & LINE_NUM0x000200UL)) return 0; |
575 | if ((flags & LEXER0x010000UL) && !(flags & TEXT_OUTPUT0x100000UL)) { |
576 | struct token t; |
577 | |
578 | t.type = CONTEXT; |
579 | t.line = ls->line; |
580 | t.name = fn; |
581 | print_tokenucpp_print_token(ls, &t, 0); |
582 | return 1; |
583 | } |
584 | print_line_info(ls, flags); |
585 | ls->oline --; /* emitted #line troubled oline */ |
586 | return 0; |
587 | } |
588 | |
589 | #ifdef UCPP_MMAP |
590 | /* |
591 | * We open() the file, then fdopen() it and fseek() to its end. If the |
592 | * fseek() worked, we try to mmap() the file, up to the point where we |
593 | * arrived. |
594 | * On an architecture where end-of-lines are multibytes and translated |
595 | * into single '\n', bad things could happen. We strongly hope that, if |
596 | * we could fseek() to the end but could not mmap(), then we can get back. |
597 | */ |
598 | static void *find_file_map; |
599 | static size_t map_length; |
600 | |
601 | FILE *fopen_mmap_file(char *name) |
602 | { |
603 | FILE *f; |
604 | int fd; |
605 | long l; |
606 | |
607 | find_file_map = 0; |
608 | fd = open(name, O_RDONLY, 0); |
609 | if (fd < 0) return 0; |
610 | l = lseek(fd, 0, SEEK_END2); |
611 | f = fdopen(fd, "r"); |
612 | if (!f) { |
613 | close(fd); |
614 | return 0; |
615 | } |
616 | if (l < 0) return f; /* not seekable */ |
617 | map_length = l; |
618 | if ((find_file_map = mmap(0, map_length, PROT_READ, |
619 | MAP_PRIVATE, fd, 0)) == MAP_FAILED) { |
620 | /* we could not mmap() the file; get back */ |
621 | find_file_map = 0; |
622 | if (fseek(f, 0, SEEK_SET0)) { |
623 | /* bwaah... can't get back. This file is cursed. */ |
624 | fclose(f); |
625 | return 0; |
626 | } |
627 | } |
628 | return f; |
629 | } |
630 | |
631 | void set_input_file(struct lexer_state *ls, FILE *f) |
632 | { |
633 | ls->input = f; |
634 | if (find_file_map) { |
635 | ls->from_mmap = 1; |
636 | ls->input_buf_sav = ls->input_buf; |
637 | ls->input_buf = find_file_map; |
638 | ls->pbuf = 0; |
639 | ls->ebuf = map_length; |
640 | } else { |
641 | ls->from_mmap = 0; |
642 | } |
643 | } |
644 | #endif |
645 | |
646 | /* |
647 | * Find a file by looking through the include path. |
648 | * return value: a FILE * on the file, opened in "r" mode, or 0. |
649 | * |
650 | * find_file_error will contain: |
651 | * FF_ERROR on error (file not found or impossible to read) |
652 | * FF_PROTECT file is protected and therefore useless to read |
653 | * FF_KNOWN file is already known |
654 | * FF_UNKNOWN file was not already known |
655 | */ |
656 | static int find_file_error; |
657 | |
658 | enum { FF_ERROR, FF_PROTECT, FF_KNOWN, FF_UNKNOWN }; |
659 | |
660 | static FILE *find_file(char *name, int localdir) |
661 | { |
662 | FILE *f; |
663 | int i, incdir = -1; |
664 | size_t nl = strlen(name); |
665 | char *s = 0; |
666 | struct found_file *ff = 0, *nff; |
667 | int lf = 0; |
668 | int nffa = 0; |
669 | |
670 | find_file_error = FF_ERROR; |
671 | protect_detect.state = -1; |
672 | protect_detect.macro = 0; |
673 | if (localdir) { |
674 | int i; |
675 | char *rfn = current_long_filename ? current_long_filename |
676 | : current_filename; |
677 | |
678 | for (i = strlen(rfn) - 1; i >= 0; i --) |
679 | #ifdef MSDOS |
680 | if (rfn[i] == '\\') break; |
681 | #else |
682 | if (rfn[i] == '/') break; |
683 | #endif |
684 | #if defined MSDOS |
685 | if (i >= 0 && *name != '\\' && (nl < 2 || name[1] != ':')) |
686 | #elif defined AMIGA |
687 | if (i >= 0 && *name != '/' && (nl < 2 || name[1] != ':')) |
688 | #else |
689 | if (i >= 0 && *name != '/') |
690 | #endif |
691 | { |
692 | /* |
693 | * current file is somewhere else, and the provided |
694 | * file name is not absolute, so we must adjust the |
695 | * base for looking for the file; besides, |
696 | * found_files and found_files_loc are irrelevant |
697 | * for this search. |
698 | */ |
699 | s = getmemmalloc(i + 2 + nl); |
700 | mmvmemcpy(s, rfn, i); |
701 | #ifdef MSDOS |
702 | s[i] = '\\'; |
703 | #else |
704 | s[i] = '/'; |
705 | #endif |
706 | mmvmemcpy(s + i + 1, name, nl); |
707 | s[i + 1 + nl] = 0; |
708 | ff = HTT_get(&found_files, s); |
709 | } else ff = HTT_get(&found_files, name); |
710 | } |
711 | if (!ff) { |
712 | struct found_file_sys *ffs = HTT_get(&found_files_sys, name); |
713 | |
714 | if (ffs) { |
715 | ff = ffs->rff; |
716 | incdir = ffs->incdir; |
717 | } |
718 | } |
719 | /* |
720 | * At that point: if the file was found in the cache, ff points to |
721 | * the cached descriptive structure; its name is s if s is not 0, |
722 | * name otherwise. |
723 | */ |
724 | if (ff) goto found_file_cache; |
725 | |
726 | /* |
727 | * This is the first time we find the file, or it was not protected. |
728 | */ |
729 | protect_detect.ff = new_found_file(); |
730 | nffa = 1; |
731 | if (localdir && |
732 | #ifdef UCPP_MMAP |
733 | (f = fopen_mmap_file(s ? s : name)) |
734 | #else |
735 | (f = fopen(s ? s : name, "r")) |
736 | #endif |
737 | ) { |
738 | lf = 1; |
739 | goto found_file; |
740 | } |
741 | /* |
742 | * If s contains a name, that name is now irrelevant: it was a |
743 | * filename for a search in the current directory, and the file |
744 | * was not found. |
745 | */ |
746 | if (s) { |
747 | freememfree(s); |
748 | s = 0; |
749 | } |
750 | for (i = 0; (size_t)i < include_path_nb; i ++) { |
751 | size_t ni = strlen(include_path[i]); |
752 | |
753 | s = getmemmalloc(ni + nl + 2); |
754 | mmvmemcpy(s, include_path[i], ni); |
755 | #ifdef AMIGA |
756 | /* contributed by Volker Barthelmann */ |
757 | if (ni == 1 && *s == '.') { |
758 | *s = 0; |
759 | ni = 0; |
760 | } |
761 | if (ni > 0 && s[ni - 1] != ':' && s[ni - 1] != '/') { |
762 | s[ni] = '/'; |
763 | mmvmemcpy(s + ni + 1, name, nl + 1); |
764 | } else { |
765 | mmvmemcpy(s + ni, name, nl + 1); |
766 | } |
767 | #else |
768 | s[ni] = '/'; |
769 | mmvmemcpy(s + ni + 1, name, nl + 1); |
770 | #endif |
771 | #ifdef MSDOS |
772 | /* on msdos systems, replace all / by \ */ |
773 | { |
774 | char *c; |
775 | |
776 | for (c = s; *c; c ++) if (*c == '/') *c = '\\'; |
777 | } |
778 | #endif |
779 | incdir = i; |
780 | if ((ff = HTT_get(&found_files, s)) != 0) { |
781 | /* |
782 | * The file is known, but not as a system include |
783 | * file under the name provided. |
784 | */ |
785 | struct found_file_sys *ffs = new_found_file_sys(); |
786 | |
787 | ffs->rff = ff; |
788 | ffs->incdir = incdir; |
789 | HTT_put(&found_files_sys, ffs, name); |
790 | freememfree(s); |
791 | s = 0; |
792 | if (nffa) { |
793 | del_found_file(protect_detect.ff); |
794 | protect_detect.ff = 0; |
795 | nffa = 0; |
796 | } |
797 | goto found_file_cache; |
798 | } |
799 | #ifdef UCPP_MMAP |
800 | f = fopen_mmap_file(s); |
801 | #else |
802 | f = fopen(s, "r"); |
803 | #endif |
804 | if (f) goto found_file; |
805 | freememfree(s); |
806 | s = 0; |
807 | } |
808 | zero_out: |
809 | if (s) freememfree(s); |
810 | if (nffa) { |
811 | del_found_file(protect_detect.ff); |
812 | protect_detect.ff = 0; |
813 | nffa = 0; |
Value stored to 'nffa' is never read | |
814 | } |
815 | return 0; |
816 | |
817 | /* |
818 | * This part is invoked when the file was found in the |
819 | * cache. |
820 | */ |
821 | found_file_cache: |
822 | if (ff->protect) { |
823 | if (get_macroucpp_get_macro(ff->protect)) { |
824 | /* file is protected, do not include it */ |
825 | find_file_error = FF_PROTECT; |
826 | goto zero_out; |
827 | } |
828 | /* file is protected but the guardian macro is |
829 | not available; disable guardian detection. */ |
830 | protect_detect.state = 0; |
831 | } |
832 | protect_detect.ff = ff; |
833 | #ifdef UCPP_MMAP |
834 | f = fopen_mmap_file(HASH_ITEM_NAME(ff)(((hash_item_header *)(ff))->ident + sizeof(unsigned))); |
835 | #else |
836 | f = fopen(HASH_ITEM_NAME(ff)(((hash_item_header *)(ff))->ident + sizeof(unsigned)), "r"); |
837 | #endif |
838 | if (!f) goto zero_out; |
839 | find_file_error = FF_KNOWN; |
840 | goto found_file_2; |
841 | |
842 | /* |
843 | * This part is invoked when we found a new file, which was not |
844 | * yet referenced. If lf == 1, then the file was found directly, |
845 | * otherwise it was found in some system include directory. |
846 | * A new found_file structure has been allocated and is in |
847 | * protect_detect.ff |
848 | */ |
849 | found_file: |
850 | if (f && ((emit_dependencies == 1 && lf && current_incdir == -1) |
851 | || emit_dependencies == 2)) { |
852 | fprintf(emit_output, " %s", s ? s : name); |
853 | } |
854 | nff = protect_detect.ff; |
855 | nff->name = sdup(name); |
856 | #ifdef AUDIT |
857 | if ( |
858 | #endif |
859 | HTT_put(&found_files, nff, s ? s : name) |
860 | #ifdef AUDIT |
861 | ) ouchucpp_ouch("filename collided with a wraith") |
862 | #endif |
863 | ; |
864 | if (!lf) { |
865 | struct found_file_sys *ffs = new_found_file_sys(); |
866 | |
867 | ffs->rff = nff; |
868 | ffs->incdir = incdir; |
869 | HTT_put(&found_files_sys, ffs, name); |
870 | } |
871 | if (s) freememfree(s); |
872 | s = 0; |
873 | find_file_error = FF_UNKNOWN; |
874 | ff = nff; |
875 | |
876 | found_file_2: |
877 | if (s) freememfree(s); |
878 | current_long_filename = HASH_ITEM_NAME(ff)(((hash_item_header *)(ff))->ident + sizeof(unsigned)); |
879 | #ifdef NO_LIBC_BUF |
880 | setbuf(f, 0); |
881 | #endif |
882 | current_incdir = incdir; |
883 | return f; |
884 | } |
885 | |
886 | /* |
887 | * Find the named file by looking through the end of the include path. |
888 | * This is for #include_next directives. |
889 | * #include_next <foo> and #include_next "foo" are considered identical, |
890 | * for all practical purposes. |
891 | */ |
892 | static FILE *find_file_next(char *name) |
893 | { |
894 | int i; |
895 | size_t nl = strlen(name); |
896 | FILE *f; |
897 | struct found_file *ff; |
898 | |
899 | find_file_error = FF_ERROR; |
900 | protect_detect.state = -1; |
901 | protect_detect.macro = 0; |
902 | for (i = current_incdir + 1; (size_t)i < include_path_nb; i ++) { |
903 | char *s; |
904 | size_t ni = strlen(include_path[i]); |
905 | |
906 | s = getmemmalloc(ni + nl + 2); |
907 | mmvmemcpy(s, include_path[i], ni); |
908 | s[ni] = '/'; |
909 | mmvmemcpy(s + ni + 1, name, nl + 1); |
910 | #ifdef MSDOS |
911 | /* on msdos systems, replace all / by \ */ |
912 | { |
913 | char *c; |
914 | |
915 | for (c = s; *c; c ++) if (*c == '/') *c = '\\'; |
916 | } |
917 | #endif |
918 | ff = HTT_get(&found_files, s); |
919 | if (ff) { |
920 | /* file was found in the cache */ |
921 | if (ff->protect) { |
922 | if (get_macroucpp_get_macro(ff->protect)) { |
923 | find_file_error = FF_PROTECT; |
924 | freememfree(s); |
925 | return 0; |
926 | } |
927 | /* file is protected but the guardian macro is |
928 | not available; disable guardian detection. */ |
929 | protect_detect.state = 0; |
930 | } |
931 | protect_detect.ff = ff; |
932 | #ifdef UCPP_MMAP |
933 | f = fopen_mmap_file(HASH_ITEM_NAME(ff)(((hash_item_header *)(ff))->ident + sizeof(unsigned))); |
934 | #else |
935 | f = fopen(HASH_ITEM_NAME(ff)(((hash_item_header *)(ff))->ident + sizeof(unsigned)), "r"); |
936 | #endif |
937 | if (!f) { |
938 | /* file is referenced but yet unavailable. */ |
939 | freememfree(s); |
940 | return 0; |
941 | } |
942 | find_file_error = FF_KNOWN; |
943 | freememfree(s); |
944 | s = HASH_ITEM_NAME(ff)(((hash_item_header *)(ff))->ident + sizeof(unsigned)); |
945 | } else { |
946 | #ifdef UCPP_MMAP |
947 | f = fopen_mmap_file(s); |
948 | #else |
949 | f = fopen(s, "r"); |
950 | #endif |
951 | if (f) { |
952 | if (emit_dependencies == 2) { |
953 | fprintf(emit_output, " %s", s); |
954 | } |
955 | ff = protect_detect.ff = new_found_file(); |
956 | ff->name = sdup(s); |
957 | #ifdef AUDIT |
958 | if ( |
959 | #endif |
960 | HTT_put(&found_files, ff, s) |
961 | #ifdef AUDIT |
962 | ) ouchucpp_ouch("filename collided with a wraith") |
963 | #endif |
964 | ; |
965 | find_file_error = FF_UNKNOWN; |
966 | freememfree(s); |
967 | s = HASH_ITEM_NAME(ff)(((hash_item_header *)(ff))->ident + sizeof(unsigned)); |
968 | } |
969 | } |
970 | if (f) { |
971 | current_long_filename = s; |
972 | current_incdir = i; |
973 | return f; |
974 | } |
975 | freememfree(s); |
976 | } |
977 | return 0; |
978 | } |
979 | |
980 | /* |
981 | * The #if directive. This function parse the expression, performs macro |
982 | * expansion (and handles the "defined" operator), and call eval_expr. |
983 | * return value: 1 if the expression is true, 0 if it is false, -1 on error. |
984 | */ |
985 | static int handle_if(struct lexer_state *ls) |
986 | { |
987 | struct token_fifo tf, tf1, tf2, tf3, *save_tf; |
988 | long l = ls->line; |
989 | unsigned long z; |
990 | int ret = 0, ltww = 1; |
991 | |
992 | /* first, get the whole line */ |
993 | tf.art = tf.nt = 0; |
994 | while (!next_tokenucpp_next_token(ls) && ls->ctok->type != NEWLINE) { |
995 | struct token t; |
996 | |
997 | if (ltww && ttMWS(ls->ctok->type)((ls->ctok->type) == NONE || (ls->ctok->type) == COMMENT || (ls->ctok->type) == OPT_NONE)) continue; |
998 | ltww = ttMWS(ls->ctok->type)((ls->ctok->type) == NONE || (ls->ctok->type) == COMMENT || (ls->ctok->type) == OPT_NONE); |
999 | t.type = ls->ctok->type; |
1000 | t.line = l; |
1001 | if (S_TOKEN(ls->ctok->type)((ls->ctok->type) >= NUMBER && (ls->ctok-> type) <= CHAR)) { |
1002 | t.name = sdup(ls->ctok->name); |
1003 | throw_awayucpp_throw_away(ls->gf, t.name); |
1004 | } |
1005 | aol(tf.t, tf.nt, t, TOKEN_LIST_MEMG)do { if (((tf.nt) % (32)) == 0) { if ((tf.nt) != 0) { (tf.t) = incmem((tf.t), (tf.nt) * sizeof(t), ((tf.nt) + (32)) * sizeof (t)); } else { (tf.t) = malloc((32) * sizeof(t)); } } (tf.t)[ (tf.nt) ++] = (t); } while (0); |
1006 | } |
1007 | if (ltww && tf.nt) if ((-- tf.nt) == 0) freememfree(tf.t); |
1008 | if (tf.nt == 0) { |
1009 | errorucpp_error(l, "void condition for a #if/#elif"); |
1010 | return -1; |
1011 | } |
1012 | /* handle the "defined" operator */ |
1013 | tf1.art = tf1.nt = 0; |
1014 | while (tf.art < tf.nt) { |
1015 | struct token *ct, rt; |
1016 | struct macro *m; |
1017 | size_t nidx, eidx; |
1018 | |
1019 | ct = tf.t + (tf.art ++); |
1020 | if (ct->type == NAME && !strcmp(ct->name, "defined")) { |
1021 | if (tf.art >= tf.nt) goto store_token; |
1022 | nidx = tf.art; |
1023 | if (ttMWS(tf.t[nidx].type)((tf.t[nidx].type) == NONE || (tf.t[nidx].type) == COMMENT || (tf.t[nidx].type) == OPT_NONE)) |
1024 | if (++ nidx >= tf.nt) goto store_token; |
1025 | if (tf.t[nidx].type == NAME) { |
1026 | eidx = nidx; |
1027 | goto check_macro; |
1028 | } |
1029 | if (tf.t[nidx].type != LPAR) goto store_token; |
1030 | if (++ nidx >= tf.nt) goto store_token; |
1031 | if (ttMWS(tf.t[nidx].type)((tf.t[nidx].type) == NONE || (tf.t[nidx].type) == COMMENT || (tf.t[nidx].type) == OPT_NONE)) |
1032 | if (++ nidx >= tf.nt) goto store_token; |
1033 | if (tf.t[nidx].type != NAME) goto store_token; |
1034 | eidx = nidx + 1; |
1035 | if (eidx >= tf.nt) goto store_token; |
1036 | if (ttMWS(tf.t[eidx].type)((tf.t[eidx].type) == NONE || (tf.t[eidx].type) == COMMENT || (tf.t[eidx].type) == OPT_NONE)) |
1037 | if (++ eidx >= tf.nt) goto store_token; |
1038 | if (tf.t[eidx].type != RPAR) goto store_token; |
1039 | goto check_macro; |
1040 | } |
1041 | store_token: |
1042 | aol(tf1.t, tf1.nt, *ct, TOKEN_LIST_MEMG)do { if (((tf1.nt) % (32)) == 0) { if ((tf1.nt) != 0) { (tf1. t) = incmem((tf1.t), (tf1.nt) * sizeof(*ct), ((tf1.nt) + (32) ) * sizeof(*ct)); } else { (tf1.t) = malloc((32) * sizeof(*ct )); } } (tf1.t)[(tf1.nt) ++] = (*ct); } while (0); |
1043 | continue; |
1044 | |
1045 | check_macro: |
1046 | m = get_macroucpp_get_macro(tf.t[nidx].name); |
1047 | rt.type = NUMBER; |
1048 | rt.name = m ? "1L" : "0L"; |
1049 | aol(tf1.t, tf1.nt, rt, TOKEN_LIST_MEMG)do { if (((tf1.nt) % (32)) == 0) { if ((tf1.nt) != 0) { (tf1. t) = incmem((tf1.t), (tf1.nt) * sizeof(rt), ((tf1.nt) + (32)) * sizeof(rt)); } else { (tf1.t) = malloc((32) * sizeof(rt)); } } (tf1.t)[(tf1.nt) ++] = (rt); } while (0); |
1050 | tf.art = eidx + 1; |
1051 | } |
1052 | freememfree(tf.t); |
1053 | if (tf1.nt == 0) { |
1054 | errorucpp_error(l, "void condition (after expansion) for a #if/#elif"); |
1055 | return -1; |
1056 | } |
1057 | |
1058 | /* perform all macro substitutions */ |
1059 | tf2.art = tf2.nt = 0; |
1060 | save_tf = ls->output_fifo; |
1061 | ls->output_fifo = &tf2; |
1062 | while (tf1.art < tf1.nt) { |
1063 | struct token *ct; |
1064 | |
1065 | ct = tf1.t + (tf1.art ++); |
1066 | if (ct->type == NAME) { |
1067 | struct macro *m = get_macroucpp_get_macro(ct->name); |
1068 | |
1069 | if (m) { |
1070 | if (substitute_macroucpp_substitute_macro(ls, m, &tf1, 0, |
1071 | #ifdef NO_PRAGMA_IN_DIRECTIVE |
1072 | 1, |
1073 | #else |
1074 | 0, |
1075 | #endif |
1076 | ct->line)) { |
1077 | ls->output_fifo = save_tf; |
1078 | goto error1; |
1079 | } |
1080 | continue; |
1081 | } |
1082 | } else if ((ct->type == SHARP || ct->type == DIG_SHARP) |
1083 | && (ls->flags & HANDLE_ASSERTIONS0x000800UL)) { |
1084 | /* we have an assertion; parse it */ |
1085 | int nnp, ltww = 1; |
1086 | size_t i = tf1.art; |
1087 | struct token_fifo atl; |
1088 | char *aname; |
1089 | struct assert *a; |
1090 | int av = 0; |
1091 | struct token rt; |
1092 | |
1093 | atl.art = atl.nt = 0; |
1094 | while (i < tf1.nt && ttMWS(tf1.t[i].type)((tf1.t[i].type) == NONE || (tf1.t[i].type) == COMMENT || (tf1 .t[i].type) == OPT_NONE)) i ++; |
1095 | if (i >= tf1.nt) goto assert_error; |
1096 | if (tf1.t[i].type != NAME) goto assert_error; |
1097 | aname = tf1.t[i ++].name; |
1098 | while (i < tf1.nt && ttMWS(tf1.t[i].type)((tf1.t[i].type) == NONE || (tf1.t[i].type) == COMMENT || (tf1 .t[i].type) == OPT_NONE)) i ++; |
1099 | if (i >= tf1.nt) goto assert_generic; |
1100 | if (tf1.t[i].type != LPAR) goto assert_generic; |
1101 | i ++; |
1102 | for (nnp = 1; nnp && i < tf1.nt; i ++) { |
1103 | if (ltww && ttMWS(tf1.t[i].type)((tf1.t[i].type) == NONE || (tf1.t[i].type) == COMMENT || (tf1 .t[i].type) == OPT_NONE)) continue; |
1104 | if (tf1.t[i].type == LPAR) nnp ++; |
1105 | else if (tf1.t[i].type == RPAR |
1106 | && (-- nnp) == 0) { |
1107 | tf1.art = i + 1; |
1108 | break; |
1109 | } |
1110 | ltww = ttMWS(tf1.t[i].type)((tf1.t[i].type) == NONE || (tf1.t[i].type) == COMMENT || (tf1 .t[i].type) == OPT_NONE); |
1111 | aol(atl.t, atl.nt, tf1.t[i], TOKEN_LIST_MEMG)do { if (((atl.nt) % (32)) == 0) { if ((atl.nt) != 0) { (atl. t) = incmem((atl.t), (atl.nt) * sizeof(tf1.t[i]), ((atl.nt) + (32)) * sizeof(tf1.t[i])); } else { (atl.t) = malloc((32) * sizeof (tf1.t[i])); } } (atl.t)[(atl.nt) ++] = (tf1.t[i]); } while ( 0); |
1112 | } |
1113 | if (nnp) goto assert_error; |
1114 | if (ltww && atl.nt && (-- atl.nt) == 0) freememfree(atl.t); |
1115 | if (atl.nt == 0) goto assert_error; |
1116 | |
1117 | /* the assertion is in aname and atl; check it */ |
1118 | a = get_assertionucpp_get_assertion(aname); |
1119 | if (a) for (i = 0; i < a->nbval; i ++) |
1120 | if (!cmp_token_listucpp_cmp_token_list(&atl, a->val + i)) { |
1121 | av = 1; |
1122 | break; |
1123 | } |
1124 | rt.type = NUMBER; |
1125 | rt.name = av ? "1" : "0"; |
1126 | aol(tf2.t, tf2.nt, rt, TOKEN_LIST_MEMG)do { if (((tf2.nt) % (32)) == 0) { if ((tf2.nt) != 0) { (tf2. t) = incmem((tf2.t), (tf2.nt) * sizeof(rt), ((tf2.nt) + (32)) * sizeof(rt)); } else { (tf2.t) = malloc((32) * sizeof(rt)); } } (tf2.t)[(tf2.nt) ++] = (rt); } while (0); |
1127 | if (atl.nt) freememfree(atl.t); |
1128 | continue; |
1129 | |
1130 | assert_generic: |
1131 | tf1.art = i; |
1132 | rt.type = NUMBER; |
1133 | rt.name = get_assertionucpp_get_assertion(aname) ? "1" : "0"; |
1134 | aol(tf2.t, tf2.nt, rt, TOKEN_LIST_MEMG)do { if (((tf2.nt) % (32)) == 0) { if ((tf2.nt) != 0) { (tf2. t) = incmem((tf2.t), (tf2.nt) * sizeof(rt), ((tf2.nt) + (32)) * sizeof(rt)); } else { (tf2.t) = malloc((32) * sizeof(rt)); } } (tf2.t)[(tf2.nt) ++] = (rt); } while (0); |
1135 | continue; |
1136 | |
1137 | assert_error: |
1138 | errorucpp_error(l, "syntax error for assertion in #if"); |
1139 | ls->output_fifo = save_tf; |
1140 | goto error1; |
1141 | } |
1142 | aol(tf2.t, tf2.nt, *ct, TOKEN_LIST_MEMG)do { if (((tf2.nt) % (32)) == 0) { if ((tf2.nt) != 0) { (tf2. t) = incmem((tf2.t), (tf2.nt) * sizeof(*ct), ((tf2.nt) + (32) ) * sizeof(*ct)); } else { (tf2.t) = malloc((32) * sizeof(*ct )); } } (tf2.t)[(tf2.nt) ++] = (*ct); } while (0); |
1143 | } |
1144 | ls->output_fifo = save_tf; |
1145 | freememfree(tf1.t); |
1146 | if (tf2.nt == 0) { |
1147 | errorucpp_error(l, "void condition (after expansion) for a #if/#elif"); |
1148 | return -1; |
1149 | } |
1150 | |
1151 | /* |
1152 | * suppress whitespace and replace rogue identifiers by 0 |
1153 | */ |
1154 | tf3.art = tf3.nt = 0; |
1155 | while (tf2.art < tf2.nt) { |
1156 | struct token *ct = tf2.t + (tf2.art ++); |
1157 | |
1158 | if (ttMWS(ct->type)((ct->type) == NONE || (ct->type) == COMMENT || (ct-> type) == OPT_NONE)) continue; |
1159 | if (ct->type == NAME) { |
1160 | /* |
1161 | * a rogue identifier; we replace it with "0". |
1162 | */ |
1163 | struct token rt; |
1164 | |
1165 | rt.type = NUMBER; |
1166 | rt.name = "0"; |
1167 | aol(tf3.t, tf3.nt, rt, TOKEN_LIST_MEMG)do { if (((tf3.nt) % (32)) == 0) { if ((tf3.nt) != 0) { (tf3. t) = incmem((tf3.t), (tf3.nt) * sizeof(rt), ((tf3.nt) + (32)) * sizeof(rt)); } else { (tf3.t) = malloc((32) * sizeof(rt)); } } (tf3.t)[(tf3.nt) ++] = (rt); } while (0); |
1168 | continue; |
1169 | } |
1170 | aol(tf3.t, tf3.nt, *ct, TOKEN_LIST_MEMG)do { if (((tf3.nt) % (32)) == 0) { if ((tf3.nt) != 0) { (tf3. t) = incmem((tf3.t), (tf3.nt) * sizeof(*ct), ((tf3.nt) + (32) ) * sizeof(*ct)); } else { (tf3.t) = malloc((32) * sizeof(*ct )); } } (tf3.t)[(tf3.nt) ++] = (*ct); } while (0); |
1171 | } |
1172 | freememfree(tf2.t); |
1173 | |
1174 | if (tf3.nt == 0) { |
1175 | errorucpp_error(l, "void condition (after expansion) for a #if/#elif"); |
1176 | return -1; |
1177 | } |
1178 | eval_lineucpp_eval_line = l; |
1179 | z = eval_exprucpp_eval_expr(&tf3, &ret, (ls->flags & WARN_STANDARD0x000001UL) != 0); |
1180 | freememfree(tf3.t); |
1181 | if (ret) return -1; |
1182 | return (z != 0); |
1183 | |
1184 | error1: |
1185 | if (tf1.nt) freememfree(tf1.t); |
1186 | if (tf2.nt) freememfree(tf2.t); |
1187 | return -1; |
1188 | } |
1189 | |
1190 | /* |
1191 | * A #include was found; parse the end of line, replace macros if |
1192 | * necessary. |
1193 | * |
1194 | * If nex is set to non-zero, the directive is considered as a #include_next |
1195 | * (extension to C99, mimicked from GNU) |
1196 | */ |
1197 | static int handle_include(struct lexer_state *ls, unsigned long flags, int nex) |
1198 | { |
1199 | int c, string_fname = 0; |
1200 | char *fname; |
1201 | unsigned char *fname2; |
1202 | size_t fname_ptr = 0; |
1203 | long l = ls->line; |
1204 | int x, y; |
1205 | FILE *f; |
1206 | struct token_fifo tf, tf2, *save_tf; |
1207 | size_t nl; |
1208 | int tgd; |
1209 | struct lexer_state alt_ls; |
1210 | |
1211 | #define left_angle(t) ((t) == LT || (t) == LEQ || (t) == LSH \ |
1212 | || (t) == ASLSH || (t) == DIG_LBRK || (t) == LBRA) |
1213 | #define right_angle(t) ((t) == GT || (t) == RSH || (t) == ARROW \ |
1214 | || (t) == DIG_RBRK || (t) == DIG_RBRA) |
1215 | |
1216 | while ((c = grap_charucpp_grap_char(ls)) >= 0 && c != '\n') { |
1217 | if (space_charucpp_space_char(c)) { |
1218 | discard_charucpp_discard_char(ls); |
1219 | continue; |
1220 | } |
1221 | if (c == '<') { |
1222 | discard_charucpp_discard_char(ls); |
1223 | while ((c = grap_charucpp_grap_char(ls)) >= 0) { |
1224 | discard_charucpp_discard_char(ls); |
1225 | if (c == '\n') goto include_last_chance; |
1226 | if (c == '>') break; |
1227 | aol(fname, fname_ptr, (char)c, FNAME_MEMG)do { if (((fname_ptr) % (32)) == 0) { if ((fname_ptr) != 0) { (fname) = incmem((fname), (fname_ptr) * sizeof((char)c), ((fname_ptr ) + (32)) * sizeof((char)c)); } else { (fname) = malloc((32) * sizeof((char)c)); } } (fname)[(fname_ptr) ++] = ((char)c); } while (0); |
1228 | } |
1229 | aol(fname, fname_ptr, (char)0, FNAME_MEMG)do { if (((fname_ptr) % (32)) == 0) { if ((fname_ptr) != 0) { (fname) = incmem((fname), (fname_ptr) * sizeof((char)0), ((fname_ptr ) + (32)) * sizeof((char)0)); } else { (fname) = malloc((32) * sizeof((char)0)); } } (fname)[(fname_ptr) ++] = ((char)0); } while (0); |
1230 | string_fname = 0; |
1231 | goto do_include; |
1232 | } else if (c == '"') { |
1233 | discard_charucpp_discard_char(ls); |
1234 | while ((c = grap_charucpp_grap_char(ls)) >= 0) { |
1235 | discard_charucpp_discard_char(ls); |
1236 | if (c == '\n') { |
1237 | /* macro replacements won't save that one */ |
1238 | if (fname_ptr) freememfree(fname); |
1239 | goto include_error; |
1240 | } |
1241 | if (c == '"') break; |
1242 | aol(fname, fname_ptr, (char)c, FNAME_MEMG)do { if (((fname_ptr) % (32)) == 0) { if ((fname_ptr) != 0) { (fname) = incmem((fname), (fname_ptr) * sizeof((char)c), ((fname_ptr ) + (32)) * sizeof((char)c)); } else { (fname) = malloc((32) * sizeof((char)c)); } } (fname)[(fname_ptr) ++] = ((char)c); } while (0); |
1243 | } |
1244 | aol(fname, fname_ptr, (char)0, FNAME_MEMG)do { if (((fname_ptr) % (32)) == 0) { if ((fname_ptr) != 0) { (fname) = incmem((fname), (fname_ptr) * sizeof((char)0), ((fname_ptr ) + (32)) * sizeof((char)0)); } else { (fname) = malloc((32) * sizeof((char)0)); } } (fname)[(fname_ptr) ++] = ((char)0); } while (0); |
1245 | string_fname = 1; |
1246 | goto do_include; |
1247 | } |
1248 | goto include_macro; |
1249 | } |
1250 | |
1251 | include_last_chance: |
1252 | /* |
1253 | * We found a '<' but not the trailing '>'; so we tokenize the |
1254 | * line, and try to act upon it. The standard lets us free in that |
1255 | * matter, and no sane programmer would use such a construct, but |
1256 | * it is no reason not to support it. |
1257 | */ |
1258 | if (fname_ptr == 0) goto include_error; |
1259 | fname2 = getmemmalloc(fname_ptr + 1); |
1260 | mmvmemcpy(fname2 + 1, fname, fname_ptr); |
1261 | fname2[0] = '<'; |
1262 | /* |
1263 | * We merely copy the lexer_state structure; this should be ok, |
1264 | * since we do want to share the memory structure (garbage_fifo), |
1265 | * and do not touch any other context-full thing. |
1266 | */ |
1267 | alt_ls = *ls; |
1268 | alt_ls.input = 0; |
1269 | alt_ls.input_string = fname2; |
1270 | alt_ls.pbuf = 0; |
1271 | alt_ls.ebuf = fname_ptr + 1; |
1272 | tf.art = tf.nt = 0; |
1273 | while (!next_tokenucpp_next_token(&alt_ls)) { |
1274 | if (!ttMWS(alt_ls.ctok->type)((alt_ls.ctok->type) == NONE || (alt_ls.ctok->type) == COMMENT || (alt_ls.ctok->type) == OPT_NONE)) { |
1275 | struct token t; |
1276 | |
1277 | t.type = alt_ls.ctok->type; |
1278 | t.line = l; |
1279 | if (S_TOKEN(alt_ls.ctok->type)((alt_ls.ctok->type) >= NUMBER && (alt_ls.ctok-> type) <= CHAR)) { |
1280 | t.name = sdup(alt_ls.ctok->name); |
1281 | throw_awayucpp_throw_away(alt_ls.gf, t.name); |
1282 | } |
1283 | aol(tf.t, tf.nt, t, TOKEN_LIST_MEMG)do { if (((tf.nt) % (32)) == 0) { if ((tf.nt) != 0) { (tf.t) = incmem((tf.t), (tf.nt) * sizeof(t), ((tf.nt) + (32)) * sizeof (t)); } else { (tf.t) = malloc((32) * sizeof(t)); } } (tf.t)[ (tf.nt) ++] = (t); } while (0); |
1284 | } |
1285 | } |
1286 | freememfree(fname2); |
1287 | if (alt_ls.pbuf < alt_ls.ebuf) goto include_error; |
1288 | /* tokenizing failed */ |
1289 | goto include_macro2; |
1290 | |
1291 | include_error: |
1292 | errorucpp_error(l, "invalid '#include'"); |
1293 | return 1; |
1294 | |
1295 | include_macro: |
1296 | tf.art = tf.nt = 0; |
1297 | while (!next_tokenucpp_next_token(ls) && ls->ctok->type != NEWLINE) { |
1298 | if (!ttMWS(ls->ctok->type)((ls->ctok->type) == NONE || (ls->ctok->type) == COMMENT || (ls->ctok->type) == OPT_NONE)) { |
1299 | struct token t; |
1300 | |
1301 | t.type = ls->ctok->type; |
1302 | t.line = l; |
1303 | if (S_TOKEN(ls->ctok->type)((ls->ctok->type) >= NUMBER && (ls->ctok-> type) <= CHAR)) { |
1304 | t.name = sdup(ls->ctok->name); |
1305 | throw_awayucpp_throw_away(ls->gf, t.name); |
1306 | } |
1307 | aol(tf.t, tf.nt, t, TOKEN_LIST_MEMG)do { if (((tf.nt) % (32)) == 0) { if ((tf.nt) != 0) { (tf.t) = incmem((tf.t), (tf.nt) * sizeof(t), ((tf.nt) + (32)) * sizeof (t)); } else { (tf.t) = malloc((32) * sizeof(t)); } } (tf.t)[ (tf.nt) ++] = (t); } while (0); |
1308 | } |
1309 | } |
1310 | include_macro2: |
1311 | tf2.art = tf2.nt = 0; |
1312 | save_tf = ls->output_fifo; |
1313 | ls->output_fifo = &tf2; |
1314 | while (tf.art < tf.nt) { |
1315 | struct token *ct; |
1316 | |
1317 | ct = tf.t + (tf.art ++); |
1318 | if (ct->type == NAME) { |
1319 | struct macro *m = get_macroucpp_get_macro(ct->name); |
1320 | if (m) { |
1321 | if (substitute_macroucpp_substitute_macro(ls, m, &tf, 0, |
1322 | #ifdef NO_PRAGMA_IN_DIRECTIVE |
1323 | 1, |
1324 | #else |
1325 | 0, |
1326 | #endif |
1327 | ct->line)) { |
1328 | ls->output_fifo = save_tf; |
1329 | return -1; |
1330 | } |
1331 | continue; |
1332 | } |
1333 | } |
1334 | aol(tf2.t, tf2.nt, *ct, TOKEN_LIST_MEMG)do { if (((tf2.nt) % (32)) == 0) { if ((tf2.nt) != 0) { (tf2. t) = incmem((tf2.t), (tf2.nt) * sizeof(*ct), ((tf2.nt) + (32) ) * sizeof(*ct)); } else { (tf2.t) = malloc((32) * sizeof(*ct )); } } (tf2.t)[(tf2.nt) ++] = (*ct); } while (0); |
1335 | } |
1336 | freememfree(tf.t); |
1337 | ls->output_fifo = save_tf; |
1338 | for (x = 0; (size_t)x < tf2.nt && ttWHI(tf2.t[x].type)(((tf2.t[x].type) == NONE || (tf2.t[x].type) == COMMENT || (tf2 .t[x].type) == OPT_NONE) || (tf2.t[x].type) == NEWLINE); x ++); |
1339 | for (y = tf2.nt - 1; y >= 0 && ttWHI(tf2.t[y].type)(((tf2.t[y].type) == NONE || (tf2.t[y].type) == COMMENT || (tf2 .t[y].type) == OPT_NONE) || (tf2.t[y].type) == NEWLINE); y --); |
1340 | if ((size_t)x >= tf2.nt) goto include_macro_err; |
1341 | if (tf2.t[x].type == STRING) { |
1342 | if (y != x) goto include_macro_err; |
1343 | if (tf2.t[x].name[0] == 'L') { |
1344 | if (ls->flags & WARN_STANDARD0x000001UL) |
1345 | warningucpp_warning(l, "wide string for #include"); |
1346 | fname = sdup(tf2.t[x].name); |
1347 | nl = strlen(fname); |
1348 | *(fname + nl - 1) = 0; |
1349 | mmvwomemmove(fname, fname + 2, nl - 2); |
1350 | } else { |
1351 | fname = sdup(tf2.t[x].name); |
1352 | nl = strlen(fname); |
1353 | *(fname + nl - 1) = 0; |
1354 | mmvwomemmove(fname, fname + 1, nl - 1); |
1355 | } |
1356 | string_fname = 1; |
1357 | } else if (left_angle(tf2.t[x].type) && right_angle(tf2.t[y].type)) { |
1358 | int i, j; |
1359 | |
1360 | if (ls->flags & WARN_ANNOYING0x000002UL) warningucpp_warning(l, "reconstruction " |
1361 | "of <foo> in #include"); |
1362 | for (j = 0, i = x; i <= y; i ++) if (!ttWHI(tf2.t[i].type)(((tf2.t[i].type) == NONE || (tf2.t[i].type) == COMMENT || (tf2 .t[i].type) == OPT_NONE) || (tf2.t[i].type) == NEWLINE)) |
1363 | j += strlen(tname(tf2.t[i])((((tf2.t[i]).type) >= NUMBER && ((tf2.t[i]).type) <= CHAR) ? (tf2.t[i]).name : operators_name[(tf2.t[i]).type ])); |
1364 | fname = getmemmalloc(j + 1); |
1365 | for (j = 0, i = x; i <= y; i ++) { |
1366 | if (ttWHI(tf2.t[i].type)(((tf2.t[i].type) == NONE || (tf2.t[i].type) == COMMENT || (tf2 .t[i].type) == OPT_NONE) || (tf2.t[i].type) == NEWLINE)) continue; |
1367 | strcpy(fname + j, tname(tf2.t[i])((((tf2.t[i]).type) >= NUMBER && ((tf2.t[i]).type) <= CHAR) ? (tf2.t[i]).name : operators_name[(tf2.t[i]).type ])); |
1368 | j += strlen(tname(tf2.t[i])((((tf2.t[i]).type) >= NUMBER && ((tf2.t[i]).type) <= CHAR) ? (tf2.t[i]).name : operators_name[(tf2.t[i]).type ])); |
1369 | } |
1370 | *(fname + j - 1) = 0; |
1371 | mmvwomemmove(fname, fname + 1, j); |
1372 | string_fname = 0; |
1373 | } else goto include_macro_err; |
1374 | freememfree(tf2.t); |
1375 | goto do_include_next; |
1376 | |
1377 | include_macro_err: |
1378 | errorucpp_error(l, "macro expansion did not produce a valid filename " |
1379 | "for #include"); |
1380 | if (tf2.nt) freememfree(tf2.t); |
1381 | return 1; |
1382 | |
1383 | do_include: |
1384 | tgd = 1; |
1385 | while (!next_tokenucpp_next_token(ls)) { |
1386 | if (tgd && !ttWHI(ls->ctok->type)(((ls->ctok->type) == NONE || (ls->ctok->type) == COMMENT || (ls->ctok->type) == OPT_NONE) || (ls->ctok ->type) == NEWLINE) |
1387 | && (ls->flags & WARN_STANDARD0x000001UL)) { |
1388 | warningucpp_warning(l, "trailing garbage in #include"); |
1389 | tgd = 0; |
1390 | } |
1391 | if (ls->ctok->type == NEWLINE) break; |
1392 | } |
1393 | |
1394 | /* the increment of ls->line is intended so that the line |
1395 | numbering is reported correctly in report_context() even if |
1396 | the #include is at the end of the file with no trailing newline */ |
1397 | if (ls->ctok->type != NEWLINE) ls->line ++; |
1398 | do_include_next: |
1399 | if (!(ls->flags & LEXER0x010000UL) && (ls->flags & KEEP_OUTPUT0x020000UL)) |
1400 | put_charucpp_put_char(ls, '\n'); |
1401 | push_file_context(ls); |
1402 | reinit_lexer_state(ls, 1); |
1403 | #ifdef MSDOS |
1404 | /* on msdos systems, replace all / by \ */ |
1405 | { |
1406 | char *d; |
1407 | |
1408 | for (d = fname; *d; d ++) if (*d == '/') *d = '\\'; |
1409 | } |
1410 | #endif |
1411 | f = nex ? find_file_next(fname) : find_file(fname, string_fname); |
1412 | if (!f) { |
1413 | current_filename = 0; |
1414 | pop_file_context(ls); |
1415 | if (find_file_error == FF_ERROR) { |
1416 | errorucpp_error(l, "file '%s' not found", fname); |
1417 | freememfree(fname); |
1418 | return 1; |
1419 | } |
1420 | /* file was found, but it is useless to include it again */ |
1421 | freememfree(fname); |
1422 | return 0; |
1423 | } |
1424 | #ifdef UCPP_MMAP |
1425 | set_input_file(ls, f); |
1426 | #else |
1427 | ls->input = f; |
1428 | #endif |
1429 | current_filename = fname; |
1430 | enter_file(ls, flags); |
1431 | return 0; |
1432 | |
1433 | #undef left_angle |
1434 | #undef right_angle |
1435 | } |
1436 | |
1437 | /* |
1438 | * for #line directives |
1439 | */ |
1440 | static int handle_line(struct lexer_state *ls, unsigned long flags) |
1441 | { |
1442 | char *fname; |
1443 | long l = ls->line; |
1444 | struct token_fifo tf, tf2, *save_tf; |
1445 | size_t nl, j; |
1446 | unsigned long z; |
1447 | |
1448 | tf.art = tf.nt = 0; |
1449 | while (!next_tokenucpp_next_token(ls) && ls->ctok->type != NEWLINE) { |
1450 | if (!ttMWS(ls->ctok->type)((ls->ctok->type) == NONE || (ls->ctok->type) == COMMENT || (ls->ctok->type) == OPT_NONE)) { |
1451 | struct token t; |
1452 | |
1453 | t.type = ls->ctok->type; |
1454 | t.line = l; |
1455 | if (S_TOKEN(ls->ctok->type)((ls->ctok->type) >= NUMBER && (ls->ctok-> type) <= CHAR)) { |
1456 | t.name = sdup(ls->ctok->name); |
1457 | throw_awayucpp_throw_away(ls->gf, t.name); |
1458 | } |
1459 | aol(tf.t, tf.nt, t, TOKEN_LIST_MEMG)do { if (((tf.nt) % (32)) == 0) { if ((tf.nt) != 0) { (tf.t) = incmem((tf.t), (tf.nt) * sizeof(t), ((tf.nt) + (32)) * sizeof (t)); } else { (tf.t) = malloc((32) * sizeof(t)); } } (tf.t)[ (tf.nt) ++] = (t); } while (0); |
1460 | } |
1461 | } |
1462 | tf2.art = tf2.nt = 0; |
1463 | save_tf = ls->output_fifo; |
1464 | ls->output_fifo = &tf2; |
1465 | while (tf.art < tf.nt) { |
1466 | struct token *ct; |
1467 | |
1468 | ct = tf.t + (tf.art ++); |
1469 | if (ct->type == NAME) { |
1470 | struct macro *m = get_macroucpp_get_macro(ct->name); |
1471 | if (m) { |
1472 | if (substitute_macroucpp_substitute_macro(ls, m, &tf, 0, |
1473 | #ifdef NO_PRAGMA_IN_DIRECTIVE |
1474 | 1, |
1475 | #else |
1476 | 0, |
1477 | #endif |
1478 | ct->line)) { |
1479 | ls->output_fifo = save_tf; |
1480 | return -1; |
1481 | } |
1482 | continue; |
1483 | } |
1484 | } |
1485 | aol(tf2.t, tf2.nt, *ct, TOKEN_LIST_MEMG)do { if (((tf2.nt) % (32)) == 0) { if ((tf2.nt) != 0) { (tf2. t) = incmem((tf2.t), (tf2.nt) * sizeof(*ct), ((tf2.nt) + (32) ) * sizeof(*ct)); } else { (tf2.t) = malloc((32) * sizeof(*ct )); } } (tf2.t)[(tf2.nt) ++] = (*ct); } while (0); |
1486 | } |
1487 | freememfree(tf.t); |
1488 | for (tf2.art = 0; tf2.art < tf2.nt && ttWHI(tf2.t[tf2.art].type)(((tf2.t[tf2.art].type) == NONE || (tf2.t[tf2.art].type) == COMMENT || (tf2.t[tf2.art].type) == OPT_NONE) || (tf2.t[tf2.art].type ) == NEWLINE); |
1489 | tf2.art ++); |
1490 | ls->output_fifo = save_tf; |
1491 | if (tf2.art == tf2.nt || (tf2.t[tf2.art].type != NUMBER |
1492 | && tf2.t[tf2.art].type != CHAR)) { |
1493 | errorucpp_error(l, "not a valid number for #line"); |
1494 | goto line_macro_err; |
1495 | } |
1496 | for (j = 0; tf2.t[tf2.art].name[j]; j ++) |
1497 | if (tf2.t[tf2.art].name[j] < '0' |
1498 | || tf2.t[tf2.art].name[j] > '9') |
1499 | if (ls->flags & WARN_STANDARD0x000001UL) |
1500 | warningucpp_warning(l, "non-standard line number in #line"); |
1501 | if (catch(eval_exception)_setjmp ((ucpp_eval_exception))) goto line_macro_err; |
1502 | z = strtoconstucpp_strtoconst(tf2.t[tf2.art].name); |
1503 | if (j > 10 || z > 2147483647U) { |
1504 | errorucpp_error(l, "out-of-bound line number for #line"); |
1505 | goto line_macro_err; |
1506 | } |
1507 | ls->oline = ls->line = z; |
1508 | if ((++ tf2.art) < tf2.nt) { |
1509 | size_t i; |
1510 | |
1511 | for (i = tf2.art; i < tf2.nt && ttMWS(tf2.t[i].type)((tf2.t[i].type) == NONE || (tf2.t[i].type) == COMMENT || (tf2 .t[i].type) == OPT_NONE); i ++); |
1512 | if (i < tf2.nt) { |
1513 | if (tf2.t[i].type != STRING) { |
1514 | errorucpp_error(l, "not a valid filename for #line"); |
1515 | goto line_macro_err; |
1516 | } |
1517 | if (tf2.t[i].name[0] == 'L') { |
1518 | if (ls->flags & WARN_STANDARD0x000001UL) { |
1519 | warningucpp_warning(l, "wide string for #line"); |
1520 | } |
1521 | fname = sdup(tf2.t[i].name); |
1522 | nl = strlen(fname); |
1523 | *(fname + nl - 1) = 0; |
1524 | mmvwomemmove(fname, fname + 2, nl - 2); |
1525 | } else { |
1526 | fname = sdup(tf2.t[i].name); |
1527 | nl = strlen(fname); |
1528 | *(fname + nl - 1) = 0; |
1529 | mmvwomemmove(fname, fname + 1, nl - 1); |
1530 | } |
1531 | if (current_filename) freememfree(current_filename); |
1532 | current_filename = fname; |
1533 | } |
1534 | for (i ++; i < tf2.nt && ttMWS(tf2.t[i].type)((tf2.t[i].type) == NONE || (tf2.t[i].type) == COMMENT || (tf2 .t[i].type) == OPT_NONE); i ++); |
1535 | if (i < tf2.nt && (ls->flags & WARN_STANDARD0x000001UL)) { |
1536 | warningucpp_warning(l, "trailing garbage in #line"); |
1537 | } |
1538 | } |
1539 | freememfree(tf2.t); |
1540 | enter_file(ls, flags); |
1541 | return 0; |
1542 | |
1543 | line_macro_err: |
1544 | if (tf2.nt) freememfree(tf2.t); |
1545 | return 1; |
1546 | } |
1547 | |
1548 | /* |
1549 | * a #error directive: we emit the message without any modification |
1550 | * (except the usual backslash+newline and trigraphs) |
1551 | */ |
1552 | static void handle_error(struct lexer_state *ls) |
1553 | { |
1554 | int c; |
1555 | size_t p = 0, lp = 128; |
1556 | long l = ls->line; |
1557 | unsigned char *buf = getmemmalloc(lp); |
1558 | |
1559 | while ((c = grap_charucpp_grap_char(ls)) >= 0 && c != '\n') { |
1560 | discard_charucpp_discard_char(ls); |
1561 | wan(buf, p, (unsigned char)c, lp)do { if ((p) == (lp)) { (lp) += (lp); (buf) = incmem((buf), ( p) * sizeof((unsigned char)c), (lp) * sizeof((unsigned char)c )); } (buf)[(p) ++] = ((unsigned char)c); } while (0); |
1562 | } |
1563 | wan(buf, p, 0, lp)do { if ((p) == (lp)) { (lp) += (lp); (buf) = incmem((buf), ( p) * sizeof(0), (lp) * sizeof(0)); } (buf)[(p) ++] = (0); } while (0); |
1564 | errorucpp_error(l, "#error%s", buf); |
1565 | freememfree(buf); |
1566 | } |
1567 | |
1568 | /* |
1569 | * convert digraph tokens to their standard equivalent. |
1570 | */ |
1571 | static int undig(int type) |
1572 | { |
1573 | static int ud[6] = { LBRK, RBRK, LBRA, RBRA, SHARP, DSHARP }; |
1574 | |
1575 | return ud[type - DIG_LBRK]; |
1576 | } |
1577 | |
1578 | #ifdef PRAGMA_TOKENIZE |
1579 | /* |
1580 | * Make a compressed representation of a token list; the contents of |
1581 | * the token_fifo are freed. Values equal to 0 are replaced by |
1582 | * PRAGMA_TOKEN_END (by default, (unsigned char)'\n') and the compressed |
1583 | * string is padded by a 0 (so that it may be * handled like a string). |
1584 | * Digraph tokens are replaced by their non-digraph equivalents. |
1585 | */ |
1586 | struct comp_token_fifo compress_token_listucpp_compress_token_list(struct token_fifo *tf) |
1587 | { |
1588 | struct comp_token_fifo ct; |
1589 | size_t l; |
1590 | |
1591 | for (l = 0, tf->art = 0; tf->art < tf->nt; tf->art ++) { |
1592 | l ++; |
1593 | if (S_TOKEN(tf->t[tf->art].type)((tf->t[tf->art].type) >= NUMBER && (tf-> t[tf->art].type) <= CHAR)) |
1594 | l += strlen(tf->t[tf->art].name) + 1; |
1595 | } |
1596 | ct.t = getmemmalloc((ct.length = l) + 1); |
1597 | for (l = 0, tf->art = 0; tf->art < tf->nt; tf->art ++) { |
1598 | int tt = tf->t[tf->art].type; |
1599 | |
1600 | if (tt == 0) tt = PRAGMA_TOKEN_END((unsigned char)'\n'); |
1601 | if (tt > DIGRAPH_TOKENS && tt < DIGRAPH_TOKENS_END) |
1602 | tt = undig(tt); |
1603 | ct.t[l ++] = tt; |
1604 | if (S_TOKEN(tt)((tt) >= NUMBER && (tt) <= CHAR)) { |
1605 | char *tn = tf->t[tf->art].name; |
1606 | size_t sl = strlen(tn); |
1607 | |
1608 | mmvmemcpy(ct.t + l, tn, sl); |
1609 | l += sl; |
1610 | ct.t[l ++] = PRAGMA_TOKEN_END((unsigned char)'\n'); |
1611 | freememfree(tn); |
1612 | } |
1613 | } |
1614 | ct.t[l] = 0; |
1615 | if (tf->nt) freememfree(tf->t); |
1616 | ct.rp = 0; |
1617 | return ct; |
1618 | } |
1619 | #endif |
1620 | |
1621 | /* |
1622 | * A #pragma directive: we make a PRAGMA token containing the rest of |
1623 | * the line. |
1624 | * |
1625 | * We strongly hope that we are called only in LEXER mode. |
1626 | */ |
1627 | static void handle_pragma(struct lexer_state *ls) |
1628 | { |
1629 | unsigned char *buf; |
1630 | struct token t; |
1631 | long l = ls->line; |
1632 | |
1633 | #ifdef PRAGMA_TOKENIZE |
1634 | struct token_fifo tf; |
1635 | |
1636 | tf.art = tf.nt = 0; |
1637 | while (!next_tokenucpp_next_token(ls) && ls->ctok->type != NEWLINE) |
1638 | if (!ttMWS(ls->ctok->type)((ls->ctok->type) == NONE || (ls->ctok->type) == COMMENT || (ls->ctok->type) == OPT_NONE)) break; |
1639 | if (ls->ctok->type != NEWLINE) { |
1640 | do { |
1641 | struct token t; |
1642 | |
1643 | t.type = ls->ctok->type; |
1644 | if (ttMWS(t.type)((t.type) == NONE || (t.type) == COMMENT || (t.type) == OPT_NONE )) continue; |
1645 | if (S_TOKEN(t.type)((t.type) >= NUMBER && (t.type) <= CHAR)) t.name = sdup(ls->ctok->name); |
1646 | aol(tf.t, tf.nt, t, TOKEN_LIST_MEMG)do { if (((tf.nt) % (32)) == 0) { if ((tf.nt) != 0) { (tf.t) = incmem((tf.t), (tf.nt) * sizeof(t), ((tf.nt) + (32)) * sizeof (t)); } else { (tf.t) = malloc((32) * sizeof(t)); } } (tf.t)[ (tf.nt) ++] = (t); } while (0); |
1647 | } while (!next_tokenucpp_next_token(ls) && ls->ctok->type != NEWLINE); |
1648 | } |
1649 | if (tf.nt == 0) { |
1650 | /* void pragma are silently ignored */ |
1651 | return; |
1652 | } |
1653 | buf = (compress_token_listucpp_compress_token_list(&tf)).t; |
1654 | #else |
1655 | int c, x = 1, y = 32; |
1656 | |
1657 | while ((c = grap_charucpp_grap_char(ls)) >= 0 && c != '\n') { |
1658 | discard_charucpp_discard_char(ls); |
1659 | if (!space_charucpp_space_char(c)) break; |
1660 | } |
1661 | /* void #pragma are ignored */ |
1662 | if (c == '\n') return; |
1663 | buf = getmemmalloc(y); |
1664 | buf[0] = c; |
1665 | while ((c = grap_charucpp_grap_char(ls)) >= 0 && c != '\n') { |
1666 | discard_charucpp_discard_char(ls); |
1667 | wan(buf, x, c, y)do { if ((x) == (y)) { (y) += (y); (buf) = incmem((buf), (x) * sizeof(c), (y) * sizeof(c)); } (buf)[(x) ++] = (c); } while ( 0); |
1668 | } |
1669 | for (x --; x >= 0 && space_charucpp_space_char(buf[x]); x --); |
1670 | x ++; |
1671 | wan(buf, x, 0, y)do { if ((x) == (y)) { (y) += (y); (buf) = incmem((buf), (x) * sizeof(0), (y) * sizeof(0)); } (buf)[(x) ++] = (0); } while ( 0); |
1672 | #endif |
1673 | t.type = PRAGMA; |
1674 | t.line = l; |
1675 | t.name = (char *)buf; |
1676 | aol(ls->output_fifo->t, ls->output_fifo->nt, t, TOKEN_LIST_MEMG)do { if (((ls->output_fifo->nt) % (32)) == 0) { if ((ls ->output_fifo->nt) != 0) { (ls->output_fifo->t) = incmem((ls->output_fifo->t), (ls->output_fifo->nt ) * sizeof(t), ((ls->output_fifo->nt) + (32)) * sizeof( t)); } else { (ls->output_fifo->t) = malloc((32) * sizeof (t)); } } (ls->output_fifo->t)[(ls->output_fifo-> nt) ++] = (t); } while (0); |
1677 | throw_awayucpp_throw_away(ls->gf, (char *)buf); |
1678 | } |
1679 | |
1680 | /* |
1681 | * We saw a # at the beginning of a line (or preceeded only by whitespace). |
1682 | * We check the directive name and act accordingly. |
1683 | */ |
1684 | static int handle_cpp(struct lexer_state *ls, int sharp_type) |
1685 | { |
1686 | #define condfset(x) do { \ |
1687 | ls->condf[(x) / 32] |= 1UL << ((x) % 32); \ |
1688 | } while (0) |
1689 | #define condfclr(x) do { \ |
1690 | ls->condf[(x) / 32] &= ~(1UL << ((x) % 32)); \ |
1691 | } while (0) |
1692 | #define condfval(x) ((ls->condf[(x) / 32] & (1UL << ((x) % 32))) != 0) |
1693 | |
1694 | long l = ls->line; |
1695 | unsigned long save_flags = ls->flags; |
1696 | int ret = 0; |
1697 | |
1698 | save_flags = ls->flags; |
1699 | ls->flags |= LEXER0x010000UL; |
1700 | while (!next_tokenucpp_next_token(ls)) { |
1701 | int t = ls->ctok->type; |
1702 | |
1703 | switch (t) { |
1704 | case COMMENT: |
1705 | if (ls->flags & WARN_ANNOYING0x000002UL) { |
1706 | warningucpp_warning(l, "comment in the middle of " |
1707 | "a cpp directive"); |
1708 | } |
1709 | /* fall through */ |
1710 | case NONE: |
1711 | continue; |
1712 | case NEWLINE: |
1713 | /* null directive */ |
1714 | if (ls->flags & WARN_ANNOYING0x000002UL) { |
1715 | /* truly an annoying warning; null directives |
1716 | are rare but may increase readability of |
1717 | some source files, and they are legal */ |
1718 | warningucpp_warning(l, "null cpp directive"); |
1719 | } |
1720 | if (!(ls->flags & LEXER0x010000UL)) put_charucpp_put_char(ls, '\n'); |
1721 | goto handle_exit2; |
1722 | case NAME: |
1723 | break; |
1724 | default: |
1725 | if (ls->flags & FAIL_SHARP0x000020UL) { |
1726 | /* LPS 20050602 - ignores '#!' if on the first line */ |
1727 | if( ( l == 1 ) && |
1728 | ( ls->condcomp ) ) |
1729 | { |
1730 | ret = 1; |
1731 | } |
1732 | else |
1733 | /* LPS 20050602 */ |
1734 | if (ls->condcomp) { |
1735 | errorucpp_error(l, "rogue '#'"); |
1736 | ret = 1; |
1737 | } else { |
1738 | if (ls->flags & WARN_STANDARD0x000001UL) { |
1739 | warningucpp_warning(l, "rogue '#' in code " |
1740 | "compiled out"); |
1741 | ret = 0; |
1742 | } |
1743 | } |
1744 | ls->flags = save_flags; |
1745 | goto handle_warp_ign; |
1746 | } else { |
1747 | struct token u; |
1748 | |
1749 | u.type = sharp_type; |
1750 | u.line = l; |
1751 | ls->flags = save_flags; |
1752 | print_tokenucpp_print_token(ls, &u, 0); |
1753 | print_tokenucpp_print_token(ls, ls->ctok, 0); |
1754 | if (ls->flags & WARN_ANNOYING0x000002UL) { |
1755 | warningucpp_warning(l, "rogue '#' dumped"); |
1756 | } |
1757 | goto handle_exit3; |
1758 | } |
1759 | } |
1760 | if (ls->condcomp) { |
1761 | if (!strcmp(ls->ctok->name, "define")) { |
1762 | ret = handle_defineucpp_handle_define(ls); |
1763 | goto handle_exit; |
1764 | } else if (!strcmp(ls->ctok->name, "undef")) { |
1765 | ret = handle_undefucpp_handle_undef(ls); |
1766 | goto handle_exit; |
1767 | } else if (!strcmp(ls->ctok->name, "if")) { |
1768 | if ((++ ls->ifnest) > 63) goto too_many_if; |
1769 | condfclr(ls->ifnest - 1); |
1770 | ret = handle_if(ls); |
1771 | if (ret > 0) ret = 0; |
1772 | else if (ret == 0) { |
1773 | ls->condcomp = 0; |
1774 | ls->condmet = 0; |
1775 | ls->condnest = ls->ifnest - 1; |
1776 | } |
1777 | else ret = 1; |
1778 | goto handle_exit; |
1779 | } else if (!strcmp(ls->ctok->name, "ifdef")) { |
1780 | if ((++ ls->ifnest) > 63) goto too_many_if; |
1781 | condfclr(ls->ifnest - 1); |
1782 | ret = handle_ifdefucpp_handle_ifdef(ls); |
1783 | if (ret > 0) ret = 0; |
1784 | else if (ret == 0) { |
1785 | ls->condcomp = 0; |
1786 | ls->condmet = 0; |
1787 | ls->condnest = ls->ifnest - 1; |
1788 | } |
1789 | else ret = 1; |
1790 | goto handle_exit; |
1791 | } else if (!strcmp(ls->ctok->name, "ifndef")) { |
1792 | if ((++ ls->ifnest) > 63) goto too_many_if; |
1793 | condfclr(ls->ifnest - 1); |
1794 | ret = handle_ifndefucpp_handle_ifndef(ls); |
1795 | if (ret > 0) ret = 0; |
1796 | else if (ret == 0) { |
1797 | ls->condcomp = 0; |
1798 | ls->condmet = 0; |
1799 | ls->condnest = ls->ifnest - 1; |
1800 | } |
1801 | else ret = 1; |
1802 | goto handle_exit; |
1803 | } else if (!strcmp(ls->ctok->name, "else")) { |
1804 | if (ls->ifnest == 0 |
1805 | || condfval(ls->ifnest - 1)) { |
1806 | errorucpp_error(l, "rogue #else"); |
1807 | ret = 1; |
1808 | goto handle_warp; |
1809 | } |
1810 | condfset(ls->ifnest - 1); |
1811 | if (ls->ifnest == 1) protect_detect.state = 0; |
1812 | ls->condcomp = 0; |
1813 | ls->condmet = 1; |
1814 | ls->condnest = ls->ifnest - 1; |
1815 | goto handle_warp; |
1816 | } else if (!strcmp(ls->ctok->name, "elif")) { |
1817 | if (ls->ifnest == 0 |
1818 | || condfval(ls->ifnest - 1)) { |
1819 | errorucpp_error(l, "rogue #elif"); |
1820 | ret = 1; |
1821 | goto handle_warp_ign; |
1822 | } |
1823 | if (ls->ifnest == 1) protect_detect.state = 0; |
1824 | ls->condcomp = 0; |
1825 | ls->condmet = 1; |
1826 | ls->condnest = ls->ifnest - 1; |
1827 | goto handle_warp_ign; |
1828 | } else if (!strcmp(ls->ctok->name, "endif")) { |
1829 | if (ls->ifnest == 0) { |
1830 | errorucpp_error(l, "unmatched #endif"); |
1831 | ret = 1; |
1832 | goto handle_warp; |
1833 | } |
1834 | if ((-- ls->ifnest) == 0 |
1835 | && protect_detect.state == 2) { |
1836 | protect_detect.state = 3; |
1837 | } |
1838 | goto handle_warp; |
1839 | } else if (!strcmp(ls->ctok->name, "include")) { |
1840 | ret = handle_include(ls, save_flags, 0); |
1841 | goto handle_exit3; |
1842 | } else if (!strcmp(ls->ctok->name, "include_next")) { |
1843 | ret = handle_include(ls, save_flags, 1); |
1844 | goto handle_exit3; |
1845 | } else if (!strcmp(ls->ctok->name, "pragma")) { |
1846 | if (!(save_flags & LEXER0x010000UL)) { |
1847 | #ifdef PRAGMA_DUMP |
1848 | /* dump #pragma in output */ |
1849 | struct token u; |
1850 | |
1851 | u.type = sharp_type; |
1852 | u.line = l; |
1853 | ls->flags = save_flags; |
1854 | print_tokenucpp_print_token(ls, &u, 0); |
1855 | print_tokenucpp_print_token(ls, ls->ctok, 0); |
1856 | while (ls->flags |= LEXER0x010000UL, |
1857 | !next_tokenucpp_next_token(ls)) { |
1858 | long save_line; |
1859 | |
1860 | ls->flags &= ~LEXER0x010000UL; |
1861 | save_line = ls->line; |
1862 | ls->line = l; |
1863 | print_tokenucpp_print_token(ls, ls->ctok, 0); |
1864 | ls->line = save_line; |
1865 | if (ls->ctok->type == NEWLINE) |
1866 | break; |
1867 | } |
1868 | goto handle_exit3; |
1869 | #else |
1870 | if (ls->flags & WARN_PRAGMA0x000010UL) |
1871 | warningucpp_warning(l, "#pragma ignored " |
1872 | "and not dumped"); |
1873 | goto handle_warp_ign; |
1874 | #endif |
1875 | } |
1876 | if (!(ls->flags & HANDLE_PRAGMA0x001000UL)) |
1877 | goto handle_warp_ign; |
1878 | handle_pragma(ls); |
1879 | goto handle_exit; |
1880 | } else if (!strcmp(ls->ctok->name, "error")) { |
1881 | ret = 1; |
1882 | handle_error(ls); |
1883 | goto handle_exit; |
1884 | } else if (!strcmp(ls->ctok->name, "line")) { |
1885 | ret = handle_line(ls, save_flags); |
1886 | goto handle_exit; |
1887 | } else if ((ls->flags & HANDLE_ASSERTIONS0x000800UL) |
1888 | && !strcmp(ls->ctok->name, "assert")) { |
1889 | ret = handle_assertucpp_handle_assert(ls); |
1890 | goto handle_exit; |
1891 | } else if ((ls->flags & HANDLE_ASSERTIONS0x000800UL) |
1892 | && !strcmp(ls->ctok->name, "unassert")) { |
1893 | ret = handle_unassertucpp_handle_unassert(ls); |
1894 | goto handle_exit; |
1895 | } |
1896 | } else { |
1897 | if (!strcmp(ls->ctok->name, "else")) { |
1898 | if (condfval(ls->ifnest - 1) |
1899 | && (ls->flags & WARN_STANDARD0x000001UL)) { |
1900 | warningucpp_warning(l, "rogue #else in code " |
1901 | "compiled out"); |
1902 | } |
1903 | if (ls->condnest == ls->ifnest - 1) { |
1904 | if (!ls->condmet) ls->condcomp = 1; |
1905 | } |
1906 | condfset(ls->ifnest - 1); |
1907 | if (ls->ifnest == 1) protect_detect.state = 0; |
1908 | goto handle_warp; |
1909 | } else if (!strcmp(ls->ctok->name, "elif")) { |
1910 | if (condfval(ls->ifnest - 1) |
1911 | && (ls->flags & WARN_STANDARD0x000001UL)) { |
1912 | warningucpp_warning(l, "rogue #elif in code " |
1913 | "compiled out"); |
1914 | } |
1915 | if (ls->condnest != ls->ifnest - 1 |
1916 | || ls->condmet) |
1917 | goto handle_warp_ign; |
1918 | if (ls->ifnest == 1) protect_detect.state = 0; |
1919 | ret = handle_if(ls); |
1920 | if (ret > 0) { |
1921 | ls->condcomp = 1; |
1922 | ls->condmet = 1; |
1923 | ret = 0; |
1924 | } else if (ret < 0) ret = 1; |
1925 | goto handle_exit; |
1926 | } else if (!strcmp(ls->ctok->name, "endif")) { |
1927 | if ((-- ls->ifnest) == ls->condnest) { |
1928 | if (ls->ifnest == 0 && |
1929 | protect_detect.state == 2) |
1930 | protect_detect.state = 3; |
1931 | ls->condcomp = 1; |
1932 | } |
1933 | goto handle_warp; |
1934 | } else if (!strcmp(ls->ctok->name, "if") |
1935 | || !strcmp(ls->ctok->name, "ifdef") |
1936 | || !strcmp(ls->ctok->name, "ifndef")) { |
1937 | if ((++ ls->ifnest) > 63) goto too_many_if; |
1938 | condfclr(ls->ifnest - 1); |
1939 | } |
1940 | goto handle_warp_ign; |
1941 | } |
1942 | /* |
1943 | * Unrecognized directive. We emit either an error or |
1944 | * an annoying warning, depending on a command-line switch. |
1945 | */ |
1946 | if (ls->flags & FAIL_SHARP0x000020UL) { |
1947 | errorucpp_error(l, "unknown cpp directive '#%s'", |
1948 | ls->ctok->name); |
1949 | goto handle_warp_ign; |
1950 | } else { |
1951 | struct token u; |
1952 | |
1953 | u.type = sharp_type; |
1954 | u.line = l; |
1955 | ls->flags = save_flags; |
1956 | print_tokenucpp_print_token(ls, &u, 0); |
1957 | print_tokenucpp_print_token(ls, ls->ctok, 0); |
1958 | if (ls->flags & WARN_ANNOYING0x000002UL) { |
1959 | warningucpp_warning(l, "rogue '#' dumped"); |
1960 | } |
1961 | } |
1962 | } |
1963 | return 1; |
1964 | |
1965 | handle_warp_ign: |
1966 | while (!next_tokenucpp_next_token(ls)) if (ls->ctok->type == NEWLINE) break; |
1967 | goto handle_exit; |
1968 | handle_warp: |
1969 | while (!next_tokenucpp_next_token(ls)) { |
1970 | if (!ttWHI(ls->ctok->type)(((ls->ctok->type) == NONE || (ls->ctok->type) == COMMENT || (ls->ctok->type) == OPT_NONE) || (ls->ctok ->type) == NEWLINE) && (ls->flags & WARN_STANDARD0x000001UL)) { |
1971 | warningucpp_warning(l, "trailing garbage in " |
1972 | "preprocessing directive"); |
1973 | } |
1974 | if (ls->ctok->type == NEWLINE) break; |
1975 | } |
1976 | handle_exit: |
1977 | if (!(ls->flags & LEXER0x010000UL)) put_charucpp_put_char(ls, '\n'); |
1978 | handle_exit3: |
1979 | if (protect_detect.state == 1) { |
1980 | protect_detect.state = 0; |
1981 | } else if (protect_detect.state == -1) { |
1982 | /* just after the #include */ |
1983 | protect_detect.state = 1; |
1984 | } |
1985 | handle_exit2: |
1986 | ls->flags = save_flags; |
1987 | return ret; |
1988 | too_many_if: |
1989 | errorucpp_error(l, "too many levels of conditional inclusion (max 63)"); |
1990 | ret = 1; |
1991 | goto handle_warp; |
1992 | #undef condfset |
1993 | #undef condfclr |
1994 | #undef condfval |
1995 | } |
1996 | |
1997 | /* |
1998 | * This is the main entry function. It maintains count of #, and call the |
1999 | * appropriate functions when it encounters a cpp directive or a macro |
2000 | * name. |
2001 | * return value: positive on error; CPPERR_EOF means "end of input reached" |
2002 | */ |
2003 | int cpp(struct lexer_state *ls) |
2004 | { |
2005 | int r = 0; |
2006 | |
2007 | while (next_tokenucpp_next_token(ls)) { |
2008 | if (protect_detect.state == 3) { |
2009 | /* |
2010 | * At that point, protect_detect.ff->protect might |
2011 | * be non-zero, if the file has been recursively |
2012 | * included, and a guardian detected. |
2013 | */ |
2014 | if (!protect_detect.ff->protect) { |
2015 | /* Cool ! A new guardian has been detected. */ |
2016 | protect_detect.ff->protect = |
2017 | protect_detect.macro; |
2018 | } else if (protect_detect.macro) { |
2019 | /* We found a guardian but an old one. */ |
2020 | freememfree(protect_detect.macro); |
2021 | } |
2022 | protect_detect.macro = 0; |
2023 | } |
2024 | if (ls->ifnest) { |
2025 | errorucpp_error(ls->line, "unterminated #if construction " |
2026 | "(depth %ld)", ls->ifnest); |
2027 | r = CPPERR_NEST900; |
2028 | } |
2029 | if (ls_depth == 0) return CPPERR_EOF1000; |
2030 | close_input(ls); |
2031 | if (!(ls->flags & LEXER0x010000UL) && !ls->ltwnl) { |
2032 | put_charucpp_put_char(ls, '\n'); |
2033 | ls->ltwnl = 1; |
2034 | } |
2035 | pop_file_context(ls); |
2036 | ls->oline ++; |
2037 | if (enter_file(ls, ls->flags)) { |
2038 | ls->ctok->type = NEWLINE; |
2039 | ls->ltwnl = 1; |
2040 | break; |
2041 | } |
2042 | } |
2043 | if (!(ls->ltwnl && (ls->ctok->type == SHARP |
2044 | || ls->ctok->type == DIG_SHARP)) |
2045 | && protect_detect.state == 1 && !ttWHI(ls->ctok->type)(((ls->ctok->type) == NONE || (ls->ctok->type) == COMMENT || (ls->ctok->type) == OPT_NONE) || (ls->ctok ->type) == NEWLINE)) { |
2046 | /* the first non-whitespace token encountered is not |
2047 | a sharp introducing a cpp directive */ |
2048 | protect_detect.state = 0; |
2049 | } |
2050 | if (protect_detect.state == 3 && !ttWHI(ls->ctok->type)(((ls->ctok->type) == NONE || (ls->ctok->type) == COMMENT || (ls->ctok->type) == OPT_NONE) || (ls->ctok ->type) == NEWLINE)) { |
2051 | /* a non-whitespace token encountered after the #endif */ |
2052 | protect_detect.state = 0; |
2053 | } |
2054 | if (ls->condcomp) { |
2055 | if (ls->ltwnl && (ls->ctok->type == SHARP |
2056 | || ls->ctok->type == DIG_SHARP)) { |
2057 | int x = handle_cpp(ls, ls->ctok->type); |
2058 | |
2059 | ls->ltwnl = 1; |
2060 | return r ? r : x; |
2061 | } |
2062 | if (ls->ctok->type == NAME) { |
2063 | struct macro *m; |
2064 | |
2065 | if ((m = get_macroucpp_get_macro(ls->ctok->name)) != 0) { |
2066 | int x; |
2067 | |
2068 | x = substitute_macroucpp_substitute_macro(ls, m, 0, 1, 0, |
2069 | ls->ctok->line); |
2070 | if (!(ls->flags & LEXER0x010000UL)) |
2071 | garbage_collectucpp_garbage_collect(ls->gf); |
2072 | return r ? r : x; |
2073 | } |
2074 | if (!(ls->flags & LEXER0x010000UL)) |
2075 | print_tokenucpp_print_token(ls, ls->ctok, 0); |
2076 | } |
2077 | } else { |
2078 | if (ls->ltwnl && (ls->ctok->type == SHARP |
2079 | || ls->ctok->type == DIG_SHARP)) { |
2080 | int x = handle_cpp(ls, ls->ctok->type); |
2081 | |
2082 | ls->ltwnl = 1; |
2083 | return r ? r : x; |
2084 | } |
2085 | } |
2086 | if (ls->ctok->type == NEWLINE) ls->ltwnl = 1; |
2087 | else if (!ttWHI(ls->ctok->type)(((ls->ctok->type) == NONE || (ls->ctok->type) == COMMENT || (ls->ctok->type) == OPT_NONE) || (ls->ctok ->type) == NEWLINE)) ls->ltwnl = 0; |
2088 | return r ? r : -1; |
2089 | } |
2090 | |
2091 | #ifndef STAND_ALONE1 |
2092 | /* |
2093 | * llex() and lex() are the lexing functions, when the preprocessor is |
2094 | * linked to another code. llex() should be called only by lex(). |
2095 | */ |
2096 | static int llex(struct lexer_state *ls) |
2097 | { |
2098 | struct token_fifo *tf = ls->output_fifo; |
2099 | int r; |
2100 | |
2101 | if (tf->nt != 0) { |
2102 | if (tf->art < tf->nt) { |
2103 | #ifdef INMACRO_FLAG |
2104 | if (!ls->inmacro) { |
2105 | ls->inmacro = 1; |
2106 | ls->macro_count ++; |
2107 | } |
2108 | #endif |
2109 | ls->ctok = tf->t + (tf->art ++); |
2110 | if (ls->ctok->type > DIGRAPH_TOKENS |
2111 | && ls->ctok->type < DIGRAPH_TOKENS_END) { |
2112 | ls->ctok->type = undig(ls->ctok->type); |
2113 | } |
2114 | return 0; |
2115 | } else { |
2116 | #ifdef INMACRO_FLAG |
2117 | ls->inmacro = 0; |
2118 | #endif |
2119 | freememfree(tf->t); |
2120 | tf->art = tf->nt = 0; |
2121 | garbage_collectucpp_garbage_collect(ls->gf); |
2122 | ls->ctok = ls->save_ctok; |
2123 | } |
2124 | } |
2125 | r = cpp(ls); |
2126 | if (ls->ctok->type > DIGRAPH_TOKENS |
2127 | && ls->ctok->type < LAST_MEANINGFUL_TOKEN) { |
2128 | ls->ctok->type = undig(ls->ctok->type); |
2129 | } |
2130 | if (r > 0) return r; |
2131 | if (r < 0) return 0; |
2132 | return llex(ls); |
2133 | } |
2134 | |
2135 | /* |
2136 | * lex() reads the next token from the processed stream and stores it |
2137 | * into ls->ctok. |
2138 | * return value: non zero on error (including CPPERR_EOF, which is not |
2139 | * quite an error) |
2140 | */ |
2141 | int lex(struct lexer_state *ls) |
2142 | { |
2143 | int r; |
2144 | |
2145 | do { |
2146 | r = llex(ls); |
2147 | #ifdef SEMPER_FIDELIS |
2148 | } while (!r && !ls->condcomp); |
2149 | #else |
2150 | } while (!r && (!ls->condcomp || (ttWHI(ls->ctok->type)(((ls->ctok->type) == NONE || (ls->ctok->type) == COMMENT || (ls->ctok->type) == OPT_NONE) || (ls->ctok ->type) == NEWLINE) && |
2151 | (!(ls->flags & LINE_NUM0x000200UL) || ls->ctok->type != NEWLINE)))); |
2152 | #endif |
2153 | return r; |
2154 | } |
2155 | #endif |
2156 | |
2157 | /* |
2158 | * check_cpp_errors() must be called when the end of input is reached; |
2159 | * it checks pending errors due to truncated constructs (actually none, |
2160 | * this is reserved for future evolutions). |
2161 | */ |
2162 | int check_cpp_errors(struct lexer_state *ls) |
2163 | { |
2164 | if (ls->flags & KEEP_OUTPUT0x020000UL) { |
2165 | put_charucpp_put_char(ls, '\n'); |
2166 | } |
2167 | if (emit_dependencies) fputc('\n', emit_output); |
2168 | #ifndef NO_UCPP_BUF1 |
2169 | if (!(ls->flags & LEXER0x010000UL)) { |
2170 | flush_output(ls); |
2171 | } |
2172 | #endif |
2173 | if ((ls->flags & WARN_TRIGRAPHS0x000004UL) && ls->count_trigraphs) |
2174 | warningucpp_warning(0, "%ld trigraph(s) encountered", ls->count_trigraphs); |
2175 | return 0; |
2176 | } |
2177 | |
2178 | /* |
2179 | * init_cpp() initializes static tables inside ucpp. It needs not be |
2180 | * called more than once. |
2181 | */ |
2182 | void init_cpp(void) |
2183 | { |
2184 | init_cppmucpp_init_cppm(); |
2185 | } |
2186 | |
2187 | /* |
2188 | * (re)init the global tables. |
2189 | * If standard_assertions is non 0, init the assertions table. |
2190 | */ |
2191 | void init_tables(int with_assertions) |
2192 | { |
2193 | time_t t; |
2194 | struct tm *ct; |
2195 | |
2196 | init_buf_lexer_stateucpp_init_buf_lexer_state(&dsharp_lexerucpp_dsharp_lexer, 0); |
2197 | #ifdef PRAGMA_TOKENIZE |
2198 | init_buf_lexer_stateucpp_init_buf_lexer_state(&tokenize_lexerucpp_tokenize_lexer, 0); |
2199 | #endif |
2200 | time(&t); |
2201 | ct = localtime(&t); |
2202 | #ifdef NOSTRFTIME |
2203 | /* we have a quite old compiler, that does not know the |
2204 | (standard since 1990) strftime() function. */ |
2205 | { |
2206 | char *c = asctime(ct); |
2207 | |
2208 | compile_timeucpp_compile_time[0] = '"'; |
2209 | mmvmemcpy(compile_timeucpp_compile_time + 1, c + 11, 8); |
2210 | compile_timeucpp_compile_time[9] = '"'; |
2211 | compile_timeucpp_compile_time[10] = 0; |
2212 | compile_dateucpp_compile_date[0] = '"'; |
2213 | mmvmemcpy(compile_dateucpp_compile_date + 1, c + 4, 7); |
2214 | mmvmemcpy(compile_dateucpp_compile_date + 8, c + 20, 4); |
2215 | compile_dateucpp_compile_date[12] = '"'; |
2216 | compile_dateucpp_compile_date[13] = 0; |
2217 | } |
2218 | #else |
2219 | strftime(compile_timeucpp_compile_time, 12, "\"%H:%M:%S\"", ct); |
2220 | strftime(compile_dateucpp_compile_date, 24, "\"%b %d %Y\"", ct); |
2221 | #endif |
2222 | init_macros(); |
2223 | if (with_assertions) init_assertions(); |
2224 | init_found_files(); |
2225 | } |
2226 | |
2227 | /* |
2228 | * Resets the include path. |
2229 | */ |
2230 | void init_include_path(char *incpath[]) |
2231 | { |
2232 | if (include_path_nb) { |
2233 | size_t i; |
2234 | |
2235 | for (i = 0; i < include_path_nb; i ++) |
2236 | freememfree(include_path[i]); |
2237 | freememfree(include_path); |
2238 | include_path_nb = 0; |
2239 | } |
2240 | if (incpath) { |
2241 | int i; |
2242 | |
2243 | for (i = 0; incpath[i]; i ++) |
2244 | aol(include_path, include_path_nb,do { if (((include_path_nb) % (16)) == 0) { if ((include_path_nb ) != 0) { (include_path) = incmem((include_path), (include_path_nb ) * sizeof(sdup(incpath[i])), ((include_path_nb) + (16)) * sizeof (sdup(incpath[i]))); } else { (include_path) = malloc((16) * sizeof (sdup(incpath[i]))); } } (include_path)[(include_path_nb) ++] = (sdup(incpath[i])); } while (0) |
2245 | sdup(incpath[i]), INCPATH_MEMG)do { if (((include_path_nb) % (16)) == 0) { if ((include_path_nb ) != 0) { (include_path) = incmem((include_path), (include_path_nb ) * sizeof(sdup(incpath[i])), ((include_path_nb) + (16)) * sizeof (sdup(incpath[i]))); } else { (include_path) = malloc((16) * sizeof (sdup(incpath[i]))); } } (include_path)[(include_path_nb) ++] = (sdup(incpath[i])); } while (0); |
2246 | } |
2247 | } |
2248 | |
2249 | /* |
2250 | * add_incpath() adds "path" to the standard include path. |
2251 | */ |
2252 | void add_incpath(char *path) |
2253 | { |
2254 | aol(include_path, include_path_nb, sdup(path), INCPATH_MEMG)do { if (((include_path_nb) % (16)) == 0) { if ((include_path_nb ) != 0) { (include_path) = incmem((include_path), (include_path_nb ) * sizeof(sdup(path)), ((include_path_nb) + (16)) * sizeof(sdup (path))); } else { (include_path) = malloc((16) * sizeof(sdup (path))); } } (include_path)[(include_path_nb) ++] = (sdup(path )); } while (0); |
2255 | } |
2256 | |
2257 | /* |
2258 | * This function cleans the memory. It should release all allocated |
2259 | * memory structures and may be called even if the current pre-processing |
2260 | * is not finished or reported an error. |
2261 | */ |
2262 | void wipeout() |
2263 | { |
2264 | struct lexer_state ls; |
2265 | |
2266 | if (include_path_nb > 0) { |
2267 | size_t i; |
2268 | |
2269 | for (i = 0; i < include_path_nb; i ++) |
2270 | freememfree(include_path[i]); |
2271 | freememfree(include_path); |
2272 | include_path = 0; |
2273 | include_path_nb = 0; |
2274 | } |
2275 | if (current_filename) freememfree(current_filename); |
2276 | current_filename = 0; |
2277 | current_long_filename = 0; |
2278 | current_incdir = -1; |
2279 | protect_detect.state = 0; |
2280 | if (protect_detect.macro) freememfree(protect_detect.macro); |
2281 | protect_detect.macro = 0; |
2282 | protect_detect.ff = 0; |
2283 | init_lexer_state(&ls); |
2284 | while (ls_depth > 0) pop_file_context(&ls); |
2285 | free_lexer_state(&ls); |
2286 | free_lexer_state(&dsharp_lexerucpp_dsharp_lexer); |
2287 | #ifdef PRAGMA_TOKENIZE |
2288 | free_lexer_state(&tokenize_lexerucpp_tokenize_lexer); |
2289 | #endif |
2290 | if (found_files_init_done) HTT_kill(&found_files); |
2291 | found_files_init_done = 0; |
2292 | if (found_files_sys_init_done) HTT_kill(&found_files_sys); |
2293 | found_files_sys_init_done = 0; |
2294 | wipe_macrosucpp_wipe_macros(); |
2295 | wipe_assertionsucpp_wipe_assertions(); |
2296 | } |
2297 | |
2298 | #ifdef STAND_ALONE1 |
2299 | /* |
2300 | * print some help |
2301 | */ |
2302 | static void usage(char *command_name) |
2303 | { |
2304 | fprintf(stderrstderr, |
2305 | "Usage: %s [options] [file]\n" |
2306 | "language options:\n" |
2307 | " -C keep comments in output\n" |
2308 | " -s keep '#' when no cpp directive is recognized\n" |
2309 | " -l do not emit line numbers\n" |
2310 | " -lg emit gcc-like line numbers\n" |
2311 | " -CC disable C++-like comments\n" |
2312 | " -a, -na, -a0 handle (or not) assertions\n" |
2313 | " -V disable macros with extra arguments\n" |
2314 | " -u understand UTF-8 in source\n" |
2315 | " -X enable -a, -u and -Y\n" |
2316 | " -c90 mimic C90 behaviour\n" |
2317 | " -t disable trigraph support\n" |
2318 | "warning options:\n" |
2319 | " -wt emit a final warning when trigaphs are encountered\n" |
2320 | " -wtt emit warnings for each trigaph encountered\n" |
2321 | " -wa emit warnings that are usually useless\n" |
2322 | " -w0 disable standard warnings\n" |
2323 | "directory options:\n" |
2324 | " -I directory add 'directory' before the standard include path\n" |
2325 | " -J directory add 'directory' after the standard include path\n" |
2326 | " -zI do not use the standard include path\n" |
2327 | " -M emit Makefile-like dependencies instead of normal " |
2328 | "output\n" |
2329 | " -Ma emit also dependancies for system files\n" |
2330 | " -o file store output in file\n" |
2331 | "macro and assertion options:\n" |
2332 | " -Dmacro predefine 'macro'\n" |
2333 | " -Dmacro=def predefine 'macro' with 'def' content\n" |
2334 | " -Umacro undefine 'macro'\n" |
2335 | " -Afoo(bar) assert foo(bar)\n" |
2336 | " -Bfoo(bar) unassert foo(bar)\n" |
2337 | " -Y predefine system-dependant macros\n" |
2338 | " -Z do not predefine special macros\n" |
2339 | " -d emit defined macros\n" |
2340 | " -e emit assertions\n" |
2341 | "misc options:\n" |
2342 | " -v print version number and settings\n" |
2343 | " -h show this help\n", |
2344 | command_name); |
2345 | } |
2346 | |
2347 | /* |
2348 | * print version and compile-time settings |
2349 | */ |
2350 | static void version(void) |
2351 | { |
2352 | size_t i; |
2353 | |
2354 | fprintf(stderrstderr, "ucpp version %d.%d\n", VERS_MAJ1, VERS_MIN3); |
2355 | fprintf(stderrstderr, "search path:\n"); |
2356 | for (i = 0; i < include_path_nb; i ++) |
2357 | fprintf(stderrstderr, " %s\n", include_path[i]); |
2358 | } |
2359 | |
2360 | /* |
2361 | * parse_opt() initializes many things according to the command-line |
2362 | * options. |
2363 | * Return values: |
2364 | * 0 on success |
2365 | * 1 on semantic error (redefinition of a special macro, for instance) |
2366 | * 2 on syntaxic error (unknown options for instance) |
2367 | */ |
2368 | static int parse_opt(int argc, char *argv[], struct lexer_state *ls) |
2369 | { |
2370 | int i, ret = 0; |
2371 | char *filename = 0; |
2372 | int with_std_incpath = 1; |
2373 | int print_version = 0, print_defs = 0, print_asserts = 0; |
2374 | int system_macros = 0, standard_assertions = 1; |
2375 | |
2376 | init_lexer_state(ls); |
2377 | ls->flags = DEFAULT_CPP_FLAGS(0x000080UL | 0x000001UL | 0x000010UL | 0x000020UL | 0x002000UL | 0x000100UL | 0x000200UL | 0x100000UL | 0x020000UL | 0x008000UL | 0x000800UL); |
2378 | emit_output = ls->output = stdoutstdout; |
2379 | for (i = 1; i < argc; i ++) if (argv[i][0] == '-') { |
2380 | if (!strcmp(argv[i], "-h")) { |
2381 | return 2; |
2382 | } else if (!strcmp(argv[i], "-C")) { |
2383 | ls->flags &= ~DISCARD_COMMENTS0x000080UL; |
2384 | } else if (!strcmp(argv[i], "-CC")) { |
2385 | ls->flags &= ~CPLUSPLUS_COMMENTS0x000100UL; |
2386 | } else if (!strcmp(argv[i], "-a")) { |
2387 | ls->flags |= HANDLE_ASSERTIONS0x000800UL; |
2388 | } else if (!strcmp(argv[i], "-na")) { |
2389 | ls->flags |= HANDLE_ASSERTIONS0x000800UL; |
2390 | standard_assertions = 0; |
2391 | } else if (!strcmp(argv[i], "-a0")) { |
2392 | ls->flags &= ~HANDLE_ASSERTIONS0x000800UL; |
2393 | } else if (!strcmp(argv[i], "-V")) { |
2394 | ls->flags &= ~MACRO_VAARG0x002000UL; |
2395 | } else if (!strcmp(argv[i], "-u")) { |
2396 | ls->flags |= UTF8_SOURCE0x004000UL; |
2397 | } else if (!strcmp(argv[i], "-X")) { |
2398 | ls->flags |= HANDLE_ASSERTIONS0x000800UL; |
2399 | ls->flags |= UTF8_SOURCE0x004000UL; |
2400 | system_macros = 1; |
2401 | } else if (!strcmp(argv[i], "-c90")) { |
2402 | ls->flags &= ~MACRO_VAARG0x002000UL; |
2403 | ls->flags &= ~CPLUSPLUS_COMMENTS0x000100UL; |
2404 | c99_compliant = 0; |
2405 | c99_hosted = -1; |
2406 | } else if (!strcmp(argv[i], "-t")) { |
2407 | ls->flags &= ~HANDLE_TRIGRAPHS0x008000UL; |
2408 | } else if (!strcmp(argv[i], "-wt")) { |
2409 | ls->flags |= WARN_TRIGRAPHS0x000004UL; |
2410 | } else if (!strcmp(argv[i], "-wtt")) { |
2411 | ls->flags |= WARN_TRIGRAPHS_MORE0x000008UL; |
2412 | } else if (!strcmp(argv[i], "-wa")) { |
2413 | ls->flags |= WARN_ANNOYING0x000002UL; |
2414 | } else if (!strcmp(argv[i], "-w0")) { |
2415 | ls->flags &= ~WARN_STANDARD0x000001UL; |
2416 | ls->flags &= ~WARN_PRAGMA0x000010UL; |
2417 | } else if (!strcmp(argv[i], "-s")) { |
2418 | ls->flags &= ~FAIL_SHARP0x000020UL; |
2419 | } else if (!strcmp(argv[i], "-l")) { |
2420 | ls->flags &= ~LINE_NUM0x000200UL; |
2421 | } else if (!strcmp(argv[i], "-lg")) { |
2422 | ls->flags |= GCC_LINE_NUM0x000400UL; |
2423 | } else if (!strcmp(argv[i], "-M")) { |
2424 | ls->flags &= ~KEEP_OUTPUT0x020000UL; |
2425 | emit_dependencies = 1; |
2426 | } else if (!strcmp(argv[i], "-Ma")) { |
2427 | ls->flags &= ~KEEP_OUTPUT0x020000UL; |
2428 | emit_dependencies = 2; |
2429 | } else if (!strcmp(argv[i], "-Y")) { |
2430 | system_macros = 1; |
2431 | } else if (!strcmp(argv[i], "-Z")) { |
2432 | no_special_macros = 1; |
2433 | } else if (!strcmp(argv[i], "-d")) { |
2434 | ls->flags &= ~KEEP_OUTPUT0x020000UL; |
2435 | print_defs = 1; |
2436 | } else if (!strcmp(argv[i], "-e")) { |
2437 | ls->flags &= ~KEEP_OUTPUT0x020000UL; |
2438 | print_asserts = 1; |
2439 | } else if (!strcmp(argv[i], "-zI")) { |
2440 | with_std_incpath = 0; |
2441 | } else if (!strcmp(argv[i], "-I") || !strcmp(argv[i], "-J")) { |
2442 | i ++; |
2443 | } else if (!strcmp(argv[i], "-o")) { |
2444 | if ((++ i) >= argc) { |
2445 | errorucpp_error(-1, "missing filename after -o"); |
2446 | return 2; |
2447 | } |
2448 | if (argv[i][0] == '-' && argv[i][1] == 0) { |
2449 | emit_output = ls->output = stdoutstdout; |
2450 | } else { |
2451 | ls->output = fopen(argv[i], "w"); |
2452 | if (!ls->output) { |
2453 | errorucpp_error(-1, "failed to open for " |
2454 | "writing: %s", argv[i]); |
2455 | return 2; |
2456 | } |
2457 | emit_output = ls->output; |
2458 | } |
2459 | } else if (!strcmp(argv[i], "-v")) { |
2460 | print_version = 1; |
2461 | } else if (argv[i][1] != 'I' && argv[i][1] != 'J' |
2462 | && argv[i][1] != 'D' && argv[i][1] != 'U' |
2463 | && argv[i][1] != 'A' && argv[i][1] != 'B') |
2464 | warningucpp_warning(-1, "unknown option '%s'", argv[i]); |
2465 | } else { |
2466 | if (filename != 0) { |
2467 | errorucpp_error(-1, "spurious duplicate filename '%s' - vs. '%s' ", argv[i], filename); |
2468 | return 2; |
2469 | } |
2470 | filename = argv[i]; |
2471 | } |
2472 | init_tables(ls->flags & HANDLE_ASSERTIONS0x000800UL); |
2473 | init_include_path(0); |
2474 | if (filename) { |
2475 | #ifdef UCPP_MMAP |
2476 | FILE *f = fopen_mmap_file(filename); |
2477 | |
2478 | ls->input = 0; |
2479 | if (f) set_input_file(ls, f); |
2480 | #else |
2481 | ls->input = fopen(filename, "r"); |
2482 | #endif |
2483 | if (!ls->input) { |
2484 | errorucpp_error(-1, "file '%s' not found", filename); |
2485 | return 1; |
2486 | } |
2487 | #ifdef NO_LIBC_BUF |
2488 | setbuf(ls->input, 0); |
2489 | #endif |
2490 | set_init_filename(filename, 1); |
2491 | } else { |
2492 | ls->input = stdinstdin; |
2493 | set_init_filename("<stdin>", 0); |
2494 | } |
2495 | for (i = 1; i < argc; i ++) |
2496 | if (argv[i][0] == '-' && argv[i][1] == 'I') |
2497 | add_incpath(argv[i][2] ? argv[i] + 2 : argv[i + 1]); |
2498 | if (system_macros) for (i = 0; system_macros_def[i]; i ++) |
2499 | ret = ret || define_macro(ls, system_macros_def[i]); |
2500 | for (i = 1; i < argc; i ++) |
2501 | if (argv[i][0] == '-' && argv[i][1] == 'D') |
2502 | ret = ret || define_macro(ls, argv[i] + 2); |
2503 | for (i = 1; i < argc; i ++) |
2504 | if (argv[i][0] == '-' && argv[i][1] == 'U') |
2505 | ret = ret || undef_macro(ls, argv[i] + 2); |
2506 | if (ls->flags & HANDLE_ASSERTIONS0x000800UL) { |
2507 | if (standard_assertions) |
2508 | for (i = 0; system_assertions_def[i]; i ++) |
2509 | make_assertion(system_assertions_def[i]); |
2510 | for (i = 1; i < argc; i ++) |
2511 | if (argv[i][0] == '-' && argv[i][1] == 'A') |
2512 | ret = ret || make_assertion(argv[i] + 2); |
2513 | for (i = 1; i < argc; i ++) |
2514 | if (argv[i][0] == '-' && argv[i][1] == 'B') |
2515 | ret = ret || destroy_assertion(argv[i] + 2); |
2516 | } else { |
2517 | for (i = 1; i < argc; i ++) |
2518 | if (argv[i][0] == '-' |
2519 | && (argv[i][1] == 'A' || argv[i][1] == 'B')) |
2520 | warningucpp_warning(-1, "assertions disabled"); |
2521 | } |
2522 | if (with_std_incpath) { |
2523 | for (i = 0; include_path_std[i]; i ++) |
2524 | add_incpath(include_path_std[i]); |
2525 | } |
2526 | for (i = 1; i < argc; i ++) |
2527 | if (argv[i][0] == '-' && argv[i][1] == 'J') |
2528 | add_incpath(argv[i][2] ? argv[i] + 2 : argv[i + 1]); |
2529 | |
2530 | if (print_version) { |
2531 | version(); |
2532 | return 1; |
2533 | } |
2534 | if (print_defs) { |
2535 | print_defines(); |
2536 | emit_defines = 1; |
2537 | } |
2538 | if (print_asserts && (ls->flags & HANDLE_ASSERTIONS0x000800UL)) { |
2539 | print_assertions(); |
2540 | emit_assertions = 1; |
2541 | } |
2542 | return ret; |
2543 | } |
2544 | |
2545 | int main(int argc, char *argv[]) |
2546 | { |
2547 | struct lexer_state ls; |
2548 | int r, fr = 0; |
2549 | |
2550 | init_cpp(); |
2551 | if ((r = parse_opt(argc, argv, &ls)) != 0) { |
2552 | if (r == 2) usage(argv[0]); |
2553 | return EXIT_FAILURE1; |
2554 | } |
2555 | enter_file(&ls, ls.flags); |
2556 | while ((r = cpp(&ls)) < CPPERR_EOF1000) fr = fr || (r > 0); |
2557 | fr = fr || check_cpp_errors(&ls); |
2558 | free_lexer_state(&ls); |
2559 | wipeout(); |
2560 | #ifdef MEM_DEBUG |
2561 | report_leaks(); |
2562 | #endif |
2563 | return fr ? EXIT_FAILURE1 : EXIT_SUCCESS0; |
2564 | } |
2565 | #endif |