Now that we do the proper (simplified) C99 number token
[smatch.git] / pre-process.c
blob783a38805671ca559855edde0cc9c4daeb3f11d7
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 /* Head is one-before-list, and last is one-past-list */
79 static struct token *for_each_ident(struct token *parent, struct token *head, struct token *(*action)(struct token *parent, struct token *head, struct token *))
81 for (;;) {
82 struct token *next = head->next;
84 /* Did we hit the end of the current expansion? */
85 if (eof_token(next))
86 break;
88 if (token_type(next) == TOKEN_IDENT)
89 next = action(parent, head, next);
91 head = next;
93 return head;
96 static struct token *is_defined(struct token *head, struct token *token, struct token *next)
98 char *string[] = { "0", "1" };
99 char *defined = string[lookup_symbol(token->ident, NS_PREPROCESSOR) != NULL];
100 struct token *newtoken = alloc_token(&token->pos);
102 token_type(newtoken) = TOKEN_NUMBER;
103 newtoken->number = defined;
104 newtoken->next = next;
105 head->next = newtoken;
106 return next;
110 struct token *defined_one_symbol(struct token *head, struct token *next)
112 struct token *token = next->next;
113 struct token *past = token->next;
115 if (match_op(token, '(')) {
116 token = past;
117 past = token->next;
118 if (!match_op(past, ')'))
119 return next;
120 past = past->next;
122 if (token_type(token) == TOKEN_IDENT)
123 return is_defined(head, token, past);
124 return next;
127 struct token variable_argument = { .next = &eof_token_entry };
129 /* Expand symbol 'sym' between 'head->next' and 'head->next->next' */
130 static struct token *expand(struct token *, struct token *, struct symbol *);
132 static void replace_with_string(struct token *token, const char *str)
134 int size = strlen(str) + 1;
135 struct string *s = __alloc_string(size);
137 s->length = size;
138 memcpy(s->data, str, size);
139 token_type(token) = TOKEN_STRING;
140 token->string = s;
143 static void replace_with_integer(struct token *token, unsigned int val)
145 char *buf = __alloc_bytes(10);
146 sprintf(buf, "%d", val);
147 token_type(token) = TOKEN_NUMBER;
148 token->number = buf;
151 struct token *expand_one_symbol(struct token *parent, struct token *head, struct token *token)
153 struct symbol *sym;
154 struct token *x;
156 /* Avoid recursive expansion */
157 x = token;
158 while ((x = x->parent) != NULL) {
159 if (parent && x->ident == parent->ident)
160 return token;
161 if (x->ident == token->ident)
162 return token;
165 sym = lookup_symbol(token->ident, NS_PREPROCESSOR);
166 if (sym) {
167 if (sym->arglist && !match_op(token->next, '('))
168 return token;
169 return expand(token, head, sym);
171 if (token->ident == &__LINE___ident) {
172 replace_with_integer(token, token->pos.line);
173 } else if (token->ident == &__FILE___ident) {
174 replace_with_string(token, (input_streams + token->pos.stream)->name);
175 } else if (token->ident == &defined_ident) {
176 return defined_one_symbol(head, token);
178 return token;
181 static struct token *expand_list(struct token *parent, struct token *head)
183 return for_each_ident(parent, head, expand_one_symbol);
186 static struct token *find_argument_end(struct token *start, struct token *arglist)
188 int nesting = 0;
190 while (!eof_token(start)) {
191 struct token *next = start->next;
192 if (match_op(next, '('))
193 nesting++;
194 else if (match_op(next, ')')) {
195 if (--nesting < 0) {
196 start->next = &eof_token_entry;
197 return next->next;
199 } else if (!nesting && match_op(next, ',') && arglist->next != &variable_argument
200 && !match_op(arglist, SPECIAL_ELLIPSIS)) {
201 next->special = SPECIAL_ARG_SEPARATOR;
202 arglist = arglist->next;
204 start = next;
206 return start;
209 static struct token *dup_token(struct token *token, struct position *streampos, struct position *pos)
211 struct token *alloc = alloc_token(streampos);
212 token_type(alloc) = token_type(token);
213 alloc->pos.newline = pos->newline;
214 alloc->pos.whitespace = pos->whitespace;
215 alloc->number = token->number;
216 return alloc;
219 static void insert(struct token *token, struct token *prev)
221 token->next = prev->next;
222 prev->next = token;
225 static struct token * replace(struct token *parent, struct token *token, struct token *prev, struct token *list)
227 struct position *pos = &token->pos;
229 prev->next = token->next;
230 while (!eof_token(list) && !match_op(list, SPECIAL_ARG_SEPARATOR)) {
231 struct token *newtok = dup_token(list, &token->pos, pos);
232 newtok->parent = parent;
233 insert(newtok, prev);
234 prev = newtok;
235 list = list->next;
236 pos = &list->pos;
238 return prev;
241 static struct token *get_argument(int nr, struct token *args)
243 if (!nr)
244 return args;
245 while (!eof_token(args)) {
246 if (match_op(args, SPECIAL_ARG_SEPARATOR))
247 if (!--nr)
248 return args->next;
249 args = args->next;
252 return args;
255 static struct token *stringify(struct token *token, struct token *arg)
257 const char *s = show_token_sequence(arg);
258 int size = strlen(s)+1;
259 struct token *newtoken = alloc_token(&token->pos);
260 struct string *string = __alloc_string(size);
262 newtoken->pos.newline = token->pos.newline;
263 memcpy(string->data, s, size);
264 string->length = size;
265 token_type(newtoken) = TOKEN_STRING;
266 newtoken->string = string;
267 newtoken->next = &eof_token_entry;
268 return newtoken;
271 static int arg_number(struct token *arglist, struct ident *ident)
273 int nr = 0;
275 while (!eof_token(arglist)) {
276 if (match_op(arglist, SPECIAL_ELLIPSIS) && ident == &__VA_ARGS___ident)
277 return nr;
278 if (arglist->ident == ident)
279 return nr;
280 nr++;
281 arglist = arglist->next;
283 return -1;
286 static struct token empty_arg_token = { .pos = { .type = TOKEN_EOF } };
288 static struct token *expand_one_arg(struct token *parent, struct token *head, struct token *token,
289 struct token *arglist, struct token *arguments)
291 int nr = arg_number(arglist, token->ident);
292 struct token *orig_head = head;
294 if (nr >= 0) {
295 struct token *arg = get_argument(nr, arguments);
296 struct token *last = token->next;
297 token->next = &eof_token_entry;
300 * Special case for gcc 'x ## arg' semantics: if 'arg' is empty
301 * then the 'x' goes away too.
303 if (match_op(head, SPECIAL_HASHHASH) && eof_token(arg)) {
304 arg = &empty_arg_token;
305 empty_arg_token.next = &eof_token_entry;
308 head = replace(NULL, token, head, arg);
309 if (!match_op(orig_head, SPECIAL_HASHHASH) && !match_op(last, SPECIAL_HASHHASH) && !match_op(orig_head, '#'))
310 head = expand_list(parent, orig_head);
311 head->next = last;
312 return head;
314 return token;
317 static void expand_arguments(struct token *parent,
318 struct token *token, struct token *head,
319 struct token *arguments, struct token *arglist)
321 for (;;) {
322 struct token *next = head->next;
324 /* Did we hit the end of the current expansion? */
325 if (eof_token(next))
326 break;
328 if (match_op(next, '#')) {
329 struct token *nextnext = next->next;
330 int nr = arg_number(arglist, nextnext->ident);
331 if (nextnext != head && nr >= 0 && token_type(nextnext) == TOKEN_IDENT) {
332 struct token *newtoken = stringify(nextnext, get_argument(nr, arguments));
333 replace(NULL, nextnext, head, newtoken);
334 continue;
336 warn(next->pos, "'#' operation is not followed by argument name");
339 if (token_type(next) == TOKEN_IDENT)
340 next = expand_one_arg(parent, head, next, arglist, arguments);
342 head = next;
347 * Possibly valid combinations:
348 * - anything + 'empty_arg_token' is empty.
349 * - ident + ident - combine (==ident)
350 * a1 ## bb = 'a1bb'
351 * - ident + number - combine (==ident)
352 * a ## 0x5 = 'a0x5'
353 * - number + number - combine (==number)
354 * 12 ## 12 = '1212'
355 * - number + ident - combine (==number)
356 * 0x ## aaa = '0xaaa'
357 * - string + string - leave as is, C will combine them anyway
358 * others cause an error and leave the tokens as separate tokens.
360 static struct token *hashhash(struct token *head, struct token *first)
362 struct token *token;
363 static char buffer[512], *p;
364 struct token *newtoken;
365 int i = 2;
368 * Special case for gcc 'x ## arg' semantics: if 'arg' is empty
369 * then the 'x' goes away too.
371 * See expand_one_arg.
373 if (token_type(first->next) == TOKEN_EOF)
374 return first->next->next;
376 p = buffer;
377 token = first;
378 do {
379 static const char *src;
380 int len;
382 switch (token_type(token)) {
383 case TOKEN_IDENT:
384 len = token->ident->len;
385 src = token->ident->name;
386 break;
387 case TOKEN_NUMBER:
388 src = token->number;
389 len = strlen(src);
390 break;
391 default:
392 goto out;
394 memcpy(p, src, len);
395 p += len;
396 token = token->next;
397 } while (--i > 0);
399 out:
400 *p++ = 0;
401 if (!*buffer)
402 return token;
404 newtoken = alloc_token(&first->pos);
405 newtoken->next = token;
407 token_type(newtoken) = token_type(first);
408 switch (token_type(newtoken)) {
409 case TOKEN_IDENT:
410 newtoken->ident = built_in_ident(buffer);
411 break;
412 case TOKEN_NUMBER: {
413 newtoken->number = __alloc_bytes(p - buffer);
414 memcpy(newtoken->number, buffer, p - buffer);
415 break;
418 return newtoken;
421 static void retokenize(struct token *head)
423 struct token * next = head->next;
424 struct token * nextnext = next->next;
425 struct token * nextnextnext = nextnext->next;
427 if (eof_token(next) || eof_token(nextnext))
428 return;
430 for (;;) {
431 if (eof_token(nextnextnext))
432 break;
434 if (match_op(nextnext, SPECIAL_HASHHASH)) {
435 next->next = nextnextnext;
436 next = hashhash(head, next);
437 head->next = next;
438 nextnext = next->next;
439 nextnextnext = nextnext->next;
440 continue;
444 head = next;
445 next = nextnext;
446 nextnext = nextnext->next;
447 nextnextnext = nextnextnext->next;
451 static struct token *expand(struct token *parent, struct token *head, struct symbol *sym)
453 struct token *arguments, *token, *last;
455 token = head->next;
456 last = token->next;
458 arguments = NULL;
459 if (sym->arglist) {
460 arguments = last->next;
461 last = find_argument_end(last, sym->arglist);
463 token->next = &eof_token_entry;
465 /* Replace the token with the token expansion */
466 replace(parent, token, head, sym->expansion);
468 /* Then, replace all the arguments with their expansions */
469 if (arguments)
470 expand_arguments(parent, token, head, arguments, sym->arglist);
472 /* Re-tokenize the sequence if any ## token exists.. */
473 retokenize(head);
475 token = head;
476 while (!eof_token(token->next))
477 token = token->next;
478 token->next = last;
479 return head;
482 static const char *token_name_sequence(struct token *token, int endop, struct token *start)
484 struct token *last;
485 static char buffer[256];
486 char *ptr = buffer;
488 last = token;
489 while (!eof_token(token) && !match_op(token, endop)) {
490 int len;
491 const char *val = token->string->data;
492 if (token_type(token) != TOKEN_STRING)
493 val = show_token(token);
494 len = strlen(val);
495 memcpy(ptr, val, len);
496 ptr += len;
497 token = token->next;
499 *ptr = 0;
500 if (endop && !match_op(token, endop))
501 warn(start->pos, "expected '>' at end of filename");
502 return buffer;
505 static int try_include(const char *path, int plen, const char *filename, int flen, struct token *head)
507 int fd;
508 static char fullname[PATH_MAX];
510 memcpy(fullname, path, plen);
511 if (plen && path[plen-1] != '/') {
512 fullname[plen] = '/';
513 plen++;
515 memcpy(fullname+plen, filename, flen);
516 fd = open(fullname, O_RDONLY);
517 if (fd >= 0) {
518 char * streamname = __alloc_bytes(plen + flen);
519 memcpy(streamname, fullname, plen + flen);
520 head->next = tokenize(streamname, fd, head->next);
521 close(fd);
522 return 1;
524 return 0;
527 static int do_include_path(const char **pptr, struct token *head, struct token *token, const char *filename, int flen)
529 const char *path;
531 while ((path = *pptr++) != NULL) {
532 if (!try_include(path, strlen(path), filename, flen, head))
533 continue;
534 return 1;
536 return 0;
540 static void do_include(int local, struct stream *stream, struct token *head, struct token *token, const char *filename)
542 int flen = strlen(filename) + 1;
544 /* Same directory as current stream? */
545 if (local) {
546 const char *path;
547 char *slash;
548 int plen;
550 path = stream->name;
551 slash = strrchr(path, '/');
552 plen = slash ? slash - path : 0;
554 if (try_include(path, plen, filename, flen, head))
555 return;
558 /* Check the standard include paths.. */
559 if (do_include_path(includepath, head, token, filename, flen))
560 return;
561 if (do_include_path(sys_includepath, head, token, filename, flen))
562 return;
563 if (do_include_path(gcc_includepath, head, token, filename, flen))
564 return;
566 error(token->pos, "unable to open '%s'", filename);
569 static int handle_include(struct stream *stream, struct token *head, struct token *token)
571 const char *filename;
572 struct token *next;
573 int expect;
575 if (stream->constant == -1)
576 stream->constant = 0;
577 if (false_nesting)
578 return 1;
579 next = token->next;
580 expect = '>';
581 if (!match_op(next, '<')) {
582 expand_list(NULL, token);
583 expect = 0;
584 next = token;
586 token = next->next;
587 filename = token_name_sequence(token, expect, token);
588 do_include(!expect, stream, head, token, filename);
589 return 1;
592 static int token_list_different(struct token *list1, struct token *list2)
594 for (;;) {
595 if (list1 == list2)
596 return 0;
597 if (!list1 || !list2)
598 return 1;
599 if (token_type(list1) != token_type(list2))
600 return 1;
601 list1 = list1->next;
602 list2 = list2->next;
607 static int handle_define(struct stream *stream, struct token *head, struct token *token)
609 struct token *arglist, *expansion;
610 struct token *left = token->next;
611 struct symbol *sym;
612 struct ident *name;
614 if (token_type(left) != TOKEN_IDENT) {
615 warn(head->pos, "expected identifier to 'define'");
616 return 0;
618 if (false_nesting)
619 return 1;
620 name = left->ident;
622 arglist = NULL;
623 expansion = left->next;
624 if (!expansion->pos.whitespace && match_op(expansion, '(')) {
625 arglist = expansion;
626 while (!eof_token(expansion)) {
627 struct token *next = expansion->next;
628 if (token_type(expansion) == TOKEN_IDENT) {
629 if (expansion->ident == &__VA_ARGS___ident)
630 warn(expansion->pos, "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro");
631 if (match_op(next, SPECIAL_ELLIPSIS)) {
632 expansion->next = &variable_argument;
633 expansion = next;
634 next = next->next;
637 if (match_op(next, ')')) {
638 // Terminate the arglist
639 expansion->next = &eof_token_entry;
640 expansion = next->next;
641 break;
643 if (match_op(next, ','))
644 expansion->next = next->next;
645 expansion = next;
647 arglist = arglist->next;
650 sym = lookup_symbol(name, NS_PREPROCESSOR);
651 if (sym) {
652 if (token_list_different(sym->expansion, expansion) ||
653 token_list_different(sym->arglist, arglist)) {
654 warn(left->pos, "preprocessor token %.*s redefined",
655 name->len, name->name);
656 info(sym->pos, "this was the original definition");
658 return 1;
660 sym = alloc_symbol(left->pos, SYM_NODE);
661 bind_symbol(sym, name, NS_PREPROCESSOR);
663 sym->expansion = expansion;
664 sym->arglist = arglist;
665 return 1;
668 static int handle_undef(struct stream *stream, struct token *head, struct token *token)
670 struct token *left = token->next;
671 struct symbol **sym;
673 if (token_type(left) != TOKEN_IDENT) {
674 warn(head->pos, "expected identifier to 'undef'");
675 return 0;
677 if (false_nesting)
678 return 1;
679 sym = &left->ident->symbols;
680 while (*sym) {
681 struct symbol *t = *sym;
682 if (t->namespace == NS_PREPROCESSOR) {
683 *sym = t->next_id;
684 return 1;
686 sym = &t->next_id;
688 return 1;
691 static int preprocessor_if(struct token *token, int true)
693 if (if_nesting == 0)
694 unmatched_if = token;
695 if (if_nesting >= MAX_NEST)
696 error(token->pos, "Maximum preprocessor conditional level exhausted");
697 elif_ignore[if_nesting] = false_nesting || true;
698 if (false_nesting || !true) {
699 false_nesting++;
700 return 1;
702 true_nesting++;
703 return 1;
706 static int token_defined(struct token *token)
708 if (token_type(token) == TOKEN_IDENT)
709 return lookup_symbol(token->ident, NS_PREPROCESSOR) != NULL;
711 warn(token->pos, "expected identifier for #if[n]def");
712 return 0;
715 static int handle_ifdef(struct stream *stream, struct token *head, struct token *token)
717 return preprocessor_if(token, token_defined(token->next));
720 static int handle_ifndef(struct stream *stream, struct token *head, struct token *token)
722 struct token *next = token->next;
723 if (stream->constant == -1) {
724 int newconstant = 0;
725 if (token_type(next) == TOKEN_IDENT) {
726 if (!stream->protect || stream->protect == next->ident) {
727 newconstant = -2;
728 stream->protect = next->ident;
729 stream->nesting = if_nesting+1;
732 stream->constant = newconstant;
734 return preprocessor_if(token, !token_defined(next));
737 static int expression_value(struct token *head)
739 struct expression *expr;
740 struct token *token;
741 long long value;
743 expand_list(NULL, head);
744 token = constant_expression(head->next, &expr);
745 if (!eof_token(token))
746 warn(token->pos, "garbage at end: %s", show_token_sequence(token));
747 value = get_expression_value(expr);
748 return value != 0;
751 static int handle_if(struct stream *stream, struct token *head, struct token *token)
753 int value = 0;
754 if (!false_nesting)
755 value = expression_value(token);
756 return preprocessor_if(token, value);
759 static int handle_elif(struct stream * stream, struct token *head, struct token *token)
761 if (stream->nesting == if_nesting)
762 stream->constant = 0;
763 if (false_nesting) {
764 /* If this whole if-thing is if'ed out, an elif cannot help */
765 if (elif_ignore[if_nesting-1])
766 return 1;
767 if (expression_value(token)) {
768 false_nesting--;
769 true_nesting++;
770 elif_ignore[if_nesting-1] = 1;
772 return 1;
774 if (true_nesting) {
775 false_nesting = 1;
776 true_nesting--;
777 return 1;
779 warn(token->pos, "unmatched '#elif'");
780 return 1;
783 static int handle_else(struct stream *stream, struct token *head, struct token *token)
785 if (stream->nesting == if_nesting)
786 stream->constant = 0;
787 if (false_nesting) {
788 /* If this whole if-thing is if'ed out, an else cannot help */
789 if (elif_ignore[if_nesting-1])
790 return 1;
791 false_nesting--;
792 true_nesting++;
793 elif_ignore[if_nesting-1] = 1;
794 return 1;
796 if (true_nesting) {
797 true_nesting--;
798 false_nesting = 1;
799 return 1;
801 warn(token->pos, "unmatched #else");
802 return 1;
805 static int handle_endif(struct stream *stream, struct token *head, struct token *token)
807 if (stream->constant == -2 && stream->nesting == if_nesting)
808 stream->constant = -1;
810 if (false_nesting) {
811 false_nesting--;
812 return 1;
814 if (true_nesting) {
815 true_nesting--;
816 return 1;
818 warn(token->pos, "unmatched #endif");
819 return 1;
822 static const char *show_token_sequence(struct token *token)
824 static char buffer[1024];
825 char *ptr = buffer;
826 int whitespace = 0;
828 if (!token)
829 return "<none>";
830 while (!eof_token(token) && !match_op(token, SPECIAL_ARG_SEPARATOR)) {
831 const char *val = show_token(token);
832 int len = strlen(val);
834 if (ptr + whitespace + len > buffer + sizeof(buffer)) {
835 warn(token->pos, "too long token expansion");
836 break;
839 if (whitespace)
840 *ptr++ = ' ';
841 memcpy(ptr, val, len);
842 ptr += len;
843 token = token->next;
844 whitespace = token->pos.whitespace;
846 *ptr = 0;
847 return buffer;
850 static int handle_warning(struct stream *stream, struct token *head, struct token *token)
852 if (false_nesting)
853 return 1;
854 warn(token->pos, "%s", show_token_sequence(token->next));
855 return 1;
858 static int handle_error(struct stream *stream, struct token *head, struct token *token)
860 if (false_nesting)
861 return 1;
862 warn(token->pos, "%s", show_token_sequence(token->next));
863 return 1;
866 static int handle_nostdinc(struct stream *stream, struct token *head, struct token *token)
868 if (false_nesting)
869 return 1;
870 includepath[0] = NULL;
871 return 1;
874 static void add_path_entry(struct token *token, const char *path)
876 int i;
878 for (i = 0; i < INCLUDEPATHS; i++) {
879 if (!includepath[i]) {
880 includepath[i] = path;
881 includepath[i+1] = NULL;
882 return;
885 warn(token->pos, "too many include path entries");
888 static int handle_add_include(struct stream *stream, struct token *head, struct token *token)
890 for (;;) {
891 token = token->next;
892 if (eof_token(token))
893 return 1;
894 if (token_type(token) != TOKEN_STRING) {
895 warn(token->pos, "expected path string");
896 return 1;
898 add_path_entry(token, token->string->data);
903 * We replace "#pragma xxx" with "__pragma__" in the token
904 * stream. Just as an example.
906 * We'll just #define that away for now, but the theory here
907 * is that we can use this to insert arbitrary token sequences
908 * to turn the pragma's into internal front-end sequences for
909 * when we actually start caring about them.
911 * So eventually this will turn into some kind of extended
912 * __attribute__() like thing, except called __pragma__(xxx).
914 static int handle_pragma(struct stream *stream, struct token *head, struct token *token)
916 struct token *next = head->next;
918 token->ident = &pragma_ident;
919 token->pos.newline = 1;
920 token->pos.whitespace = 1;
921 token->pos.pos = 1;
922 head->next = token;
923 token->next = next;
924 return 1;
927 static int handle_preprocessor_command(struct stream *stream, struct token *head, struct ident *ident, struct token *token)
929 int i;
930 static struct {
931 const char *name;
932 int (*handler)(struct stream *, struct token *, struct token *);
933 } handlers[] = {
934 { "define", handle_define },
935 { "undef", handle_undef },
936 { "ifdef", handle_ifdef },
937 { "ifndef", handle_ifndef },
938 { "else", handle_else },
939 { "endif", handle_endif },
940 { "if", handle_if },
941 { "elif", handle_elif },
942 { "warning", handle_warning },
943 { "error", handle_error },
944 { "include", handle_include },
945 { "pragma", handle_pragma },
947 // our internal preprocessor tokens
948 { "nostdinc", handle_nostdinc },
949 { "add_include", handle_add_include },
952 for (i = 0; i < (sizeof (handlers) / sizeof (handlers[0])); i++) {
953 if (match_string_ident(ident, handlers[i].name))
954 return handlers[i].handler(stream, head, token);
956 return 0;
959 static void handle_preprocessor_line(struct stream *stream, struct token * head, struct token *token)
961 if (!token)
962 return;
964 if (token_type(token) == TOKEN_IDENT)
965 if (handle_preprocessor_command(stream, head, token->ident, token))
966 return;
967 warn(token->pos, "unrecognized preprocessor line '%s'", show_token_sequence(token));
970 static void preprocessor_line(struct stream *stream, struct token * head)
972 struct token *start = head->next, *next;
973 struct token **tp = &start->next;
975 for (;;) {
976 next = *tp;
977 if (next->pos.newline)
978 break;
979 tp = &next->next;
981 head->next = next;
982 *tp = &eof_token_entry;
983 handle_preprocessor_line(stream, head, start->next);
986 static void do_preprocess(struct token *head)
988 do {
989 struct token *next = head->next;
990 struct stream *stream = input_streams + next->pos.stream;
992 if (next->pos.newline && match_op(next, '#')) {
993 preprocessor_line(stream, head);
994 continue;
997 if (false_nesting) {
998 head->next = next->next;
999 continue;
1002 switch (token_type(next)) {
1003 case TOKEN_STREAMEND:
1004 if (stream->constant == -1 && stream->protect) {
1005 stream->constant = 1;
1007 /* fallthrough */
1008 case TOKEN_STREAMBEGIN:
1009 head->next = next->next;
1010 continue;
1012 case TOKEN_IDENT:
1013 next = expand_one_symbol(next, head, next);
1014 /* fallthrough */
1015 default:
1017 * Any token expansion (even if it ended up being an
1018 * empty expansion) in this stream implies it can't
1019 * be constant.
1021 stream->constant = 0;
1024 head = next;
1025 } while (!eof_token(head));
1028 struct token * preprocess(struct token *token)
1030 struct token header = { };
1032 preprocessing = 1;
1033 header.next = token;
1034 do_preprocess(&header);
1035 if (if_nesting)
1036 warn(unmatched_if->pos, "unmatched preprocessor conditional");
1038 // Drop all expressions from pre-processing, they're not used any more.
1039 clear_expression_alloc();
1040 preprocessing = 0;
1042 return header.next;