Print this page
new smatch
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/pre-process.c
+++ new/usr/src/tools/smatch/src/pre-process.c
1 1 /*
2 2 * Do C preprocessing, based on a token list gathered by
3 3 * the tokenizer.
4 4 *
5 5 * This may not be the smartest preprocessor on the planet.
6 6 *
7 7 * Copyright (C) 2003 Transmeta Corp.
8 8 * 2003-2004 Linus Torvalds
9 9 *
10 10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 11 * of this software and associated documentation files (the "Software"), to deal
12 12 * in the Software without restriction, including without limitation the rights
13 13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 14 * copies of the Software, and to permit persons to whom the Software is
15 15 * furnished to do so, subject to the following conditions:
16 16 *
17 17 * The above copyright notice and this permission notice shall be included in
18 18 * all copies or substantial portions of the Software.
19 19 *
20 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 26 * THE SOFTWARE.
27 27 */
28 28 #include <stdio.h>
29 29 #include <stdlib.h>
30 30 #include <stdarg.h>
31 31 #include <stddef.h>
32 32 #include <string.h>
33 33 #include <ctype.h>
34 34 #include <unistd.h>
35 35 #include <fcntl.h>
36 36 #include <limits.h>
37 37 #include <time.h>
38 38 #include <dirent.h>
39 39 #include <sys/stat.h>
40 40
41 41 #include "lib.h"
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
42 42 #include "allocate.h"
43 43 #include "parse.h"
44 44 #include "token.h"
45 45 #include "symbol.h"
46 46 #include "expression.h"
47 47 #include "scope.h"
48 48
49 49 static struct ident_list *macros; // only needed for -dD
50 50 static int false_nesting = 0;
51 51 static int counter_macro = 0; // __COUNTER__ expansion
52 +static int include_level = 0;
52 53
53 54 #define INCLUDEPATHS 300
54 55 const char *includepath[INCLUDEPATHS+1] = {
55 56 "",
56 57 "/usr/include",
57 58 "/usr/local/include",
58 59 NULL
59 60 };
60 61
61 62 static const char **quote_includepath = includepath;
62 63 static const char **angle_includepath = includepath + 1;
63 64 static const char **isys_includepath = includepath + 1;
64 65 static const char **sys_includepath = includepath + 1;
65 66 static const char **dirafter_includepath = includepath + 3;
66 67
67 68 #define dirty_stream(stream) \
68 69 do { \
69 70 if (!stream->dirty) { \
70 71 stream->dirty = 1; \
71 72 if (!stream->ifndef) \
72 73 stream->protect = NULL; \
73 74 } \
74 75 } while(0)
75 76
76 77 #define end_group(stream) \
77 78 do { \
78 79 if (stream->ifndef == stream->top_if) { \
79 80 stream->ifndef = NULL; \
80 81 if (!stream->dirty) \
81 82 stream->protect = NULL; \
82 83 else if (stream->protect) \
83 84 stream->dirty = 0; \
84 85 } \
85 86 } while(0)
86 87
87 88 #define nesting_error(stream) \
88 89 do { \
89 90 stream->dirty = 1; \
90 91 stream->ifndef = NULL; \
91 92 stream->protect = NULL; \
92 93 } while(0)
93 94
94 95 static struct token *alloc_token(struct position *pos)
95 96 {
96 97 struct token *token = __alloc_token(0);
97 98
98 99 token->pos.stream = pos->stream;
99 100 token->pos.line = pos->line;
100 101 token->pos.pos = pos->pos;
101 102 token->pos.whitespace = 1;
102 103 return token;
103 104 }
104 105
105 106 /* Expand symbol 'sym' at '*list' */
106 107 static int expand(struct token **, struct symbol *);
107 108
108 109 static void replace_with_string(struct token *token, const char *str)
109 110 {
110 111 int size = strlen(str) + 1;
111 112 struct string *s = __alloc_string(size);
112 113
113 114 s->length = size;
114 115 memcpy(s->data, str, size);
115 116 token_type(token) = TOKEN_STRING;
116 117 token->string = s;
117 118 }
118 119
119 120 static void replace_with_integer(struct token *token, unsigned int val)
120 121 {
121 122 char *buf = __alloc_bytes(11);
122 123 sprintf(buf, "%u", val);
123 124 token_type(token) = TOKEN_NUMBER;
124 125 token->number = buf;
125 126 }
126 127
127 128 static struct symbol *lookup_macro(struct ident *ident)
128 129 {
129 130 struct symbol *sym = lookup_symbol(ident, NS_MACRO | NS_UNDEF);
130 131 if (sym && sym->namespace != NS_MACRO)
131 132 sym = NULL;
132 133 return sym;
133 134 }
134 135
135 136 static int token_defined(struct token *token)
136 137 {
137 138 if (token_type(token) == TOKEN_IDENT) {
138 139 struct symbol *sym = lookup_macro(token->ident);
139 140 if (sym) {
↓ open down ↓ |
78 lines elided |
↑ open up ↑ |
140 141 sym->used_in = file_scope;
141 142 return 1;
142 143 }
143 144 return 0;
144 145 }
145 146
146 147 sparse_error(token->pos, "expected preprocessor identifier");
147 148 return 0;
148 149 }
149 150
150 -static void replace_with_defined(struct token *token)
151 +static void replace_with_bool(struct token *token, bool val)
151 152 {
152 153 static const char *string[] = { "0", "1" };
153 - int defined = token_defined(token);
154 154
155 155 token_type(token) = TOKEN_NUMBER;
156 - token->number = string[defined];
156 + token->number = string[val];
157 157 }
158 158
159 +static void replace_with_defined(struct token *token)
160 +{
161 + replace_with_bool(token, token_defined(token));
162 +}
163 +
164 +static void replace_with_has_builtin(struct token *token)
165 +{
166 + struct symbol *sym = lookup_symbol(token->ident, NS_SYMBOL);
167 + replace_with_bool(token, sym && sym->builtin);
168 +}
169 +
170 +static void replace_with_has_attribute(struct token *token)
171 +{
172 + struct symbol *sym = lookup_symbol(token->ident, NS_KEYWORD);
173 + replace_with_bool(token, sym && sym->op && sym->op->attribute);
174 +}
175 +
176 +static void expand_line(struct token *token)
177 +{
178 + replace_with_integer(token, token->pos.line);
179 +}
180 +
181 +static void expand_file(struct token *token)
182 +{
183 + replace_with_string(token, stream_name(token->pos.stream));
184 +}
185 +
186 +static void expand_basefile(struct token *token)
187 +{
188 + replace_with_string(token, base_filename);
189 +}
190 +
191 +static time_t t = 0;
192 +static void expand_date(struct token *token)
193 +{
194 + static char buffer[12]; /* __DATE__: 3 + ' ' + 2 + ' ' + 4 + '\0' */
195 +
196 + if (!t)
197 + time(&t);
198 + strftime(buffer, 12, "%b %e %Y", localtime(&t));
199 + replace_with_string(token, buffer);
200 +}
201 +
202 +static void expand_time(struct token *token)
203 +{
204 + static char buffer[9]; /* __TIME__: 2 + ':' + 2 + ':' + 2 + '\0' */
205 +
206 + if (!t)
207 + time(&t);
208 + strftime(buffer, 9, "%T", localtime(&t));
209 + replace_with_string(token, buffer);
210 +}
211 +
212 +static void expand_counter(struct token *token)
213 +{
214 + replace_with_integer(token, counter_macro++);
215 +}
216 +
217 +static void expand_include_level(struct token *token)
218 +{
219 + replace_with_integer(token, include_level - 1);
220 +}
221 +
159 222 static int expand_one_symbol(struct token **list)
160 223 {
161 224 struct token *token = *list;
162 225 struct symbol *sym;
163 - static char buffer[12]; /* __DATE__: 3 + ' ' + 2 + ' ' + 4 + '\0' */
164 - static time_t t = 0;
165 226
166 227 if (token->pos.noexpand)
167 228 return 1;
168 229
169 230 sym = lookup_macro(token->ident);
170 - if (sym) {
171 - store_macro_pos(token);
231 + if (!sym)
232 + return 1;
233 + store_macro_pos(token);
234 + if (sym->expander) {
235 + sym->expander(token);
236 + return 1;
237 + } else {
172 238 sym->used_in = file_scope;
173 239 return expand(list, sym);
174 240 }
175 - if (token->ident == &__LINE___ident) {
176 - replace_with_integer(token, token->pos.line);
177 - } else if (token->ident == &__FILE___ident) {
178 - replace_with_string(token, stream_name(token->pos.stream));
179 - } else if (token->ident == &__DATE___ident) {
180 - if (!t)
181 - time(&t);
182 - strftime(buffer, 12, "%b %e %Y", localtime(&t));
183 - replace_with_string(token, buffer);
184 - } else if (token->ident == &__TIME___ident) {
185 - if (!t)
186 - time(&t);
187 - strftime(buffer, 9, "%T", localtime(&t));
188 - replace_with_string(token, buffer);
189 - } else if (token->ident == &__COUNTER___ident) {
190 - replace_with_integer(token, counter_macro++);
191 - }
192 - return 1;
193 241 }
194 242
195 243 static inline struct token *scan_next(struct token **where)
196 244 {
197 245 struct token *token = *where;
198 246 if (token_type(token) != TOKEN_UNTAINT)
199 247 return token;
200 248 do {
201 249 token->ident->tainted = 0;
202 250 token = token->next;
203 251 } while (token_type(token) == TOKEN_UNTAINT);
204 252 *where = token;
205 253 return token;
206 254 }
207 255
208 256 static void expand_list(struct token **list)
209 257 {
210 258 struct token *next;
211 259 while (!eof_token(next = scan_next(list))) {
212 260 if (token_type(next) != TOKEN_IDENT || expand_one_symbol(list))
213 261 list = &next->next;
214 262 }
215 263 }
216 264
217 265 static void preprocessor_line(struct stream *stream, struct token **line);
218 266
219 267 static struct token *collect_arg(struct token *prev, int vararg, struct position *pos, int count)
220 268 {
221 269 struct stream *stream = input_streams + prev->pos.stream;
222 270 struct token **p = &prev->next;
223 271 struct token *next;
224 272 int nesting = 0;
225 273
226 274 while (!eof_token(next = scan_next(p))) {
227 275 if (next->pos.newline && match_op(next, '#')) {
228 276 if (!next->pos.noexpand) {
229 277 sparse_error(next->pos,
230 278 "directive in argument list");
231 279 preprocessor_line(stream, p);
232 280 __free_token(next); /* Free the '#' token */
233 281 continue;
234 282 }
235 283 }
236 284 switch (token_type(next)) {
237 285 case TOKEN_STREAMEND:
238 286 case TOKEN_STREAMBEGIN:
239 287 *p = &eof_token_entry;
240 288 return next;
241 289 case TOKEN_STRING:
242 290 case TOKEN_WIDE_STRING:
243 291 if (count > 1)
244 292 next->string->immutable = 1;
245 293 break;
246 294 }
247 295 if (false_nesting) {
248 296 *p = next->next;
249 297 __free_token(next);
250 298 continue;
251 299 }
252 300 if (match_op(next, '(')) {
253 301 nesting++;
254 302 } else if (match_op(next, ')')) {
255 303 if (!nesting--)
256 304 break;
257 305 } else if (match_op(next, ',') && !nesting && !vararg) {
258 306 break;
259 307 }
260 308 next->pos.stream = pos->stream;
261 309 next->pos.line = pos->line;
262 310 next->pos.pos = pos->pos;
263 311 p = &next->next;
264 312 }
265 313 *p = &eof_token_entry;
266 314 return next;
267 315 }
268 316
269 317 /*
270 318 * We store arglist as <counter> [arg1] <number of uses for arg1> ... eof
271 319 */
272 320
273 321 struct arg {
274 322 struct token *arg;
275 323 struct token *expanded;
276 324 struct token *str;
277 325 int n_normal;
278 326 int n_quoted;
279 327 int n_str;
280 328 };
281 329
282 330 static int collect_arguments(struct token *start, struct token *arglist, struct arg *args, struct token *what)
283 331 {
284 332 int wanted = arglist->count.normal;
285 333 struct token *next = NULL;
286 334 int count = 0;
287 335
288 336 arglist = arglist->next; /* skip counter */
289 337
290 338 if (!wanted) {
291 339 next = collect_arg(start, 0, &what->pos, 0);
292 340 if (eof_token(next))
293 341 goto Eclosing;
294 342 if (!eof_token(start->next) || !match_op(next, ')')) {
295 343 count++;
296 344 goto Emany;
297 345 }
298 346 } else {
299 347 for (count = 0; count < wanted; count++) {
300 348 struct argcount *p = &arglist->next->count;
301 349 next = collect_arg(start, p->vararg, &what->pos, p->normal);
302 350 if (eof_token(next))
303 351 goto Eclosing;
304 352 if (p->vararg && wanted == 1 && eof_token(start->next))
305 353 break;
306 354 arglist = arglist->next->next;
307 355 args[count].arg = start->next;
308 356 args[count].n_normal = p->normal;
309 357 args[count].n_quoted = p->quoted;
310 358 args[count].n_str = p->str;
311 359 if (match_op(next, ')')) {
312 360 count++;
313 361 break;
314 362 }
315 363 start = next;
316 364 }
317 365 if (count == wanted && !match_op(next, ')'))
318 366 goto Emany;
319 367 if (count == wanted - 1) {
320 368 struct argcount *p = &arglist->next->count;
321 369 if (!p->vararg)
322 370 goto Efew;
323 371 args[count].arg = NULL;
324 372 args[count].n_normal = p->normal;
325 373 args[count].n_quoted = p->quoted;
326 374 args[count].n_str = p->str;
327 375 }
328 376 if (count < wanted - 1)
329 377 goto Efew;
330 378 }
331 379 what->next = next->next;
332 380 return 1;
333 381
334 382 Efew:
335 383 sparse_error(what->pos, "macro \"%s\" requires %d arguments, but only %d given",
336 384 show_token(what), wanted, count);
337 385 goto out;
338 386 Emany:
339 387 while (match_op(next, ',')) {
340 388 next = collect_arg(next, 0, &what->pos, 0);
341 389 count++;
342 390 }
343 391 if (eof_token(next))
344 392 goto Eclosing;
345 393 sparse_error(what->pos, "macro \"%s\" passed %d arguments, but takes just %d",
346 394 show_token(what), count, wanted);
347 395 goto out;
348 396 Eclosing:
349 397 sparse_error(what->pos, "unterminated argument list invoking macro \"%s\"",
350 398 show_token(what));
351 399 out:
352 400 what->next = next->next;
353 401 return 0;
354 402 }
355 403
356 404 static struct token *dup_list(struct token *list)
357 405 {
358 406 struct token *res = NULL;
359 407 struct token **p = &res;
360 408
361 409 while (!eof_token(list)) {
362 410 struct token *newtok = __alloc_token(0);
363 411 *newtok = *list;
364 412 *p = newtok;
365 413 p = &newtok->next;
366 414 list = list->next;
367 415 }
368 416 return res;
369 417 }
370 418
371 419 static const char *show_token_sequence(struct token *token, int quote)
372 420 {
373 421 static char buffer[MAX_STRING];
374 422 char *ptr = buffer;
375 423 int whitespace = 0;
376 424
377 425 if (!token && !quote)
378 426 return "<none>";
379 427 while (!eof_token(token)) {
380 428 const char *val = quote ? quote_token(token) : show_token(token);
381 429 int len = strlen(val);
382 430
383 431 if (ptr + whitespace + len >= buffer + sizeof(buffer)) {
384 432 sparse_error(token->pos, "too long token expansion");
385 433 break;
386 434 }
387 435
388 436 if (whitespace)
389 437 *ptr++ = ' ';
390 438 memcpy(ptr, val, len);
391 439 ptr += len;
392 440 token = token->next;
393 441 whitespace = token->pos.whitespace;
394 442 }
395 443 *ptr = 0;
396 444 return buffer;
397 445 }
398 446
399 447 static struct token *stringify(struct token *arg)
400 448 {
401 449 const char *s = show_token_sequence(arg, 1);
402 450 int size = strlen(s)+1;
403 451 struct token *token = __alloc_token(0);
404 452 struct string *string = __alloc_string(size);
405 453
406 454 memcpy(string->data, s, size);
407 455 string->length = size;
408 456 token->pos = arg->pos;
409 457 token_type(token) = TOKEN_STRING;
410 458 token->string = string;
411 459 token->next = &eof_token_entry;
412 460 return token;
413 461 }
414 462
415 463 static void expand_arguments(int count, struct arg *args)
416 464 {
417 465 int i;
418 466 for (i = 0; i < count; i++) {
419 467 struct token *arg = args[i].arg;
420 468 if (!arg)
421 469 arg = &eof_token_entry;
422 470 if (args[i].n_str)
423 471 args[i].str = stringify(arg);
424 472 if (args[i].n_normal) {
425 473 if (!args[i].n_quoted) {
426 474 args[i].expanded = arg;
427 475 args[i].arg = NULL;
428 476 } else if (eof_token(arg)) {
429 477 args[i].expanded = arg;
430 478 } else {
431 479 args[i].expanded = dup_list(arg);
432 480 }
433 481 expand_list(&args[i].expanded);
434 482 }
435 483 }
436 484 }
437 485
438 486 /*
439 487 * Possibly valid combinations:
440 488 * - ident + ident -> ident
441 489 * - ident + number -> ident unless number contains '.', '+' or '-'.
442 490 * - 'L' + char constant -> wide char constant
443 491 * - 'L' + string literal -> wide string literal
444 492 * - number + number -> number
445 493 * - number + ident -> number
446 494 * - number + '.' -> number
447 495 * - number + '+' or '-' -> number, if number used to end on [eEpP].
448 496 * - '.' + number -> number, if number used to start with a digit.
449 497 * - special + special -> either special or an error.
450 498 */
451 499 static enum token_type combine(struct token *left, struct token *right, char *p)
452 500 {
453 501 int len;
454 502 enum token_type t1 = token_type(left), t2 = token_type(right);
455 503
456 504 if (t1 != TOKEN_IDENT && t1 != TOKEN_NUMBER && t1 != TOKEN_SPECIAL)
457 505 return TOKEN_ERROR;
458 506
459 507 if (t1 == TOKEN_IDENT && left->ident == &L_ident) {
460 508 if (t2 >= TOKEN_CHAR && t2 < TOKEN_WIDE_CHAR)
461 509 return t2 + TOKEN_WIDE_CHAR - TOKEN_CHAR;
462 510 if (t2 == TOKEN_STRING)
463 511 return TOKEN_WIDE_STRING;
464 512 }
465 513
466 514 if (t2 != TOKEN_IDENT && t2 != TOKEN_NUMBER && t2 != TOKEN_SPECIAL)
467 515 return TOKEN_ERROR;
468 516
469 517 strcpy(p, show_token(left));
470 518 strcat(p, show_token(right));
471 519 len = strlen(p);
472 520
473 521 if (len >= 256)
474 522 return TOKEN_ERROR;
475 523
476 524 if (t1 == TOKEN_IDENT) {
477 525 if (t2 == TOKEN_SPECIAL)
478 526 return TOKEN_ERROR;
479 527 if (t2 == TOKEN_NUMBER && strpbrk(p, "+-."))
480 528 return TOKEN_ERROR;
481 529 return TOKEN_IDENT;
482 530 }
483 531
484 532 if (t1 == TOKEN_NUMBER) {
485 533 if (t2 == TOKEN_SPECIAL) {
486 534 switch (right->special) {
487 535 case '.':
488 536 break;
489 537 case '+': case '-':
490 538 if (strchr("eEpP", p[len - 2]))
491 539 break;
492 540 default:
493 541 return TOKEN_ERROR;
494 542 }
495 543 }
496 544 return TOKEN_NUMBER;
497 545 }
498 546
499 547 if (p[0] == '.' && isdigit((unsigned char)p[1]))
500 548 return TOKEN_NUMBER;
501 549
502 550 return TOKEN_SPECIAL;
503 551 }
504 552
505 553 static int merge(struct token *left, struct token *right)
506 554 {
↓ open down ↓ |
304 lines elided |
↑ open up ↑ |
507 555 static char buffer[512];
508 556 enum token_type res = combine(left, right, buffer);
509 557 int n;
510 558
511 559 switch (res) {
512 560 case TOKEN_IDENT:
513 561 left->ident = built_in_ident(buffer);
514 562 left->pos.noexpand = 0;
515 563 return 1;
516 564
517 - case TOKEN_NUMBER: {
518 - char *number = __alloc_bytes(strlen(buffer) + 1);
519 - memcpy(number, buffer, strlen(buffer) + 1);
565 + case TOKEN_NUMBER:
520 566 token_type(left) = TOKEN_NUMBER; /* could be . + num */
521 - left->number = number;
567 + left->number = xstrdup(buffer);
522 568 return 1;
523 - }
524 569
525 570 case TOKEN_SPECIAL:
526 571 if (buffer[2] && buffer[3])
527 572 break;
528 573 for (n = SPECIAL_BASE; n < SPECIAL_ARG_SEPARATOR; n++) {
529 574 if (!memcmp(buffer, combinations[n-SPECIAL_BASE], 3)) {
530 575 left->special = n;
531 576 return 1;
532 577 }
533 578 }
534 579 break;
535 580
536 581 case TOKEN_WIDE_CHAR:
537 582 case TOKEN_WIDE_STRING:
538 583 token_type(left) = res;
539 584 left->pos.noexpand = 0;
540 585 left->string = right->string;
541 586 return 1;
542 587
543 588 case TOKEN_WIDE_CHAR_EMBEDDED_0 ... TOKEN_WIDE_CHAR_EMBEDDED_3:
544 589 token_type(left) = res;
545 590 left->pos.noexpand = 0;
546 591 memcpy(left->embedded, right->embedded, 4);
547 592 return 1;
548 593
549 594 default:
550 595 ;
551 596 }
552 597 sparse_error(left->pos, "'##' failed: concatenation is not a valid token");
553 598 return 0;
554 599 }
555 600
556 601 static struct token *dup_token(struct token *token, struct position *streampos)
557 602 {
558 603 struct token *alloc = alloc_token(streampos);
559 604 token_type(alloc) = token_type(token);
560 605 alloc->pos.newline = token->pos.newline;
561 606 alloc->pos.whitespace = token->pos.whitespace;
562 607 alloc->number = token->number;
563 608 alloc->pos.noexpand = token->pos.noexpand;
564 609 return alloc;
565 610 }
566 611
567 612 static struct token **copy(struct token **where, struct token *list, int *count)
568 613 {
569 614 int need_copy = --*count;
570 615 while (!eof_token(list)) {
571 616 struct token *token;
572 617 if (need_copy)
573 618 token = dup_token(list, &list->pos);
574 619 else
575 620 token = list;
576 621 if (token_type(token) == TOKEN_IDENT && token->ident->tainted)
577 622 token->pos.noexpand = 1;
578 623 *where = token;
579 624 where = &token->next;
580 625 list = list->next;
581 626 }
582 627 *where = &eof_token_entry;
583 628 return where;
584 629 }
585 630
586 631 static int handle_kludge(struct token **p, struct arg *args)
587 632 {
588 633 struct token *t = (*p)->next->next;
589 634 while (1) {
590 635 struct arg *v = &args[t->argnum];
591 636 if (token_type(t->next) != TOKEN_CONCAT) {
592 637 if (v->arg) {
593 638 /* ignore the first ## */
594 639 *p = (*p)->next;
595 640 return 0;
596 641 }
597 642 /* skip the entire thing */
598 643 *p = t;
599 644 return 1;
600 645 }
601 646 if (v->arg && !eof_token(v->arg))
602 647 return 0; /* no magic */
603 648 t = t->next->next;
604 649 }
605 650 }
606 651
607 652 static struct token **substitute(struct token **list, struct token *body, struct arg *args)
608 653 {
609 654 struct position *base_pos = &(*list)->pos;
610 655 int *count;
611 656 enum {Normal, Placeholder, Concat} state = Normal;
612 657
613 658 for (; !eof_token(body); body = body->next) {
614 659 struct token *added, *arg;
615 660 struct token **tail;
616 661 struct token *t;
617 662
618 663 switch (token_type(body)) {
619 664 case TOKEN_GNU_KLUDGE:
620 665 /*
621 666 * GNU kludge: if we had <comma>##<vararg>, behaviour
622 667 * depends on whether we had enough arguments to have
623 668 * a vararg. If we did, ## is just ignored. Otherwise
624 669 * both , and ## are ignored. Worse, there can be
625 670 * an arbitrary number of ##<arg> in between; if all of
626 671 * those are empty, we act as if they hadn't been there,
627 672 * otherwise we act as if the kludge didn't exist.
628 673 */
629 674 t = body;
630 675 if (handle_kludge(&body, args)) {
631 676 if (state == Concat)
632 677 state = Normal;
633 678 else
634 679 state = Placeholder;
635 680 continue;
636 681 }
637 682 added = dup_token(t, base_pos);
638 683 token_type(added) = TOKEN_SPECIAL;
639 684 tail = &added->next;
640 685 break;
641 686
642 687 case TOKEN_STR_ARGUMENT:
643 688 arg = args[body->argnum].str;
644 689 count = &args[body->argnum].n_str;
645 690 goto copy_arg;
646 691
647 692 case TOKEN_QUOTED_ARGUMENT:
648 693 arg = args[body->argnum].arg;
649 694 count = &args[body->argnum].n_quoted;
650 695 if (!arg || eof_token(arg)) {
651 696 if (state == Concat)
652 697 state = Normal;
653 698 else
654 699 state = Placeholder;
655 700 continue;
656 701 }
657 702 goto copy_arg;
658 703
659 704 case TOKEN_MACRO_ARGUMENT:
660 705 arg = args[body->argnum].expanded;
661 706 count = &args[body->argnum].n_normal;
662 707 if (eof_token(arg)) {
663 708 state = Normal;
664 709 continue;
665 710 }
666 711 copy_arg:
667 712 tail = copy(&added, arg, count);
668 713 added->pos.newline = body->pos.newline;
669 714 added->pos.whitespace = body->pos.whitespace;
670 715 break;
671 716
672 717 case TOKEN_CONCAT:
673 718 if (state == Placeholder)
674 719 state = Normal;
675 720 else
676 721 state = Concat;
677 722 continue;
678 723
679 724 case TOKEN_IDENT:
680 725 added = dup_token(body, base_pos);
681 726 if (added->ident->tainted)
682 727 added->pos.noexpand = 1;
683 728 tail = &added->next;
684 729 break;
685 730
686 731 default:
687 732 added = dup_token(body, base_pos);
688 733 tail = &added->next;
689 734 break;
690 735 }
691 736
692 737 /*
693 738 * if we got to doing real concatenation, we already have
694 739 * added something into the list, so containing_token() is OK.
695 740 */
696 741 if (state == Concat && merge(containing_token(list), added)) {
697 742 *list = added->next;
698 743 if (tail != &added->next)
699 744 list = tail;
700 745 } else {
701 746 *list = added;
702 747 list = tail;
703 748 }
704 749 state = Normal;
705 750 }
706 751 *list = &eof_token_entry;
707 752 return list;
708 753 }
709 754
710 755 static int expand(struct token **list, struct symbol *sym)
711 756 {
712 757 struct token *last;
713 758 struct token *token = *list;
714 759 struct ident *expanding = token->ident;
715 760 struct token **tail;
716 761 int nargs = sym->arglist ? sym->arglist->count.normal : 0;
717 762 struct arg args[nargs];
718 763
719 764 if (expanding->tainted) {
720 765 token->pos.noexpand = 1;
721 766 return 1;
722 767 }
723 768
724 769 if (sym->arglist) {
725 770 if (!match_op(scan_next(&token->next), '('))
726 771 return 1;
727 772 if (!collect_arguments(token->next, sym->arglist, args, token))
728 773 return 1;
729 774 expand_arguments(nargs, args);
730 775 }
731 776
732 777 expanding->tainted = 1;
733 778
734 779 last = token->next;
735 780 tail = substitute(list, sym->expansion, args);
736 781 /*
737 782 * Note that it won't be eof - at least TOKEN_UNTAINT will be there.
738 783 * We still can lose the newline flag if the sucker expands to nothing,
739 784 * but the price of dealing with that is probably too high (we'd need
740 785 * to collect the flags during scan_next())
741 786 */
742 787 (*list)->pos.newline = token->pos.newline;
743 788 (*list)->pos.whitespace = token->pos.whitespace;
744 789 *tail = last;
745 790
746 791 return 0;
747 792 }
748 793
749 794 static const char *token_name_sequence(struct token *token, int endop, struct token *start)
750 795 {
751 796 static char buffer[256];
752 797 char *ptr = buffer;
753 798
754 799 while (!eof_token(token) && !match_op(token, endop)) {
755 800 int len;
756 801 const char *val = token->string->data;
757 802 if (token_type(token) != TOKEN_STRING)
758 803 val = show_token(token);
759 804 len = strlen(val);
760 805 memcpy(ptr, val, len);
761 806 ptr += len;
762 807 token = token->next;
763 808 }
764 809 *ptr = 0;
765 810 if (endop && !match_op(token, endop))
766 811 sparse_error(start->pos, "expected '>' at end of filename");
767 812 return buffer;
768 813 }
769 814
770 815 static int already_tokenized(const char *path)
771 816 {
772 817 int stream, next;
773 818
774 819 for (stream = *hash_stream(path); stream >= 0 ; stream = next) {
775 820 struct stream *s = input_streams + stream;
776 821
777 822 next = s->next_stream;
778 823 if (s->once) {
779 824 if (strcmp(path, s->name))
780 825 continue;
781 826 return 1;
782 827 }
783 828 if (s->constant != CONSTANT_FILE_YES)
784 829 continue;
785 830 if (strcmp(path, s->name))
786 831 continue;
787 832 if (s->protect && !lookup_macro(s->protect))
788 833 continue;
789 834 return 1;
790 835 }
791 836 return 0;
792 837 }
793 838
794 839 /* Handle include of header files.
795 840 * The relevant options are made compatible with gcc. The only options that
796 841 * are not supported is -withprefix and friends.
797 842 *
798 843 * Three set of include paths are known:
799 844 * quote_includepath: Path to search when using #include "file.h"
800 845 * angle_includepath: Paths to search when using #include <file.h>
801 846 * isys_includepath: Paths specified with -isystem, come before the
802 847 * built-in system include paths. Gcc would suppress
803 848 * warnings from system headers. Here we separate
804 849 * them from the angle_ ones to keep search ordering.
805 850 *
806 851 * sys_includepath: Built-in include paths.
807 852 * dirafter_includepath Paths added with -dirafter.
808 853 *
809 854 * The above is implemented as one array with pointers
810 855 * +--------------+
811 856 * quote_includepath ---> | |
812 857 * +--------------+
813 858 * | |
814 859 * +--------------+
815 860 * angle_includepath ---> | |
816 861 * +--------------+
817 862 * isys_includepath ---> | |
818 863 * +--------------+
819 864 * sys_includepath ---> | |
820 865 * +--------------+
821 866 * dirafter_includepath -> | |
822 867 * +--------------+
823 868 *
824 869 * -I dir insert dir just before isys_includepath and move the rest
825 870 * -I- makes all dirs specified with -I before to quote dirs only and
826 871 * angle_includepath is set equal to isys_includepath.
827 872 * -nostdinc removes all sys dirs by storing NULL in entry pointed
828 873 * to by * sys_includepath. Note that this will reset all dirs built-in
829 874 * and added before -nostdinc by -isystem and -idirafter.
830 875 * -isystem dir adds dir where isys_includepath points adding this dir as
831 876 * first systemdir
832 877 * -idirafter dir adds dir to the end of the list
833 878 */
834 879
835 880 static void set_stream_include_path(struct stream *stream)
836 881 {
837 882 const char *path = stream->path;
838 883 if (!path) {
839 884 const char *p = strrchr(stream->name, '/');
840 885 path = "";
841 886 if (p) {
842 887 int len = p - stream->name + 1;
843 888 char *m = malloc(len+1);
↓ open down ↓ |
310 lines elided |
↑ open up ↑ |
844 889 /* This includes the final "/" */
845 890 memcpy(m, stream->name, len);
846 891 m[len] = 0;
847 892 path = m;
848 893 }
849 894 stream->path = path;
850 895 }
851 896 includepath[0] = path;
852 897 }
853 898
899 +#ifndef PATH_MAX
900 +#define PATH_MAX 4096 // for Hurd where it's not defined
901 +#endif
902 +
854 903 static int try_include(const char *path, const char *filename, int flen, struct token **where, const char **next_path)
855 904 {
856 905 int fd;
857 906 int plen = strlen(path);
858 907 static char fullname[PATH_MAX];
859 908
860 909 memcpy(fullname, path, plen);
861 910 if (plen && path[plen-1] != '/') {
862 911 fullname[plen] = '/';
863 912 plen++;
864 913 }
865 914 memcpy(fullname+plen, filename, flen);
866 915 if (already_tokenized(fullname))
867 916 return 1;
868 917 fd = open(fullname, O_RDONLY);
869 918 if (fd >= 0) {
870 - char * streamname = __alloc_bytes(plen + flen);
871 - memcpy(streamname, fullname, plen + flen);
919 + char *streamname = xmemdup(fullname, plen + flen);
872 920 *where = tokenize(streamname, fd, *where, next_path);
873 921 close(fd);
874 922 return 1;
875 923 }
876 924 return 0;
877 925 }
878 926
879 927 static int do_include_path(const char **pptr, struct token **list, struct token *token, const char *filename, int flen)
880 928 {
881 929 const char *path;
882 930
883 931 while ((path = *pptr++) != NULL) {
884 932 if (!try_include(path, filename, flen, list, pptr))
885 933 continue;
886 934 return 1;
887 935 }
888 936 return 0;
889 937 }
890 938
891 939 static int free_preprocessor_line(struct token *token)
892 940 {
893 941 while (token_type(token) != TOKEN_EOF) {
894 942 struct token *free = token;
895 943 token = token->next;
896 944 __free_token(free);
897 945 };
898 946 return 1;
899 947 }
900 948
901 949 const char *find_include(const char *skip, const char *look_for)
902 950 {
903 951 DIR *dp;
904 952 struct dirent *entry;
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
905 953 struct stat statbuf;
906 954 const char *ret;
907 955 char cwd[PATH_MAX];
908 956 static char buf[PATH_MAX + 1];
909 957
910 958 dp = opendir(".");
911 959 if (!dp)
912 960 return NULL;
913 961
914 962 if (!getcwd(cwd, sizeof(cwd)))
915 - return NULL;
963 + goto close;
916 964
917 965 while ((entry = readdir(dp))) {
918 966 lstat(entry->d_name, &statbuf);
919 967
920 968 if (strcmp(entry->d_name, look_for) == 0) {
921 969 snprintf(buf, sizeof(buf), "%s/%s", cwd, entry->d_name);
970 + closedir(dp);
922 971 return buf;
923 972 }
924 973
925 974 if (S_ISDIR(statbuf.st_mode)) {
926 975 /* Found a directory, but ignore . and .. */
927 976 if (strcmp(".", entry->d_name) == 0 ||
928 977 strcmp("..", entry->d_name) == 0 ||
929 978 strcmp(skip, entry->d_name) == 0)
930 979 continue;
931 980
932 981 chdir(entry->d_name);
933 982 ret = find_include("", look_for);
934 983 chdir("..");
935 - if (ret)
984 + if (ret) {
985 + closedir(dp);
936 986 return ret;
987 + }
937 988 }
938 989 }
990 +close:
939 991 closedir(dp);
940 992
941 993 return NULL;
942 994 }
943 995
944 996 const char *search_dir(const char *stop, const char *look_for)
945 997 {
946 998 char cwd[PATH_MAX];
947 999 int len;
948 1000 const char *ret;
949 1001 int cnt = 0;
950 1002
951 1003 if (!getcwd(cwd, sizeof(cwd)))
952 1004 return NULL;
953 1005
954 1006 len = strlen(cwd);
955 1007 while (len >= 0) {
956 1008 ret = find_include(cnt++ ? cwd + len + 1 : "", look_for);
957 1009 if (ret)
958 1010 return ret;
959 1011
960 1012 if (strcmp(cwd, stop) == 0 ||
961 1013 strcmp(cwd, "/usr/include") == 0 ||
962 1014 strcmp(cwd, "/usr/local/include") == 0 ||
963 1015 strlen(cwd) <= 10 || /* heck... don't search /usr/lib/ */
964 1016 strcmp(cwd, "/") == 0)
965 1017 return NULL;
966 1018
967 1019 while (--len >= 0) {
968 1020 if (cwd[len] == '/') {
969 1021 cwd[len] = '\0';
970 1022 break;
971 1023 }
972 1024 }
973 1025
974 1026 chdir("..");
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
975 1027 }
976 1028 return NULL;
977 1029 }
978 1030
979 1031 static void use_best_guess_header_file(struct token *token, const char *filename, struct token **list)
980 1032 {
981 1033 char cwd[PATH_MAX];
982 1034 char dir_part[PATH_MAX];
983 1035 const char *file_part;
984 1036 const char *include_name;
1037 + static int cnt;
985 1038 int len;
986 1039
1040 + /* Avoid guessing includes recursively. */
1041 + if (cnt++ > 1000)
1042 + return;
1043 +
987 1044 if (!filename || filename[0] == '\0')
988 1045 return;
989 1046
990 1047 file_part = filename;
991 1048 while ((filename = strchr(filename, '/'))) {
992 1049 ++filename;
993 1050 if (filename[0])
994 1051 file_part = filename;
995 1052 }
996 1053
997 1054 snprintf(dir_part, sizeof(dir_part), "%s", stream_name(token->pos.stream));
998 1055 len = strlen(dir_part);
999 1056 while (--len >= 0) {
1000 1057 if (dir_part[len] == '/') {
1001 1058 dir_part[len] = '\0';
1002 1059 break;
1003 1060 }
1004 1061 }
1005 1062 if (len < 0)
1006 1063 sprintf(dir_part, ".");
1007 1064
1008 1065 if (!getcwd(cwd, sizeof(cwd)))
1009 1066 return;
1010 1067
1011 1068 chdir(dir_part);
1012 1069 include_name = search_dir(cwd, file_part);
1013 1070 chdir(cwd);
1014 1071 if (!include_name)
1015 1072 return;
1016 1073 sparse_error(token->pos, "using '%s'", include_name);
1017 1074
1018 1075 try_include("", include_name, strlen(include_name), list, includepath);
1019 1076 }
1020 1077
1021 1078 static int handle_include_path(struct stream *stream, struct token **list, struct token *token, int how)
1022 1079 {
1023 1080 const char *filename;
1024 1081 struct token *next;
1025 1082 const char **path;
1026 1083 int expect;
1027 1084 int flen;
1028 1085
1029 1086 next = token->next;
1030 1087 expect = '>';
1031 1088 if (!match_op(next, '<')) {
1032 1089 expand_list(&token->next);
1033 1090 expect = 0;
1034 1091 next = token;
1035 1092 if (match_op(token->next, '<')) {
1036 1093 next = token->next;
1037 1094 expect = '>';
1038 1095 }
1039 1096 }
1040 1097
1041 1098 token = next->next;
1042 1099 filename = token_name_sequence(token, expect, token);
1043 1100 flen = strlen(filename) + 1;
1044 1101
1045 1102 /* Absolute path? */
1046 1103 if (filename[0] == '/') {
1047 1104 if (try_include("", filename, flen, list, includepath))
1048 1105 return 0;
1049 1106 goto out;
1050 1107 }
1051 1108
1052 1109 switch (how) {
1053 1110 case 1:
1054 1111 path = stream->next_path;
1055 1112 break;
1056 1113 case 2:
1057 1114 includepath[0] = "";
1058 1115 path = includepath;
1059 1116 break;
1060 1117 default:
1061 1118 /* Dir of input file is first dir to search for quoted includes */
1062 1119 set_stream_include_path(stream);
1063 1120 path = expect ? angle_includepath : quote_includepath;
1064 1121 break;
1065 1122 }
1066 1123 /* Check the standard include paths.. */
1067 1124 if (do_include_path(path, list, token, filename, flen))
1068 1125 return 0;
1069 1126 out:
1070 1127 sparse_error(token->pos, "unable to open '%s'", filename);
1071 1128 use_best_guess_header_file(token, filename, list);
1072 1129 return 0;
1073 1130 }
1074 1131
1075 1132 static int handle_include(struct stream *stream, struct token **list, struct token *token)
1076 1133 {
1077 1134 return handle_include_path(stream, list, token, 0);
1078 1135 }
1079 1136
1080 1137 static int handle_include_next(struct stream *stream, struct token **list, struct token *token)
1081 1138 {
1082 1139 return handle_include_path(stream, list, token, 1);
1083 1140 }
1084 1141
1085 1142 static int handle_argv_include(struct stream *stream, struct token **list, struct token *token)
1086 1143 {
1087 1144 return handle_include_path(stream, list, token, 2);
1088 1145 }
1089 1146
1090 1147 static int token_different(struct token *t1, struct token *t2)
1091 1148 {
1092 1149 int different;
1093 1150
1094 1151 if (token_type(t1) != token_type(t2))
1095 1152 return 1;
1096 1153
1097 1154 switch (token_type(t1)) {
1098 1155 case TOKEN_IDENT:
1099 1156 different = t1->ident != t2->ident;
1100 1157 break;
1101 1158 case TOKEN_ARG_COUNT:
1102 1159 case TOKEN_UNTAINT:
1103 1160 case TOKEN_CONCAT:
1104 1161 case TOKEN_GNU_KLUDGE:
1105 1162 different = 0;
1106 1163 break;
1107 1164 case TOKEN_NUMBER:
1108 1165 different = strcmp(t1->number, t2->number);
1109 1166 break;
1110 1167 case TOKEN_SPECIAL:
1111 1168 different = t1->special != t2->special;
1112 1169 break;
1113 1170 case TOKEN_MACRO_ARGUMENT:
1114 1171 case TOKEN_QUOTED_ARGUMENT:
1115 1172 case TOKEN_STR_ARGUMENT:
1116 1173 different = t1->argnum != t2->argnum;
1117 1174 break;
1118 1175 case TOKEN_CHAR_EMBEDDED_0 ... TOKEN_CHAR_EMBEDDED_3:
1119 1176 case TOKEN_WIDE_CHAR_EMBEDDED_0 ... TOKEN_WIDE_CHAR_EMBEDDED_3:
1120 1177 different = memcmp(t1->embedded, t2->embedded, 4);
1121 1178 break;
1122 1179 case TOKEN_CHAR:
1123 1180 case TOKEN_WIDE_CHAR:
1124 1181 case TOKEN_STRING:
1125 1182 case TOKEN_WIDE_STRING: {
1126 1183 struct string *s1, *s2;
1127 1184
1128 1185 s1 = t1->string;
1129 1186 s2 = t2->string;
1130 1187 different = 1;
1131 1188 if (s1->length != s2->length)
1132 1189 break;
1133 1190 different = memcmp(s1->data, s2->data, s1->length);
1134 1191 break;
1135 1192 }
1136 1193 default:
1137 1194 different = 1;
1138 1195 break;
1139 1196 }
1140 1197 return different;
1141 1198 }
1142 1199
1143 1200 static int token_list_different(struct token *list1, struct token *list2)
1144 1201 {
1145 1202 for (;;) {
1146 1203 if (list1 == list2)
1147 1204 return 0;
1148 1205 if (!list1 || !list2)
1149 1206 return 1;
1150 1207 if (token_different(list1, list2))
1151 1208 return 1;
1152 1209 list1 = list1->next;
1153 1210 list2 = list2->next;
1154 1211 }
1155 1212 }
1156 1213
1157 1214 static inline void set_arg_count(struct token *token)
1158 1215 {
1159 1216 token_type(token) = TOKEN_ARG_COUNT;
1160 1217 token->count.normal = token->count.quoted =
1161 1218 token->count.str = token->count.vararg = 0;
1162 1219 }
1163 1220
1164 1221 static struct token *parse_arguments(struct token *list)
1165 1222 {
1166 1223 struct token *arg = list->next, *next = list;
1167 1224 struct argcount *count = &list->count;
1168 1225
1169 1226 set_arg_count(list);
1170 1227
1171 1228 if (match_op(arg, ')')) {
1172 1229 next = arg->next;
1173 1230 list->next = &eof_token_entry;
1174 1231 return next;
1175 1232 }
1176 1233
1177 1234 while (token_type(arg) == TOKEN_IDENT) {
1178 1235 if (arg->ident == &__VA_ARGS___ident)
1179 1236 goto Eva_args;
1180 1237 if (!++count->normal)
1181 1238 goto Eargs;
1182 1239 next = arg->next;
1183 1240
1184 1241 if (match_op(next, ',')) {
1185 1242 set_arg_count(next);
1186 1243 arg = next->next;
1187 1244 continue;
1188 1245 }
1189 1246
1190 1247 if (match_op(next, ')')) {
1191 1248 set_arg_count(next);
1192 1249 next = next->next;
1193 1250 arg->next->next = &eof_token_entry;
1194 1251 return next;
1195 1252 }
1196 1253
1197 1254 /* normal cases are finished here */
1198 1255
1199 1256 if (match_op(next, SPECIAL_ELLIPSIS)) {
1200 1257 if (match_op(next->next, ')')) {
1201 1258 set_arg_count(next);
1202 1259 next->count.vararg = 1;
1203 1260 next = next->next;
1204 1261 arg->next->next = &eof_token_entry;
1205 1262 return next->next;
1206 1263 }
1207 1264
1208 1265 arg = next;
1209 1266 goto Enotclosed;
1210 1267 }
1211 1268
1212 1269 if (eof_token(next)) {
1213 1270 goto Enotclosed;
1214 1271 } else {
1215 1272 arg = next;
1216 1273 goto Ebadstuff;
1217 1274 }
1218 1275 }
1219 1276
1220 1277 if (match_op(arg, SPECIAL_ELLIPSIS)) {
1221 1278 next = arg->next;
1222 1279 token_type(arg) = TOKEN_IDENT;
1223 1280 arg->ident = &__VA_ARGS___ident;
1224 1281 if (!match_op(next, ')'))
1225 1282 goto Enotclosed;
1226 1283 if (!++count->normal)
1227 1284 goto Eargs;
1228 1285 set_arg_count(next);
1229 1286 next->count.vararg = 1;
1230 1287 next = next->next;
1231 1288 arg->next->next = &eof_token_entry;
1232 1289 return next;
1233 1290 }
1234 1291
1235 1292 if (eof_token(arg)) {
1236 1293 arg = next;
1237 1294 goto Enotclosed;
1238 1295 }
1239 1296 if (match_op(arg, ','))
1240 1297 goto Emissing;
1241 1298 else
1242 1299 goto Ebadstuff;
1243 1300
1244 1301
1245 1302 Emissing:
1246 1303 sparse_error(arg->pos, "parameter name missing");
1247 1304 return NULL;
1248 1305 Ebadstuff:
1249 1306 sparse_error(arg->pos, "\"%s\" may not appear in macro parameter list",
1250 1307 show_token(arg));
1251 1308 return NULL;
1252 1309 Enotclosed:
1253 1310 sparse_error(arg->pos, "missing ')' in macro parameter list");
1254 1311 return NULL;
1255 1312 Eva_args:
1256 1313 sparse_error(arg->pos, "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro");
1257 1314 return NULL;
1258 1315 Eargs:
1259 1316 sparse_error(arg->pos, "too many arguments in macro definition");
1260 1317 return NULL;
1261 1318 }
1262 1319
1263 1320 static int try_arg(struct token *token, enum token_type type, struct token *arglist)
1264 1321 {
1265 1322 struct ident *ident = token->ident;
1266 1323 int nr;
1267 1324
1268 1325 if (!arglist || token_type(token) != TOKEN_IDENT)
1269 1326 return 0;
1270 1327
1271 1328 arglist = arglist->next;
1272 1329
1273 1330 for (nr = 0; !eof_token(arglist); nr++, arglist = arglist->next->next) {
1274 1331 if (arglist->ident == ident) {
1275 1332 struct argcount *count = &arglist->next->count;
1276 1333 int n;
1277 1334
1278 1335 token->argnum = nr;
1279 1336 token_type(token) = type;
1280 1337 switch (type) {
1281 1338 case TOKEN_MACRO_ARGUMENT:
1282 1339 n = ++count->normal;
1283 1340 break;
1284 1341 case TOKEN_QUOTED_ARGUMENT:
1285 1342 n = ++count->quoted;
1286 1343 break;
1287 1344 default:
1288 1345 n = ++count->str;
1289 1346 }
1290 1347 if (n)
1291 1348 return count->vararg ? 2 : 1;
1292 1349 /*
1293 1350 * XXX - need saner handling of that
1294 1351 * (>= 1024 instances of argument)
1295 1352 */
1296 1353 token_type(token) = TOKEN_ERROR;
1297 1354 return -1;
1298 1355 }
1299 1356 }
1300 1357 return 0;
1301 1358 }
1302 1359
1303 1360 static struct token *handle_hash(struct token **p, struct token *arglist)
1304 1361 {
1305 1362 struct token *token = *p;
1306 1363 if (arglist) {
1307 1364 struct token *next = token->next;
1308 1365 if (!try_arg(next, TOKEN_STR_ARGUMENT, arglist))
1309 1366 goto Equote;
1310 1367 next->pos.whitespace = token->pos.whitespace;
1311 1368 __free_token(token);
1312 1369 token = *p = next;
1313 1370 } else {
1314 1371 token->pos.noexpand = 1;
1315 1372 }
1316 1373 return token;
1317 1374
1318 1375 Equote:
1319 1376 sparse_error(token->pos, "'#' is not followed by a macro parameter");
1320 1377 return NULL;
1321 1378 }
1322 1379
1323 1380 /* token->next is ## */
1324 1381 static struct token *handle_hashhash(struct token *token, struct token *arglist)
1325 1382 {
1326 1383 struct token *last = token;
1327 1384 struct token *concat;
1328 1385 int state = match_op(token, ',');
1329 1386
1330 1387 try_arg(token, TOKEN_QUOTED_ARGUMENT, arglist);
1331 1388
1332 1389 while (1) {
1333 1390 struct token *t;
1334 1391 int is_arg;
1335 1392
1336 1393 /* eat duplicate ## */
1337 1394 concat = token->next;
1338 1395 while (match_op(t = concat->next, SPECIAL_HASHHASH)) {
1339 1396 token->next = t;
1340 1397 __free_token(concat);
1341 1398 concat = t;
1342 1399 }
1343 1400 token_type(concat) = TOKEN_CONCAT;
1344 1401
1345 1402 if (eof_token(t))
1346 1403 goto Econcat;
1347 1404
1348 1405 if (match_op(t, '#')) {
1349 1406 t = handle_hash(&concat->next, arglist);
1350 1407 if (!t)
1351 1408 return NULL;
1352 1409 }
1353 1410
1354 1411 is_arg = try_arg(t, TOKEN_QUOTED_ARGUMENT, arglist);
1355 1412
1356 1413 if (state == 1 && is_arg) {
1357 1414 state = is_arg;
1358 1415 } else {
1359 1416 last = t;
1360 1417 state = match_op(t, ',');
1361 1418 }
1362 1419
1363 1420 token = t;
1364 1421 if (!match_op(token->next, SPECIAL_HASHHASH))
1365 1422 break;
1366 1423 }
1367 1424 /* handle GNU ,##__VA_ARGS__ kludge, in all its weirdness */
1368 1425 if (state == 2)
1369 1426 token_type(last) = TOKEN_GNU_KLUDGE;
1370 1427 return token;
1371 1428
1372 1429 Econcat:
1373 1430 sparse_error(concat->pos, "'##' cannot appear at the ends of macro expansion");
1374 1431 return NULL;
1375 1432 }
1376 1433
1377 1434 static struct token *parse_expansion(struct token *expansion, struct token *arglist, struct ident *name)
1378 1435 {
1379 1436 struct token *token = expansion;
1380 1437 struct token **p;
1381 1438
1382 1439 if (match_op(token, SPECIAL_HASHHASH))
1383 1440 goto Econcat;
1384 1441
1385 1442 for (p = &expansion; !eof_token(token); p = &token->next, token = *p) {
1386 1443 if (match_op(token, '#')) {
1387 1444 token = handle_hash(p, arglist);
1388 1445 if (!token)
1389 1446 return NULL;
1390 1447 }
1391 1448 if (match_op(token->next, SPECIAL_HASHHASH)) {
1392 1449 token = handle_hashhash(token, arglist);
1393 1450 if (!token)
1394 1451 return NULL;
1395 1452 } else {
1396 1453 try_arg(token, TOKEN_MACRO_ARGUMENT, arglist);
1397 1454 }
1398 1455 switch (token_type(token)) {
1399 1456 case TOKEN_ERROR:
1400 1457 goto Earg;
1401 1458
1402 1459 case TOKEN_STRING:
1403 1460 case TOKEN_WIDE_STRING:
1404 1461 token->string->immutable = 1;
1405 1462 break;
1406 1463 }
1407 1464 }
1408 1465 token = alloc_token(&expansion->pos);
1409 1466 token_type(token) = TOKEN_UNTAINT;
1410 1467 token->ident = name;
1411 1468 token->next = *p;
1412 1469 *p = token;
↓ open down ↓ |
416 lines elided |
↑ open up ↑ |
1413 1470 return expansion;
1414 1471
1415 1472 Econcat:
1416 1473 sparse_error(token->pos, "'##' cannot appear at the ends of macro expansion");
1417 1474 return NULL;
1418 1475 Earg:
1419 1476 sparse_error(token->pos, "too many instances of argument in body");
1420 1477 return NULL;
1421 1478 }
1422 1479
1423 -static int do_handle_define(struct stream *stream, struct token **line, struct token *token, int attr)
1480 +static int do_define(struct position pos, struct token *token, struct ident *name,
1481 + struct token *arglist, struct token *expansion, int attr)
1424 1482 {
1425 - struct token *arglist, *expansion;
1426 - struct token *left = token->next;
1427 1483 struct symbol *sym;
1428 - struct ident *name;
1429 - int ret;
1484 + int ret = 1;
1430 1485
1431 - if (token_type(left) != TOKEN_IDENT) {
1432 - sparse_error(token->pos, "expected identifier to 'define'");
1433 - return 1;
1434 - }
1435 -
1436 - name = left->ident;
1437 -
1438 - arglist = NULL;
1439 - expansion = left->next;
1440 - if (!expansion->pos.whitespace) {
1441 - if (match_op(expansion, '(')) {
1442 - arglist = expansion;
1443 - expansion = parse_arguments(expansion);
1444 - if (!expansion)
1445 - return 1;
1446 - } else if (!eof_token(expansion)) {
1447 - warning(expansion->pos,
1448 - "no whitespace before object-like macro body");
1449 - }
1450 - }
1451 -
1452 1486 expansion = parse_expansion(expansion, arglist, name);
1453 1487 if (!expansion)
1454 1488 return 1;
1455 1489
1456 - ret = 1;
1457 1490 sym = lookup_symbol(name, NS_MACRO | NS_UNDEF);
1458 1491 if (sym) {
1459 1492 int clean;
1460 1493
1461 1494 if (attr < sym->attr)
1462 1495 goto out;
1463 1496
1464 1497 clean = (attr == sym->attr && sym->namespace == NS_MACRO);
1465 1498
1466 1499 if (token_list_different(sym->expansion, expansion) ||
1467 1500 token_list_different(sym->arglist, arglist)) {
1468 1501 ret = 0;
1469 1502 if ((clean && attr == SYM_ATTR_NORMAL)
1470 1503 || sym->used_in == file_scope) {
1471 - warning(left->pos, "preprocessor token %.*s redefined",
1504 + warning(pos, "preprocessor token %.*s redefined",
1472 1505 name->len, name->name);
1473 1506 info(sym->pos, "this was the original definition");
1474 1507 }
1475 1508 } else if (clean)
1476 1509 goto out;
1477 1510 }
1478 1511
1479 1512 if (!sym || sym->scope != file_scope) {
1480 - sym = alloc_symbol(left->pos, SYM_NODE);
1513 + sym = alloc_symbol(pos, SYM_NODE);
1481 1514 bind_symbol(sym, name, NS_MACRO);
1482 1515 add_ident(¯os, name);
1483 1516 ret = 0;
1484 1517 }
1485 1518
1486 1519 if (!ret) {
1487 1520 sym->expansion = expansion;
1488 1521 sym->arglist = arglist;
1489 - __free_token(token); /* Free the "define" token, but not the rest of the line */
1522 + if (token) /* Free the "define" token, but not the rest of the line */
1523 + __free_token(token);
1490 1524 }
1491 1525
1492 1526 sym->namespace = NS_MACRO;
1493 1527 sym->used_in = NULL;
1494 1528 sym->attr = attr;
1495 1529 out:
1496 1530 return ret;
1497 1531 }
1498 1532
1533 +///
1534 +// predefine a macro with a printf-formatted value
1535 +// @name: the name of the macro
1536 +// @weak: 0/1 for a normal or a weak define
1537 +// @fmt: the printf format followed by it's arguments.
1538 +//
1539 +// The type of the value is automatically infered:
1540 +// TOKEN_NUMBER if it starts by a digit, TOKEN_IDENT otherwise.
1541 +// If @fmt is null or empty, the macro is defined with an empty definition.
1542 +void predefine(const char *name, int weak, const char *fmt, ...)
1543 +{
1544 + struct ident *ident = built_in_ident(name);
1545 + struct token *value = &eof_token_entry;
1546 + int attr = weak ? SYM_ATTR_WEAK : SYM_ATTR_NORMAL;
1547 +
1548 + if (fmt && fmt[0]) {
1549 + static char buf[256];
1550 + va_list ap;
1551 +
1552 + va_start(ap, fmt);
1553 + vsnprintf(buf, sizeof(buf), fmt, ap);
1554 + va_end(ap);
1555 +
1556 + value = __alloc_token(0);
1557 + if (isdigit(buf[0])) {
1558 + token_type(value) = TOKEN_NUMBER;
1559 + value->number = xstrdup(buf);
1560 + } else {
1561 + token_type(value) = TOKEN_IDENT;
1562 + value->ident = built_in_ident(buf);
1563 + }
1564 + value->pos.whitespace = 1;
1565 + value->next = &eof_token_entry;
1566 + }
1567 +
1568 + do_define(value->pos, NULL, ident, NULL, value, attr);
1569 +}
1570 +
1571 +static int do_handle_define(struct stream *stream, struct token **line, struct token *token, int attr)
1572 +{
1573 + struct token *arglist, *expansion;
1574 + struct token *left = token->next;
1575 + struct ident *name;
1576 +
1577 + if (token_type(left) != TOKEN_IDENT) {
1578 + sparse_error(token->pos, "expected identifier to 'define'");
1579 + return 1;
1580 + }
1581 +
1582 + name = left->ident;
1583 +
1584 + arglist = NULL;
1585 + expansion = left->next;
1586 + if (!expansion->pos.whitespace) {
1587 + if (match_op(expansion, '(')) {
1588 + arglist = expansion;
1589 + expansion = parse_arguments(expansion);
1590 + if (!expansion)
1591 + return 1;
1592 + } else if (!eof_token(expansion)) {
1593 + warning(expansion->pos,
1594 + "no whitespace before object-like macro body");
1595 + }
1596 + }
1597 +
1598 + return do_define(left->pos, token, name, arglist, expansion, attr);
1599 +}
1600 +
1499 1601 static int handle_define(struct stream *stream, struct token **line, struct token *token)
1500 1602 {
1501 1603 return do_handle_define(stream, line, token, SYM_ATTR_NORMAL);
1502 1604 }
1503 1605
1504 1606 static int handle_weak_define(struct stream *stream, struct token **line, struct token *token)
1505 1607 {
1506 1608 return do_handle_define(stream, line, token, SYM_ATTR_WEAK);
1507 1609 }
1508 1610
1509 1611 static int handle_strong_define(struct stream *stream, struct token **line, struct token *token)
1510 1612 {
1511 1613 return do_handle_define(stream, line, token, SYM_ATTR_STRONG);
1512 1614 }
1513 1615
1514 1616 static int do_handle_undef(struct stream *stream, struct token **line, struct token *token, int attr)
1515 1617 {
1516 1618 struct token *left = token->next;
1517 1619 struct symbol *sym;
1518 1620
1519 1621 if (token_type(left) != TOKEN_IDENT) {
1520 1622 sparse_error(token->pos, "expected identifier to 'undef'");
1521 1623 return 1;
1522 1624 }
1523 1625
1524 1626 sym = lookup_symbol(left->ident, NS_MACRO | NS_UNDEF);
1525 1627 if (sym) {
1526 1628 if (attr < sym->attr)
1527 1629 return 1;
1528 1630 if (attr == sym->attr && sym->namespace == NS_UNDEF)
1529 1631 return 1;
1530 1632 } else if (attr <= SYM_ATTR_NORMAL)
1531 1633 return 1;
1532 1634
1533 1635 if (!sym || sym->scope != file_scope) {
1534 1636 sym = alloc_symbol(left->pos, SYM_NODE);
1535 1637 bind_symbol(sym, left->ident, NS_MACRO);
1536 1638 }
1537 1639
1538 1640 sym->namespace = NS_UNDEF;
1539 1641 sym->used_in = NULL;
1540 1642 sym->attr = attr;
1541 1643
1542 1644 return 1;
1543 1645 }
1544 1646
↓ open down ↓ |
36 lines elided |
↑ open up ↑ |
1545 1647 static int handle_undef(struct stream *stream, struct token **line, struct token *token)
1546 1648 {
1547 1649 return do_handle_undef(stream, line, token, SYM_ATTR_NORMAL);
1548 1650 }
1549 1651
1550 1652 static int handle_strong_undef(struct stream *stream, struct token **line, struct token *token)
1551 1653 {
1552 1654 return do_handle_undef(stream, line, token, SYM_ATTR_STRONG);
1553 1655 }
1554 1656
1555 -static int preprocessor_if(struct stream *stream, struct token *token, int true)
1657 +static int preprocessor_if(struct stream *stream, struct token *token, int cond)
1556 1658 {
1557 1659 token_type(token) = false_nesting ? TOKEN_SKIP_GROUPS : TOKEN_IF;
1558 1660 free_preprocessor_line(token->next);
1559 1661 token->next = stream->top_if;
1560 1662 stream->top_if = token;
1561 - if (false_nesting || true != 1)
1663 + if (false_nesting || cond != 1)
1562 1664 false_nesting++;
1563 1665 return 0;
1564 1666 }
1565 1667
1566 1668 static int handle_ifdef(struct stream *stream, struct token **line, struct token *token)
1567 1669 {
1568 1670 struct token *next = token->next;
1569 1671 int arg;
1570 1672 if (token_type(next) == TOKEN_IDENT) {
1571 1673 arg = token_defined(next);
1572 1674 } else {
1573 1675 dirty_stream(stream);
1574 1676 if (!false_nesting)
1575 1677 sparse_error(token->pos, "expected preprocessor identifier");
1576 1678 arg = -1;
1577 1679 }
1578 1680 return preprocessor_if(stream, token, arg);
1579 1681 }
1580 1682
1581 1683 static int handle_ifndef(struct stream *stream, struct token **line, struct token *token)
1582 1684 {
1583 1685 struct token *next = token->next;
1584 1686 int arg;
1585 1687 if (token_type(next) == TOKEN_IDENT) {
1586 1688 if (!stream->dirty && !stream->ifndef) {
1587 1689 if (!stream->protect) {
1588 1690 stream->ifndef = token;
1589 1691 stream->protect = next->ident;
1590 1692 } else if (stream->protect == next->ident) {
1591 1693 stream->ifndef = token;
1592 1694 stream->dirty = 1;
1593 1695 }
1594 1696 }
1595 1697 arg = !token_defined(next);
1596 1698 } else {
1597 1699 dirty_stream(stream);
1598 1700 if (!false_nesting)
1599 1701 sparse_error(token->pos, "expected preprocessor identifier");
1600 1702 arg = -1;
1601 1703 }
1602 1704
1603 1705 return preprocessor_if(stream, token, arg);
1604 1706 }
1605 1707
1606 1708 static const char *show_token_sequence(struct token *token, int quote);
1607 1709
1608 1710 /*
1609 1711 * Expression handling for #if and #elif; it differs from normal expansion
1610 1712 * due to special treatment of "defined".
1611 1713 */
1612 1714 static int expression_value(struct token **where)
1613 1715 {
1614 1716 struct expression *expr;
1615 1717 struct token *p;
1616 1718 struct token **list = where, **beginning = NULL;
1617 1719 long long value;
1618 1720 int state = 0;
↓ open down ↓ |
47 lines elided |
↑ open up ↑ |
1619 1721
1620 1722 while (!eof_token(p = scan_next(list))) {
1621 1723 switch (state) {
1622 1724 case 0:
1623 1725 if (token_type(p) != TOKEN_IDENT)
1624 1726 break;
1625 1727 if (p->ident == &defined_ident) {
1626 1728 state = 1;
1627 1729 beginning = list;
1628 1730 break;
1731 + } else if (p->ident == &__has_builtin_ident) {
1732 + state = 4;
1733 + beginning = list;
1734 + break;
1735 + } else if (p->ident == &__has_attribute_ident) {
1736 + state = 6;
1737 + beginning = list;
1738 + break;
1629 1739 }
1630 1740 if (!expand_one_symbol(list))
1631 1741 continue;
1632 1742 if (token_type(p) != TOKEN_IDENT)
1633 1743 break;
1634 1744 token_type(p) = TOKEN_ZERO_IDENT;
1635 1745 break;
1636 1746 case 1:
1637 1747 if (match_op(p, '(')) {
1638 1748 state = 2;
1639 1749 } else {
1640 1750 state = 0;
1641 1751 replace_with_defined(p);
1642 1752 *beginning = p;
1643 1753 }
1644 1754 break;
1645 1755 case 2:
1646 1756 if (token_type(p) == TOKEN_IDENT)
1647 1757 state = 3;
1648 1758 else
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
1649 1759 state = 0;
1650 1760 replace_with_defined(p);
1651 1761 *beginning = p;
1652 1762 break;
1653 1763 case 3:
1654 1764 state = 0;
1655 1765 if (!match_op(p, ')'))
1656 1766 sparse_error(p->pos, "missing ')' after \"defined\"");
1657 1767 *list = p->next;
1658 1768 continue;
1769 +
1770 + // __has_builtin(x) or __has_attribute(x)
1771 + case 4: case 6:
1772 + if (match_op(p, '(')) {
1773 + state++;
1774 + } else {
1775 + sparse_error(p->pos, "missing '(' after \"__has_%s\"",
1776 + state == 4 ? "builtin" : "attribute");
1777 + state = 0;
1778 + }
1779 + *beginning = p;
1780 + break;
1781 + case 5: case 7:
1782 + if (token_type(p) != TOKEN_IDENT) {
1783 + sparse_error(p->pos, "identifier expected");
1784 + state = 0;
1785 + break;
1786 + }
1787 + if (!match_op(p->next, ')'))
1788 + sparse_error(p->pos, "missing ')' after \"__has_%s\"",
1789 + state == 5 ? "builtin" : "attribute");
1790 + if (state == 5)
1791 + replace_with_has_builtin(p);
1792 + else
1793 + replace_with_has_attribute(p);
1794 + state = 8;
1795 + *beginning = p;
1796 + break;
1797 + case 8:
1798 + state = 0;
1799 + *list = p->next;
1800 + continue;
1659 1801 }
1660 1802 list = &p->next;
1661 1803 }
1662 1804
1663 1805 p = constant_expression(*where, &expr);
1664 1806 if (!eof_token(p))
1665 1807 sparse_error(p->pos, "garbage at end: %s", show_token_sequence(p, 0));
1666 1808 value = get_expression_value(expr);
1667 1809 return value != 0;
1668 1810 }
1669 1811
1670 1812 static int handle_if(struct stream *stream, struct token **line, struct token *token)
1671 1813 {
1672 1814 int value = 0;
1673 1815 if (!false_nesting)
1674 1816 value = expression_value(&token->next);
1675 1817
1676 1818 dirty_stream(stream);
1677 1819 return preprocessor_if(stream, token, value);
1678 1820 }
1679 1821
1680 1822 static int handle_elif(struct stream * stream, struct token **line, struct token *token)
1681 1823 {
1682 1824 struct token *top_if = stream->top_if;
1683 1825 end_group(stream);
1684 1826
1685 1827 if (!top_if) {
1686 1828 nesting_error(stream);
1687 1829 sparse_error(token->pos, "unmatched #elif within stream");
1688 1830 return 1;
1689 1831 }
1690 1832
1691 1833 if (token_type(top_if) == TOKEN_ELSE) {
1692 1834 nesting_error(stream);
1693 1835 sparse_error(token->pos, "#elif after #else");
1694 1836 if (!false_nesting)
1695 1837 false_nesting = 1;
1696 1838 return 1;
1697 1839 }
1698 1840
1699 1841 dirty_stream(stream);
1700 1842 if (token_type(top_if) != TOKEN_IF)
1701 1843 return 1;
1702 1844 if (false_nesting) {
1703 1845 false_nesting = 0;
1704 1846 if (!expression_value(&token->next))
1705 1847 false_nesting = 1;
1706 1848 } else {
1707 1849 false_nesting = 1;
1708 1850 token_type(top_if) = TOKEN_SKIP_GROUPS;
1709 1851 }
1710 1852 return 1;
1711 1853 }
1712 1854
1713 1855 static int handle_else(struct stream *stream, struct token **line, struct token *token)
1714 1856 {
1715 1857 struct token *top_if = stream->top_if;
1716 1858 end_group(stream);
1717 1859
1718 1860 if (!top_if) {
1719 1861 nesting_error(stream);
1720 1862 sparse_error(token->pos, "unmatched #else within stream");
1721 1863 return 1;
1722 1864 }
1723 1865
1724 1866 if (token_type(top_if) == TOKEN_ELSE) {
1725 1867 nesting_error(stream);
1726 1868 sparse_error(token->pos, "#else after #else");
1727 1869 }
1728 1870 if (false_nesting) {
1729 1871 if (token_type(top_if) == TOKEN_IF)
1730 1872 false_nesting = 0;
1731 1873 } else {
1732 1874 false_nesting = 1;
1733 1875 }
1734 1876 token_type(top_if) = TOKEN_ELSE;
1735 1877 return 1;
1736 1878 }
1737 1879
1738 1880 static int handle_endif(struct stream *stream, struct token **line, struct token *token)
1739 1881 {
1740 1882 struct token *top_if = stream->top_if;
1741 1883 end_group(stream);
1742 1884 if (!top_if) {
1743 1885 nesting_error(stream);
1744 1886 sparse_error(token->pos, "unmatched #endif in stream");
1745 1887 return 1;
1746 1888 }
1747 1889 if (false_nesting)
1748 1890 false_nesting--;
1749 1891 stream->top_if = top_if->next;
1750 1892 __free_token(top_if);
1751 1893 return 1;
1752 1894 }
1753 1895
1754 1896 static int handle_warning(struct stream *stream, struct token **line, struct token *token)
1755 1897 {
1756 1898 warning(token->pos, "%s", show_token_sequence(token->next, 0));
1757 1899 return 1;
1758 1900 }
1759 1901
1760 1902 static int handle_error(struct stream *stream, struct token **line, struct token *token)
1761 1903 {
1762 1904 sparse_error(token->pos, "%s", show_token_sequence(token->next, 0));
1763 1905 return 1;
1764 1906 }
1765 1907
1766 1908 static int handle_nostdinc(struct stream *stream, struct token **line, struct token *token)
1767 1909 {
1768 1910 /*
1769 1911 * Do we have any non-system includes?
1770 1912 * Clear them out if so..
1771 1913 */
1772 1914 *sys_includepath = NULL;
1773 1915 return 1;
1774 1916 }
1775 1917
1776 1918 static inline void update_inc_ptrs(const char ***where)
1777 1919 {
1778 1920
1779 1921 if (*where <= dirafter_includepath) {
1780 1922 dirafter_includepath++;
1781 1923 /* If this was the entry that we prepend, don't
1782 1924 * rise the lower entries, even if they are at
1783 1925 * the same level. */
1784 1926 if (where == &dirafter_includepath)
1785 1927 return;
1786 1928 }
1787 1929 if (*where <= sys_includepath) {
1788 1930 sys_includepath++;
1789 1931 if (where == &sys_includepath)
1790 1932 return;
1791 1933 }
1792 1934 if (*where <= isys_includepath) {
1793 1935 isys_includepath++;
1794 1936 if (where == &isys_includepath)
1795 1937 return;
1796 1938 }
1797 1939
1798 1940 /* angle_includepath is actually never updated, since we
1799 1941 * don't suppport -iquote rught now. May change some day. */
1800 1942 if (*where <= angle_includepath) {
1801 1943 angle_includepath++;
1802 1944 if (where == &angle_includepath)
1803 1945 return;
1804 1946 }
1805 1947 }
1806 1948
1807 1949 /* Add a path before 'where' and update the pointers associated with the
1808 1950 * includepath array */
1809 1951 static void add_path_entry(struct token *token, const char *path,
1810 1952 const char ***where)
1811 1953 {
1812 1954 const char **dst;
1813 1955 const char *next;
1814 1956
1815 1957 /* Need one free entry.. */
1816 1958 if (includepath[INCLUDEPATHS-2])
1817 1959 error_die(token->pos, "too many include path entries");
1818 1960
1819 1961 /* check that this is not a duplicate */
1820 1962 dst = includepath;
1821 1963 while (*dst) {
1822 1964 if (strcmp(*dst, path) == 0)
1823 1965 return;
1824 1966 dst++;
1825 1967 }
1826 1968 next = path;
1827 1969 dst = *where;
1828 1970
1829 1971 update_inc_ptrs(where);
1830 1972
1831 1973 /*
1832 1974 * Move them all up starting at dst,
1833 1975 * insert the new entry..
1834 1976 */
1835 1977 do {
1836 1978 const char *tmp = *dst;
1837 1979 *dst = next;
1838 1980 next = tmp;
1839 1981 dst++;
1840 1982 } while (next);
1841 1983 }
1842 1984
1843 1985 static int handle_add_include(struct stream *stream, struct token **line, struct token *token)
1844 1986 {
1845 1987 for (;;) {
1846 1988 token = token->next;
1847 1989 if (eof_token(token))
1848 1990 return 1;
1849 1991 if (token_type(token) != TOKEN_STRING) {
1850 1992 warning(token->pos, "expected path string");
1851 1993 return 1;
1852 1994 }
1853 1995 add_path_entry(token, token->string->data, &isys_includepath);
1854 1996 }
1855 1997 }
1856 1998
1857 1999 static int handle_add_isystem(struct stream *stream, struct token **line, struct token *token)
1858 2000 {
1859 2001 for (;;) {
1860 2002 token = token->next;
1861 2003 if (eof_token(token))
1862 2004 return 1;
1863 2005 if (token_type(token) != TOKEN_STRING) {
1864 2006 sparse_error(token->pos, "expected path string");
1865 2007 return 1;
1866 2008 }
1867 2009 add_path_entry(token, token->string->data, &sys_includepath);
1868 2010 }
1869 2011 }
1870 2012
1871 2013 static int handle_add_system(struct stream *stream, struct token **line, struct token *token)
1872 2014 {
1873 2015 for (;;) {
1874 2016 token = token->next;
1875 2017 if (eof_token(token))
1876 2018 return 1;
1877 2019 if (token_type(token) != TOKEN_STRING) {
1878 2020 sparse_error(token->pos, "expected path string");
1879 2021 return 1;
1880 2022 }
1881 2023 add_path_entry(token, token->string->data, &dirafter_includepath);
1882 2024 }
1883 2025 }
1884 2026
1885 2027 /* Add to end on includepath list - no pointer updates */
1886 2028 static void add_dirafter_entry(struct token *token, const char *path)
1887 2029 {
1888 2030 const char **dst = includepath;
1889 2031
1890 2032 /* Need one free entry.. */
1891 2033 if (includepath[INCLUDEPATHS-2])
1892 2034 error_die(token->pos, "too many include path entries");
1893 2035
1894 2036 /* Add to the end */
1895 2037 while (*dst)
1896 2038 dst++;
1897 2039 *dst = path;
1898 2040 dst++;
1899 2041 *dst = NULL;
1900 2042 }
1901 2043
1902 2044 static int handle_add_dirafter(struct stream *stream, struct token **line, struct token *token)
1903 2045 {
1904 2046 for (;;) {
1905 2047 token = token->next;
1906 2048 if (eof_token(token))
1907 2049 return 1;
1908 2050 if (token_type(token) != TOKEN_STRING) {
1909 2051 sparse_error(token->pos, "expected path string");
1910 2052 return 1;
1911 2053 }
1912 2054 add_dirafter_entry(token, token->string->data);
1913 2055 }
1914 2056 }
1915 2057
1916 2058 static int handle_split_include(struct stream *stream, struct token **line, struct token *token)
1917 2059 {
1918 2060 /*
1919 2061 * -I-
1920 2062 * From info gcc:
1921 2063 * Split the include path. Any directories specified with `-I'
1922 2064 * options before `-I-' are searched only for headers requested with
1923 2065 * `#include "FILE"'; they are not searched for `#include <FILE>'.
1924 2066 * If additional directories are specified with `-I' options after
1925 2067 * the `-I-', those directories are searched for all `#include'
1926 2068 * directives.
1927 2069 * In addition, `-I-' inhibits the use of the directory of the current
1928 2070 * file directory as the first search directory for `#include "FILE"'.
1929 2071 */
1930 2072 quote_includepath = includepath+1;
1931 2073 angle_includepath = sys_includepath;
1932 2074 return 1;
1933 2075 }
1934 2076
1935 2077 /*
1936 2078 * We replace "#pragma xxx" with "__pragma__" in the token
1937 2079 * stream. Just as an example.
1938 2080 *
1939 2081 * We'll just #define that away for now, but the theory here
1940 2082 * is that we can use this to insert arbitrary token sequences
1941 2083 * to turn the pragmas into internal front-end sequences for
1942 2084 * when we actually start caring about them.
1943 2085 *
1944 2086 * So eventually this will turn into some kind of extended
1945 2087 * __attribute__() like thing, except called __pragma__(xxx).
1946 2088 */
1947 2089 static int handle_pragma(struct stream *stream, struct token **line, struct token *token)
1948 2090 {
1949 2091 struct token *next = *line;
1950 2092
1951 2093 if (match_ident(token->next, &once_ident) && eof_token(token->next->next)) {
1952 2094 stream->once = 1;
1953 2095 return 1;
1954 2096 }
1955 2097 token->ident = &pragma_ident;
1956 2098 token->pos.newline = 1;
1957 2099 token->pos.whitespace = 1;
1958 2100 token->pos.pos = 1;
1959 2101 *line = token;
1960 2102 token->next = next;
1961 2103 return 0;
↓ open down ↓ |
293 lines elided |
↑ open up ↑ |
1962 2104 }
1963 2105
1964 2106 /*
1965 2107 * We ignore #line for now.
1966 2108 */
1967 2109 static int handle_line(struct stream *stream, struct token **line, struct token *token)
1968 2110 {
1969 2111 return 1;
1970 2112 }
1971 2113
1972 -/*
1973 - * Ignore "#ident".
1974 - */
1975 2114 static int handle_ident(struct stream *stream, struct token **line, struct token *token)
1976 2115 {
1977 2116 return 1;
1978 2117 }
1979 2118
1980 2119 static int handle_nondirective(struct stream *stream, struct token **line, struct token *token)
1981 2120 {
1982 2121 sparse_error(token->pos, "unrecognized preprocessor line '%s'", show_token_sequence(token, 0));
1983 2122 return 1;
1984 2123 }
1985 2124
1986 2125
1987 2126 static void init_preprocessor(void)
1988 2127 {
1989 2128 int i;
1990 2129 int stream = init_stream("preprocessor", -1, includepath);
1991 2130 static struct {
1992 2131 const char *name;
1993 2132 int (*handler)(struct stream *, struct token **, struct token *);
1994 2133 } normal[] = {
1995 2134 { "define", handle_define },
1996 2135 { "weak_define", handle_weak_define },
1997 2136 { "strong_define", handle_strong_define },
1998 2137 { "undef", handle_undef },
1999 2138 { "strong_undef", handle_strong_undef },
2000 2139 { "warning", handle_warning },
2001 2140 { "error", handle_error },
2002 2141 { "include", handle_include },
2003 2142 { "include_next", handle_include_next },
2004 2143 { "pragma", handle_pragma },
2005 2144 { "line", handle_line },
2006 2145 { "ident", handle_ident },
2007 2146
2008 2147 // our internal preprocessor tokens
2009 2148 { "nostdinc", handle_nostdinc },
2010 2149 { "add_include", handle_add_include },
2011 2150 { "add_isystem", handle_add_isystem },
2012 2151 { "add_system", handle_add_system },
2013 2152 { "add_dirafter", handle_add_dirafter },
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
2014 2153 { "split_include", handle_split_include },
2015 2154 { "argv_include", handle_argv_include },
2016 2155 }, special[] = {
2017 2156 { "ifdef", handle_ifdef },
2018 2157 { "ifndef", handle_ifndef },
2019 2158 { "else", handle_else },
2020 2159 { "endif", handle_endif },
2021 2160 { "if", handle_if },
2022 2161 { "elif", handle_elif },
2023 2162 };
2163 + static struct {
2164 + const char *name;
2165 + void (*expander)(struct token *);
2166 + } dynamic[] = {
2167 + { "__LINE__", expand_line },
2168 + { "__FILE__", expand_file },
2169 + { "__BASE_FILE__", expand_basefile },
2170 + { "__DATE__", expand_date },
2171 + { "__TIME__", expand_time },
2172 + { "__COUNTER__", expand_counter },
2173 + { "__INCLUDE_LEVEL__", expand_include_level },
2174 + };
2024 2175
2025 2176 for (i = 0; i < ARRAY_SIZE(normal); i++) {
2026 2177 struct symbol *sym;
2027 2178 sym = create_symbol(stream, normal[i].name, SYM_PREPROCESSOR, NS_PREPROCESSOR);
2028 2179 sym->handler = normal[i].handler;
2029 2180 sym->normal = 1;
2030 2181 }
2031 2182 for (i = 0; i < ARRAY_SIZE(special); i++) {
2032 2183 struct symbol *sym;
2033 2184 sym = create_symbol(stream, special[i].name, SYM_PREPROCESSOR, NS_PREPROCESSOR);
2034 2185 sym->handler = special[i].handler;
2035 2186 sym->normal = 0;
2036 2187 }
2188 + for (i = 0; i < ARRAY_SIZE(dynamic); i++) {
2189 + struct symbol *sym;
2190 + sym = create_symbol(stream, dynamic[i].name, SYM_NODE, NS_MACRO);
2191 + sym->expander = dynamic[i].expander;
2192 + }
2037 2193
2038 2194 counter_macro = 0;
2039 2195 }
2040 2196
2041 2197 static void handle_preprocessor_line(struct stream *stream, struct token **line, struct token *start)
2042 2198 {
2043 2199 int (*handler)(struct stream *, struct token **, struct token *);
2044 2200 struct token *token = start->next;
2045 2201 int is_normal = 1;
2046 2202
2047 2203 if (eof_token(token))
2048 2204 return;
2049 2205
2050 2206 if (token_type(token) == TOKEN_IDENT) {
2051 2207 struct symbol *sym = lookup_symbol(token->ident, NS_PREPROCESSOR);
2052 2208 if (sym) {
2053 2209 handler = sym->handler;
2054 2210 is_normal = sym->normal;
2055 2211 } else {
2056 2212 handler = handle_nondirective;
2057 2213 }
2058 2214 } else if (token_type(token) == TOKEN_NUMBER) {
2059 2215 handler = handle_line;
2060 2216 } else {
2061 2217 handler = handle_nondirective;
2062 2218 }
2063 2219
2064 2220 if (is_normal) {
2065 2221 dirty_stream(stream);
2066 2222 if (false_nesting)
2067 2223 goto out;
2068 2224 }
2069 2225 if (!handler(stream, line, token)) /* all set */
2070 2226 return;
2071 2227
2072 2228 out:
2073 2229 free_preprocessor_line(token);
2074 2230 }
2075 2231
2076 2232 static void preprocessor_line(struct stream *stream, struct token **line)
2077 2233 {
2078 2234 struct token *start = *line, *next;
2079 2235 struct token **tp = &start->next;
2080 2236
2081 2237 for (;;) {
2082 2238 next = *tp;
2083 2239 if (next->pos.newline)
2084 2240 break;
2085 2241 tp = &next->next;
2086 2242 }
2087 2243 *line = next;
2088 2244 *tp = &eof_token_entry;
2089 2245 handle_preprocessor_line(stream, line, start);
2090 2246 }
2091 2247
2092 2248 static void do_preprocess(struct token **list)
2093 2249 {
2094 2250 struct token *next;
2095 2251
2096 2252 while (!eof_token(next = scan_next(list))) {
2097 2253 struct stream *stream = input_streams + next->pos.stream;
2098 2254
2099 2255 if (next->pos.newline && match_op(next, '#')) {
2100 2256 if (!next->pos.noexpand) {
2101 2257 preprocessor_line(stream, list);
2102 2258 __free_token(next); /* Free the '#' token */
2103 2259 continue;
2104 2260 }
2105 2261 }
2106 2262
2107 2263 switch (token_type(next)) {
↓ open down ↓ |
61 lines elided |
↑ open up ↑ |
2108 2264 case TOKEN_STREAMEND:
2109 2265 if (stream->top_if) {
2110 2266 nesting_error(stream);
2111 2267 sparse_error(stream->top_if->pos, "unterminated preprocessor conditional");
2112 2268 stream->top_if = NULL;
2113 2269 false_nesting = 0;
2114 2270 }
2115 2271 if (!stream->dirty)
2116 2272 stream->constant = CONSTANT_FILE_YES;
2117 2273 *list = next->next;
2274 + include_level--;
2118 2275 continue;
2119 2276 case TOKEN_STREAMBEGIN:
2120 2277 *list = next->next;
2278 + include_level++;
2121 2279 continue;
2122 2280
2123 2281 default:
2124 2282 dirty_stream(stream);
2125 2283 if (false_nesting) {
2126 2284 *list = next->next;
2127 2285 __free_token(next);
2128 2286 continue;
2129 2287 }
2130 2288
2131 2289 if (token_type(next) != TOKEN_IDENT ||
2132 2290 expand_one_symbol(list))
2133 2291 list = &next->next;
2134 2292 }
2135 2293 }
2136 2294 }
2137 2295
2138 2296 void init_include_path(void)
2139 2297 {
2140 2298 FILE *fp;
2141 2299 char path[256];
2142 2300 char arch[32];
2143 2301 char os[32];
2144 2302
2145 2303 fp = popen("/bin/uname -m", "r");
2146 2304 if (!fp)
2147 2305 return;
2148 2306 if (!fgets(arch, sizeof(arch) - 1, fp))
2149 2307 return;
2150 2308 pclose(fp);
2151 2309 if (arch[strlen(arch) - 1] == '\n')
2152 2310 arch[strlen(arch) - 1] = '\0';
2153 2311
2154 2312 fp = popen("/bin/uname -o", "r");
2155 2313 if (!fp)
2156 2314 return;
2157 2315 fgets(os, sizeof(os) - 1, fp);
2158 2316 pclose(fp);
2159 2317
2160 2318 if (strcmp(os, "GNU/Linux\n") != 0)
2161 2319 return;
2162 2320 strcpy(os, "linux-gnu");
2163 2321
2164 2322 snprintf(path, sizeof(path), "/usr/include/%s-%s/", arch, os);
2165 2323 add_pre_buffer("#add_system \"%s/\"\n", path);
2166 2324 }
2167 2325
2168 2326 struct token * preprocess(struct token *token)
2169 2327 {
2170 2328 preprocessing = 1;
2171 2329 init_preprocessor();
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
2172 2330 do_preprocess(&token);
2173 2331
2174 2332 // Drop all expressions from preprocessing, they're not used any more.
2175 2333 // This is not true when we have multiple files, though ;/
2176 2334 // clear_expression_alloc();
2177 2335 preprocessing = 0;
2178 2336
2179 2337 return token;
2180 2338 }
2181 2339
2340 +static int is_VA_ARGS_token(struct token *token)
2341 +{
2342 + return (token_type(token) == TOKEN_IDENT) &&
2343 + (token->ident == &__VA_ARGS___ident);
2344 +}
2345 +
2182 2346 static void dump_macro(struct symbol *sym)
2183 2347 {
2184 2348 int nargs = sym->arglist ? sym->arglist->count.normal : 0;
2185 2349 struct token *args[nargs];
2186 2350 struct token *token;
2187 2351
2188 2352 printf("#define %s", show_ident(sym->ident));
2189 2353 token = sym->arglist;
2190 2354 if (token) {
2191 2355 const char *sep = "";
2192 2356 int narg = 0;
2193 2357 putchar('(');
2194 2358 for (; !eof_token(token); token = token->next) {
2195 2359 if (token_type(token) == TOKEN_ARG_COUNT)
2196 2360 continue;
2197 - printf("%s%s", sep, show_token(token));
2361 + if (is_VA_ARGS_token(token))
2362 + printf("%s...", sep);
2363 + else
2364 + printf("%s%s", sep, show_token(token));
2198 2365 args[narg++] = token;
2199 - sep = ", ";
2366 + sep = ",";
2200 2367 }
2201 2368 putchar(')');
2202 2369 }
2203 - putchar(' ');
2204 2370
2205 2371 token = sym->expansion;
2206 - while (!eof_token(token)) {
2372 + while (token_type(token) != TOKEN_UNTAINT) {
2207 2373 struct token *next = token->next;
2374 + if (token->pos.whitespace)
2375 + putchar(' ');
2208 2376 switch (token_type(token)) {
2209 - case TOKEN_UNTAINT:
2377 + case TOKEN_CONCAT:
2378 + printf("##");
2210 2379 break;
2380 + case TOKEN_STR_ARGUMENT:
2381 + printf("#");
2382 + /* fall-through */
2383 + case TOKEN_QUOTED_ARGUMENT:
2211 2384 case TOKEN_MACRO_ARGUMENT:
2212 2385 token = args[token->argnum];
2213 2386 /* fall-through */
2214 2387 default:
2215 2388 printf("%s", show_token(token));
2216 - if (next->pos.whitespace)
2217 - putchar(' ');
2218 2389 }
2219 2390 token = next;
2220 2391 }
2221 2392 putchar('\n');
2222 2393 }
2223 2394
2224 2395 void dump_macro_definitions(void)
2225 2396 {
2226 2397 struct ident *name;
2227 2398
2228 2399 FOR_EACH_PTR(macros, name) {
2229 2400 struct symbol *sym = lookup_macro(name);
2230 2401 if (sym)
2231 2402 dump_macro(sym);
2232 2403 } END_FOR_EACH_PTR(name);
2233 2404 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX