Bug Summary

File:workdir/unxlngi6.pro/CustomTarget/ucpp/source/cpp.c
Location:line 1653, column 2
Description:Memory is never released; potential leak of memory pointed to by 'ct.t'

Annotated Source Code

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
58static char *include_path_std[] = { STD_INCLUDE_PATH"/usr/local/include", "/usr/include", 0 };
59#endif
60static char **include_path;
61static size_t include_path_nb = 0;
62
63int no_special_macros = 0;
64int emit_dependencies = 0, emit_defines = 0, emit_assertions = 0;
65FILE *emit_output;
66
67#ifdef STAND_ALONE1
68static char *system_macros_def[] = { STD_MACROS0, 0 };
69static char *system_assertions_def[] = { STD_ASSERT0, 0 };
70#endif
71
72char *current_filename = 0, *current_long_filename = 0;
73static 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 */
82void 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 */
97void 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 */
123void 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
157struct garbage_fifo {
158 char **garbage;
159 size_t ngarb, memgarb;
160};
161
162/*
163 * throw_away() marks a string to be collected later
164 */
165void 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 */
173void 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
181static 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
188static 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 */
199char *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
224char *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 */
237struct 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 */
246struct found_file_sys {
247 hash_item_header head; /* first field */
248 struct found_file *rff;
249 int incdir;
250};
251
252static HTT found_files, found_files_sys;
253static int found_files_init_done = 0, found_files_sys_init_done = 0;
254
255static 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
264static 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
273static 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
282static 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 */
293struct protect protect_detect;
294static struct protect *protect_detect_stack = 0;
295
296void 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
313static 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 */
326static 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 */
353void 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 */
381void 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 */
390static 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 */
416static 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 */
435static struct file_context {
436 struct lexer_state ls;
437 char *name, *long_name;
438 int incdir;
439} *ls_stack;
440static size_t ls_depth = 0;
441
442static 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
456static 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 */
480struct 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 */
499void 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 */
512void 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 */
543static 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 */
569int 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 */
598static void *find_file_map;
599static size_t map_length;
600
601FILE *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
631void 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 */
656static int find_file_error;
657
658enum { FF_ERROR, FF_PROTECT, FF_KNOWN, FF_UNKNOWN };
659
660static 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 }
808zero_out:
809 if (s) freememfree(s);
810 if (nffa) {
811 del_found_file(protect_detect.ff);
812 protect_detect.ff = 0;
813 nffa = 0;
814 }
815 return 0;
816
817 /*
818 * This part is invoked when the file was found in the
819 * cache.
820 */
821found_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 */
849found_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
876found_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 */
892static 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 */
985static 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
1184error1:
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 */
1197static 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
1251include_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
1291include_error:
1292 errorucpp_error(l, "invalid '#include'");
1293 return 1;
1294
1295include_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 }
1310include_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
1377include_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
1383do_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 ++;
1398do_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 */
1440static 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
1543line_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 */
1552static 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 */
1571static 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 */
1586struct 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 ++) {
7
Loop condition is true. Entering loop body
8
Loop condition is false. Execution continues on line 1596
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);
9
Within the expansion of the macro 'getmem':
a
Memory is allocated
1597 for (l = 0, tf->art = 0; tf->art < tf->nt; tf->art ++) {
10
Loop condition is true. Entering loop body
12
Loop condition is false. Execution continues on line 1614
1598 int tt = tf->t[tf->art].type;
1599
1600 if (tt == 0) tt = PRAGMA_TOKEN_END((unsigned char)'\n');
11
Taking false branch
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);
13
Taking true branch
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 */
1627static 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) {
1
Taking true branch
1640 do {
4
Loop condition is false. Exiting loop
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;
2
Taking false branch
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)
;
3
Within the expansion of the macro 'aol':
1647 } while (!next_tokenucpp_next_token(ls) && ls->ctok->type != NEWLINE);
1648 }
1649 if (tf.nt == 0) {
5
Taking false branch
1650 /* void pragma are silently ignored */
1651 return;
1652 }
1653 buf = (compress_token_listucpp_compress_token_list(&tf)).t;
6
Within the expansion of the macro 'compress_token_list':
a
Calling 'ucpp_compress_token_list'
b
Returned allocated memory
14
Memory is never released; potential leak of memory pointed to by 'ct.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 */
1684static 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
1965handle_warp_ign:
1966 while (!next_tokenucpp_next_token(ls)) if (ls->ctok->type == NEWLINE) break;
1967 goto handle_exit;
1968handle_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 }
1976handle_exit:
1977 if (!(ls->flags & LEXER0x010000UL)) put_charucpp_put_char(ls, '\n');
1978handle_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 }
1985handle_exit2:
1986 ls->flags = save_flags;
1987 return ret;
1988too_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 */
2003int 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 */
2096static 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 */
2141int 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 */
2162int 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 */
2182void 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 */
2191void 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 */
2230void 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 */
2252void 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 */
2262void 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 */
2302static 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 */
2350static 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 */
2368static 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
2545int 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