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