add an is_constant_expression, only try to fold expressions that are really constant...
[cparser] / ast.c
1 #include <config.h>
2
3 #include "ast_t.h"
4 #include "type_t.h"
5
6 #include <assert.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <ctype.h>
10
11 #include "adt/error.h"
12
13 struct obstack ast_obstack;
14
15 static FILE *out;
16 static int   indent;
17
18 static void print_statement(const statement_t *statement);
19
20 void change_indent(int delta)
21 {
22         indent += delta;
23         assert(indent >= 0);
24 }
25
26 void print_indent(void)
27 {
28         for(int i = 0; i < indent; ++i)
29                 fprintf(out, "\t");
30 }
31
32 static void print_const(const const_expression_t *cnst)
33 {
34         if(cnst->expression.datatype == NULL)
35                 return;
36
37         if(is_type_integer(cnst->expression.datatype)) {
38                 fprintf(out, "%lld", cnst->v.int_value);
39         } else if(is_type_floating(cnst->expression.datatype)) {
40                 fprintf(out, "%Lf", cnst->v.float_value);
41         }
42 }
43
44 static void print_quoted_string(const char *string)
45 {
46         fputc('"', out);
47         for(const char *c = string; *c != '\0'; ++c) {
48                 switch(*c) {
49                 case '\"':  fputs("\\\"", out); break;
50                 case '\\':  fputs("\\\\", out); break;
51                 case '\a':  fputs("\\a", out); break;
52                 case '\b':  fputs("\\b", out); break;
53                 case '\f':  fputs("\\f", out); break;
54                 case '\n':  fputs("\\n", out); break;
55                 case '\r':  fputs("\\r", out); break;
56                 case '\t':  fputs("\\t", out); break;
57                 case '\v':  fputs("\\v", out); break;
58                 case '\?':  fputs("\\?", out); break;
59                 default:
60                         if(!isprint(*c)) {
61                                 fprintf(out, "\\x%x", *c);
62                                 break;
63                         }
64                         fputc(*c, out);
65                         break;
66                 }
67         }
68         fputc('"', out);
69 }
70
71 static void print_string_literal(
72                 const string_literal_expression_t *string_literal)
73 {
74         print_quoted_string(string_literal->value);
75 }
76
77 static void print_wide_string_literal(
78         const wide_string_literal_expression_t *const wstr)
79 {
80         fputs("L\"", out);
81         for (const wchar_rep_t *c   = wstr->value.begin,
82                                *end = c + wstr->value.size;
83              c != end; ++c) {
84                 switch (*c) {
85                         case L'\"':  fputs("\\\"", out); break;
86                         case L'\\':  fputs("\\\\", out); break;
87                         case L'\a':  fputs("\\a",  out); break;
88                         case L'\b':  fputs("\\b",  out); break;
89                         case L'\f':  fputs("\\f",  out); break;
90                         case L'\n':  fputs("\\n",  out); break;
91                         case L'\r':  fputs("\\r",  out); break;
92                         case L'\t':  fputs("\\t",  out); break;
93                         case L'\v':  fputs("\\v",  out); break;
94                         case L'\?':  fputs("\\?",  out); break;
95                         default: {
96                                 const unsigned tc = *c;
97                                 if (tc < 0x80U) {
98                                         if (!isprint(*c))  {
99                                                 fprintf(out, "\\%03o", (char)*c);
100                                         } else {
101                                                 fputc(*c, out);
102                                         }
103                                 } else if (tc < 0x800) {
104                                         fputc(0xC0 | (tc >> 6),   out);
105                                         fputc(0x80 | (tc & 0x3F), out);
106                                 } else if (tc < 0x10000) {
107                                         fputc(0xE0 | ( tc >> 12),         out);
108                                         fputc(0x80 | ((tc >>  6) & 0x3F), out);
109                                         fputc(0x80 | ( tc        & 0x3F), out);
110                                 } else {
111                                         fputc(0xF0 | ( tc >> 18),         out);
112                                         fputc(0x80 | ((tc >> 12) & 0x3F), out);
113                                         fputc(0x80 | ((tc >>  6) & 0x3F), out);
114                                         fputc(0x80 | ( tc        & 0x3F), out);
115                                 }
116                         }
117                 }
118         }
119         fputc('"', out);
120 }
121
122 static void print_call_expression(const call_expression_t *call)
123 {
124         print_expression(call->function);
125         fprintf(out, "(");
126         call_argument_t *argument = call->arguments;
127         int              first    = 1;
128         while(argument != NULL) {
129                 if(!first) {
130                         fprintf(out, ", ");
131                 } else {
132                         first = 0;
133                 }
134                 print_expression(argument->expression);
135
136                 argument = argument->next;
137         }
138         fprintf(out, ")");
139 }
140
141 static void print_binary_expression(const binary_expression_t *binexpr)
142 {
143         fprintf(out, "(");
144         print_expression(binexpr->left);
145         fprintf(out, " ");
146         switch(binexpr->expression.type) {
147         case EXPR_BINARY_COMMA:              fputs(",", out);     break;
148         case EXPR_BINARY_ASSIGN:             fputs("=", out);     break;
149         case EXPR_BINARY_ADD:                fputs("+", out);     break;
150         case EXPR_BINARY_SUB:                fputs("-", out);     break;
151         case EXPR_BINARY_MUL:                fputs("*", out);     break;
152         case EXPR_BINARY_MOD:                fputs("%", out);     break;
153         case EXPR_BINARY_DIV:                fputs("/", out);     break;
154         case EXPR_BINARY_BITWISE_OR:         fputs("|", out);     break;
155         case EXPR_BINARY_BITWISE_AND:        fputs("&", out);     break;
156         case EXPR_BINARY_BITWISE_XOR:        fputs("^", out);     break;
157         case EXPR_BINARY_LOGICAL_OR:         fputs("||", out);    break;
158         case EXPR_BINARY_LOGICAL_AND:        fputs("&&", out);    break;
159         case EXPR_BINARY_NOTEQUAL:           fputs("!=", out);    break;
160         case EXPR_BINARY_EQUAL:              fputs("==", out);    break;
161         case EXPR_BINARY_LESS:               fputs("<", out);     break;
162         case EXPR_BINARY_LESSEQUAL:          fputs("<=", out);    break;
163         case EXPR_BINARY_GREATER:            fputs(">", out);     break;
164         case EXPR_BINARY_GREATEREQUAL:       fputs(">=", out);    break;
165         case EXPR_BINARY_SHIFTLEFT:          fputs("<<", out);    break;
166         case EXPR_BINARY_SHIFTRIGHT:         fputs(">>", out);    break;
167
168         case EXPR_BINARY_ADD_ASSIGN:         fputs("+=", out);    break;
169         case EXPR_BINARY_SUB_ASSIGN:         fputs("-=", out);    break;
170         case EXPR_BINARY_MUL_ASSIGN:         fputs("*=", out);    break;
171         case EXPR_BINARY_MOD_ASSIGN:         fputs("%=", out);    break;
172         case EXPR_BINARY_DIV_ASSIGN:         fputs("/=", out);    break;
173         case EXPR_BINARY_BITWISE_OR_ASSIGN:  fputs("|=", out);    break;
174         case EXPR_BINARY_BITWISE_AND_ASSIGN: fputs("&=", out);    break;
175         case EXPR_BINARY_BITWISE_XOR_ASSIGN: fputs("^=", out);    break;
176         case EXPR_BINARY_SHIFTLEFT_ASSIGN:   fputs("<<=", out);   break;
177         case EXPR_BINARY_SHIFTRIGHT_ASSIGN:  fputs(">>=", out);   break;
178         default: panic("invalid binexpression found");
179         }
180         fprintf(out, " ");
181         print_expression(binexpr->right);
182         fprintf(out, ")");
183 }
184
185 static void print_unary_expression(const unary_expression_t *unexpr)
186 {
187         switch(unexpr->expression.type) {
188         case EXPR_UNARY_NEGATE:           fputs("-", out);  break;
189         case EXPR_UNARY_PLUS:             fputs("+", out);  break;
190         case EXPR_UNARY_NOT:              fputs("!", out);  break;
191         case EXPR_UNARY_BITWISE_NEGATE:   fputs("~", out);  break;
192         case EXPR_UNARY_PREFIX_INCREMENT: fputs("++", out); break;
193         case EXPR_UNARY_PREFIX_DECREMENT: fputs("--", out); break;
194         case EXPR_UNARY_DEREFERENCE:      fputs("*", out);  break;
195         case EXPR_UNARY_TAKE_ADDRESS:     fputs("&", out);  break;
196
197         case EXPR_UNARY_POSTFIX_INCREMENT:
198                 fputs("(", out);
199                 print_expression(unexpr->value);
200                 fputs(")", out);
201                 fputs("++", out);
202                 return;
203         case EXPR_UNARY_POSTFIX_DECREMENT:
204                 fputs("(", out);
205                 print_expression(unexpr->value);
206                 fputs(")", out);
207                 fputs("--", out);
208                 return;
209         case EXPR_UNARY_CAST:
210                 fputs("(", out);
211                 print_type(unexpr->expression.datatype);
212                 fputs(")", out);
213                 break;
214         case EXPR_UNARY_CAST_IMPLICIT:
215                 print_expression(unexpr->value);
216                 return;
217         default:
218                 panic("invalid unary expression found");
219         }
220         fputs("(", out);
221         print_expression(unexpr->value);
222         fputs(")", out);
223 }
224
225 static void print_reference_expression(const reference_expression_t *ref)
226 {
227         fprintf(out, "%s", ref->declaration->symbol->string);
228 }
229
230 static void print_array_expression(const array_access_expression_t *expression)
231 {
232         if(!expression->flipped) {
233                 fputs("(", out);
234                 print_expression(expression->array_ref);
235                 fputs(")[", out);
236                 print_expression(expression->index);
237                 fputs("]", out);
238         } else {
239                 fputs("(", out);
240                 print_expression(expression->index);
241                 fputs(")[", out);
242                 print_expression(expression->array_ref);
243                 fputs("]", out);
244         }
245 }
246
247 static void print_sizeof_expression(const sizeof_expression_t *expression)
248 {
249         fputs("sizeof", out);
250         if(expression->size_expression != NULL) {
251                 fputc('(', out);
252                 print_expression(expression->size_expression);
253                 fputc(')', out);
254         } else {
255                 fputc('(', out);
256                 print_type(expression->type);
257                 fputc(')', out);
258         }
259 }
260
261 static void print_builtin_symbol(const builtin_symbol_expression_t *expression)
262 {
263         fputs(expression->symbol->string, out);
264 }
265
266 static void print_conditional(const conditional_expression_t *expression)
267 {
268         fputs("(", out);
269         print_expression(expression->condition);
270         fputs(" ? ", out);
271         print_expression(expression->true_expression);
272         fputs(" : ", out);
273         print_expression(expression->false_expression);
274         fputs(")", out);
275 }
276
277 static void print_va_start(const va_start_expression_t *const expression)
278 {
279         fputs("__builtin_va_start(", out);
280         print_expression(expression->ap);
281         fputs(", ", out);
282         fputs(expression->parameter->symbol->string, out);
283         fputs(")", out);
284 }
285
286 static void print_va_arg(const va_arg_expression_t *expression)
287 {
288         fputs("__builtin_va_arg(", out);
289         print_expression(expression->ap);
290         fputs(", ", out);
291         print_type(expression->expression.datatype);
292         fputs(")", out);
293 }
294
295 static void print_select(const select_expression_t *expression)
296 {
297         print_expression(expression->compound);
298         if(expression->compound->base.datatype == NULL ||
299                         expression->compound->base.datatype->type == TYPE_POINTER) {
300                 fputs("->", out);
301         } else {
302                 fputc('.', out);
303         }
304         fputs(expression->symbol->string, out);
305 }
306
307 static void print_classify_type_expression(
308         const classify_type_expression_t *const expr)
309 {
310         fputs("__builtin_classify_type(", out);
311         print_expression(expr->type_expression);
312         fputc(')', out);
313 }
314
315 void print_expression(const expression_t *expression)
316 {
317         switch(expression->type) {
318         case EXPR_UNKNOWN:
319         case EXPR_INVALID:
320                 fprintf(out, "*invalid expression*");
321                 break;
322         case EXPR_CONST:
323                 print_const(&expression->conste);
324                 break;
325         case EXPR_FUNCTION:
326         case EXPR_PRETTY_FUNCTION:
327         case EXPR_STRING_LITERAL:
328                 print_string_literal(&expression->string);
329                 break;
330         case EXPR_WIDE_STRING_LITERAL:
331                 print_wide_string_literal(&expression->wide_string);
332                 break;
333         case EXPR_CALL:
334                 print_call_expression(&expression->call);
335                 break;
336         EXPR_BINARY_CASES
337                 print_binary_expression(&expression->binary);
338                 break;
339         case EXPR_REFERENCE:
340                 print_reference_expression(&expression->reference);
341                 break;
342         case EXPR_ARRAY_ACCESS:
343                 print_array_expression(&expression->array_access);
344                 break;
345         EXPR_UNARY_CASES
346                 print_unary_expression(&expression->unary);
347                 break;
348         case EXPR_SIZEOF:
349                 print_sizeof_expression(&expression->sizeofe);
350                 break;
351         case EXPR_BUILTIN_SYMBOL:
352                 print_builtin_symbol(&expression->builtin_symbol);
353                 break;
354         case EXPR_CONDITIONAL:
355                 print_conditional(&expression->conditional);
356                 break;
357         case EXPR_VA_START:
358                 print_va_start(&expression->va_starte);
359         case EXPR_VA_ARG:
360                 print_va_arg(&expression->va_arge);
361                 break;
362         case EXPR_SELECT:
363                 print_select(&expression->select);
364                 break;
365         case EXPR_CLASSIFY_TYPE:
366                 print_classify_type_expression(&expression->classify_type);
367                 break;
368
369         case EXPR_OFFSETOF:
370         case EXPR_STATEMENT:
371                 /* TODO */
372                 fprintf(out, "some expression of type %d", (int) expression->type);
373                 break;
374         }
375 }
376
377 static void print_compound_statement(const compound_statement_t *block)
378 {
379         fputs("{\n", out);
380         indent++;
381
382         statement_t *statement = block->statements;
383         while(statement != NULL) {
384                 print_indent();
385                 print_statement(statement);
386
387                 statement = statement->base.next;
388         }
389         indent--;
390         print_indent();
391         fputs("}\n", out);
392 }
393
394 static void print_return_statement(const return_statement_t *statement)
395 {
396         fprintf(out, "return ");
397         if(statement->return_value != NULL)
398                 print_expression(statement->return_value);
399         fputs(";\n", out);
400 }
401
402 static void print_expression_statement(const expression_statement_t *statement)
403 {
404         print_expression(statement->expression);
405         fputs(";\n", out);
406 }
407
408 static void print_goto_statement(const goto_statement_t *statement)
409 {
410         fprintf(out, "goto ");
411         fputs(statement->label->symbol->string, out);
412         fprintf(stderr, "(%p)", (void*) statement->label);
413         fputs(";\n", out);
414 }
415
416 static void print_label_statement(const label_statement_t *statement)
417 {
418         fprintf(stderr, "(%p)", (void*) statement->label);
419         fprintf(out, "%s:\n", statement->label->symbol->string);
420         if(statement->label_statement != NULL) {
421                 print_statement(statement->label_statement);
422         }
423 }
424
425 static void print_if_statement(const if_statement_t *statement)
426 {
427         fputs("if(", out);
428         print_expression(statement->condition);
429         fputs(") ", out);
430         if(statement->true_statement != NULL) {
431                 print_statement(statement->true_statement);
432         }
433
434         if(statement->false_statement != NULL) {
435                 print_indent();
436                 fputs("else ", out);
437                 print_statement(statement->false_statement);
438         }
439 }
440
441 static void print_switch_statement(const switch_statement_t *statement)
442 {
443         fputs("switch(", out);
444         print_expression(statement->expression);
445         fputs(") ", out);
446         print_statement(statement->body);
447 }
448
449 static void print_case_label(const case_label_statement_t *statement)
450 {
451         if(statement->expression == NULL) {
452                 fputs("default:\n", out);
453         } else {
454                 fputs("case ", out);
455                 print_expression(statement->expression);
456                 fputs(":\n", out);
457         }
458         print_statement(statement->label_statement);
459 }
460
461 static void print_declaration_statement(
462                 const declaration_statement_t *statement)
463 {
464         int first = 1;
465         declaration_t *declaration = statement->declarations_begin;
466         for( ; declaration != statement->declarations_end->next;
467                declaration = declaration->next) {
468                 if(!first) {
469                         print_indent();
470                 } else {
471                         first = 0;
472                 }
473                 print_declaration(declaration);
474                 fputc('\n', out);
475         }
476 }
477
478 static void print_while_statement(const while_statement_t *statement)
479 {
480         fputs("while(", out);
481         print_expression(statement->condition);
482         fputs(") ", out);
483         print_statement(statement->body);
484 }
485
486 static void print_do_while_statement(const do_while_statement_t *statement)
487 {
488         fputs("do ", out);
489         print_statement(statement->body);
490         print_indent();
491         fputs("while(", out);
492         print_expression(statement->condition);
493         fputs(");\n", out);
494 }
495
496 static void print_for_statement(const for_statement_t *statement)
497 {
498         fputs("for(", out);
499         if(statement->context.declarations != NULL) {
500                 assert(statement->initialisation == NULL);
501                 print_declaration(statement->context.declarations);
502                 if(statement->context.declarations->next != NULL) {
503                         panic("multiple declarations in for statement not supported yet");
504                 }
505                 fputc(' ', out);
506         } else {
507                 if(statement->initialisation) {
508                         print_expression(statement->initialisation);
509                 }
510                 fputs("; ", out);
511         }
512         if(statement->condition != NULL) {
513                 print_expression(statement->condition);
514         }
515         fputs("; ", out);
516         if(statement->step != NULL) {
517                 print_expression(statement->step);
518         }
519         fputs(")", out);
520         print_statement(statement->body);
521 }
522
523 static void print_asm_constraints(asm_constraint_t *constraints)
524 {
525         asm_constraint_t *constraint = constraints;
526         for( ; constraint != NULL; constraint = constraint->next) {
527                 if(constraint != constraints)
528                         fputs(", ", out);
529
530                 if(constraint->symbol) {
531                         fprintf(out, "[%s] ", constraint->symbol->string);
532                 }
533                 print_quoted_string(constraint->constraints);
534                 fputs(" (", out);
535                 print_expression(constraint->expression);
536                 fputs(")", out);
537         }
538 }
539
540 static void print_asm_clobbers(asm_clobber_t *clobbers)
541 {
542         asm_clobber_t *clobber = clobbers;
543         for( ; clobber != NULL; clobber = clobber->next) {
544                 if(clobber != clobbers)
545                         fputs(", ", out);
546
547                 print_quoted_string(clobber->clobber);
548         }
549 }
550
551 static void print_asm_statement(const asm_statement_t *statement)
552 {
553         fputs("asm ", out);
554         if(statement->is_volatile) {
555                 fputs("volatile ", out);
556         }
557         fputs("(", out);
558         print_quoted_string(statement->asm_text);
559         if(statement->inputs == NULL && statement->outputs == NULL
560                         && statement->clobbers == NULL)
561                 goto end_of_print_asm_statement;
562
563         fputs(" : ", out);
564         print_asm_constraints(statement->inputs);
565         if(statement->outputs == NULL && statement->clobbers == NULL)
566                 goto end_of_print_asm_statement;
567
568         fputs(" : ", out);
569         print_asm_constraints(statement->outputs);
570         if(statement->clobbers == NULL)
571                 goto end_of_print_asm_statement;
572
573         fputs(" : ", out);
574         print_asm_clobbers(statement->clobbers);
575
576 end_of_print_asm_statement:
577         fputs(");\n", out);
578 }
579
580 void print_statement(const statement_t *statement)
581 {
582         switch(statement->type) {
583         case STATEMENT_COMPOUND:
584                 print_compound_statement(&statement->compound);
585                 break;
586         case STATEMENT_RETURN:
587                 print_return_statement(&statement->returns);
588                 break;
589         case STATEMENT_EXPRESSION:
590                 print_expression_statement(&statement->expression);
591                 break;
592         case STATEMENT_LABEL:
593                 print_label_statement(&statement->label);
594                 break;
595         case STATEMENT_GOTO:
596                 print_goto_statement(&statement->gotos);
597                 break;
598         case STATEMENT_CONTINUE:
599                 fputs("continue;\n", out);
600                 break;
601         case STATEMENT_BREAK:
602                 fputs("break;\n", out);
603                 break;
604         case STATEMENT_IF:
605                 print_if_statement(&statement->ifs);
606                 break;
607         case STATEMENT_SWITCH:
608                 print_switch_statement(&statement->switchs);
609                 break;
610         case STATEMENT_CASE_LABEL:
611                 print_case_label(&statement->case_label);
612                 break;
613         case STATEMENT_DECLARATION:
614                 print_declaration_statement(&statement->declaration);
615                 break;
616         case STATEMENT_WHILE:
617                 print_while_statement(&statement->whiles);
618                 break;
619         case STATEMENT_DO_WHILE:
620                 print_do_while_statement(&statement->do_while);
621                 break;
622         case STATEMENT_FOR:
623                 print_for_statement(&statement->fors);
624                 break;
625         case STATEMENT_ASM:
626                 print_asm_statement(&statement->asms);
627                 break;
628         case STATEMENT_INVALID:
629                 fprintf(out, "*invalid statement*");
630                 break;
631         }
632 }
633
634 static void print_storage_class(unsigned storage_class)
635 {
636         switch((storage_class_tag_t) storage_class) {
637         case STORAGE_CLASS_ENUM_ENTRY:
638         case STORAGE_CLASS_NONE:
639                 break;
640         case STORAGE_CLASS_TYPEDEF:       fputs("typedef ",        out); break;
641         case STORAGE_CLASS_EXTERN:        fputs("extern ",         out); break;
642         case STORAGE_CLASS_STATIC:        fputs("static ",         out); break;
643         case STORAGE_CLASS_AUTO:          fputs("auto ",           out); break;
644         case STORAGE_CLASS_REGISTER:      fputs("register ",       out); break;
645         case STORAGE_CLASS_THREAD:        fputs("__thread",        out); break;
646         case STORAGE_CLASS_THREAD_EXTERN: fputs("extern __thread", out); break;
647         case STORAGE_CLASS_THREAD_STATIC: fputs("static __thread", out); break;
648         }
649 }
650
651 void print_initializer(const initializer_t *initializer)
652 {
653         if(initializer->type == INITIALIZER_VALUE) {
654                 const initializer_value_t *value = &initializer->value;
655                 print_expression(value->value);
656                 return;
657         }
658
659         assert(initializer->type == INITIALIZER_LIST);
660         fputs("{ ", out);
661         const initializer_list_t *list = &initializer->list;
662
663         for(size_t i = 0 ; i < list->len; ++i) {
664                 if(i > 0) {
665                         fputs(", ", out);
666                 }
667                 print_initializer(list->initializers[i]);
668         }
669         fputs("}", out);
670 }
671
672 static void print_normal_declaration(const declaration_t *declaration)
673 {
674         print_storage_class(declaration->storage_class);
675         if(declaration->is_inline) {
676                 if (declaration->decl_modifiers & DM_FORCEINLINE)
677                         fputs("__forceinline ", out);
678                 else
679                         fputs("inline ", out);
680         }
681         print_type_ext(declaration->type, declaration->symbol,
682                        &declaration->context);
683
684         if(declaration->type->type == TYPE_FUNCTION) {
685                 if(declaration->init.statement != NULL) {
686                         fputs("\n", out);
687                         print_statement(declaration->init.statement);
688                         return;
689                 }
690         } else if(declaration->init.initializer != NULL) {
691                 fputs(" = ", out);
692                 print_initializer(declaration->init.initializer);
693         }
694         fputc(';', out);
695 }
696
697 void print_declaration(const declaration_t *declaration)
698 {
699         if(declaration->namespc != NAMESPACE_NORMAL &&
700                         declaration->symbol == NULL)
701                 return;
702
703         switch(declaration->namespc) {
704         case NAMESPACE_NORMAL:
705                 print_normal_declaration(declaration);
706                 break;
707         case NAMESPACE_STRUCT:
708                 fputs("struct ", out);
709                 fputs(declaration->symbol->string, out);
710                 fputc(' ', out);
711                 print_compound_definition(declaration);
712                 fputc(';', out);
713                 break;
714         case NAMESPACE_UNION:
715                 fputs("union ", out);
716                 fputs(declaration->symbol->string, out);
717                 fputc(' ', out);
718                 print_compound_definition(declaration);
719                 fputc(';', out);
720                 break;
721         case NAMESPACE_ENUM:
722                 fputs("enum ", out);
723                 fputs(declaration->symbol->string, out);
724                 fputc(' ', out);
725                 print_enum_definition(declaration);
726                 fputc(';', out);
727                 break;
728         }
729 }
730
731 void print_ast(const translation_unit_t *unit)
732 {
733         inc_type_visited();
734
735         declaration_t *declaration = unit->context.declarations;
736         for( ; declaration != NULL; declaration = declaration->next) {
737                 if(declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
738                         continue;
739                 if(declaration->namespc != NAMESPACE_NORMAL &&
740                                 declaration->symbol == NULL)
741                         continue;
742
743                 print_indent();
744                 print_declaration(declaration);
745                 fputc('\n', out);
746         }
747 }
748
749 bool is_constant_expression(const expression_t *expression)
750 {
751         switch(expression->type) {
752
753         case EXPR_CONST:
754         case EXPR_STRING_LITERAL:
755         case EXPR_WIDE_STRING_LITERAL:
756         case EXPR_SIZEOF:
757         case EXPR_CLASSIFY_TYPE:
758         case EXPR_FUNCTION:
759         case EXPR_PRETTY_FUNCTION:
760         case EXPR_OFFSETOF:
761                 return true;
762
763         case EXPR_BUILTIN_SYMBOL:
764         case EXPR_CALL:
765         case EXPR_REFERENCE:
766         case EXPR_SELECT:
767         case EXPR_VA_START:
768         case EXPR_VA_ARG:
769         case EXPR_STATEMENT:
770         case EXPR_UNARY_POSTFIX_INCREMENT:
771         case EXPR_UNARY_POSTFIX_DECREMENT:
772         case EXPR_UNARY_PREFIX_INCREMENT:
773         case EXPR_UNARY_PREFIX_DECREMENT:
774         case EXPR_BINARY_ASSIGN:
775         case EXPR_BINARY_MUL_ASSIGN:
776         case EXPR_BINARY_DIV_ASSIGN:
777         case EXPR_BINARY_MOD_ASSIGN:
778         case EXPR_BINARY_ADD_ASSIGN:
779         case EXPR_BINARY_SUB_ASSIGN:
780         case EXPR_BINARY_SHIFTLEFT_ASSIGN:
781         case EXPR_BINARY_SHIFTRIGHT_ASSIGN:
782         case EXPR_BINARY_BITWISE_AND_ASSIGN:
783         case EXPR_BINARY_BITWISE_XOR_ASSIGN:
784         case EXPR_BINARY_BITWISE_OR_ASSIGN:
785         case EXPR_BINARY_COMMA:
786                 return false;
787
788         case EXPR_UNARY_NEGATE:
789         case EXPR_UNARY_PLUS:
790         case EXPR_UNARY_BITWISE_NEGATE:
791         case EXPR_UNARY_NOT:
792         case EXPR_UNARY_DEREFERENCE:
793         case EXPR_UNARY_TAKE_ADDRESS:
794         case EXPR_UNARY_CAST:
795         case EXPR_UNARY_CAST_IMPLICIT:
796                 return is_constant_expression(expression->unary.value);
797
798         case EXPR_BINARY_ADD:
799         case EXPR_BINARY_SUB:
800         case EXPR_BINARY_MUL:
801         case EXPR_BINARY_DIV:
802         case EXPR_BINARY_MOD:
803         case EXPR_BINARY_EQUAL:
804         case EXPR_BINARY_NOTEQUAL:
805         case EXPR_BINARY_LESS:
806         case EXPR_BINARY_LESSEQUAL:
807         case EXPR_BINARY_GREATER:
808         case EXPR_BINARY_GREATEREQUAL:
809         case EXPR_BINARY_BITWISE_AND:
810         case EXPR_BINARY_BITWISE_OR:
811         case EXPR_BINARY_BITWISE_XOR:
812         case EXPR_BINARY_LOGICAL_AND:
813         case EXPR_BINARY_LOGICAL_OR:
814         case EXPR_BINARY_SHIFTLEFT:
815         case EXPR_BINARY_SHIFTRIGHT:
816         case EXPR_BINARY_ISGREATER:
817         case EXPR_BINARY_ISGREATEREQUAL:
818         case EXPR_BINARY_ISLESS:
819         case EXPR_BINARY_ISLESSEQUAL:
820         case EXPR_BINARY_ISLESSGREATER:
821         case EXPR_BINARY_ISUNORDERED:
822                 return is_constant_expression(expression->binary.left)
823                         && is_constant_expression(expression->binary.right);
824
825         case EXPR_CONDITIONAL:
826                 /* TODO: not correct, we only have to test expressions which are
827                  * evaluated, which means either the true or false part might be not
828                  * constant */
829                 return is_constant_expression(expression->conditional.condition)
830                         && is_constant_expression(expression->conditional.true_expression)
831                         && is_constant_expression(expression->conditional.false_expression);
832
833         case EXPR_ARRAY_ACCESS:
834                 return is_constant_expression(expression->array_access.array_ref)
835                         && is_constant_expression(expression->array_access.index);
836
837         case EXPR_UNKNOWN:
838         case EXPR_INVALID:
839                 break;
840         }
841         panic("invalid expression found (is constant expression)");
842 }
843
844
845 void init_ast(void)
846 {
847         obstack_init(&ast_obstack);
848 }
849
850 void exit_ast(void)
851 {
852         obstack_free(&ast_obstack, NULL);
853 }
854
855 void ast_set_output(FILE *stream)
856 {
857         out = stream;
858         type_set_output(stream);
859 }
860
861 void* (allocate_ast) (size_t size)
862 {
863         return _allocate_ast(size);
864 }