Print constant suffixes and properly print floats.
[cparser] / ast.c
1 /*
2  * This file is part of cparser.
3  * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18  * 02111-1307, USA.
19  */
20 #include <config.h>
21
22 #include "ast_t.h"
23 #include "symbol_t.h"
24 #include "type_t.h"
25 #include "parser.h"
26 #include "lang_features.h"
27
28 #include <assert.h>
29 #include <math.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33
34 #include "adt/error.h"
35
36 struct obstack ast_obstack;
37
38 static FILE *out;
39 static int   indent;
40
41 /** If set, implicit casts are printed. */
42 bool print_implicit_casts = false;
43
44 /** If set parenthesis are printed to indicate operator precedence. */
45 bool print_parenthesis = false;
46
47 static void print_statement(const statement_t *statement);
48 static void print_expression_prec(const expression_t *expression, unsigned prec);
49
50 void change_indent(int delta)
51 {
52         indent += delta;
53         assert(indent >= 0);
54 }
55
56 void print_indent(void)
57 {
58         for(int i = 0; i < indent; ++i)
59                 fprintf(out, "\t");
60 }
61
62 enum precedence_t {
63         PREC_BOTTOM  =  0,
64         PREC_COMMA   =  2, /* ,                                    left to right */
65         PREC_ASSIGN  =  4, /* = += -= *= /= %= <<= >>= &= ^= |=    right to left */
66         PREC_COND    =  6, /* ?:                                   right to left */
67         PREC_LOG_OR  =  8, /* ||                                   left to right */
68         PREC_LOG_AND = 10, /* &&                                   left to right */
69         PREC_BIT_OR  = 12, /* |                                    left to right */
70         PREC_BIT_XOR = 14, /* ^                                    left to right */
71         PREC_BIT_AND = 16, /* &                                    left to right */
72         PREC_EQ      = 18, /* == !=                                left to right */
73         PREC_CMP     = 20, /* < <= > >=                            left to right */
74         PREC_SHF     = 22, /* << >>                                left to right */
75         PREC_PLUS    = 24, /* + -                                  left to right */
76         PREC_MUL     = 26, /* * / %                                left to right */
77         PREC_UNARY   = 28, /* ! ~ ++ -- + - (type) * & sizeof      right to left */
78         PREC_ACCESS  = 30, /* () [] -> .                           left to right */
79         PREC_PRIM    = 32, /* primary */
80         PREC_TOP     = 34
81 };
82
83 /**
84  * Returns 1 if a given precedence level has right-to-left
85  * associativity, else -1.
86  *
87  * @param precedence   the operator precedence
88  */
89 static int right_to_left(unsigned precedence) {
90         return (precedence == PREC_ASSIGN || precedence == PREC_COND ||
91                 precedence == PREC_UNARY) ? 1 : -1;
92 }
93
94 /**
95  * Return the precedence of an expression given by its kind.
96  *
97  * @param kind   the expression kind
98  */
99 static unsigned get_expression_precedence(expression_kind_t kind)
100 {
101         static const unsigned prec[] = {
102                 [EXPR_UNKNOWN]                   = PREC_PRIM,
103                 [EXPR_INVALID]                   = PREC_PRIM,
104                 [EXPR_REFERENCE]                 = PREC_PRIM,
105                 [EXPR_CHARACTER_CONSTANT]        = PREC_PRIM,
106                 [EXPR_WIDE_CHARACTER_CONSTANT]   = PREC_PRIM,
107                 [EXPR_CONST]                     = PREC_PRIM,
108                 [EXPR_STRING_LITERAL]            = PREC_PRIM,
109                 [EXPR_WIDE_STRING_LITERAL]       = PREC_PRIM,
110                 [EXPR_COMPOUND_LITERAL]          = PREC_UNARY,
111                 [EXPR_CALL]                      = PREC_PRIM,
112                 [EXPR_CONDITIONAL]               = PREC_COND,
113                 [EXPR_SELECT]                    = PREC_ACCESS,
114                 [EXPR_ARRAY_ACCESS]              = PREC_ACCESS,
115                 [EXPR_SIZEOF]                    = PREC_UNARY,
116                 [EXPR_CLASSIFY_TYPE]             = PREC_UNARY,
117                 [EXPR_ALIGNOF]                   = PREC_UNARY,
118
119                 [EXPR_FUNCNAME]                  = PREC_PRIM,
120                 [EXPR_BUILTIN_SYMBOL]            = PREC_PRIM,
121                 [EXPR_BUILTIN_CONSTANT_P]        = PREC_PRIM,
122                 [EXPR_BUILTIN_PREFETCH]          = PREC_PRIM,
123                 [EXPR_OFFSETOF]                  = PREC_PRIM,
124                 [EXPR_VA_START]                  = PREC_PRIM,
125                 [EXPR_VA_ARG]                    = PREC_PRIM,
126                 [EXPR_STATEMENT]                 = PREC_ACCESS,
127
128                 [EXPR_UNARY_NEGATE]              = PREC_UNARY,
129                 [EXPR_UNARY_PLUS]                = PREC_UNARY,
130                 [EXPR_UNARY_BITWISE_NEGATE]      = PREC_UNARY,
131                 [EXPR_UNARY_NOT]                 = PREC_UNARY,
132                 [EXPR_UNARY_DEREFERENCE]         = PREC_UNARY,
133                 [EXPR_UNARY_TAKE_ADDRESS]        = PREC_UNARY,
134                 [EXPR_UNARY_POSTFIX_INCREMENT]   = PREC_UNARY,
135                 [EXPR_UNARY_POSTFIX_DECREMENT]   = PREC_UNARY,
136                 [EXPR_UNARY_PREFIX_INCREMENT]    = PREC_UNARY,
137                 [EXPR_UNARY_PREFIX_DECREMENT]    = PREC_UNARY,
138                 [EXPR_UNARY_CAST]                = PREC_UNARY,
139                 [EXPR_UNARY_CAST_IMPLICIT]       = PREC_UNARY,
140                 [EXPR_UNARY_ASSUME]              = PREC_PRIM,
141
142                 [EXPR_BINARY_ADD]                = PREC_PLUS,
143                 [EXPR_BINARY_SUB]                = PREC_PLUS,
144                 [EXPR_BINARY_MUL]                = PREC_MUL,
145                 [EXPR_BINARY_DIV]                = PREC_MUL,
146                 [EXPR_BINARY_MOD]                = PREC_MUL,
147                 [EXPR_BINARY_EQUAL]              = PREC_EQ,
148                 [EXPR_BINARY_NOTEQUAL]           = PREC_EQ,
149                 [EXPR_BINARY_LESS]               = PREC_CMP,
150                 [EXPR_BINARY_LESSEQUAL]          = PREC_CMP,
151                 [EXPR_BINARY_GREATER]            = PREC_CMP,
152                 [EXPR_BINARY_GREATEREQUAL]       = PREC_CMP,
153                 [EXPR_BINARY_BITWISE_AND]        = PREC_BIT_AND,
154                 [EXPR_BINARY_BITWISE_OR]         = PREC_BIT_OR,
155                 [EXPR_BINARY_BITWISE_XOR]        = PREC_BIT_XOR,
156                 [EXPR_BINARY_LOGICAL_AND]        = PREC_LOG_AND,
157                 [EXPR_BINARY_LOGICAL_OR]         = PREC_LOG_OR,
158                 [EXPR_BINARY_SHIFTLEFT]          = PREC_SHF,
159                 [EXPR_BINARY_SHIFTRIGHT]         = PREC_SHF,
160                 [EXPR_BINARY_ASSIGN]             = PREC_ASSIGN,
161                 [EXPR_BINARY_MUL_ASSIGN]         = PREC_ASSIGN,
162                 [EXPR_BINARY_DIV_ASSIGN]         = PREC_ASSIGN,
163                 [EXPR_BINARY_MOD_ASSIGN]         = PREC_ASSIGN,
164                 [EXPR_BINARY_ADD_ASSIGN]         = PREC_ASSIGN,
165                 [EXPR_BINARY_SUB_ASSIGN]         = PREC_ASSIGN,
166                 [EXPR_BINARY_SHIFTLEFT_ASSIGN]   = PREC_ASSIGN,
167                 [EXPR_BINARY_SHIFTRIGHT_ASSIGN]  = PREC_ASSIGN,
168                 [EXPR_BINARY_BITWISE_AND_ASSIGN] = PREC_ASSIGN,
169                 [EXPR_BINARY_BITWISE_XOR_ASSIGN] = PREC_ASSIGN,
170                 [EXPR_BINARY_BITWISE_OR_ASSIGN]  = PREC_ASSIGN,
171                 [EXPR_BINARY_COMMA]              = PREC_COMMA,
172
173                 [EXPR_BINARY_BUILTIN_EXPECT]     = PREC_PRIM,
174                 [EXPR_BINARY_ISGREATER]          = PREC_PRIM,
175                 [EXPR_BINARY_ISGREATEREQUAL]     = PREC_PRIM,
176                 [EXPR_BINARY_ISLESS]             = PREC_PRIM,
177                 [EXPR_BINARY_ISLESSEQUAL]        = PREC_PRIM,
178                 [EXPR_BINARY_ISLESSGREATER]      = PREC_PRIM,
179                 [EXPR_BINARY_ISUNORDERED]        = PREC_PRIM
180         };
181         assert((unsigned)kind < (sizeof(prec)/sizeof(prec[0])));
182         unsigned res = prec[kind];
183
184         assert(res != PREC_BOTTOM);
185         return res;
186 }
187
188 /**
189  * Print a constant expression.
190  *
191  * @param cnst  the constant expression
192  */
193 static void print_const(const const_expression_t *cnst)
194 {
195         if(cnst->base.type == NULL)
196                 return;
197
198         const type_t *const type = skip_typeref(cnst->base.type);
199
200         if (is_type_integer(type)) {
201                 fprintf(out, "%lld", cnst->v.int_value);
202         } else if (is_type_float(type)) {
203                 long double const val = cnst->v.float_value;
204                 fprintf(out, "%.20Lg", val);
205                 if (isfinite(val) && truncl(val) == val)
206                         fputs(".0", out);
207         } else {
208                 panic("unknown constant");
209         }
210
211         char const* suffix;
212         switch (type->atomic.akind) {
213                 case ATOMIC_TYPE_UINT:        suffix = "U";   break;
214                 case ATOMIC_TYPE_LONG:        suffix = "L";   break;
215                 case ATOMIC_TYPE_ULONG:       suffix = "UL";  break;
216                 case ATOMIC_TYPE_LONGLONG:    suffix = "LL";  break;
217                 case ATOMIC_TYPE_ULONGLONG:   suffix = "ULL"; break;
218                 case ATOMIC_TYPE_FLOAT:       suffix = "F";   break;
219                 case ATOMIC_TYPE_LONG_DOUBLE: suffix = "L";   break;
220
221                 default: suffix = NULL; break;
222         }
223         if (suffix != NULL)
224                 fputs(suffix, out);
225 }
226
227 /**
228  * Print a quoted string constant.
229  *
230  * @param string  the string constant
231  * @param border  the border char
232  * @param skip    number of chars to skip at the end
233  */
234 static void print_quoted_string(const string_t *const string, char border, int skip)
235 {
236         fputc(border, out);
237         const char *end = string->begin + string->size - skip;
238         for (const char *c = string->begin; c != end; ++c) {
239                 if (*c == border) {
240                         fputc('\\', out);
241                 }
242                 switch(*c) {
243                 case '\\':  fputs("\\\\", out); break;
244                 case '\a':  fputs("\\a", out); break;
245                 case '\b':  fputs("\\b", out); break;
246                 case '\f':  fputs("\\f", out); break;
247                 case '\n':  fputs("\\n", out); break;
248                 case '\r':  fputs("\\r", out); break;
249                 case '\t':  fputs("\\t", out); break;
250                 case '\v':  fputs("\\v", out); break;
251                 case '\?':  fputs("\\?", out); break;
252                 case 27:
253                         if (c_mode & _GNUC) {
254                                 fputs("\\e", out); break;
255                         }
256                         /*fallthrough*/
257                 default:
258                         if(!isprint(*c)) {
259                                 fprintf(out, "\\%03o", *c);
260                                 break;
261                         }
262                         fputc(*c, out);
263                         break;
264                 }
265         }
266         fputc(border, out);
267 }
268
269 /**
270  * Prints a wide string literal expression.
271  *
272  * @param wstr    the wide string literal expression
273  * @param border  the border char
274  * @param skip    number of chars to skip at the end
275  */
276 static void print_quoted_wide_string(const wide_string_t *const wstr,
277                                      char border, int skip)
278 {
279         fputc('L', out);
280         fputc(border, out);
281         const wchar_rep_t *end = wstr->begin + wstr->size - skip;
282         for (const wchar_rep_t *c = wstr->begin; c != end; ++c) {
283                 switch (*c) {
284                         case L'\"':  fputs("\\\"", out); break;
285                         case L'\\':  fputs("\\\\", out); break;
286                         case L'\a':  fputs("\\a",  out); break;
287                         case L'\b':  fputs("\\b",  out); break;
288                         case L'\f':  fputs("\\f",  out); break;
289                         case L'\n':  fputs("\\n",  out); break;
290                         case L'\r':  fputs("\\r",  out); break;
291                         case L'\t':  fputs("\\t",  out); break;
292                         case L'\v':  fputs("\\v",  out); break;
293                         case L'\?':  fputs("\\?",  out); break;
294                         case 27:
295                                 if (c_mode & _GNUC) {
296                                         fputs("\\e", out); break;
297                                 }
298                                 /*fallthrough*/
299                         default: {
300                                 const unsigned tc = *c;
301                                 if (tc < 0x80U) {
302                                         if (!isprint(*c))  {
303                                                 fprintf(out, "\\%03o", (char)*c);
304                                         } else {
305                                                 fputc(*c, out);
306                                         }
307                                 } else if (tc < 0x800) {
308                                         fputc(0xC0 | (tc >> 6),   out);
309                                         fputc(0x80 | (tc & 0x3F), out);
310                                 } else if (tc < 0x10000) {
311                                         fputc(0xE0 | ( tc >> 12),         out);
312                                         fputc(0x80 | ((tc >>  6) & 0x3F), out);
313                                         fputc(0x80 | ( tc        & 0x3F), out);
314                                 } else {
315                                         fputc(0xF0 | ( tc >> 18),         out);
316                                         fputc(0x80 | ((tc >> 12) & 0x3F), out);
317                                         fputc(0x80 | ((tc >>  6) & 0x3F), out);
318                                         fputc(0x80 | ( tc        & 0x3F), out);
319                                 }
320                         }
321                 }
322         }
323         fputc(border, out);
324 }
325
326 /**
327  * Print a constant character expression.
328  *
329  * @param cnst  the constant character expression
330  */
331 static void print_character_constant(const const_expression_t *cnst)
332 {
333         print_quoted_string(&cnst->v.character, '\'', 0);
334 }
335
336 static void print_wide_character_constant(const const_expression_t *cnst)
337 {
338         print_quoted_wide_string(&cnst->v.wide_character, '\'', 0);
339 }
340
341 /**
342  * Prints a string literal expression.
343  *
344  * @param string_literal  the string literal expression
345  */
346 static void print_string_literal(
347                 const string_literal_expression_t *string_literal)
348 {
349         print_quoted_string(&string_literal->value, '"', 1);
350 }
351
352 /**
353  * Prints a predefined symbol.
354  */
355 static void print_funcname(
356                 const funcname_expression_t *funcname)
357 {
358         const char *s = "";
359         switch(funcname->kind) {
360         case FUNCNAME_FUNCTION:        s = (c_mode & _C99) ? "__func__" : "__FUNCTION__"; break;
361         case FUNCNAME_PRETTY_FUNCTION: s = "__PRETTY_FUNCTION__"; break;
362         case FUNCNAME_FUNCSIG:         s = "__FUNCSIG__"; break;
363         case FUNCNAME_FUNCDNAME:       s = "__FUNCDNAME__"; break;
364         }
365         fputc('"', out);
366         fputs(s, out);
367         fputc('"', out);
368 }
369
370 static void print_wide_string_literal(
371         const wide_string_literal_expression_t *const wstr)
372 {
373         print_quoted_wide_string(&wstr->value, '"', 1);
374 }
375
376 static void print_compound_literal(
377                 const compound_literal_expression_t *expression)
378 {
379         fputc('(', out);
380         print_type(expression->type);
381         fputs(") ", out);
382         print_initializer(expression->initializer);
383 }
384
385 /**
386  * Prints a call expression.
387  *
388  * @param call  the call expression
389  */
390 static void print_call_expression(const call_expression_t *call)
391 {
392         unsigned prec = get_expression_precedence(call->base.kind);
393         print_expression_prec(call->function, prec);
394         fprintf(out, "(");
395         call_argument_t *argument = call->arguments;
396         int              first    = 1;
397         while(argument != NULL) {
398                 if(!first) {
399                         fprintf(out, ", ");
400                 } else {
401                         first = 0;
402                 }
403                 print_expression_prec(argument->expression, PREC_COMMA + 1);
404
405                 argument = argument->next;
406         }
407         fprintf(out, ")");
408 }
409
410 /**
411  * Prints a binary expression.
412  *
413  * @param binexpr   the binary expression
414  */
415 static void print_binary_expression(const binary_expression_t *binexpr)
416 {
417         unsigned prec = get_expression_precedence(binexpr->base.kind);
418         int      r2l  = right_to_left(prec);
419
420         if(binexpr->base.kind == EXPR_BINARY_BUILTIN_EXPECT) {
421                 fputs("__builtin_expect(", out);
422                 print_expression_prec(binexpr->left, prec);
423                 fputs(", ", out);
424                 print_expression_prec(binexpr->right, prec);
425                 fputc(')', out);
426                 return;
427         }
428
429         print_expression_prec(binexpr->left, prec + r2l);
430         if (binexpr->base.kind != EXPR_BINARY_COMMA) {
431                 fputc(' ', out);
432         }
433         switch (binexpr->base.kind) {
434         case EXPR_BINARY_COMMA:              fputs(",", out);     break;
435         case EXPR_BINARY_ASSIGN:             fputs("=", out);     break;
436         case EXPR_BINARY_ADD:                fputs("+", out);     break;
437         case EXPR_BINARY_SUB:                fputs("-", out);     break;
438         case EXPR_BINARY_MUL:                fputs("*", out);     break;
439         case EXPR_BINARY_MOD:                fputs("%", out);     break;
440         case EXPR_BINARY_DIV:                fputs("/", out);     break;
441         case EXPR_BINARY_BITWISE_OR:         fputs("|", out);     break;
442         case EXPR_BINARY_BITWISE_AND:        fputs("&", out);     break;
443         case EXPR_BINARY_BITWISE_XOR:        fputs("^", out);     break;
444         case EXPR_BINARY_LOGICAL_OR:         fputs("||", out);    break;
445         case EXPR_BINARY_LOGICAL_AND:        fputs("&&", out);    break;
446         case EXPR_BINARY_NOTEQUAL:           fputs("!=", out);    break;
447         case EXPR_BINARY_EQUAL:              fputs("==", out);    break;
448         case EXPR_BINARY_LESS:               fputs("<", out);     break;
449         case EXPR_BINARY_LESSEQUAL:          fputs("<=", out);    break;
450         case EXPR_BINARY_GREATER:            fputs(">", out);     break;
451         case EXPR_BINARY_GREATEREQUAL:       fputs(">=", out);    break;
452         case EXPR_BINARY_SHIFTLEFT:          fputs("<<", out);    break;
453         case EXPR_BINARY_SHIFTRIGHT:         fputs(">>", out);    break;
454
455         case EXPR_BINARY_ADD_ASSIGN:         fputs("+=", out);    break;
456         case EXPR_BINARY_SUB_ASSIGN:         fputs("-=", out);    break;
457         case EXPR_BINARY_MUL_ASSIGN:         fputs("*=", out);    break;
458         case EXPR_BINARY_MOD_ASSIGN:         fputs("%=", out);    break;
459         case EXPR_BINARY_DIV_ASSIGN:         fputs("/=", out);    break;
460         case EXPR_BINARY_BITWISE_OR_ASSIGN:  fputs("|=", out);    break;
461         case EXPR_BINARY_BITWISE_AND_ASSIGN: fputs("&=", out);    break;
462         case EXPR_BINARY_BITWISE_XOR_ASSIGN: fputs("^=", out);    break;
463         case EXPR_BINARY_SHIFTLEFT_ASSIGN:   fputs("<<=", out);   break;
464         case EXPR_BINARY_SHIFTRIGHT_ASSIGN:  fputs(">>=", out);   break;
465         default: panic("invalid binexpression found");
466         }
467         fputc(' ', out);
468         print_expression_prec(binexpr->right, prec - r2l);
469 }
470
471 /**
472  * Prints an unary expression.
473  *
474  * @param unexpr   the unary expression
475  */
476 static void print_unary_expression(const unary_expression_t *unexpr)
477 {
478         unsigned prec = get_expression_precedence(unexpr->base.kind);
479         switch(unexpr->base.kind) {
480         case EXPR_UNARY_NEGATE:           fputs("-", out);  break;
481         case EXPR_UNARY_PLUS:             fputs("+", out);  break;
482         case EXPR_UNARY_NOT:              fputs("!", out);  break;
483         case EXPR_UNARY_BITWISE_NEGATE:   fputs("~", out);  break;
484         case EXPR_UNARY_PREFIX_INCREMENT: fputs("++", out); break;
485         case EXPR_UNARY_PREFIX_DECREMENT: fputs("--", out); break;
486         case EXPR_UNARY_DEREFERENCE:      fputs("*", out);  break;
487         case EXPR_UNARY_TAKE_ADDRESS:     fputs("&", out);  break;
488
489         case EXPR_UNARY_POSTFIX_INCREMENT:
490                 print_expression_prec(unexpr->value, prec);
491                 fputs("++", out);
492                 return;
493         case EXPR_UNARY_POSTFIX_DECREMENT:
494                 print_expression_prec(unexpr->value, prec);
495                 fputs("--", out);
496                 return;
497         case EXPR_UNARY_CAST_IMPLICIT:
498         case EXPR_UNARY_CAST:
499                 fputc('(', out);
500                 print_type(unexpr->base.type);
501                 fputc(')', out);
502                 break;
503         case EXPR_UNARY_ASSUME:
504                 fputs("__assume(", out);
505                 print_expression_prec(unexpr->value, PREC_COMMA + 1);
506                 fputc(')', out);
507                 return;
508         default:
509                 panic("invalid unary expression found");
510         }
511         print_expression_prec(unexpr->value, prec);
512 }
513
514 /**
515  * Prints a reference expression.
516  *
517  * @param ref   the reference expression
518  */
519 static void print_reference_expression(const reference_expression_t *ref)
520 {
521         fprintf(out, "%s", ref->declaration->symbol->string);
522 }
523
524 /**
525  * Prints an array expression.
526  *
527  * @param expression   the array expression
528  */
529 static void print_array_expression(const array_access_expression_t *expression)
530 {
531         unsigned prec = get_expression_precedence(expression->base.kind);
532         if(!expression->flipped) {
533                 print_expression_prec(expression->array_ref, prec);
534                 fputc('[', out);
535                 print_expression_prec(expression->index, PREC_BOTTOM);
536                 fputc(']', out);
537         } else {
538                 print_expression_prec(expression->index, prec);
539                 fputc('[', out);
540                 print_expression_prec(expression->array_ref, PREC_BOTTOM);
541                 fputc(']', out);
542         }
543 }
544
545 /**
546  * Prints a typeproperty expression (sizeof or __alignof__).
547  *
548  * @param expression   the type property expression
549  */
550 static void print_typeprop_expression(const typeprop_expression_t *expression)
551 {
552         if (expression->base.kind == EXPR_SIZEOF) {
553                 fputs("sizeof", out);
554         } else {
555                 assert(expression->base.kind == EXPR_ALIGNOF);
556                 fputs("__alignof__", out);
557         }
558         if(expression->tp_expression != NULL) {
559                 /* always print the '()' here, sizeof x is right but unusual */
560                 fputc('(', out);
561                 print_expression_prec(expression->tp_expression, PREC_ACCESS);
562                 fputc(')', out);
563         } else {
564                 fputc('(', out);
565                 print_type(expression->type);
566                 fputc(')', out);
567         }
568 }
569
570 /**
571  * Prints an builtin symbol.
572  *
573  * @param expression   the builtin symbol expression
574  */
575 static void print_builtin_symbol(const builtin_symbol_expression_t *expression)
576 {
577         fputs(expression->symbol->string, out);
578 }
579
580 /**
581  * Prints a builtin constant expression.
582  *
583  * @param expression   the builtin constant expression
584  */
585 static void print_builtin_constant(const builtin_constant_expression_t *expression)
586 {
587         fputs("__builtin_constant_p(", out);
588         print_expression_prec(expression->value, PREC_COMMA + 1);
589         fputc(')', out);
590 }
591
592 /**
593  * Prints a builtin prefetch expression.
594  *
595  * @param expression   the builtin prefetch expression
596  */
597 static void print_builtin_prefetch(const builtin_prefetch_expression_t *expression)
598 {
599         fputs("__builtin_prefetch(", out);
600         print_expression_prec(expression->adr, PREC_COMMA + 1);
601         if (expression->rw) {
602                 fputc(',', out);
603                 print_expression_prec(expression->rw, PREC_COMMA + 1);
604         }
605         if (expression->locality) {
606                 fputc(',', out);
607                 print_expression_prec(expression->locality, PREC_COMMA + 1);
608         }
609         fputc(')', out);
610 }
611
612 /**
613  * Prints a conditional expression.
614  *
615  * @param expression   the conditional expression
616  */
617 static void print_conditional(const conditional_expression_t *expression)
618 {
619         unsigned prec = get_expression_precedence(expression->base.kind);
620         fputs("(", out);
621         print_expression_prec(expression->condition, prec);
622         fputs(" ? ", out);
623         if (expression->true_expression != NULL) {
624                 print_expression_prec(expression->true_expression, prec);
625                 fputs(" : ", out);
626         } else {
627                 fputs(": ", out);
628         }
629         print_expression_prec(expression->false_expression, prec);
630         fputs(")", out);
631 }
632
633 /**
634  * Prints a va_start expression.
635  *
636  * @param expression   the va_start expression
637  */
638 static void print_va_start(const va_start_expression_t *const expression)
639 {
640         fputs("__builtin_va_start(", out);
641         print_expression_prec(expression->ap, PREC_COMMA + 1);
642         fputs(", ", out);
643         fputs(expression->parameter->symbol->string, out);
644         fputs(")", out);
645 }
646
647 /**
648  * Prints a va_arg expression.
649  *
650  * @param expression   the va_arg expression
651  */
652 static void print_va_arg(const va_arg_expression_t *expression)
653 {
654         fputs("__builtin_va_arg(", out);
655         print_expression_prec(expression->ap, PREC_COMMA + 1);
656         fputs(", ", out);
657         print_type(expression->base.type);
658         fputs(")", out);
659 }
660
661 /**
662  * Prints a select expression (. or ->).
663  *
664  * @param expression   the select expression
665  */
666 static void print_select(const select_expression_t *expression)
667 {
668         unsigned prec = get_expression_precedence(expression->base.kind);
669         print_expression_prec(expression->compound, prec);
670         if(is_type_pointer(skip_typeref(expression->compound->base.type))) {
671                 fputs("->", out);
672         } else {
673                 fputc('.', out);
674         }
675         fputs(expression->symbol->string, out);
676 }
677
678 /**
679  * Prints a type classify expression.
680  *
681  * @param expr   the type classify expression
682  */
683 static void print_classify_type_expression(
684         const classify_type_expression_t *const expr)
685 {
686         fputs("__builtin_classify_type(", out);
687         print_expression_prec(expr->type_expression, PREC_COMMA + 1);
688         fputc(')', out);
689 }
690
691 /**
692  * Prints a designator.
693  *
694  * @param designator  the designator
695  */
696 static void print_designator(const designator_t *designator)
697 {
698         for ( ; designator != NULL; designator = designator->next) {
699                 if (designator->symbol == NULL) {
700                         fputc('[', out);
701                         print_expression_prec(designator->array_index, PREC_BOTTOM);
702                         fputc(']', out);
703                 } else {
704                         fputc('.', out);
705                         fputs(designator->symbol->string, out);
706                 }
707         }
708 }
709
710 /**
711  * Prints an offsetof expression.
712  *
713  * @param expression   the offset expression
714  */
715 static void print_offsetof_expression(const offsetof_expression_t *expression)
716 {
717         fputs("__builtin_offsetof", out);
718         fputc('(', out);
719         print_type(expression->type);
720         fputc(',', out);
721         print_designator(expression->designator);
722         fputc(')', out);
723 }
724
725 /**
726  * Prints a statement expression.
727  *
728  * @param expression   the statement expression
729  */
730 static void print_statement_expression(const statement_expression_t *expression)
731 {
732         fputc('(', out);
733         print_statement(expression->statement);
734         fputc(')', out);
735 }
736
737 /**
738  * Prints an expression with parenthesis if needed.
739  *
740  * @param expression  the expression to print
741  * @param top_prec    the precedence of the user of this expression.
742  */
743 static void print_expression_prec(const expression_t *expression, unsigned top_prec)
744 {
745         if (expression->kind == EXPR_UNARY_CAST_IMPLICIT && !print_implicit_casts) {
746                 expression = expression->unary.value;
747         }
748         unsigned prec = get_expression_precedence(expression->base.kind);
749         if (print_parenthesis && top_prec != PREC_BOTTOM)
750                 top_prec = PREC_TOP;
751         if (top_prec > prec)
752                 fputc('(', out);
753         switch(expression->kind) {
754         case EXPR_UNKNOWN:
755         case EXPR_INVALID:
756                 fprintf(out, "$invalid expression$");
757                 break;
758         case EXPR_CHARACTER_CONSTANT:
759                 print_character_constant(&expression->conste);
760                 break;
761         case EXPR_WIDE_CHARACTER_CONSTANT:
762                 print_wide_character_constant(&expression->conste);
763                 break;
764         case EXPR_CONST:
765                 print_const(&expression->conste);
766                 break;
767         case EXPR_FUNCNAME:
768                 print_funcname(&expression->funcname);
769                 break;
770         case EXPR_STRING_LITERAL:
771                 print_string_literal(&expression->string);
772                 break;
773         case EXPR_WIDE_STRING_LITERAL:
774                 print_wide_string_literal(&expression->wide_string);
775                 break;
776         case EXPR_COMPOUND_LITERAL:
777                 print_compound_literal(&expression->compound_literal);
778                 break;
779         case EXPR_CALL:
780                 print_call_expression(&expression->call);
781                 break;
782         EXPR_BINARY_CASES
783                 print_binary_expression(&expression->binary);
784                 break;
785         case EXPR_REFERENCE:
786                 print_reference_expression(&expression->reference);
787                 break;
788         case EXPR_ARRAY_ACCESS:
789                 print_array_expression(&expression->array_access);
790                 break;
791         EXPR_UNARY_CASES
792                 print_unary_expression(&expression->unary);
793                 break;
794         case EXPR_SIZEOF:
795         case EXPR_ALIGNOF:
796                 print_typeprop_expression(&expression->typeprop);
797                 break;
798         case EXPR_BUILTIN_SYMBOL:
799                 print_builtin_symbol(&expression->builtin_symbol);
800                 break;
801         case EXPR_BUILTIN_CONSTANT_P:
802                 print_builtin_constant(&expression->builtin_constant);
803                 break;
804         case EXPR_BUILTIN_PREFETCH:
805                 print_builtin_prefetch(&expression->builtin_prefetch);
806                 break;
807         case EXPR_CONDITIONAL:
808                 print_conditional(&expression->conditional);
809                 break;
810         case EXPR_VA_START:
811                 print_va_start(&expression->va_starte);
812                 break;
813         case EXPR_VA_ARG:
814                 print_va_arg(&expression->va_arge);
815                 break;
816         case EXPR_SELECT:
817                 print_select(&expression->select);
818                 break;
819         case EXPR_CLASSIFY_TYPE:
820                 print_classify_type_expression(&expression->classify_type);
821                 break;
822         case EXPR_OFFSETOF:
823                 print_offsetof_expression(&expression->offsetofe);
824                 break;
825         case EXPR_STATEMENT:
826                 print_statement_expression(&expression->statement);
827                 break;
828
829         default:
830                 /* TODO */
831                 fprintf(out, "some expression of type %d", (int) expression->kind);
832                 break;
833         }
834         if (top_prec > prec)
835                 fputc(')', out);
836 }
837
838 /**
839  * Print an compound statement.
840  *
841  * @param block  the compound statement
842  */
843 static void print_compound_statement(const compound_statement_t *block)
844 {
845         fputs("{\n", out);
846         ++indent;
847
848         statement_t *statement = block->statements;
849         while(statement != NULL) {
850                 if (statement->base.kind == STATEMENT_CASE_LABEL)
851                         --indent;
852                 print_indent();
853                 print_statement(statement);
854
855                 statement = statement->base.next;
856         }
857         --indent;
858         print_indent();
859         fputs("}\n", out);
860 }
861
862 /**
863  * Print a return statement.
864  *
865  * @param statement  the return statement
866  */
867 static void print_return_statement(const return_statement_t *statement)
868 {
869         fprintf(out, "return ");
870         if(statement->value != NULL)
871                 print_expression(statement->value);
872         fputs(";\n", out);
873 }
874
875 /**
876  * Print an expression statement.
877  *
878  * @param statement  the expression statement
879  */
880 static void print_expression_statement(const expression_statement_t *statement)
881 {
882         print_expression(statement->expression);
883         fputs(";\n", out);
884 }
885
886 /**
887  * Print a goto statement.
888  *
889  * @param statement  the goto statement
890  */
891 static void print_goto_statement(const goto_statement_t *statement)
892 {
893         fprintf(out, "goto ");
894         fputs(statement->label->symbol->string, out);
895         fprintf(stderr, "(%p)", (void*) statement->label);
896         fputs(";\n", out);
897 }
898
899 /**
900  * Print a label statement.
901  *
902  * @param statement  the label statement
903  */
904 static void print_label_statement(const label_statement_t *statement)
905 {
906         fprintf(stderr, "(%p)", (void*) statement->label);
907         fprintf(out, "%s:\n", statement->label->symbol->string);
908         print_statement(statement->statement);
909 }
910
911 /**
912  * Print an if statement.
913  *
914  * @param statement  the if statement
915  */
916 static void print_if_statement(const if_statement_t *statement)
917 {
918         fputs("if (", out);
919         print_expression(statement->condition);
920         fputs(") ", out);
921         print_statement(statement->true_statement);
922
923         if(statement->false_statement != NULL) {
924                 print_indent();
925                 fputs("else ", out);
926                 print_statement(statement->false_statement);
927         }
928 }
929
930 /**
931  * Print a switch statement.
932  *
933  * @param statement  the switch statement
934  */
935 static void print_switch_statement(const switch_statement_t *statement)
936 {
937         fputs("switch (", out);
938         print_expression(statement->expression);
939         fputs(") ", out);
940         print_statement(statement->body);
941 }
942
943 /**
944  * Print a case label (including the default label).
945  *
946  * @param statement  the case label statement
947  */
948 static void print_case_label(const case_label_statement_t *statement)
949 {
950         if(statement->expression == NULL) {
951                 fputs("default:\n", out);
952         } else {
953                 fputs("case ", out);
954                 print_expression(statement->expression);
955                 if (statement->end_range != NULL) {
956                         fputs(" ... ", out);
957                         print_expression(statement->end_range);
958                 }
959                 fputs(":\n", out);
960         }
961         ++indent;
962         if(statement->statement != NULL) {
963                 if (statement->statement->base.kind == STATEMENT_CASE_LABEL) {
964                         --indent;
965                 }
966                 print_indent();
967                 print_statement(statement->statement);
968         }
969 }
970
971 /**
972  * Print a declaration statement.
973  *
974  * @param statement   the statement
975  */
976 static void print_declaration_statement(
977                 const declaration_statement_t *statement)
978 {
979         bool first = true;
980         for (declaration_t *declaration = statement->declarations_begin;
981              declaration != statement->declarations_end->next;
982              declaration = declaration->next) {
983                 if (declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
984                         continue;
985                 if (declaration->implicit)
986                         continue;
987
988                 if (!first) {
989                         print_indent();
990                 } else {
991                         first = false;
992                 }
993                 print_declaration(declaration);
994                 fputc('\n', out);
995         }
996 }
997
998 /**
999  * Print a while statement.
1000  *
1001  * @param statement   the statement
1002  */
1003 static void print_while_statement(const while_statement_t *statement)
1004 {
1005         fputs("while (", out);
1006         print_expression(statement->condition);
1007         fputs(") ", out);
1008         print_statement(statement->body);
1009 }
1010
1011 /**
1012  * Print a do-while statement.
1013  *
1014  * @param statement   the statement
1015  */
1016 static void print_do_while_statement(const do_while_statement_t *statement)
1017 {
1018         fputs("do ", out);
1019         print_statement(statement->body);
1020         print_indent();
1021         fputs("while (", out);
1022         print_expression(statement->condition);
1023         fputs(");\n", out);
1024 }
1025
1026 /**
1027  * Print a for statement.
1028  *
1029  * @param statement   the statement
1030  */
1031 static void print_for_statement(const for_statement_t *statement)
1032 {
1033         fputs("for (", out);
1034         declaration_t *decl = statement->scope.declarations;
1035         while (decl != NULL && decl->implicit)
1036                 decl = decl->next;
1037         if (decl != NULL) {
1038                 assert(statement->initialisation == NULL);
1039                 print_declaration(decl);
1040                 if (decl->next != NULL) {
1041                         panic("multiple declarations in for statement not supported yet");
1042                 }
1043                 fputc(' ', out);
1044         } else {
1045                 if(statement->initialisation) {
1046                         print_expression(statement->initialisation);
1047                 }
1048                 fputs("; ", out);
1049         }
1050         if(statement->condition != NULL) {
1051                 print_expression(statement->condition);
1052         }
1053         fputs("; ", out);
1054         if(statement->step != NULL) {
1055                 print_expression(statement->step);
1056         }
1057         fputs(") ", out);
1058         print_statement(statement->body);
1059 }
1060
1061 /**
1062  * Print assembler arguments.
1063  *
1064  * @param arguments   the arguments
1065  */
1066 static void print_asm_arguments(asm_argument_t *arguments)
1067 {
1068         asm_argument_t *argument = arguments;
1069         for( ; argument != NULL; argument = argument->next) {
1070                 if(argument != arguments)
1071                         fputs(", ", out);
1072
1073                 if(argument->symbol) {
1074                         fprintf(out, "[%s] ", argument->symbol->string);
1075                 }
1076                 print_quoted_string(&argument->constraints, '"', 1);
1077                 fputs(" (", out);
1078                 print_expression(argument->expression);
1079                 fputs(")", out);
1080         }
1081 }
1082
1083 /**
1084  * Print assembler clobbers.
1085  *
1086  * @param clobbers   the clobbers
1087  */
1088 static void print_asm_clobbers(asm_clobber_t *clobbers)
1089 {
1090         asm_clobber_t *clobber = clobbers;
1091         for( ; clobber != NULL; clobber = clobber->next) {
1092                 if(clobber != clobbers)
1093                         fputs(", ", out);
1094
1095                 print_quoted_string(&clobber->clobber, '"', 1);
1096         }
1097 }
1098
1099 /**
1100  * Print an assembler statement.
1101  *
1102  * @param statement   the statement
1103  */
1104 static void print_asm_statement(const asm_statement_t *statement)
1105 {
1106         fputs("asm ", out);
1107         if(statement->is_volatile) {
1108                 fputs("volatile ", out);
1109         }
1110         fputs("(", out);
1111         print_quoted_string(&statement->asm_text, '"', 1);
1112         if(statement->inputs == NULL && statement->outputs == NULL
1113                         && statement->clobbers == NULL)
1114                 goto end_of_print_asm_statement;
1115
1116         fputs(" : ", out);
1117         print_asm_arguments(statement->inputs);
1118         if(statement->outputs == NULL && statement->clobbers == NULL)
1119                 goto end_of_print_asm_statement;
1120
1121         fputs(" : ", out);
1122         print_asm_arguments(statement->outputs);
1123         if(statement->clobbers == NULL)
1124                 goto end_of_print_asm_statement;
1125
1126         fputs(" : ", out);
1127         print_asm_clobbers(statement->clobbers);
1128
1129 end_of_print_asm_statement:
1130         fputs(");\n", out);
1131 }
1132
1133 /**
1134  * Print a microsoft __try statement.
1135  *
1136  * @param statement   the statement
1137  */
1138 static void print_ms_try_statement(const ms_try_statement_t *statement)
1139 {
1140         fputs("__try ", out);
1141         print_statement(statement->try_statement);
1142         print_indent();
1143         if(statement->except_expression != NULL) {
1144                 fputs("__except(", out);
1145                 print_expression(statement->except_expression);
1146                 fputs(") ", out);
1147         } else {
1148                 fputs("__finally ", out);
1149         }
1150         print_statement(statement->final_statement);
1151 }
1152
1153 /**
1154  * Print a microsoft __leave statement.
1155  *
1156  * @param statement   the statement
1157  */
1158 static void print_leave_statement(const leave_statement_t *statement)
1159 {
1160         (void) statement;
1161         fputs("__leave;\n", out);
1162 }
1163
1164 /**
1165  * Print a statement.
1166  *
1167  * @param statement   the statement
1168  */
1169 void print_statement(const statement_t *statement)
1170 {
1171         switch(statement->kind) {
1172         case STATEMENT_EMPTY:
1173                 fputs(";\n", out);
1174                 break;
1175         case STATEMENT_COMPOUND:
1176                 print_compound_statement(&statement->compound);
1177                 break;
1178         case STATEMENT_RETURN:
1179                 print_return_statement(&statement->returns);
1180                 break;
1181         case STATEMENT_EXPRESSION:
1182                 print_expression_statement(&statement->expression);
1183                 break;
1184         case STATEMENT_LABEL:
1185                 print_label_statement(&statement->label);
1186                 break;
1187         case STATEMENT_GOTO:
1188                 print_goto_statement(&statement->gotos);
1189                 break;
1190         case STATEMENT_CONTINUE:
1191                 fputs("continue;\n", out);
1192                 break;
1193         case STATEMENT_BREAK:
1194                 fputs("break;\n", out);
1195                 break;
1196         case STATEMENT_IF:
1197                 print_if_statement(&statement->ifs);
1198                 break;
1199         case STATEMENT_SWITCH:
1200                 print_switch_statement(&statement->switchs);
1201                 break;
1202         case STATEMENT_CASE_LABEL:
1203                 print_case_label(&statement->case_label);
1204                 break;
1205         case STATEMENT_DECLARATION:
1206                 print_declaration_statement(&statement->declaration);
1207                 break;
1208         case STATEMENT_WHILE:
1209                 print_while_statement(&statement->whiles);
1210                 break;
1211         case STATEMENT_DO_WHILE:
1212                 print_do_while_statement(&statement->do_while);
1213                 break;
1214         case STATEMENT_FOR:
1215                 print_for_statement(&statement->fors);
1216                 break;
1217         case STATEMENT_ASM:
1218                 print_asm_statement(&statement->asms);
1219                 break;
1220         case STATEMENT_MS_TRY:
1221                 print_ms_try_statement(&statement->ms_try);
1222                 break;
1223         case STATEMENT_LEAVE:
1224                 print_leave_statement(&statement->leave);
1225                 break;
1226         case STATEMENT_INVALID:
1227                 fprintf(out, "$invalid statement$");
1228                 break;
1229         }
1230 }
1231
1232 /**
1233  * Print a storage class.
1234  *
1235  * @param storage_class   the storage class
1236  */
1237 static void print_storage_class(storage_class_tag_t storage_class)
1238 {
1239         switch(storage_class) {
1240         case STORAGE_CLASS_ENUM_ENTRY:
1241         case STORAGE_CLASS_NONE:
1242                 break;
1243         case STORAGE_CLASS_TYPEDEF:       fputs("typedef ",        out); break;
1244         case STORAGE_CLASS_EXTERN:        fputs("extern ",         out); break;
1245         case STORAGE_CLASS_STATIC:        fputs("static ",         out); break;
1246         case STORAGE_CLASS_AUTO:          fputs("auto ",           out); break;
1247         case STORAGE_CLASS_REGISTER:      fputs("register ",       out); break;
1248         case STORAGE_CLASS_THREAD:        fputs("__thread",        out); break;
1249         case STORAGE_CLASS_THREAD_EXTERN: fputs("extern __thread", out); break;
1250         case STORAGE_CLASS_THREAD_STATIC: fputs("static __thread", out); break;
1251         }
1252 }
1253
1254 /**
1255  * Print an initializer.
1256  *
1257  * @param initializer  the initializer
1258  */
1259 void print_initializer(const initializer_t *initializer)
1260 {
1261         if(initializer == NULL) {
1262                 fputs("{}", out);
1263                 return;
1264         }
1265
1266         switch(initializer->kind) {
1267         case INITIALIZER_VALUE: {
1268                 const initializer_value_t *value = &initializer->value;
1269                 print_expression(value->value);
1270                 return;
1271         }
1272         case INITIALIZER_LIST: {
1273                 assert(initializer->kind == INITIALIZER_LIST);
1274                 fputs("{ ", out);
1275                 const initializer_list_t *list = &initializer->list;
1276
1277                 for(size_t i = 0 ; i < list->len; ++i) {
1278                         const initializer_t *sub_init = list->initializers[i];
1279                         print_initializer(list->initializers[i]);
1280                         if(i < list->len-1) {
1281                                 if(sub_init == NULL || sub_init->kind != INITIALIZER_DESIGNATOR)
1282                                         fputs(", ", out);
1283                         }
1284                 }
1285                 fputs(" }", out);
1286                 return;
1287         }
1288         case INITIALIZER_STRING:
1289                 print_quoted_string(&initializer->string.string, '"', 1);
1290                 return;
1291         case INITIALIZER_WIDE_STRING:
1292                 print_quoted_wide_string(&initializer->wide_string.string, '"', 1);
1293                 return;
1294         case INITIALIZER_DESIGNATOR:
1295                 print_designator(initializer->designator.designator);
1296                 fputs(" = ", out);
1297                 return;
1298         }
1299
1300         panic("invalid initializer kind found");
1301 }
1302
1303 /**
1304  * Print microsoft extended declaration modifiers.
1305  */
1306 static void print_ms_modifiers(const declaration_t *declaration) {
1307         if((c_mode & _MS) == 0)
1308                 return;
1309
1310         decl_modifiers_t modifiers = declaration->modifiers;
1311
1312         /* DM_FORCEINLINE handled outside. */
1313         if ((modifiers & ~DM_FORCEINLINE) != 0    ||
1314             declaration->alignment        != 0    ||
1315             declaration->get_property_sym != NULL ||
1316             declaration->put_property_sym != NULL) {
1317                 char *next = "(";
1318
1319                 fputs("__declspec", out);
1320                 if(modifiers & DM_DLLIMPORT) {
1321                         fputs(next, out); next = ", "; fputs("dllimport", out);
1322                 }
1323                 if(modifiers & DM_DLLEXPORT) {
1324                         fputs(next, out); next = ", "; fputs("dllexport", out);
1325                 }
1326                 if(modifiers & DM_THREAD) {
1327                         fputs(next, out); next = ", "; fputs("thread", out);
1328                 }
1329                 if(modifiers & DM_NAKED) {
1330                         fputs(next, out); next = ", "; fputs("naked", out);
1331                 }
1332                 if(modifiers & DM_THREAD) {
1333                         fputs(next, out); next = ", "; fputs("thread", out);
1334                 }
1335                 if(modifiers & DM_SELECTANY) {
1336                         fputs(next, out); next = ", "; fputs("selectany", out);
1337                 }
1338                 if(modifiers & DM_NOTHROW) {
1339                         fputs(next, out); next = ", "; fputs("nothrow", out);
1340                 }
1341                 if(modifiers & DM_NORETURN) {
1342                         fputs(next, out); next = ", "; fputs("noreturn", out);
1343                 }
1344                 if(modifiers & DM_NOINLINE) {
1345                         fputs(next, out); next = ", "; fputs("noinline", out);
1346                 }
1347                 if (modifiers & DM_DEPRECATED) {
1348                         fputs(next, out); next = ", "; fputs("deprecated", out);
1349                         if(declaration->deprecated_string != NULL)
1350                                 fprintf(out, "(\"%s\")", declaration->deprecated_string);
1351                 }
1352                 if(declaration->alignment != 0) {
1353                         fputs(next, out); next = ", "; fprintf(out, "align(%u)", declaration->alignment);
1354                 }
1355                 if(modifiers & DM_RESTRICT) {
1356                         fputs(next, out); next = ", "; fputs("restrict", out);
1357                 }
1358                 if(modifiers & DM_NOALIAS) {
1359                         fputs(next, out); next = ", "; fputs("noalias", out);
1360                 }
1361             if(declaration->get_property_sym != NULL || declaration->put_property_sym != NULL) {
1362                 char *comma = "";
1363                         fputs(next, out); next = ", "; fprintf(out, "property(");
1364                 if(declaration->get_property_sym != NULL) {
1365                         fprintf(out, "get=%s", declaration->get_property_sym->string);
1366                         comma = ", ";
1367                         }
1368                 if(declaration->put_property_sym != NULL)
1369                         fprintf(out, "%sput=%s", comma, declaration->put_property_sym->string);
1370                         fputc(')', out);
1371                 }
1372                 fputs(") ", out);
1373         }
1374 }
1375
1376 /**
1377  * Print a declaration in the NORMAL namespace.
1378  *
1379  * @param declaration  the declaration
1380  */
1381 static void print_normal_declaration(const declaration_t *declaration)
1382 {
1383         print_storage_class((storage_class_tag_t) declaration->declared_storage_class);
1384         if (declaration->is_inline) {
1385                 if (declaration->modifiers & DM_FORCEINLINE) {
1386                         fputs("__forceinline ", out);
1387                 } else if (declaration->modifiers & DM_MICROSOFT_INLINE) {
1388                         fputs("__inline ", out);
1389                 } else {
1390                         fputs("inline ", out);
1391                 }
1392         }
1393         print_ms_modifiers(declaration);
1394         print_type_ext(declaration->type, declaration->symbol,
1395                        &declaration->scope);
1396
1397         if(declaration->type->kind == TYPE_FUNCTION) {
1398                 if(declaration->init.statement != NULL) {
1399                         fputs("\n", out);
1400                         print_statement(declaration->init.statement);
1401                         return;
1402                 }
1403         } else if(declaration->init.initializer != NULL) {
1404                 fputs(" = ", out);
1405                 print_initializer(declaration->init.initializer);
1406         }
1407         fputc(';', out);
1408 }
1409
1410 /**
1411  * Prints an expression.
1412  *
1413  * @param expression  the expression
1414  */
1415 void print_expression(const expression_t *expression) {
1416         print_expression_prec(expression, PREC_BOTTOM);
1417 }
1418
1419 /**
1420  * Print a declaration.
1421  *
1422  * @param declaration  the declaration
1423  */
1424 void print_declaration(const declaration_t *declaration)
1425 {
1426         if(declaration->namespc != NAMESPACE_NORMAL &&
1427                         declaration->symbol == NULL)
1428                 return;
1429
1430         switch(declaration->namespc) {
1431         case NAMESPACE_NORMAL:
1432                 print_normal_declaration(declaration);
1433                 break;
1434         case NAMESPACE_STRUCT:
1435                 fputs("struct ", out);
1436                 fputs(declaration->symbol->string, out);
1437                 fputc(' ', out);
1438                 print_compound_definition(declaration);
1439                 fputc(';', out);
1440                 break;
1441         case NAMESPACE_UNION:
1442                 fputs("union ", out);
1443                 fputs(declaration->symbol->string, out);
1444                 fputc(' ', out);
1445                 print_compound_definition(declaration);
1446                 fputc(';', out);
1447                 break;
1448         case NAMESPACE_ENUM:
1449                 fputs("enum ", out);
1450                 fputs(declaration->symbol->string, out);
1451                 fputc(' ', out);
1452                 print_enum_definition(declaration);
1453                 fputc(';', out);
1454                 break;
1455         }
1456 }
1457
1458 /**
1459  * Print the AST of a translation unit.
1460  *
1461  * @param unit   the translation unit
1462  */
1463 void print_ast(const translation_unit_t *unit)
1464 {
1465         inc_type_visited();
1466
1467         declaration_t *declaration = unit->scope.declarations;
1468         for( ; declaration != NULL; declaration = declaration->next) {
1469                 if(declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
1470                         continue;
1471                 if(declaration->namespc != NAMESPACE_NORMAL &&
1472                                 declaration->symbol == NULL)
1473                         continue;
1474                 if (declaration->implicit)
1475                         continue;
1476
1477                 print_indent();
1478                 print_declaration(declaration);
1479                 fputc('\n', out);
1480         }
1481 }
1482
1483 bool is_constant_initializer(const initializer_t *initializer)
1484 {
1485         switch(initializer->kind) {
1486         case INITIALIZER_STRING:
1487         case INITIALIZER_WIDE_STRING:
1488         case INITIALIZER_DESIGNATOR:
1489                 return true;
1490
1491         case INITIALIZER_VALUE:
1492                 return is_constant_expression(initializer->value.value);
1493
1494         case INITIALIZER_LIST:
1495                 for(size_t i = 0; i < initializer->list.len; ++i) {
1496                         initializer_t *sub_initializer = initializer->list.initializers[i];
1497                         if(!is_constant_initializer(sub_initializer))
1498                                 return false;
1499                 }
1500                 return true;
1501         }
1502         panic("invalid initializer kind found");
1503 }
1504
1505 static bool is_object_with_linker_constant_address(const expression_t *expression)
1506 {
1507         switch(expression->kind) {
1508         case EXPR_UNARY_DEREFERENCE:
1509                 return is_address_constant(expression->unary.value);
1510
1511         case EXPR_SELECT: {
1512                 type_t *base_type = skip_typeref(expression->select.compound->base.type);
1513                 if(is_type_pointer(base_type)) {
1514                         /* it's a -> */
1515                         return is_address_constant(expression->select.compound);
1516                 } else {
1517                         return is_object_with_linker_constant_address(expression->select.compound);
1518                 }
1519         }
1520
1521         case EXPR_ARRAY_ACCESS:
1522                 return is_constant_expression(expression->array_access.index)
1523                         && is_address_constant(expression->array_access.array_ref);
1524
1525         case EXPR_REFERENCE: {
1526                 declaration_t *declaration = expression->reference.declaration;
1527                 switch((storage_class_tag_t) declaration->storage_class) {
1528                 case STORAGE_CLASS_NONE:
1529                 case STORAGE_CLASS_EXTERN:
1530                 case STORAGE_CLASS_STATIC:
1531                         return true;
1532                 default:
1533                         return false;
1534                 }
1535         }
1536
1537         default:
1538                 return false;
1539         }
1540 }
1541
1542 bool is_address_constant(const expression_t *expression)
1543 {
1544         switch(expression->kind) {
1545         case EXPR_UNARY_TAKE_ADDRESS:
1546                 return is_object_with_linker_constant_address(expression->unary.value);
1547
1548         case EXPR_UNARY_DEREFERENCE: {
1549                 type_t *real_type
1550                         = revert_automatic_type_conversion(expression->unary.value);
1551                 /* dereferencing a function is a NOP */
1552                 if(is_type_function(real_type)) {
1553                         return is_address_constant(expression->unary.value);
1554                 }
1555
1556                 /* fallthrough */
1557         }
1558
1559         case EXPR_UNARY_CAST: {
1560                 type_t *dest = skip_typeref(expression->base.type);
1561                 if (!is_type_pointer(dest) &&
1562                                 ! (dest->kind == TYPE_ATOMIC
1563                                         && (get_atomic_type_flags(dest->atomic.akind) & ATOMIC_TYPE_FLAG_INTEGER)
1564                                         && (get_atomic_type_size(dest->atomic.akind) >= get_atomic_type_size(get_intptr_kind()))))
1565                         return false;
1566
1567                 return (is_constant_expression(expression->unary.value)
1568                         || is_address_constant(expression->unary.value));
1569         }
1570
1571         case EXPR_BINARY_ADD:
1572         case EXPR_BINARY_SUB: {
1573                 expression_t *left  = expression->binary.left;
1574                 expression_t *right = expression->binary.right;
1575
1576                 if(is_type_pointer(skip_typeref(left->base.type))) {
1577                         return is_address_constant(left) && is_constant_expression(right);
1578                 } else if(is_type_pointer(skip_typeref(right->base.type))) {
1579                         return is_constant_expression(left)     && is_address_constant(right);
1580                 }
1581
1582                 return false;
1583         }
1584
1585         case EXPR_REFERENCE: {
1586                 declaration_t *declaration = expression->reference.declaration;
1587                 type_t *type = skip_typeref(declaration->type);
1588                 if(is_type_function(type))
1589                         return true;
1590                 if(is_type_array(type)) {
1591                         return is_object_with_linker_constant_address(expression);
1592                 }
1593                 return false;
1594         }
1595
1596         default:
1597                 return false;
1598         }
1599 }
1600
1601 static bool is_builtin_const_call(const expression_t *expression)
1602 {
1603         expression_t *function = expression->call.function;
1604         if (function->kind != EXPR_BUILTIN_SYMBOL) {
1605                 return false;
1606         }
1607
1608         symbol_t *symbol = function->builtin_symbol.symbol;
1609
1610         switch (symbol->ID) {
1611         case T___builtin_huge_val:
1612         case T___builtin_nan:
1613         case T___builtin_nanf:
1614         case T___builtin_nand:
1615                 return true;
1616         }
1617
1618         return false;
1619 }
1620
1621 static bool is_constant_pointer(const expression_t *expression)
1622 {
1623         if (is_constant_expression(expression))
1624                 return true;
1625
1626         switch (expression->kind) {
1627         case EXPR_SELECT:
1628                 return is_constant_pointer(expression->select.compound);
1629         case EXPR_UNARY_CAST:
1630                 return is_constant_pointer(expression->unary.value);
1631         default:
1632                 return false;
1633         }
1634 }
1635
1636 static bool is_object_with_constant_address(const expression_t *expression)
1637 {
1638         switch(expression->kind) {
1639         case EXPR_SELECT: {
1640                 expression_t *compound      = expression->select.compound;
1641                 type_t       *compound_type = compound->base.type;
1642                 compound_type = skip_typeref(compound_type);
1643                 if(is_type_pointer(compound_type)) {
1644                         return is_constant_pointer(compound);
1645                 } else {
1646                         return is_object_with_constant_address(compound);
1647                 }
1648         }
1649         case EXPR_ARRAY_ACCESS:
1650                 return is_constant_pointer(expression->array_access.array_ref)
1651                         && is_constant_expression(expression->array_access.index);
1652         case EXPR_UNARY_DEREFERENCE:
1653                 return is_constant_pointer(expression->unary.value);
1654         default:
1655                 return false;
1656         }
1657 }
1658
1659 bool is_constant_expression(const expression_t *expression)
1660 {
1661         switch(expression->kind) {
1662
1663         case EXPR_CONST:
1664         case EXPR_CHARACTER_CONSTANT:
1665         case EXPR_WIDE_CHARACTER_CONSTANT:
1666         case EXPR_STRING_LITERAL:
1667         case EXPR_WIDE_STRING_LITERAL:
1668         case EXPR_CLASSIFY_TYPE:
1669         case EXPR_FUNCNAME:
1670         case EXPR_OFFSETOF:
1671         case EXPR_ALIGNOF:
1672         case EXPR_BUILTIN_CONSTANT_P:
1673                 return true;
1674
1675         case EXPR_SIZEOF: {
1676                 type_t *type = expression->typeprop.type;
1677                 if (type == NULL)
1678                         type = expression->typeprop.tp_expression->base.type;
1679
1680                 type = skip_typeref(type);
1681                 if (is_type_array(type) && type->array.is_vla)
1682                         return false;
1683                 return true;
1684         }
1685
1686         case EXPR_BUILTIN_SYMBOL:
1687         case EXPR_BUILTIN_PREFETCH:
1688         case EXPR_SELECT:
1689         case EXPR_VA_START:
1690         case EXPR_VA_ARG:
1691         case EXPR_STATEMENT:
1692         case EXPR_UNARY_POSTFIX_INCREMENT:
1693         case EXPR_UNARY_POSTFIX_DECREMENT:
1694         case EXPR_UNARY_PREFIX_INCREMENT:
1695         case EXPR_UNARY_PREFIX_DECREMENT:
1696         case EXPR_UNARY_ASSUME: /* has VOID type */
1697         case EXPR_UNARY_DEREFERENCE:
1698         case EXPR_BINARY_ASSIGN:
1699         case EXPR_BINARY_MUL_ASSIGN:
1700         case EXPR_BINARY_DIV_ASSIGN:
1701         case EXPR_BINARY_MOD_ASSIGN:
1702         case EXPR_BINARY_ADD_ASSIGN:
1703         case EXPR_BINARY_SUB_ASSIGN:
1704         case EXPR_BINARY_SHIFTLEFT_ASSIGN:
1705         case EXPR_BINARY_SHIFTRIGHT_ASSIGN:
1706         case EXPR_BINARY_BITWISE_AND_ASSIGN:
1707         case EXPR_BINARY_BITWISE_XOR_ASSIGN:
1708         case EXPR_BINARY_BITWISE_OR_ASSIGN:
1709         case EXPR_BINARY_COMMA:
1710                 return false;
1711
1712         case EXPR_UNARY_TAKE_ADDRESS:
1713                 return is_object_with_constant_address(expression->unary.value);
1714
1715         case EXPR_CALL:
1716                 return is_builtin_const_call(expression);
1717
1718         case EXPR_UNARY_NEGATE:
1719         case EXPR_UNARY_PLUS:
1720         case EXPR_UNARY_BITWISE_NEGATE:
1721         case EXPR_UNARY_NOT:
1722                 return is_constant_expression(expression->unary.value);
1723
1724         case EXPR_UNARY_CAST:
1725         case EXPR_UNARY_CAST_IMPLICIT:
1726                 return is_type_arithmetic(skip_typeref(expression->base.type))
1727                         && is_constant_expression(expression->unary.value);
1728
1729         case EXPR_BINARY_ADD:
1730         case EXPR_BINARY_SUB:
1731         case EXPR_BINARY_MUL:
1732         case EXPR_BINARY_DIV:
1733         case EXPR_BINARY_MOD:
1734         case EXPR_BINARY_EQUAL:
1735         case EXPR_BINARY_NOTEQUAL:
1736         case EXPR_BINARY_LESS:
1737         case EXPR_BINARY_LESSEQUAL:
1738         case EXPR_BINARY_GREATER:
1739         case EXPR_BINARY_GREATEREQUAL:
1740         case EXPR_BINARY_BITWISE_AND:
1741         case EXPR_BINARY_BITWISE_OR:
1742         case EXPR_BINARY_BITWISE_XOR:
1743         case EXPR_BINARY_LOGICAL_AND:
1744         case EXPR_BINARY_LOGICAL_OR:
1745         case EXPR_BINARY_SHIFTLEFT:
1746         case EXPR_BINARY_SHIFTRIGHT:
1747         case EXPR_BINARY_BUILTIN_EXPECT:
1748         case EXPR_BINARY_ISGREATER:
1749         case EXPR_BINARY_ISGREATEREQUAL:
1750         case EXPR_BINARY_ISLESS:
1751         case EXPR_BINARY_ISLESSEQUAL:
1752         case EXPR_BINARY_ISLESSGREATER:
1753         case EXPR_BINARY_ISUNORDERED:
1754                 return is_constant_expression(expression->binary.left)
1755                         && is_constant_expression(expression->binary.right);
1756
1757         case EXPR_COMPOUND_LITERAL:
1758                 return is_constant_initializer(expression->compound_literal.initializer);
1759
1760         case EXPR_CONDITIONAL: {
1761                 expression_t *condition = expression->conditional.condition;
1762                 if(!is_constant_expression(condition))
1763                         return false;
1764
1765                 long val = fold_constant(condition);
1766                 if(val != 0)
1767                         return is_constant_expression(expression->conditional.true_expression);
1768                 else
1769                         return is_constant_expression(expression->conditional.false_expression);
1770         }
1771
1772         case EXPR_ARRAY_ACCESS:
1773                 return is_constant_expression(expression->array_access.array_ref)
1774                         && is_constant_expression(expression->array_access.index);
1775
1776         case EXPR_REFERENCE: {
1777                 declaration_t *declaration = expression->reference.declaration;
1778                 if(declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
1779                         return true;
1780
1781                 return false;
1782         }
1783
1784         case EXPR_INVALID:
1785                 return true;
1786
1787         case EXPR_UNKNOWN:
1788                 break;
1789         }
1790         panic("invalid expression found (is constant expression)");
1791 }
1792
1793 /**
1794  * Initialize the AST construction.
1795  */
1796 void init_ast(void)
1797 {
1798         obstack_init(&ast_obstack);
1799 }
1800
1801 /**
1802  * Free the AST.
1803  */
1804 void exit_ast(void)
1805 {
1806         obstack_free(&ast_obstack, NULL);
1807 }
1808
1809 /**
1810  * Set the output stream for the AST printer.
1811  *
1812  * @param stream  the output stream
1813  */
1814 void ast_set_output(FILE *stream)
1815 {
1816         out = stream;
1817         type_set_output(stream);
1818 }
1819
1820 /**
1821  * Allocate an AST object of the given size.
1822  *
1823  * @param size  the size of the object to allocate
1824  *
1825  * @return  A new allocated object in the AST memeory space.
1826  */
1827 void *(allocate_ast)(size_t size)
1828 {
1829         return _allocate_ast(size);
1830 }