[PATCH] line-splicing fixes in sparse
[smatch.git] / pre-process.c
blobe648035b15e5f3dc08db0f134ce92d457b28fc62
1 /*
2 * Do C preprocessing, based on a token list gathered by
3 * the tokenizer.
5 * This may not be the smartest preprocessor on the planet.
7 * Copyright (C) 2003 Transmeta Corp.
8 * 2003 Linus Torvalds
10 * Licensed under the Open Software License version 1.1
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <stdarg.h>
15 #include <stddef.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <limits.h>
22 #include "pre-process.h"
23 #include "lib.h"
24 #include "parse.h"
25 #include "token.h"
26 #include "symbol.h"
27 #include "expression.h"
29 int verbose = 0;
30 int preprocessing = 0;
32 #define MAX_NEST (256)
33 static int true_nesting = 0;
34 static int false_nesting = 0;
35 static struct token *unmatched_if = NULL;
36 static char elif_ignore[MAX_NEST];
37 #define if_nesting (true_nesting + false_nesting)
39 #define INCLUDEPATHS 32
40 const char *includepath[INCLUDEPATHS+1] = {
41 NULL
44 const char *sys_includepath[] = {
45 "/usr/include",
46 "/usr/local/include",
47 NULL,
50 const char *gcc_includepath[] = {
51 GCC_INTERNAL_INCLUDE,
52 NULL
57 * This is stupid - the tokenizer already guarantees unique
58 * identifiers, so we should just compare identifier pointers
60 int match_string_ident(struct ident *ident, const char *str)
62 return !str[ident->len] && !memcmp(str, ident->name, ident->len);
65 static struct token *alloc_token(struct position *pos)
67 struct token *token = __alloc_token(0);
69 token->pos.stream = pos->stream;
70 token->pos.line = pos->line;
71 token->pos.pos = pos->pos;
72 token->pos.whitespace = 1;
73 return token;
76 static const char *show_token_sequence(struct token *token);
78 static struct token *is_defined(struct token *head, struct token *token, struct token *next)
80 char *string[] = { "0", "1" };
81 char *defined = string[lookup_symbol(token->ident, NS_PREPROCESSOR) != NULL];
82 struct token *newtoken = alloc_token(&token->pos);
84 token_type(newtoken) = TOKEN_NUMBER;
85 newtoken->number = defined;
86 newtoken->next = next;
87 head->next = newtoken;
88 return next;
92 struct token *defined_one_symbol(struct token *head, struct token *next)
94 struct token *token = next->next;
95 struct token *past = token->next;
97 if (match_op(token, '(')) {
98 token = past;
99 past = token->next;
100 if (!match_op(past, ')'))
101 return next;
102 past = past->next;
104 if (token_type(token) == TOKEN_IDENT)
105 return is_defined(head, token, past);
106 return next;
109 struct token variable_argument = { .next = &eof_token_entry };
111 /* Expand symbol 'sym' between 'head->next' and 'head->next->next' */
112 static struct token *expand(struct token *, struct symbol *);
114 static void replace_with_string(struct token *token, const char *str)
116 int size = strlen(str) + 1;
117 struct string *s = __alloc_string(size);
119 s->length = size;
120 memcpy(s->data, str, size);
121 token_type(token) = TOKEN_STRING;
122 token->string = s;
125 static void replace_with_integer(struct token *token, unsigned int val)
127 char *buf = __alloc_bytes(10);
128 sprintf(buf, "%d", val);
129 token_type(token) = TOKEN_NUMBER;
130 token->number = buf;
133 struct token *expand_one_symbol(struct token *head, struct token *token)
135 struct symbol *sym;
137 if (token->pos.noexpand)
138 return token;
140 sym = lookup_symbol(token->ident, NS_PREPROCESSOR);
141 if (sym)
142 return expand(head, sym);
143 if (token->ident == &__LINE___ident) {
144 replace_with_integer(token, token->pos.line);
145 } else if (token->ident == &__FILE___ident) {
146 replace_with_string(token, (input_streams + token->pos.stream)->name);
147 } else if (token->ident == &defined_ident) {
148 return defined_one_symbol(head, token);
150 return token;
153 static inline void eat_untaint(struct token *head, struct token *token)
155 do {
156 token->ident->tainted = 0;
157 token = token->next;
158 } while (token_type(token) == TOKEN_UNTAINT);
159 head->next = token;
162 static struct token *expand_list(struct token *head)
164 for (;;) {
165 struct token *next = head->next;
167 /* Did we hit the end of the current expansion? */
168 if (eof_token(next))
169 break;
171 switch (token_type(next)) {
172 case TOKEN_IDENT:
173 next = expand_one_symbol(head, next);
174 break;
175 case TOKEN_UNTAINT:
176 eat_untaint(head, next);
177 continue;
180 head = next;
182 return head;
185 static struct token *find_argument_end(struct token *start, struct token *arglist)
187 int nesting = 0;
189 while (!eof_token(start)) {
190 struct token *next = start->next;
191 if (token_type(next) == TOKEN_UNTAINT) {
192 eat_untaint(start, next);
193 continue;
194 } else if (token_type(next) == TOKEN_IDENT) {
195 if (next->ident->tainted)
196 next->pos.noexpand = 1;
197 } else if (match_op(next, '('))
198 nesting++;
199 else if (match_op(next, ')')) {
200 if (--nesting < 0) {
201 start->next = &eof_token_entry;
202 return next->next;
204 } else if (!nesting && match_op(next, ',') && arglist->next != &variable_argument) {
205 next->special = SPECIAL_ARG_SEPARATOR;
206 arglist = arglist->next;
208 start = next;
210 return start;
213 static struct token *dup_token(struct token *token, struct position *streampos, struct position *pos)
215 struct token *alloc = alloc_token(streampos);
216 token_type(alloc) = token_type(token);
217 alloc->pos.newline = pos->newline;
218 alloc->pos.whitespace = pos->whitespace;
219 alloc->pos.noexpand = token->pos.noexpand;
220 alloc->number = token->number;
221 return alloc;
224 static void insert(struct token *token, struct token *prev)
226 token->next = prev->next;
227 prev->next = token;
230 static struct token * replace(struct token *token, struct token *prev, struct token *list)
232 struct position *pos = &token->pos;
234 prev->next = token->next;
235 while (!eof_token(list) && !match_op(list, SPECIAL_ARG_SEPARATOR)) {
236 struct token *newtok = dup_token(list, &token->pos, pos);
237 insert(newtok, prev);
238 prev = newtok;
239 list = list->next;
240 pos = &list->pos;
242 return prev;
245 static struct token *get_argument(int nr, struct token *args)
247 if (!nr)
248 return args;
249 while (!eof_token(args)) {
250 if (match_op(args, SPECIAL_ARG_SEPARATOR))
251 if (!--nr)
252 return args->next;
253 args = args->next;
256 return args;
259 static struct token *stringify(struct token *token, struct token *arg)
261 const char *s = show_token_sequence(arg);
262 int size = strlen(s)+1;
263 struct token *newtoken = alloc_token(&token->pos);
264 struct string *string = __alloc_string(size);
266 newtoken->pos.newline = token->pos.newline;
267 memcpy(string->data, s, size);
268 string->length = size;
269 token_type(newtoken) = TOKEN_STRING;
270 newtoken->string = string;
271 newtoken->next = &eof_token_entry;
272 return newtoken;
275 static struct token empty_arg_token = { .pos = { .type = TOKEN_EOF } };
277 static struct token *expand_one_arg(struct token *head, struct token *token, struct token *arguments, int do_expand)
279 int nr = token->argnum;
280 struct token *orig_head = head;
281 struct token *arg = get_argument(nr, arguments);
282 struct token *last = token->next;
283 token->next = &eof_token_entry;
286 * Special case for gcc 'x ## arg' semantics: if 'arg' is empty
287 * then the 'x' goes away too.
288 * NB: that's not what gcc kludge is about; later -- AV
290 if (token_type(head) == TOKEN_CONCAT && eof_token(arg)) {
291 arg = &empty_arg_token;
292 empty_arg_token.next = &eof_token_entry;
295 head = replace(token, head, arg);
296 if (do_expand)
297 head = expand_list(orig_head);
298 head->next = last;
299 return head;
302 static void expand_arguments(struct token *token, struct token *head,
303 struct token *arguments)
305 for (;;) {
306 struct token *next = head->next;
308 /* Did we hit the end of the current expansion? */
309 if (eof_token(next))
310 break;
312 if (token_type(next) == TOKEN_STR_ARGUMENT) {
313 int nr = next->argnum;
314 struct token *newtoken = stringify(next, get_argument(nr, arguments));
315 next = replace(next, head, newtoken);
316 } else if (token_type(next) == TOKEN_MACRO_ARGUMENT)
317 next = expand_one_arg(head, next, arguments, 1);
318 else if (token_type(next) == TOKEN_QUOTED_ARGUMENT)
319 next = expand_one_arg(head, next, arguments, 0);
321 head = next;
326 * Possibly valid combinations:
327 * - anything + 'empty_arg_token' is empty.
328 * - ident + ident - combine (==ident)
329 * a1 ## bb = 'a1bb'
330 * - ident + number - combine (==ident)
331 * a ## 0x5 = 'a0x5'
332 * - number + number - combine (==number)
333 * 12 ## 12 = '1212'
334 * - number + ident - combine (==number)
335 * 0x ## aaa = '0xaaa'
336 * - string + string - leave as is, C will combine them anyway
337 * others cause an error and leave the tokens as separate tokens.
339 static struct token *hashhash(struct token *head, struct token *first)
341 struct token *token;
342 static char buffer[512], *p;
343 struct token *newtoken;
344 int i = 2;
347 * Special case for gcc 'x ## arg' semantics: if 'arg' is empty
348 * then the 'x' goes away too.
350 * See expand_one_arg.
352 if (token_type(first->next) == TOKEN_EOF)
353 return first->next->next;
355 p = buffer;
356 token = first;
357 do {
358 static const char *src;
359 int len;
361 switch (token_type(token)) {
362 case TOKEN_IDENT:
363 len = token->ident->len;
364 src = token->ident->name;
365 break;
366 case TOKEN_NUMBER:
367 src = token->number;
368 len = strlen(src);
369 break;
370 default:
371 goto out;
373 memcpy(p, src, len);
374 p += len;
375 token = token->next;
376 } while (--i > 0);
378 out:
379 *p++ = 0;
380 if (!*buffer)
381 return token;
383 newtoken = alloc_token(&first->pos);
384 newtoken->next = token;
386 token_type(newtoken) = token_type(first);
387 switch (token_type(newtoken)) {
388 case TOKEN_IDENT:
389 newtoken->ident = built_in_ident(buffer);
390 break;
391 case TOKEN_NUMBER: {
392 newtoken->number = __alloc_bytes(p - buffer);
393 memcpy(newtoken->number, buffer, p - buffer);
394 break;
397 return newtoken;
400 static void retokenize(struct token *head)
402 struct token * next = head->next;
403 struct token * nextnext = next->next;
404 struct token * nextnextnext = nextnext->next;
406 if (eof_token(next) || eof_token(nextnext))
407 return;
409 for (;;) {
410 if (eof_token(nextnextnext))
411 break;
413 if (token_type(nextnext) == TOKEN_CONCAT) {
414 next->next = nextnextnext;
415 next = hashhash(head, next);
416 head->next = next;
417 nextnext = next->next;
418 nextnextnext = nextnext->next;
419 continue;
423 head = next;
424 next = nextnext;
425 nextnext = nextnext->next;
426 nextnextnext = nextnextnext->next;
430 static struct token *expand(struct token *head, struct symbol *sym)
432 struct token *arguments, *last;
433 struct token *token = head->next;
434 struct ident *expanding = token->ident;
436 if (expanding->tainted) {
437 token->pos.noexpand = 1;
438 return token;
441 if (sym->arglist) {
442 if (token_type(token->next) == TOKEN_UNTAINT)
443 eat_untaint(token, token->next);
444 arguments = token->next;
445 if (!match_op(arguments, '('))
446 return token;
447 last = find_argument_end(arguments, sym->arglist);
448 arguments = arguments->next;
449 } else {
450 arguments = NULL;
451 last = token->next;
453 token->next = &eof_token_entry;
455 /* Replace the token with the token expansion */
456 replace(token, head, sym->expansion);
458 /* Then, replace all the arguments with their expansions */
459 if (arguments)
460 expand_arguments(token, head, arguments);
462 /* Re-tokenize the sequence if any ## token exists.. */
463 retokenize(head);
465 token = head;
466 while (!eof_token(token->next))
467 token = token->next;
468 token->next = last;
470 expanding->tainted = 1;
472 return head;
475 static const char *token_name_sequence(struct token *token, int endop, struct token *start)
477 struct token *last;
478 static char buffer[256];
479 char *ptr = buffer;
481 last = token;
482 while (!eof_token(token) && !match_op(token, endop)) {
483 int len;
484 const char *val = token->string->data;
485 if (token_type(token) != TOKEN_STRING)
486 val = show_token(token);
487 len = strlen(val);
488 memcpy(ptr, val, len);
489 ptr += len;
490 token = token->next;
492 *ptr = 0;
493 if (endop && !match_op(token, endop))
494 warn(start->pos, "expected '>' at end of filename");
495 return buffer;
498 static int try_include(const char *path, int plen, const char *filename, int flen, struct token *head)
500 int fd;
501 static char fullname[PATH_MAX];
503 memcpy(fullname, path, plen);
504 if (plen && path[plen-1] != '/') {
505 fullname[plen] = '/';
506 plen++;
508 memcpy(fullname+plen, filename, flen);
509 fd = open(fullname, O_RDONLY);
510 if (fd >= 0) {
511 char * streamname = __alloc_bytes(plen + flen);
512 memcpy(streamname, fullname, plen + flen);
513 head->next = tokenize(streamname, fd, head->next);
514 close(fd);
515 return 1;
517 return 0;
520 static int do_include_path(const char **pptr, struct token *head, struct token *token, const char *filename, int flen)
522 const char *path;
524 while ((path = *pptr++) != NULL) {
525 if (!try_include(path, strlen(path), filename, flen, head))
526 continue;
527 return 1;
529 return 0;
533 static void do_include(int local, struct stream *stream, struct token *head, struct token *token, const char *filename)
535 int flen = strlen(filename) + 1;
537 /* Same directory as current stream? */
538 if (local) {
539 const char *path;
540 char *slash;
541 int plen;
543 path = stream->name;
544 slash = strrchr(path, '/');
545 plen = slash ? slash - path : 0;
547 if (try_include(path, plen, filename, flen, head))
548 return;
551 /* Check the standard include paths.. */
552 if (do_include_path(includepath, head, token, filename, flen))
553 return;
554 if (do_include_path(sys_includepath, head, token, filename, flen))
555 return;
556 if (do_include_path(gcc_includepath, head, token, filename, flen))
557 return;
559 error(token->pos, "unable to open '%s'", filename);
562 static int handle_include(struct stream *stream, struct token *head, struct token *token)
564 const char *filename;
565 struct token *next;
566 int expect;
568 if (stream->constant == -1)
569 stream->constant = 0;
570 if (false_nesting)
571 return 1;
572 next = token->next;
573 expect = '>';
574 if (!match_op(next, '<')) {
575 expand_list(token);
576 expect = 0;
577 next = token;
579 token = next->next;
580 filename = token_name_sequence(token, expect, token);
581 do_include(!expect, stream, head, token, filename);
582 return 1;
585 static int token_different(struct token *t1, struct token *t2)
587 int different;
589 if (token_type(t1) != token_type(t2))
590 return 1;
592 switch (token_type(t1)) {
593 case TOKEN_IDENT:
594 different = t1->ident != t2->ident;
595 break;
596 case TOKEN_UNTAINT:
597 case TOKEN_CONCAT:
598 different = 0;
599 break;
600 case TOKEN_NUMBER:
601 different = strcmp(t1->number, t2->number);
602 break;
603 case TOKEN_SPECIAL:
604 different = t1->special != t2->special;
605 break;
606 case TOKEN_MACRO_ARGUMENT:
607 case TOKEN_QUOTED_ARGUMENT:
608 case TOKEN_STR_ARGUMENT:
609 different = t1->argnum != t2->argnum;
610 break;
611 case TOKEN_CHAR:
612 different = t1->character != t2->character;
613 break;
614 case TOKEN_STRING: {
615 struct string *s1, *s2;
617 s1 = t1->string;
618 s2 = t2->string;
619 different = 1;
620 if (s1->length != s2->length)
621 break;
622 different = memcmp(s1->data, s2->data, s1->length);
623 break;
625 default:
626 different = 1;
627 break;
629 return different;
632 static int token_list_different(struct token *list1, struct token *list2)
634 for (;;) {
635 if (list1 == list2)
636 return 0;
637 if (!list1 || !list2)
638 return 1;
639 if (token_different(list1, list2))
640 return 1;
641 list1 = list1->next;
642 list2 = list2->next;
646 static struct token *parse_arguments(struct token *list)
648 struct token *arg = list->next, *next = list;
650 if (match_op(arg, ')')) {
651 list->next = &eof_token_entry;
652 return arg->next;
655 while (token_type(arg) == TOKEN_IDENT) {
656 if (arg->ident == &__VA_ARGS___ident)
657 goto Eva_args;
658 next = arg->next;
660 if (match_op(next, ',')) {
661 arg = arg->next = next->next;
662 continue;
665 if (match_op(next, ')')) {
666 arg->next = &eof_token_entry;
667 return next->next;
670 /* normal cases are finished here */
672 if (match_op(next, SPECIAL_ELLIPSIS)) {
673 arg->next = &variable_argument;
674 if (match_op(next->next, ')'))
675 return next->next->next;
677 arg = next;
678 goto Enotclosed;
681 if (eof_token(next)) {
682 goto Enotclosed;
683 } else {
684 arg = next;
685 goto Ebadstuff;
689 if (match_op(arg, SPECIAL_ELLIPSIS)) {
690 next = arg->next;
691 token_type(arg) = TOKEN_IDENT;
692 arg->ident = &__VA_ARGS___ident;
693 arg->next = &variable_argument;
694 if (!match_op(next, ')'))
695 goto Enotclosed;
696 return next->next;
699 if (eof_token(arg)) {
700 arg = next;
701 goto Enotclosed;
703 if (match_op(arg, ','))
704 goto Emissing;
705 else
706 goto Ebadstuff;
709 Emissing:
710 warn(arg->pos, "parameter name missing");
711 return NULL;
712 Ebadstuff:
713 warn(arg->pos, "\"%s\" may not appear in macro parameter list",
714 show_token(arg));
715 return NULL;
716 Enotclosed:
717 warn(arg->pos, "missing ')' in macro parameter list");
718 return NULL;
719 Eva_args:
720 warn(arg->pos, "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro");
721 return NULL;
724 static int try_arg(struct token *token, enum token_type type, struct token *arglist)
726 struct ident *ident = token->ident;
727 int nr;
729 if (!arglist || token_type(token) != TOKEN_IDENT)
730 return 0;
732 for (nr = 0; !eof_token(arglist); nr++, arglist = arglist->next) {
733 if (arglist->ident == ident) {
734 token->argnum = nr;
735 token_type(token) = type;
736 return 1;
739 return 0;
742 static struct token *parse_expansion(struct token *expansion, struct token *arglist, struct ident *name)
744 struct token *token = expansion;
745 struct token **p;
747 if (match_op(token, SPECIAL_HASHHASH))
748 goto Econcat;
750 for (p = &expansion; !eof_token(token); p = &token->next, token = *p) {
751 if (match_op(token, '#') && arglist) {
752 struct token *next = token->next;
753 if (!try_arg(next, TOKEN_STR_ARGUMENT, arglist))
754 goto Equote;
755 token = *p = next;
756 } else if (match_op(token, SPECIAL_HASHHASH)) {
757 struct token *next = token->next;
758 token_type(token) = TOKEN_CONCAT;
759 if (try_arg(next, TOKEN_QUOTED_ARGUMENT, arglist))
760 token = next;
761 else if (match_op(next, SPECIAL_HASHHASH))
762 token = next;
763 else if (eof_token(next))
764 goto Econcat;
765 } else if (match_op(token->next, SPECIAL_HASHHASH)) {
766 try_arg(token, TOKEN_QUOTED_ARGUMENT, arglist);
767 } else {
768 try_arg(token, TOKEN_MACRO_ARGUMENT, arglist);
771 token = alloc_token(&expansion->pos);
772 token_type(token) = TOKEN_UNTAINT;
773 token->ident = name;
774 token->next = *p;
775 *p = token;
776 return expansion;
778 Equote:
779 warn(token->pos, "'#' is not followed by a macro parameter");
780 return NULL;
782 Econcat:
783 warn(token->pos, "'##' cannot appear at the ends of macro expansion");
784 return NULL;
787 static int handle_define(struct stream *stream, struct token *head, struct token *token)
789 struct token *arglist, *expansion;
790 struct token *left = token->next;
791 struct symbol *sym;
792 struct ident *name;
794 if (token_type(left) != TOKEN_IDENT) {
795 warn(head->pos, "expected identifier to 'define'");
796 return 0;
798 if (false_nesting)
799 return 1;
800 name = left->ident;
802 arglist = NULL;
803 expansion = left->next;
804 if (!expansion->pos.whitespace && match_op(expansion, '(')) {
805 arglist = expansion;
806 expansion = parse_arguments(expansion);
807 if (!expansion)
808 return 1;
809 arglist = arglist->next;
812 expansion = parse_expansion(expansion, arglist, name);
813 if (!expansion)
814 return 1;
816 sym = lookup_symbol(name, NS_PREPROCESSOR);
817 if (sym) {
818 if (token_list_different(sym->expansion, expansion) ||
819 token_list_different(sym->arglist, arglist)) {
820 warn(left->pos, "preprocessor token %.*s redefined",
821 name->len, name->name);
822 info(sym->pos, "this was the original definition");
824 return 1;
826 sym = alloc_symbol(left->pos, SYM_NODE);
827 bind_symbol(sym, name, NS_PREPROCESSOR);
829 sym->expansion = expansion;
830 sym->arglist = arglist;
831 return 1;
834 static int handle_undef(struct stream *stream, struct token *head, struct token *token)
836 struct token *left = token->next;
837 struct symbol **sym;
839 if (token_type(left) != TOKEN_IDENT) {
840 warn(head->pos, "expected identifier to 'undef'");
841 return 0;
843 if (false_nesting)
844 return 1;
845 sym = &left->ident->symbols;
846 while (*sym) {
847 struct symbol *t = *sym;
848 if (t->namespace == NS_PREPROCESSOR) {
849 *sym = t->next_id;
850 return 1;
852 sym = &t->next_id;
854 return 1;
857 static int preprocessor_if(struct token *token, int true)
859 if (if_nesting == 0)
860 unmatched_if = token;
861 if (if_nesting >= MAX_NEST)
862 error(token->pos, "Maximum preprocessor conditional level exhausted");
863 elif_ignore[if_nesting] = false_nesting || true;
864 if (false_nesting || !true) {
865 false_nesting++;
866 return 1;
868 true_nesting++;
869 return 1;
872 static int token_defined(struct token *token)
874 if (token_type(token) == TOKEN_IDENT)
875 return lookup_symbol(token->ident, NS_PREPROCESSOR) != NULL;
877 warn(token->pos, "expected identifier for #if[n]def");
878 return 0;
881 static int handle_ifdef(struct stream *stream, struct token *head, struct token *token)
883 return preprocessor_if(token, token_defined(token->next));
886 static int handle_ifndef(struct stream *stream, struct token *head, struct token *token)
888 struct token *next = token->next;
889 if (stream->constant == -1) {
890 int newconstant = 0;
891 if (token_type(next) == TOKEN_IDENT) {
892 if (!stream->protect || stream->protect == next->ident) {
893 newconstant = -2;
894 stream->protect = next->ident;
895 stream->nesting = if_nesting+1;
898 stream->constant = newconstant;
900 return preprocessor_if(token, !token_defined(next));
903 static int expression_value(struct token *head)
905 struct expression *expr;
906 struct token *token;
907 long long value;
909 expand_list(head);
910 token = constant_expression(head->next, &expr);
911 if (!eof_token(token))
912 warn(token->pos, "garbage at end: %s", show_token_sequence(token));
913 value = get_expression_value(expr);
914 return value != 0;
917 static int handle_if(struct stream *stream, struct token *head, struct token *token)
919 int value = 0;
920 if (!false_nesting)
921 value = expression_value(token);
922 return preprocessor_if(token, value);
925 static int handle_elif(struct stream * stream, struct token *head, struct token *token)
927 if (stream->nesting == if_nesting)
928 stream->constant = 0;
929 if (false_nesting) {
930 /* If this whole if-thing is if'ed out, an elif cannot help */
931 if (elif_ignore[if_nesting-1])
932 return 1;
933 if (expression_value(token)) {
934 false_nesting--;
935 true_nesting++;
936 elif_ignore[if_nesting-1] = 1;
938 return 1;
940 if (true_nesting) {
941 false_nesting = 1;
942 true_nesting--;
943 return 1;
945 warn(token->pos, "unmatched '#elif'");
946 return 1;
949 static int handle_else(struct stream *stream, struct token *head, struct token *token)
951 if (stream->nesting == if_nesting)
952 stream->constant = 0;
953 if (false_nesting) {
954 /* If this whole if-thing is if'ed out, an else cannot help */
955 if (elif_ignore[if_nesting-1])
956 return 1;
957 false_nesting--;
958 true_nesting++;
959 elif_ignore[if_nesting-1] = 1;
960 return 1;
962 if (true_nesting) {
963 true_nesting--;
964 false_nesting = 1;
965 return 1;
967 warn(token->pos, "unmatched #else");
968 return 1;
971 static int handle_endif(struct stream *stream, struct token *head, struct token *token)
973 if (stream->constant == -2 && stream->nesting == if_nesting)
974 stream->constant = -1;
976 if (false_nesting) {
977 false_nesting--;
978 return 1;
980 if (true_nesting) {
981 true_nesting--;
982 return 1;
984 warn(token->pos, "unmatched #endif");
985 return 1;
988 static const char *show_token_sequence(struct token *token)
990 static char buffer[1024];
991 char *ptr = buffer;
992 int whitespace = 0;
994 if (!token)
995 return "<none>";
996 while (!eof_token(token) && !match_op(token, SPECIAL_ARG_SEPARATOR)) {
997 const char *val = show_token(token);
998 int len = strlen(val);
1000 if (ptr + whitespace + len > buffer + sizeof(buffer)) {
1001 warn(token->pos, "too long token expansion");
1002 break;
1005 if (whitespace)
1006 *ptr++ = ' ';
1007 memcpy(ptr, val, len);
1008 ptr += len;
1009 token = token->next;
1010 whitespace = token->pos.whitespace;
1012 *ptr = 0;
1013 return buffer;
1016 static int handle_warning(struct stream *stream, struct token *head, struct token *token)
1018 if (false_nesting)
1019 return 1;
1020 warn(token->pos, "%s", show_token_sequence(token->next));
1021 return 1;
1024 static int handle_error(struct stream *stream, struct token *head, struct token *token)
1026 if (false_nesting)
1027 return 1;
1028 warn(token->pos, "%s", show_token_sequence(token->next));
1029 return 1;
1032 static int handle_nostdinc(struct stream *stream, struct token *head, struct token *token)
1034 if (false_nesting)
1035 return 1;
1036 includepath[0] = NULL;
1037 return 1;
1040 static void add_path_entry(struct token *token, const char *path)
1042 int i;
1044 for (i = 0; i < INCLUDEPATHS; i++) {
1045 if (!includepath[i]) {
1046 includepath[i] = path;
1047 includepath[i+1] = NULL;
1048 return;
1051 warn(token->pos, "too many include path entries");
1054 static int handle_add_include(struct stream *stream, struct token *head, struct token *token)
1056 for (;;) {
1057 token = token->next;
1058 if (eof_token(token))
1059 return 1;
1060 if (token_type(token) != TOKEN_STRING) {
1061 warn(token->pos, "expected path string");
1062 return 1;
1064 add_path_entry(token, token->string->data);
1069 * We replace "#pragma xxx" with "__pragma__" in the token
1070 * stream. Just as an example.
1072 * We'll just #define that away for now, but the theory here
1073 * is that we can use this to insert arbitrary token sequences
1074 * to turn the pragma's into internal front-end sequences for
1075 * when we actually start caring about them.
1077 * So eventually this will turn into some kind of extended
1078 * __attribute__() like thing, except called __pragma__(xxx).
1080 static int handle_pragma(struct stream *stream, struct token *head, struct token *token)
1082 struct token *next = head->next;
1084 token->ident = &pragma_ident;
1085 token->pos.newline = 1;
1086 token->pos.whitespace = 1;
1087 token->pos.pos = 1;
1088 head->next = token;
1089 token->next = next;
1090 return 1;
1093 static int handle_preprocessor_command(struct stream *stream, struct token *head, struct ident *ident, struct token *token)
1095 int i;
1096 static struct {
1097 const char *name;
1098 int (*handler)(struct stream *, struct token *, struct token *);
1099 } handlers[] = {
1100 { "define", handle_define },
1101 { "undef", handle_undef },
1102 { "ifdef", handle_ifdef },
1103 { "ifndef", handle_ifndef },
1104 { "else", handle_else },
1105 { "endif", handle_endif },
1106 { "if", handle_if },
1107 { "elif", handle_elif },
1108 { "warning", handle_warning },
1109 { "error", handle_error },
1110 { "include", handle_include },
1111 { "pragma", handle_pragma },
1113 // our internal preprocessor tokens
1114 { "nostdinc", handle_nostdinc },
1115 { "add_include", handle_add_include },
1118 for (i = 0; i < (sizeof (handlers) / sizeof (handlers[0])); i++) {
1119 if (match_string_ident(ident, handlers[i].name))
1120 return handlers[i].handler(stream, head, token);
1122 return 0;
1125 static void handle_preprocessor_line(struct stream *stream, struct token * head, struct token *token)
1127 if (!token)
1128 return;
1130 if (token_type(token) == TOKEN_IDENT)
1131 if (handle_preprocessor_command(stream, head, token->ident, token))
1132 return;
1133 warn(token->pos, "unrecognized preprocessor line '%s'", show_token_sequence(token));
1136 static void preprocessor_line(struct stream *stream, struct token * head)
1138 struct token *start = head->next, *next;
1139 struct token **tp = &start->next;
1141 for (;;) {
1142 next = *tp;
1143 if (next->pos.newline)
1144 break;
1145 tp = &next->next;
1147 head->next = next;
1148 *tp = &eof_token_entry;
1149 handle_preprocessor_line(stream, head, start->next);
1152 static void do_preprocess(struct token *head)
1154 do {
1155 struct token *next = head->next;
1156 struct stream *stream = input_streams + next->pos.stream;
1158 if (next->pos.newline && match_op(next, '#')) {
1159 preprocessor_line(stream, head);
1160 continue;
1163 if (false_nesting) {
1164 head->next = next->next;
1165 continue;
1168 switch (token_type(next)) {
1169 case TOKEN_STREAMEND:
1170 if (stream->constant == -1 && stream->protect) {
1171 stream->constant = 1;
1173 /* fallthrough */
1174 case TOKEN_STREAMBEGIN:
1175 head->next = next->next;
1176 continue;
1178 case TOKEN_UNTAINT:
1179 eat_untaint(head, next);
1180 continue;
1182 case TOKEN_IDENT:
1183 next = expand_one_symbol(head, next);
1184 /* fallthrough */
1185 default:
1187 * Any token expansion (even if it ended up being an
1188 * empty expansion) in this stream implies it can't
1189 * be constant.
1191 stream->constant = 0;
1194 head = next;
1195 } while (!eof_token(head));
1198 struct token * preprocess(struct token *token)
1200 struct token header = { };
1202 preprocessing = 1;
1203 header.next = token;
1204 do_preprocess(&header);
1205 if (if_nesting)
1206 warn(unmatched_if->pos, "unmatched preprocessor conditional");
1208 // Drop all expressions from pre-processing, they're not used any more.
1209 clear_expression_alloc();
1210 preprocessing = 0;
1212 return header.next;