summaryrefslogtreecommitdiffhomepage
path: root/src/output/amgc_output_compound.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/output/amgc_output_compound.c')
-rw-r--r--src/output/amgc_output_compound.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/src/output/amgc_output_compound.c b/src/output/amgc_output_compound.c
new file mode 100644
index 0000000..bbc85d9
--- /dev/null
+++ b/src/output/amgc_output_compound.c
@@ -0,0 +1,300 @@
+/**********************************************************/
+/* apimagic: cparser-based API normalization utility */
+/* Copyright (C) 2015--2016 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.APIMAGIC. */
+/**********************************************************/
+
+#include <stdio.h>
+
+#include <cparser/ast/ast_t.h>
+#include <cparser/ast/type.h>
+#include <cparser/ast/type_t.h>
+#include <cparser/ast/entity_t.h>
+#include <cparser/ast/symbol_t.h>
+
+#include <apimagic/apimagic.h>
+#include "apimagic_driver_impl.h"
+
+static int output_string(
+ FILE * fout,
+ const char * fmt,
+ const char * string,
+ const char * brace,
+ int * len)
+{
+ int ret = fout
+ ? fprintf(fout,fmt,string,brace)
+ : snprintf(0,0,fmt,string,brace);
+
+ if (len && (ret > 0))
+ *len += ret;
+
+ return ret;
+}
+
+static int output_compound(
+ union entity_t const * entity,
+ int depth,
+ const struct amgc_layout * layout,
+ FILE * fout)
+{
+ struct compound_t const * compound;
+ type_qualifiers_t tquals;
+ union entity_t const * subentity;
+ const union type_t * type;
+ const struct declaration_t * decl;
+ const char * fmt;
+ const char * name;
+ const char * brace;
+ bool ftabs;
+ bool fspace;
+ int len;
+ int width;
+ int ptrdepth;
+ int symwidth;
+ int i;
+
+ if (entity->base.symbol && (depth == 0)) {
+ name = entity->base.symbol->string;
+ brace = " {";
+ } else {
+ name = "";
+ brace = "{";
+ }
+
+ compound = 0;
+
+ if (entity->kind == ENTITY_STRUCT)
+ fmt = "struct %s%s\n";
+ else if (entity->kind == ENTITY_UNION)
+ fmt = "union %s%s\n";
+ else if (entity->kind != ENTITY_COMPOUND_MEMBER)
+ return -1;
+ else if (entity->declaration.type->kind == TYPE_COMPOUND_STRUCT)
+ fmt = "struct %s%s\n";
+ else if (entity->declaration.type->kind == TYPE_COMPOUND_UNION)
+ fmt = "union %s%s\n";
+ else if (entity->declaration.type->kind == TYPE_POINTER) {
+ type = entity->declaration.type;
+
+ for (; type->kind == TYPE_POINTER; )
+ type = type->pointer.points_to;
+
+ compound = type->compound.compound;
+ entity = compound->members.first_entity;
+
+ if (type->kind == TYPE_COMPOUND_STRUCT)
+ fmt = "struct %s%s\n";
+ else if (type->kind == TYPE_COMPOUND_UNION)
+ fmt = "union %s%s\n";
+ else
+ return -1;
+ } else
+ return -1;
+
+
+ if (compound)
+ (void)0;
+ else if (entity->kind == ENTITY_COMPOUND_MEMBER) {
+ compound = entity->declaration.type->compound.compound;
+ entity = compound->members.first_entity;
+ } else {
+ compound = &entity->compound;
+ entity = compound->members.first_entity;
+ }
+
+
+ if (depth && fout && (fputc('\n',fout) < 0))
+ return -1;
+
+ for (i=0; i<depth; i++)
+ if (output_string(fout,"\t","","",0) < 0)
+ return -1;
+
+ if (output_string(fout,fmt,name,brace,&len) < 0)
+ return -1;
+
+
+ for (width=0,depth++; entity; entity=entity->base.next) {
+ type = entity->declaration.type;
+ len = 0;
+
+ while (type->kind == TYPE_ARRAY)
+ type = type->array.element_type;
+
+ for (ptrdepth=0; type->kind==TYPE_POINTER; ptrdepth++)
+ type = type->pointer.points_to;
+
+ tquals = type->base.qualifiers;
+ ftabs = true;
+
+ switch (type->kind) {
+ case TYPE_TYPEDEF:
+ fmt = "%s ";
+ name = type->typedeft.typedefe->base.symbol->string;
+ break;
+
+ case TYPE_ATOMIC:
+ fmt = "%s ";
+ name = get_atomic_kind_name(type->atomic.akind);
+ break;
+
+ case TYPE_COMPOUND_STRUCT:
+ case TYPE_COMPOUND_UNION:
+ compound = type->compound.compound;
+ subentity = compound->members.first_entity;
+ decl = type->typedeft.typedefe;
+
+ if (!subentity || decl->base.symbol) {
+ name = decl->base.symbol->string;
+ fmt = (type->kind == TYPE_COMPOUND_STRUCT)
+ ? "struct %s " : "union %s ";
+ } else {
+ ftabs = false;
+ name = "";
+ fmt = "";
+
+ if (output_compound(
+ entity,depth,
+ layout,fout) < 0)
+ return -1;
+ }
+
+ break;
+
+ case TYPE_VOID:
+ fmt = "%s ";
+ name = "void";
+ break;
+
+ default:
+ fmt = "";
+ name = "";
+
+ if (fout)
+ fprintf(fout,"UNHANDLED TYPE! %d ",
+ type->kind);
+
+ break;
+ }
+
+ if (ftabs)
+ for (i=0; i<depth; i++)
+ if (output_string(fout,"\t","","",0) < 0)
+ return -1;
+
+ if (tquals & TYPE_QUALIFIER_CONST)
+ if (output_string(fout,"const ","","",&len) < 0)
+ return -1;
+
+ if (output_string(fout,fmt,name,"",&len) < 0)
+ return -1;
+
+ for (fspace=ptrdepth; ptrdepth; ptrdepth--) {
+ type = entity->declaration.type;
+
+ while (type->kind == TYPE_ARRAY)
+ type = type->array.element_type;
+
+ for (i=0; i<ptrdepth; i++)
+ type = type->pointer.points_to;
+
+ if (type->base.qualifiers & TYPE_QUALIFIER_CONST)
+ if (type->kind == TYPE_POINTER)
+ if (output_string(fout," const ",
+ "","",&len) < 0)
+ return -1;
+
+ if (output_string(fout,"*","","",&len) < 0)
+ return -1;
+ }
+
+ if (fspace)
+ len++;
+
+ if (fout) {
+ symwidth = layout->symwidth;
+
+ symwidth += layout->tabwidth;
+ symwidth &= (~(layout->tabwidth-1));
+
+ len &= (~(layout->tabwidth-1));
+
+ while (len < symwidth) {
+ if (fputc('\t',fout) < 0)
+ return -1;
+ else
+ len += layout->tabwidth;
+ }
+ } else if (len > width)
+ width = len;
+
+ if (output_string(fout,"%s",
+ entity->base.symbol->string,
+ "",0) < 0)
+ return -1;
+
+ type = entity->declaration.type;
+
+ while (fout && type->kind == TYPE_ARRAY) {
+ if (fprintf(fout,
+ type->array.size ? "[%zu]" : "[]",
+ type->array.size) < 0)
+ return -1;
+
+ type = type->array.element_type;
+ }
+
+ if (fout && fputs(";\n",fout) < 0)
+ return -1;
+
+ if (!ftabs && fout && entity->base.next)
+ if (fputc('\n',fout) < 0)
+ return -1;
+ }
+
+ if (!fout)
+ return width;
+
+ if (--depth) {
+ for (i=0; i<depth; i++)
+ if (output_string(fout,"\t","","",0) < 0)
+ return -1;
+
+ if (output_string(fout,"} ","","",0) < 0)
+ return -1;
+ } else {
+ if (output_string(fout,"};\n","","",0) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+int amgc_output_compound(
+ const struct amgc_unit_ctx * uctx,
+ const struct amgc_entity * aentity,
+ const struct amgc_layout * layout,
+ FILE * fout)
+{
+ struct amgc_layout elayout;
+
+ if (layout && layout->symwidth)
+ return output_compound(aentity->entity,0,layout,fout);
+
+ if (layout)
+ memcpy(&elayout,layout,sizeof(elayout));
+ else
+ memset(&elayout,0,sizeof(elayout));
+
+ if ((elayout.symwidth = output_compound(aentity->entity,0,layout,0)) < 0)
+ return -1;
+
+ if (elayout.tabwidth == 0)
+ elayout.tabwidth = AMGC_TAB_WIDTH;
+
+ if (output_compound(aentity->entity,0,&elayout,fout) < 0)
+ return -1;
+
+ return 0;
+}