more work on local variable support
[cparser] / ast.c
diff --git a/ast.c b/ast.c
index 6590f57..5bd7cea 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -16,9 +16,14 @@ static FILE *out;
 static int   indent;
 
 static void print_statement(const statement_t *statement);
-static void print_declaration(const declaration_t *declaration);
 
-static void print_indent(void)
+void change_indent(int delta)
+{
+       indent += delta;
+       assert(indent >= 0);
+}
+
+void print_indent(void)
 {
        for(int i = 0; i < indent; ++i)
                fprintf(out, "\t");
@@ -26,7 +31,14 @@ static void print_indent(void)
 
 static void print_const(const const_t *cnst)
 {
-       fprintf(out, "%d", cnst->value);
+       if(cnst->expression.datatype == NULL)
+               return;
+
+       if(is_type_integer(cnst->expression.datatype)) {
+               fprintf(out, "%d", cnst->v.int_value);
+       } else if(is_type_floating(cnst->expression.datatype)) {
+               fprintf(out, "%Lf", cnst->v.float_value);
+       }
 }
 
 static void print_string_literal(const string_literal_t *string_literal)
@@ -58,7 +70,7 @@ static void print_string_literal(const string_literal_t *string_literal)
 
 static void print_call_expression(const call_expression_t *call)
 {
-       print_expression(call->method);
+       print_expression(call->function);
        fprintf(out, "(");
        call_argument_t *argument = call->arguments;
        int              first    = 1;
@@ -190,6 +202,38 @@ static void print_builtin_symbol(const builtin_symbol_expression_t *expression)
        fputs(expression->symbol->string, out);
 }
 
+static void print_conditional(const conditional_expression_t *expression)
+{
+       fputs("(", out);
+       print_expression(expression->condition);
+       fputs(" ? ", out);
+       print_expression(expression->true_expression);
+       fputs(" : ", out);
+       print_expression(expression->false_expression);
+       fputs(")", out);
+}
+
+static void print_va_arg(const va_arg_expression_t *expression)
+{
+       fputs("__builtin_va_arg(", out);
+       print_expression(expression->arg);
+       fputs(", ", out);
+       print_type(expression->expression.datatype);
+       fputs(")", out);
+}
+
+static void print_select(const select_expression_t *expression)
+{
+       print_expression(expression->compound);
+       if(expression->compound->datatype == NULL ||
+                       expression->compound->datatype->type == TYPE_POINTER) {
+               fputs("->", out);
+       } else {
+               fputc('.', out);
+       }
+       fputs(expression->symbol->string, out);
+}
+
 void print_expression(const expression_t *expression)
 {
        switch(expression->type) {
@@ -225,11 +269,18 @@ void print_expression(const expression_t *expression)
        case EXPR_BUILTIN_SYMBOL:
                print_builtin_symbol((const builtin_symbol_expression_t*) expression);
                break;
-
        case EXPR_CONDITIONAL:
+               print_conditional((const conditional_expression_t*) expression);
+               break;
+       case EXPR_VA_ARG:
+               print_va_arg((const va_arg_expression_t*) expression);
+               break;
+       case EXPR_SELECT:
+               print_select((const select_expression_t*) expression);
+               break;
+
        case EXPR_OFFSETOF:
        case EXPR_STATEMENT:
-       case EXPR_SELECT:
                /* TODO */
                fprintf(out, "some expression of type %d", expression->type);
                break;
@@ -321,10 +372,17 @@ static void print_case_label(const case_label_statement_t *statement)
 static void print_declaration_statement(
                const declaration_statement_t *statement)
 {
+       int first = 1;
        declaration_t *declaration = statement->declarations_begin;
        for( ; declaration != statement->declarations_end->next;
               declaration = declaration->next) {
+               if(!first) {
+                       print_indent();
+               } else {
+                       first = 0;
+               }
                print_declaration(declaration);
+               fputc('\n', out);
        }
 }
 
@@ -346,9 +404,27 @@ static void print_do_while_statement(const do_while_statement_t *statement)
        fputs(");\n", out);
 }
 
-static void print_for_statemenet(const for_statement_t *statement)
+static void print_for_statement(const for_statement_t *statement)
 {
-       fprintf(out, "for(TODO) ");
+       fputs("for(", out);
+       if(statement->context.declarations != NULL) {
+               assert(statement->initialisation == NULL);
+               print_declaration(statement->context.declarations);
+               if(statement->context.declarations->next != NULL) {
+                       panic("multiple declarations in for statement not supported yet");
+               }
+       } else if(statement->initialisation) {
+               print_expression(statement->initialisation);
+       }
+       fputs("; ", out);
+       if(statement->condition != NULL) {
+               print_expression(statement->condition);
+       }
+       fputs("; ", out);
+       if(statement->step != NULL) {
+               print_expression(statement->step);
+       }
+       fputs(")", out);
        print_statement(statement->body);
 }
 
@@ -395,7 +471,7 @@ void print_statement(const statement_t *statement)
                print_do_while_statement((const do_while_statement_t*) statement);
                break;
        case STATEMENT_FOR:
-               print_for_statemenet((const for_statement_t*) statement);
+               print_for_statement((const for_statement_t*) statement);
                break;
        case STATEMENT_INVALID:
                fprintf(out, "*invalid statement*");
@@ -417,30 +493,93 @@ static void print_storage_class(storage_class_t storage_class)
        }
 }
 
-static void print_declaration(const declaration_t *declaration)
+void print_initializer(const initializer_t *initializer)
+{
+       if(initializer->type == INITIALIZER_VALUE) {
+               print_expression(initializer->v.value);
+               return;
+       }
+
+       assert(initializer->type == INITIALIZER_LIST);
+       fputs("{ ", out);
+       initializer_t *iter = initializer->v.list;
+       for( ; iter != NULL; iter = iter->next) {
+               print_initializer(iter);
+               if(iter->next != NULL) {
+                       fputs(", ", out);
+               }
+       }
+       fputs("}", out);
+}
+
+static void print_normal_declaration(const declaration_t *declaration)
 {
        print_storage_class(declaration->storage_class);
        print_type_ext(declaration->type, declaration->symbol,
                       &declaration->context);
-       if(declaration->statement != NULL) {
-               fputs("\n", out);
-               print_statement(declaration->statement);
-       } else if(declaration->initializer != NULL) {
+       if(declaration->type->type == TYPE_FUNCTION) {
+               if(declaration->init.statement != NULL) {
+                       fputs("\n", out);
+                       print_statement(declaration->init.statement);
+                       return;
+               }
+       } else if(declaration->init.initializer != NULL) {
                fputs(" = ", out);
-               print_expression(declaration->initializer);
-               fprintf(out, ";\n");
-       } else {
-               fprintf(out, ";\n");
+               print_initializer(declaration->init.initializer);
+       }
+       fputc(';', out);
+}
+
+void print_declaration(const declaration_t *declaration)
+{
+       if(declaration->namespace != NAMESPACE_NORMAL &&
+                       declaration->symbol == NULL)
+               return;
+
+       switch(declaration->namespace) {
+       case NAMESPACE_NORMAL:
+               print_normal_declaration(declaration);
+               break;
+       case NAMESPACE_STRUCT:
+               fputs("struct ", out);
+               fputs(declaration->symbol->string, out);
+               fputc(' ', out);
+               print_compound_definition(declaration);
+               fputc(';', out);
+               break;
+       case NAMESPACE_UNION:
+               fputs("union ", out);
+               fputs(declaration->symbol->string, out);
+               fputc(' ', out);
+               print_compound_definition(declaration);
+               fputc(';', out);
+               break;
+       case NAMESPACE_ENUM:
+               fputs("enum ", out);
+               fputs(declaration->symbol->string, out);
+               fputc(' ', out);
+               print_enum_definition(declaration);
+               fputc(';', out);
+               break;
        }
 }
 
 void print_ast(const translation_unit_t *unit)
 {
+       inc_type_visited();
+       set_print_compound_entries(true);
+
        declaration_t *declaration = unit->context.declarations;
-       while(declaration != NULL) {
-               print_declaration(declaration);
+       for( ; declaration != NULL; declaration = declaration->next) {
+               if(declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
+                       continue;
+               if(declaration->namespace != NAMESPACE_NORMAL &&
+                               declaration->symbol == NULL)
+                       continue;
 
-               declaration = declaration->next;
+               print_indent();
+               print_declaration(declaration);
+               fputc('\n', out);
        }
 }