Create "inline.c", which contains the function "copy_statement()",
[smatch.git] / pre-process.c
blob5bbe32cce6992931777ce444f3da264e29999938
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.
9 * Licensed under the Open Software License version 1.1
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <stdarg.h>
14 #include <stddef.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <limits.h>
21 #include "pre-process.h"
22 #include "lib.h"
23 #include "parse.h"
24 #include "token.h"
25 #include "symbol.h"
26 #include "expression.h"
28 int preprocessing = 0;
30 #define MAXNEST (16)
31 static int true_nesting = 0;
32 static int false_nesting = 0;
33 static struct token *unmatched_if = NULL;
34 static int elif_ignore[MAXNEST];
35 #define if_nesting (true_nesting + false_nesting)
37 #define INCLUDEPATHS 32
38 const char *includepath[INCLUDEPATHS+1] = {
39 NULL
42 const char *sys_includepath[] = {
43 "/usr/include",
44 "/usr/local/include",
45 NULL,
48 const char *gcc_includepath[] = {
49 GCC_INTERNAL_INCLUDE,
50 NULL
55 * This is stupid - the tokenizer already guarantees unique
56 * identifiers, so we should just compare identifier pointers
58 int match_string_ident(struct ident *ident, const char *str)
60 return !str[ident->len] && !memcmp(str, ident->name, ident->len);
63 static struct token *alloc_token(struct position *pos)
65 struct token *token = __alloc_token(0);
67 token->pos.stream = pos->stream;
68 token->pos.line = pos->line;
69 token->pos.pos = pos->pos;
70 token->pos.whitespace = 1;
71 return token;
74 static const char *show_token_sequence(struct token *token);
76 /* Head is one-before-list, and last is one-past-list */
77 static struct token *for_each_ident(struct token *parent, struct token *head, struct token *(*action)(struct token *parent, struct token *head, struct token *))
79 for (;;) {
80 struct token *next = head->next;
82 /* Did we hit the end of the current expansion? */
83 if (eof_token(next))
84 break;
86 if (token_type(next) == TOKEN_IDENT)
87 next = action(parent, head, next);
89 head = next;
91 return head;
94 static struct token *is_defined(struct token *head, struct token *token, struct token *next)
96 char *string[] = { "0", "1" };
97 char *defined = string[lookup_symbol(token->ident, NS_PREPROCESSOR) != NULL];
98 struct token *newtoken = alloc_token(&token->pos);
100 token_type(newtoken) = TOKEN_INTEGER;
101 newtoken->integer = defined;
102 newtoken->next = next;
103 head->next = newtoken;
104 return next;
108 struct token *defined_one_symbol(struct token *head, struct token *next)
110 struct token *token = next->next;
111 struct token *past = token->next;
113 if (match_op(token, '(')) {
114 token = past;
115 past = token->next;
116 if (!match_op(past, ')'))
117 return next;
118 past = past->next;
120 if (token_type(token) == TOKEN_IDENT)
121 return is_defined(head, token, past);
122 return next;
125 /* Expand symbol 'sym' between 'head->next' and 'head->next->next' */
126 static struct token *expand(struct token *, struct token *, struct symbol *);
128 static void replace_with_string(struct token *token, const char *str)
130 int size = strlen(str) + 1;
131 struct string *s = __alloc_string(size);
133 s->length = size;
134 memcpy(s->data, str, size);
135 token_type(token) = TOKEN_STRING;
136 token->string = s;
139 static void replace_with_integer(struct token *token, unsigned int val)
141 char *buf = __alloc_bytes(10);
142 sprintf(buf, "%d", val);
143 token_type(token) = TOKEN_INTEGER;
144 token->integer = buf;
147 struct token *expand_one_symbol(struct token *parent, struct token *head, struct token *token)
149 struct symbol *sym;
150 struct token *x;
152 /* Avoid recursive expansion */
153 x = token;
154 while ((x = x->parent) != NULL) {
155 if (parent && x->ident == parent->ident)
156 return token;
157 if (x->ident == token->ident)
158 return token;
161 sym = lookup_symbol(token->ident, NS_PREPROCESSOR);
162 if (sym) {
163 if (sym->arglist && !match_op(token->next, '('))
164 return token;
165 return expand(token, head, sym);
167 if (!memcmp(token->ident->name, "__LINE__", 9)) {
168 replace_with_integer(token, token->pos.line);
169 } else if (!memcmp(token->ident->name, "__FILE__", 9)) {
170 replace_with_string(token, (input_streams + token->pos.stream)->name);
171 } else if (!memcmp(token->ident->name, "defined", 8)) {
172 return defined_one_symbol(head, token);
174 return token;
177 static struct token *expand_list(struct token *parent, struct token *head)
179 return for_each_ident(parent, head, expand_one_symbol);
182 static struct token *find_argument_end(struct token *start)
184 int nesting = 0;
186 while (!eof_token(start)) {
187 struct token *next = start->next;
188 if (match_op(next, '('))
189 nesting++;
190 else if (match_op(next, ')')) {
191 if (--nesting < 0) {
192 start->next = &eof_token_entry;
193 return next->next;
195 } else if (!nesting && match_op(next, ','))
196 next->special = SPECIAL_ARG_SEPARATOR;
197 start = next;
199 return start;
202 static struct token *dup_token(struct token *token, struct position *pos, int newline)
204 struct token *alloc = alloc_token(pos);
205 token_type(alloc) = token_type(token);
206 alloc->pos.line = pos->line;
207 alloc->pos.newline = newline;
208 alloc->integer = token->integer;
209 return alloc;
212 static void insert(struct token *token, struct token *prev)
214 token->next = prev->next;
215 prev->next = token;
218 static struct token * replace(struct token *parent, struct token *token, struct token *prev, struct token *list)
220 int newline = token->pos.newline;
222 prev->next = token->next;
223 while (!eof_token(list) && !match_op(list, SPECIAL_ARG_SEPARATOR)) {
224 struct token *newtok = dup_token(list, &token->pos, newline);
225 newtok->parent = parent;
226 newline = 0;
227 insert(newtok, prev);
228 prev = newtok;
229 list = list->next;
231 return prev;
234 static struct token *get_argument(int nr, struct token *args)
236 if (!nr)
237 return args;
238 while (!eof_token(args)) {
239 if (match_op(args, SPECIAL_ARG_SEPARATOR))
240 if (!--nr)
241 return args->next;
242 args = args->next;
245 return args;
248 static struct token *stringify(struct token *token, struct token *arg)
250 const char *s = show_token_sequence(arg);
251 int size = strlen(s)+1;
252 struct token *newtoken = alloc_token(&token->pos);
253 struct string *string = __alloc_string(size);
255 newtoken->pos.newline = token->pos.newline;
256 memcpy(string->data, s, size);
257 string->length = size;
258 token_type(newtoken) = TOKEN_STRING;
259 newtoken->string = string;
260 newtoken->next = &eof_token_entry;
261 return newtoken;
264 static int arg_number(struct token *arglist, struct ident *ident)
266 int nr = 0;
268 while (!eof_token(arglist)) {
269 if (arglist->ident == ident)
270 return nr;
271 nr++;
272 arglist = arglist->next;
274 return -1;
277 static struct token empty_arg_token = { .pos = { .type = TOKEN_EOF } };
279 static struct token *expand_one_arg(struct token *parent, struct token *head, struct token *token,
280 struct token *arglist, struct token *arguments)
282 int nr = arg_number(arglist, token->ident);
283 struct token *orig_head = head;
285 if (nr >= 0) {
286 struct token *arg = get_argument(nr, arguments);
287 struct token *last = token->next;
288 token->next = &eof_token_entry;
291 * Special case for gcc 'x ## arg' semantics: if 'arg' is empty
292 * then the 'x' goes away too.
294 if (match_op(head, SPECIAL_HASHHASH) && eof_token(arg)) {
295 arg = &empty_arg_token;
296 empty_arg_token.next = &eof_token_entry;
299 head = replace(NULL, token, head, arg);
300 if (!match_op(orig_head, SPECIAL_HASHHASH) && !match_op(last, SPECIAL_HASHHASH) && !match_op(orig_head, '#'))
301 head = expand_list(parent, orig_head);
302 head->next = last;
303 return head;
305 return token;
308 static void expand_arguments(struct token *parent,
309 struct token *token, struct token *head,
310 struct token *arguments, struct token *arglist)
312 for (;;) {
313 struct token *next = head->next;
315 /* Did we hit the end of the current expansion? */
316 if (eof_token(next))
317 break;
319 if (match_op(next, '#')) {
320 struct token *nextnext = next->next;
321 int nr = arg_number(arglist, nextnext->ident);
322 if (nextnext != head && nr >= 0 && token_type(nextnext) == TOKEN_IDENT) {
323 struct token *newtoken = stringify(nextnext, get_argument(nr, arguments));
324 replace(NULL, nextnext, head, newtoken);
325 continue;
327 warn(next->pos, "'#' operation is not followed by argument name");
330 if (token_type(next) == TOKEN_IDENT)
331 next = expand_one_arg(parent, head, next, arglist, arguments);
333 head = next;
338 * Possibly valid combinations:
339 * - anything + 'empty_arg_token' is empty.
340 * - ident + ident - combine (==ident)
341 * - ident + number - combine (==ident)
342 * - number + number - combine (==number)
343 * - number + ident - combine (==number)
344 * - string + string - leave as is, C will combine them anyway
345 * others cause an error and leave the two tokens as separate tokens.
347 static struct token *hashhash(struct token *head, struct token *first, struct token *second)
349 static char buffer[512], *p;
350 struct token *newtoken;
351 static const char *src;
352 int len;
354 first->next = second;
357 * Special case for gcc 'x ## arg' semantics: if 'arg' is empty
358 * then the 'x' goes away too.
360 * See expand_one_arg.
362 if (token_type(second) == TOKEN_EOF) {
363 head->next = second->next;
364 return head;
367 p = buffer;
368 switch (token_type(first)) {
369 case TOKEN_INTEGER:
370 len = strlen(first->integer);
371 src = first->integer;
372 break;
373 case TOKEN_IDENT:
374 len = first->ident->len;
375 src = first->ident->name;
376 break;
377 default:
378 return second;
380 memcpy(p, src, len);
381 p += len;
383 switch (token_type(second)) {
384 case TOKEN_INTEGER:
385 len = strlen(second->integer);
386 src = second->integer;
387 break;
388 case TOKEN_IDENT:
389 len = second->ident->len;
390 src = second->ident->name;
391 break;
392 default:
393 return second;
395 memcpy(p, src, len);
396 p += len;
397 *p++ = 0;
399 newtoken = alloc_token(&first->pos);
400 head->next = newtoken;
401 token_type(newtoken) = token_type(first);
402 switch (token_type(newtoken)) {
403 case TOKEN_IDENT:
404 newtoken->ident = built_in_ident(buffer);
405 break;
406 case TOKEN_INTEGER:
407 newtoken->integer = __alloc_bytes(p - buffer);
408 memcpy(newtoken->integer, buffer, p - buffer);
409 break;
411 return newtoken;
414 static void retokenize(struct token *head)
416 struct token * next = head->next;
417 struct token * nextnext = next->next;
418 struct token * nextnextnext = nextnext->next;
420 if (eof_token(next) || eof_token(nextnext))
421 return;
423 for (;;) {
424 if (eof_token(nextnextnext))
425 break;
427 if (match_op(nextnext, SPECIAL_HASHHASH)) {
428 struct token *newtoken = hashhash(head, next, nextnextnext);
430 next = newtoken;
431 nextnext = nextnextnext->next;
432 nextnextnext = nextnext->next;
434 newtoken->next = nextnext;
435 if (!eof_token(nextnext))
436 continue;
437 break;
440 head = next;
441 next = nextnext;
442 nextnext = nextnext->next;
443 nextnextnext = nextnextnext->next;
447 static struct token *expand(struct token *parent, struct token *head, struct symbol *sym)
449 struct token *arguments, *token, *last;
451 token = head->next;
452 last = token->next;
454 arguments = NULL;
455 if (sym->arglist) {
456 arguments = last->next;
457 last = find_argument_end(last);
459 token->next = &eof_token_entry;
461 /* Replace the token with the token expansion */
462 replace(parent, token, head, sym->expansion);
464 /* Then, replace all the arguments with their expansions */
465 if (arguments)
466 expand_arguments(parent, token, head, arguments, sym->arglist);
468 /* Re-tokenize the sequence if any ## token exists.. */
469 retokenize(head);
471 token = head;
472 while (!eof_token(token->next))
473 token = token->next;
474 token->next = last;
475 return head;
478 static const char *token_name_sequence(struct token *token, int endop, struct token *start)
480 struct token *last;
481 static char buffer[256];
482 char *ptr = buffer;
484 last = token;
485 while (!eof_token(token) && !match_op(token, endop)) {
486 int len;
487 const char *val = token->string->data;
488 if (token_type(token) != TOKEN_STRING)
489 val = show_token(token);
490 len = strlen(val);
491 memcpy(ptr, val, len);
492 ptr += len;
493 token = token->next;
495 *ptr = 0;
496 if (endop && !match_op(token, endop))
497 warn(start->pos, "expected '>' at end of filename");
498 return buffer;
501 static int try_include(const char *path, int plen, const char *filename, int flen, struct token *head)
503 int fd;
504 static char fullname[PATH_MAX];
506 memcpy(fullname, path, plen);
507 if (plen && path[plen-1] != '/') {
508 fullname[plen] = '/';
509 plen++;
511 memcpy(fullname+plen, filename, flen);
512 fd = open(fullname, O_RDONLY);
513 if (fd >= 0) {
514 char * streamname = __alloc_bytes(plen + flen);
515 memcpy(streamname, fullname, plen + flen);
516 head->next = tokenize(streamname, fd, head->next);
517 close(fd);
518 return 1;
520 return 0;
523 static int do_include_path(const char **pptr, struct token *head, struct token *token, const char *filename, int flen)
525 const char *path;
527 while ((path = *pptr++) != NULL) {
528 if (!try_include(path, strlen(path), filename, flen, head))
529 continue;
530 return 1;
532 return 0;
536 static void do_include(int local, struct stream *stream, struct token *head, struct token *token, const char *filename)
538 int flen = strlen(filename) + 1;
540 /* Same directory as current stream? */
541 if (local) {
542 const char *path;
543 char *slash;
544 int plen;
546 path = stream->name;
547 slash = strrchr(path, '/');
548 plen = slash ? slash - path : 0;
550 if (try_include(path, plen, filename, flen, head))
551 return;
554 /* Check the standard include paths.. */
555 if (do_include_path(includepath, head, token, filename, flen))
556 return;
557 if (do_include_path(sys_includepath, head, token, filename, flen))
558 return;
559 if (do_include_path(gcc_includepath, head, token, filename, flen))
560 return;
562 error(token->pos, "unable to open '%s'", filename);
565 static int handle_include(struct stream *stream, struct token *head, struct token *token)
567 const char *filename;
568 struct token *next;
569 int expect;
571 if (stream->constant == -1)
572 stream->constant = 0;
573 if (false_nesting)
574 return 1;
575 next = token->next;
576 expect = '>';
577 if (!match_op(next, '<')) {
578 expand_list(NULL, token);
579 expect = 0;
580 next = token;
582 token = next->next;
583 filename = token_name_sequence(token, expect, token);
584 do_include(!expect, stream, head, token, filename);
585 return 1;
588 static int token_list_different(struct token *list1, struct token *list2)
590 for (;;) {
591 if (list1 == list2)
592 return 0;
593 if (!list1 || !list2)
594 return 1;
595 if (token_type(list1) != token_type(list2))
596 return 1;
597 list1 = list1->next;
598 list2 = list2->next;
603 static int handle_define(struct stream *stream, struct token *head, struct token *token)
605 struct token *arglist, *expansion;
606 struct token *left = token->next;
607 struct symbol *sym;
608 struct ident *name;
610 if (token_type(left) != TOKEN_IDENT) {
611 warn(head->pos, "expected identifier to 'define'");
612 return 0;
614 if (false_nesting)
615 return 1;
616 name = left->ident;
618 arglist = NULL;
619 expansion = left->next;
620 if (!expansion->pos.whitespace && match_op(expansion, '(')) {
621 arglist = expansion;
622 while (!eof_token(expansion)) {
623 struct token *next = expansion->next;
624 if (match_op(next, ')')) {
625 // Terminate the arglist
626 expansion->next = &eof_token_entry;
627 expansion = next->next;
628 break;
630 if (match_op(next, ','))
631 expansion->next = next->next;
632 expansion = next;
634 arglist = arglist->next;
637 sym = lookup_symbol(name, NS_PREPROCESSOR);
638 if (sym) {
639 if (token_list_different(sym->expansion, expansion) ||
640 token_list_different(sym->arglist, arglist)) {
641 warn(left->pos, "preprocessor token redefined");
642 warn(sym->pos, "this was the original definition");
644 return 1;
646 sym = alloc_symbol(left->pos, SYM_NODE);
647 bind_symbol(sym, name, NS_PREPROCESSOR);
649 sym->expansion = expansion;
650 sym->arglist = arglist;
651 return 1;
654 static int handle_undef(struct stream *stream, struct token *head, struct token *token)
656 struct token *left = token->next;
657 struct symbol **sym;
659 if (token_type(left) != TOKEN_IDENT) {
660 warn(head->pos, "expected identifier to 'undef'");
661 return 0;
663 if (false_nesting)
664 return 1;
665 sym = &left->ident->symbols;
666 while (*sym) {
667 struct symbol *t = *sym;
668 if (t->namespace == NS_PREPROCESSOR) {
669 *sym = t->next_id;
670 return 1;
672 sym = &t->next_id;
674 return 1;
677 static int preprocessor_if(struct token *token, int true)
679 if (if_nesting == 0)
680 unmatched_if = token;
681 elif_ignore[if_nesting] = false_nesting || true;
682 if (false_nesting || !true) {
683 false_nesting++;
684 return 1;
686 true_nesting++;
687 return 1;
690 static int token_defined(struct token *token)
692 if (token_type(token) == TOKEN_IDENT)
693 return lookup_symbol(token->ident, NS_PREPROCESSOR) != NULL;
695 warn(token->pos, "expected identifier for #if[n]def");
696 return 0;
699 static int handle_ifdef(struct stream *stream, struct token *head, struct token *token)
701 return preprocessor_if(token, token_defined(token->next));
704 static int handle_ifndef(struct stream *stream, struct token *head, struct token *token)
706 struct token *next = token->next;
707 if (stream->constant == -1) {
708 int newconstant = 0;
709 if (token_type(next) == TOKEN_IDENT) {
710 if (!stream->protect || stream->protect == next->ident) {
711 newconstant = -2;
712 stream->protect = next->ident;
713 stream->nesting = if_nesting+1;
716 stream->constant = newconstant;
718 return preprocessor_if(token, !token_defined(next));
721 static int expression_value(struct token *head)
723 struct expression *expr;
724 struct token *token;
725 long long value;
727 expand_list(NULL, head);
728 token = constant_expression(head->next, &expr);
729 if (!eof_token(token))
730 warn(token->pos, "garbage at end: %s", show_token_sequence(token));
731 value = get_expression_value(expr);
732 return value != 0;
735 static int handle_if(struct stream *stream, struct token *head, struct token *token)
737 int value = 0;
738 if (!false_nesting)
739 value = expression_value(token);
740 return preprocessor_if(token, value);
743 static int handle_elif(struct stream * stream, struct token *head, struct token *token)
745 if (stream->nesting == if_nesting)
746 stream->constant = 0;
747 if (false_nesting) {
748 /* If this whole if-thing is if'ed out, an elif cannot help */
749 if (elif_ignore[if_nesting-1])
750 return 1;
751 if (expression_value(token)) {
752 false_nesting--;
753 true_nesting++;
754 elif_ignore[if_nesting-1] = 1;
756 return 1;
758 if (true_nesting) {
759 false_nesting = 1;
760 true_nesting--;
761 return 1;
763 warn(token->pos, "unmatched '#elif'");
764 return 1;
767 static int handle_else(struct stream *stream, struct token *head, struct token *token)
769 if (stream->nesting == if_nesting)
770 stream->constant = 0;
771 if (false_nesting) {
772 /* If this whole if-thing is if'ed out, an else cannot help */
773 if (elif_ignore[if_nesting-1])
774 return 1;
775 false_nesting--;
776 true_nesting++;
777 elif_ignore[if_nesting-1] = 1;
778 return 1;
780 if (true_nesting) {
781 true_nesting--;
782 false_nesting = 1;
783 return 1;
785 warn(token->pos, "unmatched #else");
786 return 1;
789 static int handle_endif(struct stream *stream, struct token *head, struct token *token)
791 if (stream->constant == -2 && stream->nesting == if_nesting)
792 stream->constant = -1;
794 if (false_nesting) {
795 false_nesting--;
796 return 1;
798 if (true_nesting) {
799 true_nesting--;
800 return 1;
802 warn(token->pos, "unmatched #endif");
803 return 1;
806 static const char *show_token_sequence(struct token *token)
808 static char buffer[256];
809 char *ptr = buffer;
810 int whitespace = 0;
812 if (!token)
813 return "<none>";
814 while (!eof_token(token) && !match_op(token, SPECIAL_ARG_SEPARATOR)) {
815 const char *val = show_token(token);
816 int len = strlen(val);
817 if (whitespace)
818 *ptr++ = ' ';
819 memcpy(ptr, val, len);
820 ptr += len;
821 token = token->next;
822 whitespace = token->pos.whitespace;
824 *ptr = 0;
825 return buffer;
828 static int handle_warning(struct stream *stream, struct token *head, struct token *token)
830 if (false_nesting)
831 return 1;
832 warn(token->pos, "%s", show_token_sequence(token->next));
833 return 1;
836 static int handle_error(struct stream *stream, struct token *head, struct token *token)
838 if (false_nesting)
839 return 1;
840 warn(token->pos, "%s", show_token_sequence(token->next));
841 return 1;
844 static int handle_nostdinc(struct stream *stream, struct token *head, struct token *token)
846 if (false_nesting)
847 return 1;
848 includepath[0] = NULL;
849 return 1;
852 static void add_path_entry(struct token *token, const char *path)
854 int i;
856 for (i = 0; i < INCLUDEPATHS; i++) {
857 if (!includepath[i]) {
858 includepath[i] = path;
859 includepath[i+1] = NULL;
860 return;
863 warn(token->pos, "too many include path entries");
866 static int handle_add_include(struct stream *stream, struct token *head, struct token *token)
868 for (;;) {
869 token = token->next;
870 if (eof_token(token))
871 return 1;
872 if (token_type(token) != TOKEN_STRING) {
873 warn(token->pos, "expected path string");
874 return 1;
876 add_path_entry(token, token->string->data);
881 * We replace "#pragma xxx" with "__pragma__" in the token
882 * stream. Just as an example.
884 * We'll just #define that away for now, but the theory here
885 * is that we can use this to insert arbitrary token sequences
886 * to turn the pragma's into internal front-end sequences for
887 * when we actually start caring about them.
889 * So eventually this will turn into some kind of extended
890 * __attribute__() like thing, except called __pragma__(xxx).
892 static int handle_pragma(struct stream *stream, struct token *head, struct token *token)
894 struct token *next = head->next;
896 token->ident = &pragma_ident;
897 token->pos.newline = 1;
898 token->pos.whitespace = 1;
899 token->pos.pos = 1;
900 head->next = token;
901 token->next = next;
902 return 1;
905 static int handle_preprocessor_command(struct stream *stream, struct token *head, struct ident *ident, struct token *token)
907 int i;
908 static struct {
909 const char *name;
910 int (*handler)(struct stream *, struct token *, struct token *);
911 } handlers[] = {
912 { "define", handle_define },
913 { "undef", handle_undef },
914 { "ifdef", handle_ifdef },
915 { "ifndef", handle_ifndef },
916 { "else", handle_else },
917 { "endif", handle_endif },
918 { "if", handle_if },
919 { "elif", handle_elif },
920 { "warning", handle_warning },
921 { "error", handle_error },
922 { "include", handle_include },
923 { "pragma", handle_pragma },
925 // our internal preprocessor tokens
926 { "nostdinc", handle_nostdinc },
927 { "add_include", handle_add_include },
930 for (i = 0; i < (sizeof (handlers) / sizeof (handlers[0])); i++) {
931 if (match_string_ident(ident, handlers[i].name))
932 return handlers[i].handler(stream, head, token);
934 return 0;
937 static void handle_preprocessor_line(struct stream *stream, struct token * head, struct token *token)
939 if (!token)
940 return;
942 if (token_type(token) == TOKEN_IDENT)
943 if (handle_preprocessor_command(stream, head, token->ident, token))
944 return;
945 warn(token->pos, "unrecognized preprocessor line '%s'", show_token_sequence(token));
948 static void preprocessor_line(struct stream *stream, struct token * head)
950 struct token *start = head->next, *next;
951 struct token **tp = &start->next;
953 for (;;) {
954 next = *tp;
955 if (next->pos.newline)
956 break;
957 tp = &next->next;
959 head->next = next;
960 *tp = &eof_token_entry;
961 handle_preprocessor_line(stream, head, start->next);
964 static void do_preprocess(struct token *head)
966 do {
967 struct token *next = head->next;
968 struct stream *stream = input_streams + next->pos.stream;
970 if (next->pos.newline && match_op(next, '#')) {
971 preprocessor_line(stream, head);
972 continue;
975 if (false_nesting) {
976 head->next = next->next;
977 continue;
980 switch (token_type(next)) {
981 case TOKEN_STREAMEND:
982 if (stream->constant == -1 && stream->protect) {
983 stream->constant = 1;
985 /* fallthrough */
986 case TOKEN_STREAMBEGIN:
987 head->next = next->next;
988 continue;
990 case TOKEN_IDENT:
991 next = expand_one_symbol(next, head, next);
992 /* fallthrough */
993 default:
995 * Any token expansion (even if it ended up being an
996 * empty expansion) in this stream implies it can't
997 * be constant.
999 stream->constant = 0;
1002 head = next;
1003 } while (!eof_token(head));
1006 struct token * preprocess(struct token *token)
1008 struct token header = { };
1010 preprocessing = 1;
1011 header.next = token;
1012 do_preprocess(&header);
1013 if (if_nesting)
1014 warn(unmatched_if->pos, "unmatched preprocessor conditional");
1016 // Drop all expressions from pre-processing, they're not used any more.
1017 clear_expression_alloc();
1018 preprocessing = 0;
1020 return header.next;