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' |
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; | |||
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 |