add some assert where typedef/typeof types should not be used, add missing skip_typer...
[cparser] / ast.c
1 #include <config.h>
2
3 #include "ast_t.h"
4 #include "type_t.h"
5
6 #include <assert.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <ctype.h>
10
11 #include "adt/error.h"
12
13 struct obstack ast_obstack;
14
15 static FILE *out;
16 static int   indent;
17
18 static void print_statement(const statement_t *statement);
19
20 void change_indent(int delta)
21 {
22         indent += delta;
23         assert(indent >= 0);
24 }
25
26 void print_indent(void)
27 {
28         for(int i = 0; i < indent; ++i)
29                 fprintf(out, "\t");
30 }
31
32 static void print_const(const const_t *cnst)
33 {
34         if(cnst->expression.datatype == NULL)
35                 return;
36
37         if(is_type_integer(cnst->expression.datatype)) {
38                 fprintf(out, "%lld", cnst->v.int_value);
39         } else if(is_type_floating(cnst->expression.datatype)) {
40                 fprintf(out, "%Lf", cnst->v.float_value);
41         }
42 }
43
44 static void print_string_literal(const string_literal_t *string_literal)
45 {
46         fputc('"', out);
47         for(const char *c = string_literal->value; *c != '\0'; ++c) {
48                 switch(*c) {
49                 case '\"':  fputs("\\\"", out); break;
50                 case '\\':  fputs("\\\\", out); break;
51                 case '\a':  fputs("\\a", out); break;
52                 case '\b':  fputs("\\b", out); break;
53                 case '\f':  fputs("\\f", out); break;
54                 case '\n':  fputs("\\n", out); break;
55                 case '\r':  fputs("\\r", out); break;
56                 case '\t':  fputs("\\t", out); break;
57                 case '\v':  fputs("\\v", out); break;
58                 case '\?':  fputs("\\?", out); break;
59                 default:
60                         if(!isprint(*c)) {
61                                 fprintf(out, "\\x%x", *c);
62                                 break;
63                         }
64                         fputc(*c, out);
65                         break;
66                 }
67         }
68         fputc('"', out);
69 }
70
71 static void print_call_expression(const call_expression_t *call)
72 {
73         print_expression(call->function);
74         fprintf(out, "(");
75         call_argument_t *argument = call->arguments;
76         int              first    = 1;
77         while(argument != NULL) {
78                 if(!first) {
79                         fprintf(out, ", ");
80                 } else {
81                         first = 0;
82                 }
83                 print_expression(argument->expression);
84
85                 argument = argument->next;
86         }
87         fprintf(out, ")");
88 }
89
90 static void print_binary_expression(const binary_expression_t *binexpr)
91 {
92         fprintf(out, "(");
93         print_expression(binexpr->left);
94         fprintf(out, " ");
95         switch(binexpr->type) {
96         case BINEXPR_INVALID:            fputs("INVOP", out); break;
97         case BINEXPR_COMMA:              fputs(",", out);     break;
98         case BINEXPR_ASSIGN:             fputs("=", out);     break;
99         case BINEXPR_ADD:                fputs("+", out);     break;
100         case BINEXPR_SUB:                fputs("-", out);     break;
101         case BINEXPR_MUL:                fputs("*", out);     break;
102         case BINEXPR_MOD:                fputs("%", out);     break;
103         case BINEXPR_DIV:                fputs("/", out);     break;
104         case BINEXPR_BITWISE_OR:         fputs("|", out);     break;
105         case BINEXPR_BITWISE_AND:        fputs("&", out);     break;
106         case BINEXPR_BITWISE_XOR:        fputs("^", out);     break;
107         case BINEXPR_LOGICAL_OR:         fputs("||", out);    break;
108         case BINEXPR_LOGICAL_AND:        fputs("&&", out);    break;
109         case BINEXPR_NOTEQUAL:           fputs("!=", out);    break;
110         case BINEXPR_EQUAL:              fputs("==", out);    break;
111         case BINEXPR_LESS:               fputs("<", out);     break;
112         case BINEXPR_LESSEQUAL:          fputs("<=", out);    break;
113         case BINEXPR_GREATER:            fputs(">", out);     break;
114         case BINEXPR_GREATEREQUAL:       fputs(">=", out);    break;
115         case BINEXPR_SHIFTLEFT:          fputs("<<", out);    break;
116         case BINEXPR_SHIFTRIGHT:         fputs(">>", out);    break;
117
118         case BINEXPR_ADD_ASSIGN:         fputs("+=", out);    break;
119         case BINEXPR_SUB_ASSIGN:         fputs("-=", out);    break;
120         case BINEXPR_MUL_ASSIGN:         fputs("*=", out);    break;
121         case BINEXPR_MOD_ASSIGN:         fputs("%=", out);    break;
122         case BINEXPR_DIV_ASSIGN:         fputs("/=", out);    break;
123         case BINEXPR_BITWISE_OR_ASSIGN:  fputs("|=", out);    break;
124         case BINEXPR_BITWISE_AND_ASSIGN: fputs("&=", out);    break;
125         case BINEXPR_BITWISE_XOR_ASSIGN: fputs("^=", out);    break;
126         case BINEXPR_SHIFTLEFT_ASSIGN:   fputs("<<=", out);   break;
127         case BINEXPR_SHIFTRIGHT_ASSIGN:  fputs(">>=", out);   break;
128         }
129         fprintf(out, " ");
130         print_expression(binexpr->right);
131         fprintf(out, ")");
132 }
133
134 static void print_unary_expression(const unary_expression_t *unexpr)
135 {
136         switch(unexpr->type) {
137         case UNEXPR_NEGATE:           fputs("-", out);  break;
138         case UNEXPR_PLUS:             fputs("+", out);  break;
139         case UNEXPR_NOT:              fputs("!", out);  break;
140         case UNEXPR_BITWISE_NEGATE:   fputs("~", out);  break;
141         case UNEXPR_PREFIX_INCREMENT: fputs("++", out); break;
142         case UNEXPR_PREFIX_DECREMENT: fputs("--", out); break;
143         case UNEXPR_DEREFERENCE:      fputs("*", out);  break;
144         case UNEXPR_TAKE_ADDRESS:     fputs("&", out);  break;
145
146         case UNEXPR_POSTFIX_INCREMENT:
147                 fputs("(", out);
148                 print_expression(unexpr->value);
149                 fputs(")", out);
150                 fputs("++", out);
151                 return;
152         case UNEXPR_POSTFIX_DECREMENT:
153                 fputs("(", out);
154                 print_expression(unexpr->value);
155                 fputs(")", out);
156                 fputs("--", out);
157                 return;
158         case UNEXPR_CAST:
159                 fputs("(", out);
160                 print_type(unexpr->expression.datatype);
161                 fputs(")", out);
162                 break;
163         case UNEXPR_INVALID:
164                 fprintf(out, "unop%d", (int) unexpr->type);
165                 break;
166         }
167         fputs("(", out);
168         print_expression(unexpr->value);
169         fputs(")", out);
170 }
171
172 static void print_reference_expression(const reference_expression_t *ref)
173 {
174         fprintf(out, "%s", ref->declaration->symbol->string);
175 }
176
177 static void print_array_expression(const array_access_expression_t *expression)
178 {
179         if(!expression->flipped) {
180                 fputs("(", out);
181                 print_expression(expression->array_ref);
182                 fputs(")[", out);
183                 print_expression(expression->index);
184                 fputs("]", out);
185         } else {
186                 fputs("(", out);
187                 print_expression(expression->index);
188                 fputs(")[", out);
189                 print_expression(expression->array_ref);
190                 fputs("]", out);
191         }
192 }
193
194 static void print_sizeof_expression(const sizeof_expression_t *expression)
195 {
196         fputs("sizeof", out);
197         if(expression->size_expression != NULL) {
198                 fputc('(', out);
199                 print_expression(expression->size_expression);
200                 fputc(')', out);
201         } else {
202                 fputc('(', out);
203                 print_type(expression->type);
204                 fputc(')', out);
205         }
206 }
207
208 static void print_builtin_symbol(const builtin_symbol_expression_t *expression)
209 {
210         fputs(expression->symbol->string, out);
211 }
212
213 static void print_conditional(const conditional_expression_t *expression)
214 {
215         fputs("(", out);
216         print_expression(expression->condition);
217         fputs(" ? ", out);
218         print_expression(expression->true_expression);
219         fputs(" : ", out);
220         print_expression(expression->false_expression);
221         fputs(")", out);
222 }
223
224 static void print_va_arg(const va_arg_expression_t *expression)
225 {
226         fputs("__builtin_va_arg(", out);
227         print_expression(expression->arg);
228         fputs(", ", out);
229         print_type(expression->expression.datatype);
230         fputs(")", out);
231 }
232
233 static void print_select(const select_expression_t *expression)
234 {
235         print_expression(expression->compound);
236         if(expression->compound->datatype == NULL ||
237                         expression->compound->datatype->type == TYPE_POINTER) {
238                 fputs("->", out);
239         } else {
240                 fputc('.', out);
241         }
242         fputs(expression->symbol->string, out);
243 }
244
245 static void print_classify_type_expression(
246         const classify_type_expression_t *const expr)
247 {
248         fputs("__builtin_classify_type(", out);
249         print_expression(expr->type_expression);
250         fputc(')', out);
251 }
252
253 void print_expression(const expression_t *expression)
254 {
255         switch(expression->type) {
256         case EXPR_UNKNOWN:
257         case EXPR_INVALID:
258                 fprintf(out, "*invalid expression*");
259                 break;
260         case EXPR_CONST:
261                 print_const((const const_t*) expression);
262                 break;
263         case EXPR_FUNCTION:
264         case EXPR_PRETTY_FUNCTION:
265         case EXPR_STRING_LITERAL:
266                 print_string_literal((const string_literal_t*) expression);
267                 break;
268         case EXPR_CALL:
269                 print_call_expression((const call_expression_t*) expression);
270                 break;
271         case EXPR_BINARY:
272                 print_binary_expression((const binary_expression_t*) expression);
273                 break;
274         case EXPR_REFERENCE:
275                 print_reference_expression((const reference_expression_t*) expression);
276                 break;
277         case EXPR_ARRAY_ACCESS:
278                 print_array_expression((const array_access_expression_t*) expression);
279                 break;
280         case EXPR_UNARY:
281                 print_unary_expression((const unary_expression_t*) expression);
282                 break;
283         case EXPR_SIZEOF:
284                 print_sizeof_expression((const sizeof_expression_t*) expression);
285                 break;
286         case EXPR_BUILTIN_SYMBOL:
287                 print_builtin_symbol((const builtin_symbol_expression_t*) expression);
288                 break;
289         case EXPR_CONDITIONAL:
290                 print_conditional((const conditional_expression_t*) expression);
291                 break;
292         case EXPR_VA_ARG:
293                 print_va_arg((const va_arg_expression_t*) expression);
294                 break;
295         case EXPR_SELECT:
296                 print_select((const select_expression_t*) expression);
297                 break;
298         case EXPR_CLASSIFY_TYPE:
299                 print_classify_type_expression((const classify_type_expression_t*)expression);
300                 break;
301
302         case EXPR_OFFSETOF:
303         case EXPR_STATEMENT:
304                 /* TODO */
305                 fprintf(out, "some expression of type %d", (int) expression->type);
306                 break;
307         }
308 }
309
310 static void print_compound_statement(const compound_statement_t *block)
311 {
312         fputs("{\n", out);
313         indent++;
314
315         statement_t *statement = block->statements;
316         while(statement != NULL) {
317                 print_indent();
318                 print_statement(statement);
319
320                 statement = statement->next;
321         }
322         indent--;
323         print_indent();
324         fputs("}\n", out);
325 }
326
327 static void print_return_statement(const return_statement_t *statement)
328 {
329         fprintf(out, "return ");
330         if(statement->return_value != NULL)
331                 print_expression(statement->return_value);
332         fputs(";\n", out);
333 }
334
335 static void print_expression_statement(const expression_statement_t *statement)
336 {
337         print_expression(statement->expression);
338         fputs(";\n", out);
339 }
340
341 static void print_goto_statement(const goto_statement_t *statement)
342 {
343         fprintf(out, "goto ");
344         fputs(statement->label->symbol->string, out);
345         fprintf(stderr, "(%p)", (void*) statement->label);
346         fputs(";\n", out);
347 }
348
349 static void print_label_statement(const label_statement_t *statement)
350 {
351         fprintf(stderr, "(%p)", (void*) statement->label);
352         fprintf(out, "%s:\n", statement->label->symbol->string);
353         if(statement->label_statement != NULL) {
354                 print_statement(statement->label_statement);
355         }
356 }
357
358 static void print_if_statement(const if_statement_t *statement)
359 {
360         fputs("if(", out);
361         print_expression(statement->condition);
362         fputs(") ", out);
363         if(statement->true_statement != NULL) {
364                 print_statement(statement->true_statement);
365         }
366
367         if(statement->false_statement != NULL) {
368                 print_indent();
369                 fputs("else ", out);
370                 print_statement(statement->false_statement);
371         }
372 }
373
374 static void print_switch_statement(const switch_statement_t *statement)
375 {
376         fputs("switch(", out);
377         print_expression(statement->expression);
378         fputs(") ", out);
379         print_statement(statement->body);
380 }
381
382 static void print_case_label(const case_label_statement_t *statement)
383 {
384         if(statement->expression == NULL) {
385                 fputs("default:\n", out);
386         } else {
387                 fputs("case ", out);
388                 print_expression(statement->expression);
389                 fputs(":\n", out);
390         }
391         print_statement(statement->label_statement);
392 }
393
394 static void print_declaration_statement(
395                 const declaration_statement_t *statement)
396 {
397         int first = 1;
398         declaration_t *declaration = statement->declarations_begin;
399         for( ; declaration != statement->declarations_end->next;
400                declaration = declaration->next) {
401                 if(!first) {
402                         print_indent();
403                 } else {
404                         first = 0;
405                 }
406                 print_declaration(declaration);
407                 fputc('\n', out);
408         }
409 }
410
411 static void print_while_statement(const while_statement_t *statement)
412 {
413         fputs("while(", out);
414         print_expression(statement->condition);
415         fputs(") ", out);
416         print_statement(statement->body);
417 }
418
419 static void print_do_while_statement(const do_while_statement_t *statement)
420 {
421         fputs("do ", out);
422         print_statement(statement->body);
423         print_indent();
424         fputs("while(", out);
425         print_expression(statement->condition);
426         fputs(");\n", out);
427 }
428
429 static void print_for_statement(const for_statement_t *statement)
430 {
431         fputs("for(", out);
432         if(statement->context.declarations != NULL) {
433                 assert(statement->initialisation == NULL);
434                 print_declaration(statement->context.declarations);
435                 if(statement->context.declarations->next != NULL) {
436                         panic("multiple declarations in for statement not supported yet");
437                 }
438                 fputc(' ', out);
439         } else {
440                 if(statement->initialisation) {
441                         print_expression(statement->initialisation);
442                 }
443                 fputs("; ", out);
444         }
445         if(statement->condition != NULL) {
446                 print_expression(statement->condition);
447         }
448         fputs("; ", out);
449         if(statement->step != NULL) {
450                 print_expression(statement->step);
451         }
452         fputs(")", out);
453         print_statement(statement->body);
454 }
455
456 void print_statement(const statement_t *statement)
457 {
458         switch(statement->type) {
459         case STATEMENT_COMPOUND:
460                 print_compound_statement((const compound_statement_t*) statement);
461                 break;
462         case STATEMENT_RETURN:
463                 print_return_statement((const return_statement_t*) statement);
464                 break;
465         case STATEMENT_EXPRESSION:
466                 print_expression_statement((const expression_statement_t*) statement);
467                 break;
468         case STATEMENT_LABEL:
469                 print_label_statement((const label_statement_t*) statement);
470                 break;
471         case STATEMENT_GOTO:
472                 print_goto_statement((const goto_statement_t*) statement);
473                 break;
474         case STATEMENT_CONTINUE:
475                 fputs("continue;\n", out);
476                 break;
477         case STATEMENT_BREAK:
478                 fputs("break;\n", out);
479                 break;
480         case STATEMENT_IF:
481                 print_if_statement((const if_statement_t*) statement);
482                 break;
483         case STATEMENT_SWITCH:
484                 print_switch_statement((const switch_statement_t*) statement);
485                 break;
486         case STATEMENT_CASE_LABEL:
487                 print_case_label((const case_label_statement_t*) statement);
488                 break;
489         case STATEMENT_DECLARATION:
490                 print_declaration_statement((const declaration_statement_t*) statement);
491                 break;
492         case STATEMENT_WHILE:
493                 print_while_statement((const while_statement_t*) statement);
494                 break;
495         case STATEMENT_DO_WHILE:
496                 print_do_while_statement((const do_while_statement_t*) statement);
497                 break;
498         case STATEMENT_FOR:
499                 print_for_statement((const for_statement_t*) statement);
500                 break;
501         case STATEMENT_INVALID:
502                 fprintf(out, "*invalid statement*");
503                 break;
504         }
505 }
506
507 static void print_storage_class(storage_class_t storage_class)
508 {
509         switch(storage_class) {
510         case STORAGE_CLASS_ENUM_ENTRY:
511         case STORAGE_CLASS_NONE:
512                 break;
513         case STORAGE_CLASS_TYPEDEF:  fputs("typedef ", out); break;
514         case STORAGE_CLASS_EXTERN:   fputs("extern ", out); break;
515         case STORAGE_CLASS_STATIC:   fputs("static ", out); break;
516         case STORAGE_CLASS_AUTO:     fputs("auto ", out); break;
517         case STORAGE_CLASS_REGISTER: fputs("register ", out); break;
518         }
519 }
520
521 void print_initializer(const initializer_t *initializer)
522 {
523         if(initializer->type == INITIALIZER_VALUE) {
524                 const initializer_value_t *value = &initializer->value;
525                 print_expression(value->value);
526                 return;
527         }
528
529         assert(initializer->type == INITIALIZER_LIST);
530         fputs("{ ", out);
531         const initializer_list_t *list = &initializer->list;
532
533         for(size_t i = 0 ; i < list->len; ++i) {
534                 if(i > 0) {
535                         fputs(", ", out);
536                 }
537                 print_initializer(list->initializers[i]);
538         }
539         fputs("}", out);
540 }
541
542 static void print_normal_declaration(const declaration_t *declaration)
543 {
544         print_storage_class((storage_class_t)declaration->storage_class);
545         print_type_ext(declaration->type, declaration->symbol,
546                        &declaration->context);
547         if(declaration->is_inline) {
548                 fputs("inline ", out);
549         }
550
551         if(declaration->type->type == TYPE_FUNCTION) {
552                 if(declaration->init.statement != NULL) {
553                         fputs("\n", out);
554                         print_statement(declaration->init.statement);
555                         return;
556                 }
557         } else if(declaration->init.initializer != NULL) {
558                 fputs(" = ", out);
559                 print_initializer(declaration->init.initializer);
560         }
561         fputc(';', out);
562 }
563
564 void print_declaration(const declaration_t *declaration)
565 {
566         if(declaration->namespc != NAMESPACE_NORMAL &&
567                         declaration->symbol == NULL)
568                 return;
569
570         switch(declaration->namespc) {
571         case NAMESPACE_NORMAL:
572                 print_normal_declaration(declaration);
573                 break;
574         case NAMESPACE_STRUCT:
575                 fputs("struct ", out);
576                 fputs(declaration->symbol->string, out);
577                 fputc(' ', out);
578                 print_compound_definition(declaration);
579                 fputc(';', out);
580                 break;
581         case NAMESPACE_UNION:
582                 fputs("union ", out);
583                 fputs(declaration->symbol->string, out);
584                 fputc(' ', out);
585                 print_compound_definition(declaration);
586                 fputc(';', out);
587                 break;
588         case NAMESPACE_ENUM:
589                 fputs("enum ", out);
590                 fputs(declaration->symbol->string, out);
591                 fputc(' ', out);
592                 print_enum_definition(declaration);
593                 fputc(';', out);
594                 break;
595         }
596 }
597
598 void print_ast(const translation_unit_t *unit)
599 {
600         inc_type_visited();
601         set_print_compound_entries(true);
602
603         declaration_t *declaration = unit->context.declarations;
604         for( ; declaration != NULL; declaration = declaration->next) {
605                 if(declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
606                         continue;
607                 if(declaration->namespc != NAMESPACE_NORMAL &&
608                                 declaration->symbol == NULL)
609                         continue;
610
611                 print_indent();
612                 print_declaration(declaration);
613                 fputc('\n', out);
614         }
615 }
616
617 void init_ast(void)
618 {
619         obstack_init(&ast_obstack);
620 }
621
622 void exit_ast(void)
623 {
624         obstack_free(&ast_obstack, NULL);
625 }
626
627 void ast_set_output(FILE *stream)
628 {
629         out = stream;
630         type_set_output(stream);
631 }
632
633 void* (allocate_ast) (size_t size)
634 {
635         return _allocate_ast(size);
636 }