4bf325829c0182c6c19b9d4b7474155ac79f0bc0
[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 /** If set, implicit casts are printed. */
19 bool print_implicit_casts = false;
20
21 /** If set parenthesis are printed to indicate operator precedence. */
22 bool print_parenthesis = false;
23
24 static void print_statement(const statement_t *statement);
25 static void print_expression_prec(const expression_t *expression, unsigned prec);
26
27 void change_indent(int delta)
28 {
29         indent += delta;
30         assert(indent >= 0);
31 }
32
33 void print_indent(void)
34 {
35         for(int i = 0; i < indent; ++i)
36                 fprintf(out, "\t");
37 }
38
39 enum precedence_t {
40         PREC_BOTTOM  =  0,
41         PREC_COMMA   =  2, /* ,                                    left to right */
42         PREC_ASSIGN  =  4, /* = += -= *= /= %= <<= >>= &= ^= |=    right to left */
43         PREC_COND    =  6, /* ?:                                   right to left */
44         PREC_LOG_OR  =  8, /* ||                                   left to right */
45         PREC_LOG_AND = 10, /* &&                                   left to right */
46         PREC_BIT_OR  = 12, /* |                                    left to right */
47         PREC_BIT_XOR = 14, /* ^                                    left to right */
48         PREC_BIT_AND = 16, /* &                                    left to right */
49         PREC_EQ      = 18, /* == !=                                left to right */
50         PREC_CMP     = 20, /* < <= > >=                            left to right */
51         PREC_SHF     = 22, /* << >>                                left to right */
52         PREC_PLUS    = 24, /* + -                                  left to right */
53         PREC_MUL     = 26, /* * / %                                left to right */
54         PREC_UNARY   = 28, /* ! ~ ++ -- + - (type) * & sizeof      right to left */
55         PREC_ACCESS  = 30, /* () [] -> .                           left to right */
56         PREC_PRIM    = 32, /* primary */
57         PREC_TOP     = 34
58 };
59
60 /**
61  * Returns 1 if a given precedence level has right-to-left
62  * associativity, else -1.
63  *
64  * @param precedence   the operator precedence
65  */
66 static int right_to_left(unsigned precedence) {
67         return (precedence == PREC_ASSIGN || precedence == PREC_COND ||
68                 precedence == PREC_UNARY) ? 1 : -1;
69 }
70
71 /**
72  * Return the precedence of an expression given by its kind.
73  *
74  * @param kind   the expression kind
75  */
76 static unsigned get_expression_precedence(expression_kind_t kind)
77 {
78         static const unsigned prec[] = {
79                 [EXPR_UNKNOWN]                   = PREC_PRIM,
80                 [EXPR_INVALID]                   = PREC_PRIM,
81                 [EXPR_REFERENCE]                 = PREC_PRIM,
82                 [EXPR_CHAR_CONST]                = PREC_PRIM,
83                 [EXPR_CONST]                     = PREC_PRIM,
84                 [EXPR_STRING_LITERAL]            = PREC_PRIM,
85                 [EXPR_WIDE_STRING_LITERAL]       = PREC_PRIM,
86                 [EXPR_CALL]                      = PREC_PRIM,
87                 [EXPR_CONDITIONAL]               = PREC_COND,
88                 [EXPR_SELECT]                    = PREC_ACCESS,
89                 [EXPR_ARRAY_ACCESS]              = PREC_ACCESS,
90                 [EXPR_SIZEOF]                    = PREC_UNARY,
91                 [EXPR_CLASSIFY_TYPE]             = PREC_UNARY,
92                 [EXPR_ALIGNOF]                   = PREC_UNARY,
93
94                 [EXPR_FUNCTION]                  = PREC_PRIM,
95                 [EXPR_PRETTY_FUNCTION]           = PREC_PRIM,
96                 [EXPR_BUILTIN_SYMBOL]            = PREC_PRIM,
97                 [EXPR_BUILTIN_CONSTANT_P]        = PREC_PRIM,
98                 [EXPR_BUILTIN_PREFETCH]          = PREC_PRIM,
99                 [EXPR_OFFSETOF]                  = PREC_PRIM,
100                 [EXPR_VA_START]                  = PREC_PRIM,
101                 [EXPR_VA_ARG]                    = PREC_PRIM,
102                 [EXPR_STATEMENT]                 = PREC_ACCESS,
103
104                 [EXPR_UNARY_NEGATE]              = PREC_UNARY,
105                 [EXPR_UNARY_PLUS]                = PREC_UNARY,
106                 [EXPR_UNARY_BITWISE_NEGATE]      = PREC_UNARY,
107                 [EXPR_UNARY_NOT]                 = PREC_UNARY,
108                 [EXPR_UNARY_DEREFERENCE]         = PREC_UNARY,
109                 [EXPR_UNARY_TAKE_ADDRESS]        = PREC_UNARY,
110                 [EXPR_UNARY_POSTFIX_INCREMENT]   = PREC_UNARY,
111                 [EXPR_UNARY_POSTFIX_DECREMENT]   = PREC_UNARY,
112                 [EXPR_UNARY_PREFIX_INCREMENT]    = PREC_UNARY,
113                 [EXPR_UNARY_PREFIX_DECREMENT]    = PREC_UNARY,
114                 [EXPR_UNARY_CAST]                = PREC_UNARY,
115                 [EXPR_UNARY_CAST_IMPLICIT]       = PREC_UNARY,
116                 [EXPR_UNARY_ASSUME]              = PREC_PRIM,
117                 [EXPR_UNARY_BITFIELD_EXTRACT]    = PREC_ACCESS,
118
119                 [EXPR_BINARY_ADD]                = PREC_PLUS,
120                 [EXPR_BINARY_SUB]                = PREC_PLUS,
121                 [EXPR_BINARY_MUL]                = PREC_MUL,
122                 [EXPR_BINARY_DIV]                = PREC_MUL,
123                 [EXPR_BINARY_MOD]                = PREC_MUL,
124                 [EXPR_BINARY_EQUAL]              = PREC_EQ,
125                 [EXPR_BINARY_NOTEQUAL]           = PREC_EQ,
126                 [EXPR_BINARY_LESS]               = PREC_CMP,
127                 [EXPR_BINARY_LESSEQUAL]          = PREC_CMP,
128                 [EXPR_BINARY_GREATER]            = PREC_CMP,
129                 [EXPR_BINARY_GREATEREQUAL]       = PREC_CMP,
130                 [EXPR_BINARY_BITWISE_AND]        = PREC_BIT_AND,
131                 [EXPR_BINARY_BITWISE_OR]         = PREC_BIT_OR,
132                 [EXPR_BINARY_BITWISE_XOR]        = PREC_BIT_XOR,
133                 [EXPR_BINARY_LOGICAL_AND]        = PREC_LOG_AND,
134                 [EXPR_BINARY_LOGICAL_OR]         = PREC_LOG_OR,
135                 [EXPR_BINARY_SHIFTLEFT]          = PREC_SHF,
136                 [EXPR_BINARY_SHIFTRIGHT]         = PREC_SHF,
137                 [EXPR_BINARY_ASSIGN]             = PREC_ASSIGN,
138                 [EXPR_BINARY_MUL_ASSIGN]         = PREC_ASSIGN,
139                 [EXPR_BINARY_DIV_ASSIGN]         = PREC_ASSIGN,
140                 [EXPR_BINARY_MOD_ASSIGN]         = PREC_ASSIGN,
141                 [EXPR_BINARY_ADD_ASSIGN]         = PREC_ASSIGN,
142                 [EXPR_BINARY_SUB_ASSIGN]         = PREC_ASSIGN,
143                 [EXPR_BINARY_SHIFTLEFT_ASSIGN]   = PREC_ASSIGN,
144                 [EXPR_BINARY_SHIFTRIGHT_ASSIGN]  = PREC_ASSIGN,
145                 [EXPR_BINARY_BITWISE_AND_ASSIGN] = PREC_ASSIGN,
146                 [EXPR_BINARY_BITWISE_XOR_ASSIGN] = PREC_ASSIGN,
147                 [EXPR_BINARY_BITWISE_OR_ASSIGN]  = PREC_ASSIGN,
148                 [EXPR_BINARY_COMMA]              = PREC_COMMA,
149
150                 [EXPR_BINARY_BUILTIN_EXPECT]     = PREC_PRIM,
151                 [EXPR_BINARY_ISGREATER]          = PREC_PRIM,
152                 [EXPR_BINARY_ISGREATEREQUAL]     = PREC_PRIM,
153                 [EXPR_BINARY_ISLESS]             = PREC_PRIM,
154                 [EXPR_BINARY_ISLESSEQUAL]        = PREC_PRIM,
155                 [EXPR_BINARY_ISLESSGREATER]      = PREC_PRIM,
156                 [EXPR_BINARY_ISUNORDERED]        = PREC_PRIM
157         };
158 #ifndef NDEBUG
159         if ((unsigned)kind >= (sizeof(prec)/sizeof(prec[0]))) {
160                 panic("wrong expression kind");
161         }
162         unsigned res = prec[kind];
163         if (res == PREC_BOTTOM) {
164                 panic("expression kind not defined in get_expression_precedence()");
165         }
166 #endif
167         return res;
168 }
169
170 /**
171  * Print a constant expression.
172  *
173  * @param cnst  the constant expression
174  */
175 static void print_const(const const_expression_t *cnst)
176 {
177         if(cnst->base.type == NULL)
178                 return;
179
180         const type_t *const type = skip_typeref(cnst->base.type);
181
182         if (is_type_integer(type)) {
183                 fprintf(out, "%lld", cnst->v.int_value);
184         } else if (is_type_float(type)) {
185                 fprintf(out, "%Lf", cnst->v.float_value);
186         } else {
187                 panic("unknown constant");
188         }
189 }
190
191 /**
192  * Print a quoted string constant.
193  *
194  * @param string  the string constant
195  * @param border  the border char
196  */
197 static void print_quoted_string(const string_t *const string, char border)
198 {
199         fputc(border, out);
200         const char *end = string->begin + string->size;
201         for (const char *c = string->begin; c != end; ++c) {
202                 if (*c == border) {
203                         fputc('\\', out);
204                 }
205                 switch(*c) {
206                 case '\\':  fputs("\\\\", out); break;
207                 case '\a':  fputs("\\a", out); break;
208                 case '\b':  fputs("\\b", out); break;
209                 case '\f':  fputs("\\f", out); break;
210                 case '\n':  fputs("\\n", out); break;
211                 case '\r':  fputs("\\r", out); break;
212                 case '\t':  fputs("\\t", out); break;
213                 case '\v':  fputs("\\v", out); break;
214                 case '\?':  fputs("\\?", out); break;
215                 default:
216                         if(!isprint(*c)) {
217                                 fprintf(out, "\\%03o", *c);
218                                 break;
219                         }
220                         fputc(*c, out);
221                         break;
222                 }
223         }
224         fputc(border, out);
225 }
226
227 /**
228  * Print a constant character expression.
229  *
230  * @param cnst  the constant character expression
231  */
232 static void print_char_const(const const_expression_t *cnst)
233 {
234         print_quoted_string(&cnst->v.chars, '\'');
235 }
236
237 /**
238  * Prints a string literal expression.
239  *
240  * @param string_literal  the string literal expression
241  */
242 static void print_string_literal(
243                 const string_literal_expression_t *string_literal)
244 {
245         print_quoted_string(&string_literal->value, '"');
246 }
247
248 /**
249  * Prints a wide string literal expression.
250  *
251  * @param wstr  the wide string literal expression
252  */
253 static void print_wide_string_literal(
254         const wide_string_literal_expression_t *const wstr)
255 {
256         fputs("L\"", out);
257         for (const wchar_rep_t *c   = wstr->value.begin,
258                                *end = c + wstr->value.size;
259              c != end; ++c) {
260                 switch (*c) {
261                         case L'\"':  fputs("\\\"", out); break;
262                         case L'\\':  fputs("\\\\", out); break;
263                         case L'\a':  fputs("\\a",  out); break;
264                         case L'\b':  fputs("\\b",  out); break;
265                         case L'\f':  fputs("\\f",  out); break;
266                         case L'\n':  fputs("\\n",  out); break;
267                         case L'\r':  fputs("\\r",  out); break;
268                         case L'\t':  fputs("\\t",  out); break;
269                         case L'\v':  fputs("\\v",  out); break;
270                         case L'\?':  fputs("\\?",  out); break;
271                         default: {
272                                 const unsigned tc = *c;
273                                 if (tc < 0x80U) {
274                                         if (!isprint(*c))  {
275                                                 fprintf(out, "\\%03o", (char)*c);
276                                         } else {
277                                                 fputc(*c, out);
278                                         }
279                                 } else if (tc < 0x800) {
280                                         fputc(0xC0 | (tc >> 6),   out);
281                                         fputc(0x80 | (tc & 0x3F), out);
282                                 } else if (tc < 0x10000) {
283                                         fputc(0xE0 | ( tc >> 12),         out);
284                                         fputc(0x80 | ((tc >>  6) & 0x3F), out);
285                                         fputc(0x80 | ( tc        & 0x3F), out);
286                                 } else {
287                                         fputc(0xF0 | ( tc >> 18),         out);
288                                         fputc(0x80 | ((tc >> 12) & 0x3F), out);
289                                         fputc(0x80 | ((tc >>  6) & 0x3F), out);
290                                         fputc(0x80 | ( tc        & 0x3F), out);
291                                 }
292                         }
293                 }
294         }
295         fputc('"', out);
296 }
297
298 /**
299  * Prints a call expression.
300  *
301  * @param call  the call expression
302  */
303 static void print_call_expression(const call_expression_t *call)
304 {
305         unsigned prec = get_expression_precedence(call->base.kind);
306         print_expression_prec(call->function, prec);
307         fprintf(out, "(");
308         call_argument_t *argument = call->arguments;
309         int              first    = 1;
310         while(argument != NULL) {
311                 if(!first) {
312                         fprintf(out, ", ");
313                 } else {
314                         first = 0;
315                 }
316                 print_expression_prec(argument->expression, PREC_COMMA + 1);
317
318                 argument = argument->next;
319         }
320         fprintf(out, ")");
321 }
322
323 /**
324  * Prints a binary expression.
325  *
326  * @param binexpr   the binary expression
327  */
328 static void print_binary_expression(const binary_expression_t *binexpr)
329 {
330         unsigned prec = get_expression_precedence(binexpr->base.kind);
331         int      r2l  = right_to_left(prec);
332
333         if(binexpr->base.kind == EXPR_BINARY_BUILTIN_EXPECT) {
334                 fputs("__builtin_expect(", out);
335                 print_expression_prec(binexpr->left, prec);
336                 fputs(", ", out);
337                 print_expression_prec(binexpr->right, prec);
338                 fputc(')', out);
339                 return;
340         }
341
342         print_expression_prec(binexpr->left, prec + r2l);
343         if (binexpr->base.kind != EXPR_BINARY_COMMA) {
344                 fputc(' ', out);
345         }
346         switch (binexpr->base.kind) {
347         case EXPR_BINARY_COMMA:              fputs(",", out);     break;
348         case EXPR_BINARY_ASSIGN:             fputs("=", out);     break;
349         case EXPR_BINARY_ADD:                fputs("+", out);     break;
350         case EXPR_BINARY_SUB:                fputs("-", out);     break;
351         case EXPR_BINARY_MUL:                fputs("*", out);     break;
352         case EXPR_BINARY_MOD:                fputs("%", out);     break;
353         case EXPR_BINARY_DIV:                fputs("/", out);     break;
354         case EXPR_BINARY_BITWISE_OR:         fputs("|", out);     break;
355         case EXPR_BINARY_BITWISE_AND:        fputs("&", out);     break;
356         case EXPR_BINARY_BITWISE_XOR:        fputs("^", out);     break;
357         case EXPR_BINARY_LOGICAL_OR:         fputs("||", out);    break;
358         case EXPR_BINARY_LOGICAL_AND:        fputs("&&", out);    break;
359         case EXPR_BINARY_NOTEQUAL:           fputs("!=", out);    break;
360         case EXPR_BINARY_EQUAL:              fputs("==", out);    break;
361         case EXPR_BINARY_LESS:               fputs("<", out);     break;
362         case EXPR_BINARY_LESSEQUAL:          fputs("<=", out);    break;
363         case EXPR_BINARY_GREATER:            fputs(">", out);     break;
364         case EXPR_BINARY_GREATEREQUAL:       fputs(">=", out);    break;
365         case EXPR_BINARY_SHIFTLEFT:          fputs("<<", out);    break;
366         case EXPR_BINARY_SHIFTRIGHT:         fputs(">>", out);    break;
367
368         case EXPR_BINARY_ADD_ASSIGN:         fputs("+=", out);    break;
369         case EXPR_BINARY_SUB_ASSIGN:         fputs("-=", out);    break;
370         case EXPR_BINARY_MUL_ASSIGN:         fputs("*=", out);    break;
371         case EXPR_BINARY_MOD_ASSIGN:         fputs("%=", out);    break;
372         case EXPR_BINARY_DIV_ASSIGN:         fputs("/=", out);    break;
373         case EXPR_BINARY_BITWISE_OR_ASSIGN:  fputs("|=", out);    break;
374         case EXPR_BINARY_BITWISE_AND_ASSIGN: fputs("&=", out);    break;
375         case EXPR_BINARY_BITWISE_XOR_ASSIGN: fputs("^=", out);    break;
376         case EXPR_BINARY_SHIFTLEFT_ASSIGN:   fputs("<<=", out);   break;
377         case EXPR_BINARY_SHIFTRIGHT_ASSIGN:  fputs(">>=", out);   break;
378         default: panic("invalid binexpression found");
379         }
380         fputc(' ', out);
381         print_expression_prec(binexpr->right, prec - r2l);
382 }
383
384 /**
385  * Prints an unary expression.
386  *
387  * @param unexpr   the unary expression
388  */
389 static void print_unary_expression(const unary_expression_t *unexpr)
390 {
391         unsigned prec = get_expression_precedence(unexpr->base.kind);
392         switch(unexpr->base.kind) {
393         case EXPR_UNARY_NEGATE:           fputs("-", out);  break;
394         case EXPR_UNARY_PLUS:             fputs("+", out);  break;
395         case EXPR_UNARY_NOT:              fputs("!", out);  break;
396         case EXPR_UNARY_BITWISE_NEGATE:   fputs("~", out);  break;
397         case EXPR_UNARY_PREFIX_INCREMENT: fputs("++", out); break;
398         case EXPR_UNARY_PREFIX_DECREMENT: fputs("--", out); break;
399         case EXPR_UNARY_DEREFERENCE:      fputs("*", out);  break;
400         case EXPR_UNARY_TAKE_ADDRESS:     fputs("&", out);  break;
401
402         case EXPR_UNARY_BITFIELD_EXTRACT:
403                 print_expression_prec(unexpr->value, prec);
404                 return;
405
406         case EXPR_UNARY_POSTFIX_INCREMENT:
407                 print_expression_prec(unexpr->value, prec);
408                 fputs("++", out);
409                 return;
410         case EXPR_UNARY_POSTFIX_DECREMENT:
411                 print_expression_prec(unexpr->value, prec);
412                 fputs("--", out);
413                 return;
414         case EXPR_UNARY_CAST_IMPLICIT:
415                 if(!print_implicit_casts) {
416                         print_expression_prec(unexpr->value, prec);
417                         return;
418                 }
419                 /* fallthrough */
420         case EXPR_UNARY_CAST:
421                 fputc('(', out);
422                 print_type(unexpr->base.type);
423                 fputc(')', out);
424                 break;
425         case EXPR_UNARY_ASSUME:
426                 fputs("__assume(", out);
427                 print_expression_prec(unexpr->value, PREC_COMMA + 1);
428                 fputc(')', out);
429                 return;
430         default:
431                 panic("invalid unary expression found");
432         }
433         print_expression_prec(unexpr->value, prec);
434 }
435
436 /**
437  * Prints a reference expression.
438  *
439  * @param ref   the reference expression
440  */
441 static void print_reference_expression(const reference_expression_t *ref)
442 {
443         fprintf(out, "%s", ref->declaration->symbol->string);
444 }
445
446 /**
447  * Prints an array expression.
448  *
449  * @param expression   the array expression
450  */
451 static void print_array_expression(const array_access_expression_t *expression)
452 {
453         unsigned prec = get_expression_precedence(expression->base.kind);
454         if(!expression->flipped) {
455                 print_expression_prec(expression->array_ref, prec);
456                 fputc('[', out);
457                 print_expression_prec(expression->index, prec);
458                 fputc(']', out);
459         } else {
460                 print_expression_prec(expression->index, prec);
461                 fputc('[', out);
462                 print_expression_prec(expression->array_ref, prec);
463                 fputc(']', out);
464         }
465 }
466
467 /**
468  * Prints a typeproperty expression (sizeof or __alignof__).
469  *
470  * @param expression   the type property expression
471  */
472 static void print_typeprop_expression(const typeprop_expression_t *expression)
473 {
474         if (expression->base.kind == EXPR_SIZEOF) {
475                 fputs("sizeof", out);
476         } else {
477                 assert(expression->base.kind == EXPR_ALIGNOF);
478                 fputs("__alignof__", out);
479         }
480         if(expression->tp_expression != NULL) {
481                 /* always print the '()' here, sizeof x is right but unusual */
482                 fputc('(', out);
483                 print_expression_prec(expression->tp_expression, PREC_ACCESS);
484                 fputc(')', out);
485         } else {
486                 fputc('(', out);
487                 print_type(expression->type);
488                 fputc(')', out);
489         }
490 }
491
492 /**
493  * Prints an builtin symbol.
494  *
495  * @param expression   the builtin symbol expression
496  */
497 static void print_builtin_symbol(const builtin_symbol_expression_t *expression)
498 {
499         fputs(expression->symbol->string, out);
500 }
501
502 /**
503  * Prints a builtin constant expression.
504  *
505  * @param expression   the builtin constant expression
506  */
507 static void print_builtin_constant(const builtin_constant_expression_t *expression)
508 {
509         fputs("__builtin_constant_p(", out);
510         print_expression_prec(expression->value, PREC_COMMA + 1);
511         fputc(')', out);
512 }
513
514 /**
515  * Prints a builtin prefetch expression.
516  *
517  * @param expression   the builtin prefetch expression
518  */
519 static void print_builtin_prefetch(const builtin_prefetch_expression_t *expression)
520 {
521         fputs("__builtin_prefetch(", out);
522         print_expression_prec(expression->adr, PREC_COMMA + 1);
523         if (expression->rw) {
524                 fputc(',', out);
525                 print_expression_prec(expression->rw, PREC_COMMA + 1);
526         }
527         if (expression->locality) {
528                 fputc(',', out);
529                 print_expression_prec(expression->locality, PREC_COMMA + 1);
530         }
531         fputc(')', out);
532 }
533
534 /**
535  * Prints a conditional expression.
536  *
537  * @param expression   the conditional expression
538  */
539 static void print_conditional(const conditional_expression_t *expression)
540 {
541         unsigned prec = get_expression_precedence(expression->base.kind);
542         fputs("(", out);
543         print_expression_prec(expression->condition, prec);
544         fputs(" ? ", out);
545         print_expression_prec(expression->true_expression, prec);
546         fputs(" : ", out);
547         print_expression_prec(expression->false_expression, prec);
548         fputs(")", out);
549 }
550
551 /**
552  * Prints a va_start expression.
553  *
554  * @param expression   the va_start expression
555  */
556 static void print_va_start(const va_start_expression_t *const expression)
557 {
558         fputs("__builtin_va_start(", out);
559         print_expression_prec(expression->ap, PREC_COMMA + 1);
560         fputs(", ", out);
561         fputs(expression->parameter->symbol->string, out);
562         fputs(")", out);
563 }
564
565 /**
566  * Prints a va_arg expression.
567  *
568  * @param expression   the va_arg expression
569  */
570 static void print_va_arg(const va_arg_expression_t *expression)
571 {
572         fputs("__builtin_va_arg(", out);
573         print_expression_prec(expression->ap, PREC_COMMA + 1);
574         fputs(", ", out);
575         print_type(expression->base.type);
576         fputs(")", out);
577 }
578
579 /**
580  * Prints a select expression (. or ->).
581  *
582  * @param expression   the select expression
583  */
584 static void print_select(const select_expression_t *expression)
585 {
586         unsigned prec = get_expression_precedence(expression->base.kind);
587         print_expression_prec(expression->compound, prec);
588         if(expression->compound->base.type == NULL ||
589                         expression->compound->base.type->kind == TYPE_POINTER) {
590                 fputs("->", out);
591         } else {
592                 fputc('.', out);
593         }
594         fputs(expression->symbol->string, out);
595 }
596
597 /**
598  * Prints a type classify expression.
599  *
600  * @param expr   the type classify expression
601  */
602 static void print_classify_type_expression(
603         const classify_type_expression_t *const expr)
604 {
605         fputs("__builtin_classify_type(", out);
606         print_expression_prec(expr->type_expression, PREC_COMMA + 1);
607         fputc(')', out);
608 }
609
610 /**
611  * Prints a designator.
612  *
613  * @param designator  the designator
614  */
615 static void print_designator(const designator_t *designator)
616 {
617         fputs(designator->symbol->string, out);
618         for (designator = designator->next; designator != NULL; designator = designator->next) {
619                 if (designator->array_access) {
620                         fputc('[', out);
621                         print_expression_prec(designator->array_access, PREC_ACCESS);
622                         fputc(']', out);
623                 } else {
624                         fputc('.', out);
625                         fputs(designator->symbol->string, out);
626                 }
627         }
628 }
629
630 /**
631  * Prints an offsetof expression.
632  *
633  * @param expression   the offset expression
634  */
635 static void print_offsetof_expression(const offsetof_expression_t *expression)
636 {
637         fputs("__builtin_offsetof", out);
638         fputc('(', out);
639         print_type(expression->type);
640         fputc(',', out);
641         print_designator(expression->designator);
642         fputc(')', out);
643 }
644
645 /**
646  * Prints a statement expression.
647  *
648  * @param expression   the statement expression
649  */
650 static void print_statement_expression(const statement_expression_t *expression)
651 {
652         fputc('(', out);
653         print_statement(expression->statement);
654         fputc(')', out);
655 }
656
657 /**
658  * Prints an expression with parenthesis if needed.
659  *
660  * @param expression  the expression to print
661  * @param top_prec    the precedence of the user of this expression.
662  */
663 static void print_expression_prec(const expression_t *expression, unsigned top_prec)
664 {
665         unsigned prec = get_expression_precedence(expression->base.kind);
666         if (print_parenthesis && top_prec != PREC_BOTTOM)
667                 top_prec = PREC_TOP;
668         if (top_prec > prec)
669                 fputc('(', out);
670         switch(expression->kind) {
671         case EXPR_UNKNOWN:
672         case EXPR_INVALID:
673                 fprintf(out, "*invalid expression*");
674                 break;
675         case EXPR_CHAR_CONST:
676                 print_char_const(&expression->conste);
677                 break;
678         case EXPR_CONST:
679                 print_const(&expression->conste);
680                 break;
681         case EXPR_FUNCTION:
682         case EXPR_PRETTY_FUNCTION:
683         case EXPR_STRING_LITERAL:
684                 print_string_literal(&expression->string);
685                 break;
686         case EXPR_WIDE_STRING_LITERAL:
687                 print_wide_string_literal(&expression->wide_string);
688                 break;
689         case EXPR_CALL:
690                 print_call_expression(&expression->call);
691                 break;
692         EXPR_BINARY_CASES
693                 print_binary_expression(&expression->binary);
694                 break;
695         case EXPR_REFERENCE:
696                 print_reference_expression(&expression->reference);
697                 break;
698         case EXPR_ARRAY_ACCESS:
699                 print_array_expression(&expression->array_access);
700                 break;
701         EXPR_UNARY_CASES
702                 print_unary_expression(&expression->unary);
703                 break;
704         case EXPR_SIZEOF:
705         case EXPR_ALIGNOF:
706                 print_typeprop_expression(&expression->typeprop);
707                 break;
708         case EXPR_BUILTIN_SYMBOL:
709                 print_builtin_symbol(&expression->builtin_symbol);
710                 break;
711         case EXPR_BUILTIN_CONSTANT_P:
712                 print_builtin_constant(&expression->builtin_constant);
713                 break;
714         case EXPR_BUILTIN_PREFETCH:
715                 print_builtin_prefetch(&expression->builtin_prefetch);
716                 break;
717         case EXPR_CONDITIONAL:
718                 print_conditional(&expression->conditional);
719                 break;
720         case EXPR_VA_START:
721                 print_va_start(&expression->va_starte);
722                 break;
723         case EXPR_VA_ARG:
724                 print_va_arg(&expression->va_arge);
725                 break;
726         case EXPR_SELECT:
727                 print_select(&expression->select);
728                 break;
729         case EXPR_CLASSIFY_TYPE:
730                 print_classify_type_expression(&expression->classify_type);
731                 break;
732         case EXPR_OFFSETOF:
733                 print_offsetof_expression(&expression->offsetofe);
734                 break;
735         case EXPR_STATEMENT:
736                 print_statement_expression(&expression->statement);
737                 break;
738
739         default:
740                 /* TODO */
741                 fprintf(out, "some expression of type %d", (int) expression->kind);
742                 break;
743         }
744         if (top_prec > prec)
745                 fputc(')', out);
746 }
747
748 /**
749  * Print an compound statement.
750  *
751  * @param block  the compound statement
752  */
753 static void print_compound_statement(const compound_statement_t *block)
754 {
755         fputs("{\n", out);
756         ++indent;
757
758         statement_t *statement = block->statements;
759         while(statement != NULL) {
760                 if (statement->base.kind == STATEMENT_CASE_LABEL)
761                         --indent;
762                 print_indent();
763                 print_statement(statement);
764
765                 statement = statement->base.next;
766         }
767         --indent;
768         print_indent();
769         fputs("}\n", out);
770 }
771
772 /**
773  * Print a return statement.
774  *
775  * @param statement  the return statement
776  */
777 static void print_return_statement(const return_statement_t *statement)
778 {
779         fprintf(out, "return ");
780         if(statement->value != NULL)
781                 print_expression(statement->value);
782         fputs(";\n", out);
783 }
784
785 /**
786  * Print an expression statement.
787  *
788  * @param statement  the expression statement
789  */
790 static void print_expression_statement(const expression_statement_t *statement)
791 {
792         print_expression(statement->expression);
793         fputs(";\n", out);
794 }
795
796 /**
797  * Print a goto statement.
798  *
799  * @param statement  the goto statement
800  */
801 static void print_goto_statement(const goto_statement_t *statement)
802 {
803         fprintf(out, "goto ");
804         fputs(statement->label->symbol->string, out);
805         fprintf(stderr, "(%p)", (void*) statement->label);
806         fputs(";\n", out);
807 }
808
809 /**
810  * Print a label statement.
811  *
812  * @param statement  the label statement
813  */
814 static void print_label_statement(const label_statement_t *statement)
815 {
816         fprintf(stderr, "(%p)", (void*) statement->label);
817         fprintf(out, "%s:\n", statement->label->symbol->string);
818         if(statement->statement != NULL) {
819                 print_statement(statement->statement);
820         }
821 }
822
823 /**
824  * Print an if statement.
825  *
826  * @param statement  the if statement
827  */
828 static void print_if_statement(const if_statement_t *statement)
829 {
830         fputs("if(", out);
831         print_expression(statement->condition);
832         fputs(") ", out);
833         if(statement->true_statement != NULL) {
834                 print_statement(statement->true_statement);
835         }
836
837         if(statement->false_statement != NULL) {
838                 print_indent();
839                 fputs("else ", out);
840                 print_statement(statement->false_statement);
841         }
842 }
843
844 /**
845  * Print a switch statement.
846  *
847  * @param statement  the switch statement
848  */
849 static void print_switch_statement(const switch_statement_t *statement)
850 {
851         fputs("switch(", out);
852         print_expression(statement->expression);
853         fputs(") ", out);
854         print_statement(statement->body);
855 }
856
857 /**
858  * Print a case label (including the default label).
859  *
860  * @param statement  the case label statement
861  */
862 static void print_case_label(const case_label_statement_t *statement)
863 {
864         if(statement->expression == NULL) {
865                 fputs("default:\n", out);
866         } else {
867                 fputs("case ", out);
868                 print_expression(statement->expression);
869                 if (statement->end_range != NULL) {
870                         fputs(" ... ", out);
871                         print_expression(statement->end_range);
872                 }
873                 fputs(":\n", out);
874         }
875         ++indent;
876         if(statement->statement != NULL) {
877                 if (statement->statement->base.kind == STATEMENT_CASE_LABEL) {
878                         --indent;
879                 }
880                 print_indent();
881                 print_statement(statement->statement);
882         }
883 }
884
885 /**
886  * Print a declaration statement.
887  *
888  * @param statement   the statement
889  */
890 static void print_declaration_statement(
891                 const declaration_statement_t *statement)
892 {
893         int first = 1;
894         declaration_t *declaration = statement->declarations_begin;
895         for( ; declaration != statement->declarations_end->next;
896                declaration = declaration->next) {
897                 if(!first) {
898                         print_indent();
899                 } else {
900                         first = 0;
901                 }
902                 print_declaration(declaration);
903                 fputc('\n', out);
904         }
905 }
906
907 /**
908  * Print a while statement.
909  *
910  * @param statement   the statement
911  */
912 static void print_while_statement(const while_statement_t *statement)
913 {
914         fputs("while(", out);
915         print_expression(statement->condition);
916         fputs(") ", out);
917         print_statement(statement->body);
918 }
919
920 /**
921  * Print a do-while statement.
922  *
923  * @param statement   the statement
924  */
925 static void print_do_while_statement(const do_while_statement_t *statement)
926 {
927         fputs("do ", out);
928         print_statement(statement->body);
929         print_indent();
930         fputs("while(", out);
931         print_expression(statement->condition);
932         fputs(");\n", out);
933 }
934
935 /**
936  * Print a for statement.
937  *
938  * @param statement   the statement
939  */
940 static void print_for_statement(const for_statement_t *statement)
941 {
942         fputs("for(", out);
943         if(statement->scope.declarations != NULL) {
944                 assert(statement->initialisation == NULL);
945                 print_declaration(statement->scope.declarations);
946                 if(statement->scope.declarations->next != NULL) {
947                         panic("multiple declarations in for statement not supported yet");
948                 }
949                 fputc(' ', out);
950         } else {
951                 if(statement->initialisation) {
952                         print_expression(statement->initialisation);
953                 }
954                 fputs("; ", out);
955         }
956         if(statement->condition != NULL) {
957                 print_expression(statement->condition);
958         }
959         fputs("; ", out);
960         if(statement->step != NULL) {
961                 print_expression(statement->step);
962         }
963         fputs(")", out);
964         print_statement(statement->body);
965 }
966
967 /**
968  * Print assembler constraints.
969  *
970  * @param constraints   the constraints
971  */
972 static void print_asm_constraints(asm_constraint_t *constraints)
973 {
974         asm_constraint_t *constraint = constraints;
975         for( ; constraint != NULL; constraint = constraint->next) {
976                 if(constraint != constraints)
977                         fputs(", ", out);
978
979                 if(constraint->symbol) {
980                         fprintf(out, "[%s] ", constraint->symbol->string);
981                 }
982                 print_quoted_string(&constraint->constraints, '"');
983                 fputs(" (", out);
984                 print_expression(constraint->expression);
985                 fputs(")", out);
986         }
987 }
988
989 /**
990  * Print assembler clobbers.
991  *
992  * @param clobbers   the clobbers
993  */
994 static void print_asm_clobbers(asm_clobber_t *clobbers)
995 {
996         asm_clobber_t *clobber = clobbers;
997         for( ; clobber != NULL; clobber = clobber->next) {
998                 if(clobber != clobbers)
999                         fputs(", ", out);
1000
1001                 print_quoted_string(&clobber->clobber, '"');
1002         }
1003 }
1004
1005 /**
1006  * Print an assembler statement.
1007  *
1008  * @param statement   the statement
1009  */
1010 static void print_asm_statement(const asm_statement_t *statement)
1011 {
1012         fputs("asm ", out);
1013         if(statement->is_volatile) {
1014                 fputs("volatile ", out);
1015         }
1016         fputs("(", out);
1017         print_quoted_string(&statement->asm_text, '"');
1018         if(statement->inputs == NULL && statement->outputs == NULL
1019                         && statement->clobbers == NULL)
1020                 goto end_of_print_asm_statement;
1021
1022         fputs(" : ", out);
1023         print_asm_constraints(statement->inputs);
1024         if(statement->outputs == NULL && statement->clobbers == NULL)
1025                 goto end_of_print_asm_statement;
1026
1027         fputs(" : ", out);
1028         print_asm_constraints(statement->outputs);
1029         if(statement->clobbers == NULL)
1030                 goto end_of_print_asm_statement;
1031
1032         fputs(" : ", out);
1033         print_asm_clobbers(statement->clobbers);
1034
1035 end_of_print_asm_statement:
1036         fputs(");\n", out);
1037 }
1038
1039 /**
1040  * Print a statement.
1041  *
1042  * @param statement   the statement
1043  */
1044 void print_statement(const statement_t *statement)
1045 {
1046         switch(statement->kind) {
1047         case STATEMENT_COMPOUND:
1048                 print_compound_statement(&statement->compound);
1049                 break;
1050         case STATEMENT_RETURN:
1051                 print_return_statement(&statement->returns);
1052                 break;
1053         case STATEMENT_EXPRESSION:
1054                 print_expression_statement(&statement->expression);
1055                 break;
1056         case STATEMENT_LABEL:
1057                 print_label_statement(&statement->label);
1058                 break;
1059         case STATEMENT_GOTO:
1060                 print_goto_statement(&statement->gotos);
1061                 break;
1062         case STATEMENT_CONTINUE:
1063                 fputs("continue;\n", out);
1064                 break;
1065         case STATEMENT_BREAK:
1066                 fputs("break;\n", out);
1067                 break;
1068         case STATEMENT_IF:
1069                 print_if_statement(&statement->ifs);
1070                 break;
1071         case STATEMENT_SWITCH:
1072                 print_switch_statement(&statement->switchs);
1073                 break;
1074         case STATEMENT_CASE_LABEL:
1075                 print_case_label(&statement->case_label);
1076                 break;
1077         case STATEMENT_DECLARATION:
1078                 print_declaration_statement(&statement->declaration);
1079                 break;
1080         case STATEMENT_WHILE:
1081                 print_while_statement(&statement->whiles);
1082                 break;
1083         case STATEMENT_DO_WHILE:
1084                 print_do_while_statement(&statement->do_while);
1085                 break;
1086         case STATEMENT_FOR:
1087                 print_for_statement(&statement->fors);
1088                 break;
1089         case STATEMENT_ASM:
1090                 print_asm_statement(&statement->asms);
1091                 break;
1092         case STATEMENT_INVALID:
1093                 fprintf(out, "*invalid statement*");
1094                 break;
1095         }
1096 }
1097
1098 /**
1099  * Print a storage class.
1100  *
1101  * @param storage_class   the storage class
1102  */
1103 static void print_storage_class(unsigned storage_class)
1104 {
1105         switch((storage_class_tag_t) storage_class) {
1106         case STORAGE_CLASS_ENUM_ENTRY:
1107         case STORAGE_CLASS_NONE:
1108                 break;
1109         case STORAGE_CLASS_TYPEDEF:       fputs("typedef ",        out); break;
1110         case STORAGE_CLASS_EXTERN:        fputs("extern ",         out); break;
1111         case STORAGE_CLASS_STATIC:        fputs("static ",         out); break;
1112         case STORAGE_CLASS_AUTO:          fputs("auto ",           out); break;
1113         case STORAGE_CLASS_REGISTER:      fputs("register ",       out); break;
1114         case STORAGE_CLASS_THREAD:        fputs("__thread",        out); break;
1115         case STORAGE_CLASS_THREAD_EXTERN: fputs("extern __thread", out); break;
1116         case STORAGE_CLASS_THREAD_STATIC: fputs("static __thread", out); break;
1117         }
1118 }
1119
1120 /**
1121  * Print an initializer.
1122  *
1123  * @param initializer  the initializer
1124  */
1125 void print_initializer(const initializer_t *initializer)
1126 {
1127         if(initializer->kind == INITIALIZER_VALUE) {
1128                 const initializer_value_t *value = &initializer->value;
1129                 print_expression(value->value);
1130                 return;
1131         }
1132
1133         assert(initializer->kind == INITIALIZER_LIST);
1134         fputs("{ ", out);
1135         const initializer_list_t *list = &initializer->list;
1136
1137         for(size_t i = 0 ; i < list->len; ++i) {
1138                 if(i > 0) {
1139                         fputs(", ", out);
1140                 }
1141                 print_initializer(list->initializers[i]);
1142         }
1143         fputs("}", out);
1144 }
1145
1146 /**
1147  * Print a declaration in the NORMAL namespace.
1148  *
1149  * @param declaration  the declaration
1150  */
1151 static void print_normal_declaration(const declaration_t *declaration)
1152 {
1153         print_storage_class(declaration->storage_class);
1154         if(declaration->is_inline) {
1155                 if (declaration->modifiers & DM_FORCEINLINE)
1156                         fputs("__forceinline ", out);
1157                 else
1158                         fputs("inline ", out);
1159         }
1160         print_type_ext(declaration->type, declaration->symbol,
1161                        &declaration->scope);
1162
1163         if(declaration->type->kind == TYPE_FUNCTION) {
1164                 if(declaration->init.statement != NULL) {
1165                         fputs("\n", out);
1166                         print_statement(declaration->init.statement);
1167                         return;
1168                 }
1169         } else if(declaration->init.initializer != NULL) {
1170                 fputs(" = ", out);
1171                 print_initializer(declaration->init.initializer);
1172         }
1173         fputc(';', out);
1174 }
1175
1176 /**
1177  * Prints an expression.
1178  *
1179  * @param expression  the expression
1180  */
1181 void print_expression(const expression_t *expression) {
1182         print_expression_prec(expression, PREC_BOTTOM);
1183 }
1184
1185 /**
1186  * Print a declaration.
1187  *
1188  * @param declaration  the declaration
1189  */
1190 void print_declaration(const declaration_t *declaration)
1191 {
1192         if(declaration->namespc != NAMESPACE_NORMAL &&
1193                         declaration->symbol == NULL)
1194                 return;
1195
1196         switch(declaration->namespc) {
1197         case NAMESPACE_NORMAL:
1198                 print_normal_declaration(declaration);
1199                 break;
1200         case NAMESPACE_STRUCT:
1201                 fputs("struct ", out);
1202                 fputs(declaration->symbol->string, out);
1203                 fputc(' ', out);
1204                 print_compound_definition(declaration);
1205                 fputc(';', out);
1206                 break;
1207         case NAMESPACE_UNION:
1208                 fputs("union ", out);
1209                 fputs(declaration->symbol->string, out);
1210                 fputc(' ', out);
1211                 print_compound_definition(declaration);
1212                 fputc(';', out);
1213                 break;
1214         case NAMESPACE_ENUM:
1215                 fputs("enum ", out);
1216                 fputs(declaration->symbol->string, out);
1217                 fputc(' ', out);
1218                 print_enum_definition(declaration);
1219                 fputc(';', out);
1220                 break;
1221         }
1222 }
1223
1224 /**
1225  * Print the AST of a translation unit.
1226  *
1227  * @param unit   the translation unit
1228  */
1229 void print_ast(const translation_unit_t *unit)
1230 {
1231         inc_type_visited();
1232
1233         declaration_t *declaration = unit->scope.declarations;
1234         for( ; declaration != NULL; declaration = declaration->next) {
1235                 if(declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
1236                         continue;
1237                 if(declaration->namespc != NAMESPACE_NORMAL &&
1238                                 declaration->symbol == NULL)
1239                         continue;
1240
1241                 print_indent();
1242                 print_declaration(declaration);
1243                 fputc('\n', out);
1244         }
1245 }
1246
1247 /**
1248  * Returns true if a given expression is a compile time
1249  * constant.
1250  *
1251  * @param expression  the expression to check
1252  */
1253 bool is_constant_expression(const expression_t *expression)
1254 {
1255         switch(expression->kind) {
1256
1257         case EXPR_CONST:
1258         case EXPR_CHAR_CONST:
1259         case EXPR_STRING_LITERAL:
1260         case EXPR_WIDE_STRING_LITERAL:
1261         case EXPR_SIZEOF:
1262         case EXPR_CLASSIFY_TYPE:
1263         case EXPR_FUNCTION:
1264         case EXPR_PRETTY_FUNCTION:
1265         case EXPR_OFFSETOF:
1266         case EXPR_ALIGNOF:
1267         case EXPR_BUILTIN_CONSTANT_P:
1268                 return true;
1269
1270         case EXPR_BUILTIN_SYMBOL:
1271         case EXPR_BUILTIN_PREFETCH:
1272         case EXPR_CALL:
1273         case EXPR_SELECT:
1274         case EXPR_VA_START:
1275         case EXPR_VA_ARG:
1276         case EXPR_STATEMENT:
1277         case EXPR_UNARY_POSTFIX_INCREMENT:
1278         case EXPR_UNARY_POSTFIX_DECREMENT:
1279         case EXPR_UNARY_PREFIX_INCREMENT:
1280         case EXPR_UNARY_PREFIX_DECREMENT:
1281         case EXPR_UNARY_BITFIELD_EXTRACT:
1282         case EXPR_UNARY_ASSUME: /* has VOID type */
1283         case EXPR_BINARY_ASSIGN:
1284         case EXPR_BINARY_MUL_ASSIGN:
1285         case EXPR_BINARY_DIV_ASSIGN:
1286         case EXPR_BINARY_MOD_ASSIGN:
1287         case EXPR_BINARY_ADD_ASSIGN:
1288         case EXPR_BINARY_SUB_ASSIGN:
1289         case EXPR_BINARY_SHIFTLEFT_ASSIGN:
1290         case EXPR_BINARY_SHIFTRIGHT_ASSIGN:
1291         case EXPR_BINARY_BITWISE_AND_ASSIGN:
1292         case EXPR_BINARY_BITWISE_XOR_ASSIGN:
1293         case EXPR_BINARY_BITWISE_OR_ASSIGN:
1294         case EXPR_BINARY_COMMA:
1295                 return false;
1296
1297         case EXPR_UNARY_NEGATE:
1298         case EXPR_UNARY_PLUS:
1299         case EXPR_UNARY_BITWISE_NEGATE:
1300         case EXPR_UNARY_NOT:
1301         case EXPR_UNARY_DEREFERENCE:
1302         case EXPR_UNARY_TAKE_ADDRESS:
1303         case EXPR_UNARY_CAST:
1304         case EXPR_UNARY_CAST_IMPLICIT:
1305                 return is_constant_expression(expression->unary.value);
1306
1307         case EXPR_BINARY_ADD:
1308         case EXPR_BINARY_SUB:
1309         case EXPR_BINARY_MUL:
1310         case EXPR_BINARY_DIV:
1311         case EXPR_BINARY_MOD:
1312         case EXPR_BINARY_EQUAL:
1313         case EXPR_BINARY_NOTEQUAL:
1314         case EXPR_BINARY_LESS:
1315         case EXPR_BINARY_LESSEQUAL:
1316         case EXPR_BINARY_GREATER:
1317         case EXPR_BINARY_GREATEREQUAL:
1318         case EXPR_BINARY_BITWISE_AND:
1319         case EXPR_BINARY_BITWISE_OR:
1320         case EXPR_BINARY_BITWISE_XOR:
1321         case EXPR_BINARY_LOGICAL_AND:
1322         case EXPR_BINARY_LOGICAL_OR:
1323         case EXPR_BINARY_SHIFTLEFT:
1324         case EXPR_BINARY_SHIFTRIGHT:
1325         case EXPR_BINARY_BUILTIN_EXPECT:
1326         case EXPR_BINARY_ISGREATER:
1327         case EXPR_BINARY_ISGREATEREQUAL:
1328         case EXPR_BINARY_ISLESS:
1329         case EXPR_BINARY_ISLESSEQUAL:
1330         case EXPR_BINARY_ISLESSGREATER:
1331         case EXPR_BINARY_ISUNORDERED:
1332                 return is_constant_expression(expression->binary.left)
1333                         && is_constant_expression(expression->binary.right);
1334
1335         case EXPR_CONDITIONAL:
1336                 /* TODO: not correct, we only have to test expressions which are
1337                  * evaluated, which means either the true or false part might be not
1338                  * constant */
1339                 return is_constant_expression(expression->conditional.condition)
1340                         && is_constant_expression(expression->conditional.true_expression)
1341                         && is_constant_expression(expression->conditional.false_expression);
1342
1343         case EXPR_ARRAY_ACCESS:
1344                 return is_constant_expression(expression->array_access.array_ref)
1345                         && is_constant_expression(expression->array_access.index);
1346
1347         case EXPR_REFERENCE: {
1348                 declaration_t *declaration = expression->reference.declaration;
1349                 if(declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
1350                         return true;
1351
1352                 return false;
1353         }
1354
1355         case EXPR_UNKNOWN:
1356         case EXPR_INVALID:
1357                 break;
1358         }
1359         panic("invalid expression found (is constant expression)");
1360 }
1361
1362 /**
1363  * Initialize the AST construction.
1364  */
1365 void init_ast(void)
1366 {
1367         obstack_init(&ast_obstack);
1368 }
1369
1370 /**
1371  * Free the AST.
1372  */
1373 void exit_ast(void)
1374 {
1375         obstack_free(&ast_obstack, NULL);
1376 }
1377
1378 /**
1379  * Set the output stream for the AST printer.
1380  *
1381  * @param stream  the output stream
1382  */
1383 void ast_set_output(FILE *stream)
1384 {
1385         out = stream;
1386         type_set_output(stream);
1387 }
1388
1389 /**
1390  * Allocate an AST object of the given size.
1391  *
1392  * @param size  the size of the object to allocate
1393  *
1394  * @return  A new allocated object in the AST memeory space.
1395  */
1396 void *(allocate_ast)(size_t size)
1397 {
1398         return _allocate_ast(size);
1399 }