updated Makefiles
[cparser] / ast.c
diff --git a/ast.c b/ast.c
index e109754..87d490e 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -41,11 +41,10 @@ static void print_const(const const_expression_t *cnst)
        }
 }
 
-static void print_string_literal(
-               const string_literal_expression_t *string_literal)
+static void print_quoted_string(const char *string)
 {
        fputc('"', out);
-       for(const char *c = string_literal->value; *c != '\0'; ++c) {
+       for(const char *c = string; *c != '\0'; ++c) {
                switch(*c) {
                case '\"':  fputs("\\\"", out); break;
                case '\\':  fputs("\\\\", out); break;
@@ -69,6 +68,57 @@ static void print_string_literal(
        fputc('"', out);
 }
 
+static void print_string_literal(
+               const string_literal_expression_t *string_literal)
+{
+       print_quoted_string(string_literal->value);
+}
+
+static void print_wide_string_literal(
+       const wide_string_literal_expression_t *const wstr)
+{
+       fputs("L\"", out);
+       for (const wchar_rep_t *c   = wstr->value.begin,
+                              *end = c + wstr->value.size;
+            c != end; ++c) {
+               switch (*c) {
+                       case L'\"':  fputs("\\\"", out); break;
+                       case L'\\':  fputs("\\\\", out); break;
+                       case L'\a':  fputs("\\a",  out); break;
+                       case L'\b':  fputs("\\b",  out); break;
+                       case L'\f':  fputs("\\f",  out); break;
+                       case L'\n':  fputs("\\n",  out); break;
+                       case L'\r':  fputs("\\r",  out); break;
+                       case L'\t':  fputs("\\t",  out); break;
+                       case L'\v':  fputs("\\v",  out); break;
+                       case L'\?':  fputs("\\?",  out); break;
+                       default: {
+                               const unsigned tc = *c;
+                               if (tc < 0x80U) {
+                                       if (!isprint(*c))  {
+                                               fprintf(out, "\\%03o", (char)*c);
+                                       } else {
+                                               fputc(*c, out);
+                                       }
+                               } else if (tc < 0x800) {
+                                       fputc(0xC0 | (tc >> 6),   out);
+                                       fputc(0x80 | (tc & 0x3F), out);
+                               } else if (tc < 0x10000) {
+                                       fputc(0xE0 | ( tc >> 12),         out);
+                                       fputc(0x80 | ((tc >>  6) & 0x3F), out);
+                                       fputc(0x80 | ( tc        & 0x3F), out);
+                               } else {
+                                       fputc(0xF0 | ( tc >> 18),         out);
+                                       fputc(0x80 | ((tc >> 12) & 0x3F), out);
+                                       fputc(0x80 | ((tc >>  6) & 0x3F), out);
+                                       fputc(0x80 | ( tc        & 0x3F), out);
+                               }
+                       }
+               }
+       }
+       fputc('"', out);
+}
+
 static void print_call_expression(const call_expression_t *call)
 {
        print_expression(call->function);
@@ -161,6 +211,9 @@ static void print_unary_expression(const unary_expression_t *unexpr)
                print_type(unexpr->expression.datatype);
                fputs(")", out);
                break;
+       case UNEXPR_CAST_IMPLICIT:
+               print_expression(unexpr->value);
+               return;
        case UNEXPR_INVALID:
                fprintf(out, "unop%d", (int) unexpr->type);
                break;
@@ -266,6 +319,9 @@ void print_expression(const expression_t *expression)
        case EXPR_STRING_LITERAL:
                print_string_literal(&expression->string);
                break;
+       case EXPR_WIDE_STRING_LITERAL:
+               print_wide_string_literal(&expression->wide_string);
+               break;
        case EXPR_CALL:
                print_call_expression(&expression->call);
                break;
@@ -454,23 +510,80 @@ static void print_for_statement(const for_statement_t *statement)
        print_statement(statement->body);
 }
 
+static void print_asm_constraints(asm_constraint_t *constraints)
+{
+       asm_constraint_t *constraint = constraints;
+       for( ; constraint != NULL; constraint = constraint->next) {
+               if(constraint != constraints)
+                       fputs(", ", out);
+
+               if(constraint->symbol) {
+                       fprintf(out, "[%s] ", constraint->symbol->string);
+               }
+               print_quoted_string(constraint->constraints);
+               fputs(" (", out);
+               print_expression(constraint->expression);
+               fputs(")", out);
+       }
+}
+
+static void print_asm_clobbers(asm_clobber_t *clobbers)
+{
+       asm_clobber_t *clobber = clobbers;
+       for( ; clobber != NULL; clobber = clobber->next) {
+               if(clobber != clobbers)
+                       fputs(", ", out);
+
+               print_quoted_string(clobber->clobber);
+       }
+}
+
+static void print_asm_statement(const asm_statement_t *statement)
+{
+       fputs("asm ", out);
+       if(statement->is_volatile) {
+               fputs("volatile ", out);
+       }
+       fputs("(", out);
+       print_quoted_string(statement->asm_text);
+       if(statement->inputs == NULL && statement->outputs == NULL
+                       && statement->clobbers == NULL)
+               goto end_of_print_asm_statement;
+
+       fputs(" : ", out);
+       print_asm_constraints(statement->inputs);
+       if(statement->outputs == NULL && statement->clobbers == NULL)
+               goto end_of_print_asm_statement;
+
+       fputs(" : ", out);
+       print_asm_constraints(statement->outputs);
+       if(statement->clobbers == NULL)
+               goto end_of_print_asm_statement;
+
+       fputs(" : ", out);
+       print_asm_clobbers(statement->clobbers);
+
+end_of_print_asm_statement:
+       fputs(");\n", out);
+}
+
 void print_statement(const statement_t *statement)
 {
        switch(statement->type) {
        case STATEMENT_COMPOUND:
-               print_compound_statement((const compound_statement_t*) statement);
+               print_compound_statement(&statement->compound);
                break;
        case STATEMENT_RETURN:
-               print_return_statement((const return_statement_t*) statement);
+               print_return_statement(&statement->returns);
                break;
        case STATEMENT_EXPRESSION:
-               print_expression_statement((const expression_statement_t*) statement);
+               print_expression_statement(&statement->expression);
                break;
        case STATEMENT_LABEL:
-               print_label_statement((const label_statement_t*) statement);
+               print_label_statement(&statement->label);
                break;
        case STATEMENT_GOTO:
-               print_goto_statement((const goto_statement_t*) statement);
+               print_goto_statement(&statement->gotos);
                break;
        case STATEMENT_CONTINUE:
                fputs("continue;\n", out);
@@ -479,25 +592,28 @@ void print_statement(const statement_t *statement)
                fputs("break;\n", out);
                break;
        case STATEMENT_IF:
-               print_if_statement((const if_statement_t*) statement);
+               print_if_statement(&statement->ifs);
                break;
        case STATEMENT_SWITCH:
-               print_switch_statement((const switch_statement_t*) statement);
+               print_switch_statement(&statement->switchs);
                break;
        case STATEMENT_CASE_LABEL:
-               print_case_label((const case_label_statement_t*) statement);
+               print_case_label(&statement->case_label);
                break;
        case STATEMENT_DECLARATION:
-               print_declaration_statement((const declaration_statement_t*) statement);
+               print_declaration_statement(&statement->declaration);
                break;
        case STATEMENT_WHILE:
-               print_while_statement((const while_statement_t*) statement);
+               print_while_statement(&statement->whiles);
                break;
        case STATEMENT_DO_WHILE:
-               print_do_while_statement((const do_while_statement_t*) statement);
+               print_do_while_statement(&statement->do_while);
                break;
        case STATEMENT_FOR:
-               print_for_statement((const for_statement_t*) statement);
+               print_for_statement(&statement->fors);
+               break;
+       case STATEMENT_ASM:
+               print_asm_statement(&statement->asms);
                break;
        case STATEMENT_INVALID:
                fprintf(out, "*invalid statement*");
@@ -546,11 +662,11 @@ void print_initializer(const initializer_t *initializer)
 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->is_inline) {
                fputs("inline ", out);
        }
+       print_type_ext(declaration->type, declaration->symbol,
+                      &declaration->context);
 
        if(declaration->type->type == TYPE_FUNCTION) {
                if(declaration->init.statement != NULL) {