/**********************************************************/ /* apimagic: cparser-based API normalization utility */ /* Copyright (C) 2015--2021 Z. Gilboa */ /* Released under GPLv2 and GPLv3; see COPYING.APIMAGIC. */ /**********************************************************/ #include #include #include #include #include #include #include #include "apimagic_driver_impl.h" static int output_string( int * fdout, const char * fmt, const char * string, const char * brace, int * len) { int ret = fdout ? amgc_dprintf(*fdout,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, int * fdout) { 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 && fdout && (amgc_dprintf(*fdout,"\n") < 0)) return -1; for (i=0; ibase.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,fdout) < 0) return -1; } break; case TYPE_VOID: fmt = "%s "; name = "void"; break; default: fmt = ""; name = ""; if (fdout) amgc_dprintf( *fdout, "UNHANDLED TYPE! %d ", type->kind); break; } if (ftabs) for (i=0; ideclaration.type; while (type->kind == TYPE_ARRAY) type = type->array.element_type; for (i=0; ipointer.points_to; if (type->base.qualifiers & TYPE_QUALIFIER_CONST) if (type->kind == TYPE_POINTER) if (output_string(fdout," const ", "","",&len) < 0) return -1; if (output_string(fdout,"*","","",&len) < 0) return -1; } if (fspace) len++; if (fdout) { symwidth = layout->symwidth; symwidth += layout->tabwidth; symwidth &= (~(layout->tabwidth-1)); len &= (~(layout->tabwidth-1)); while (len < symwidth) { if (amgc_dprintf(*fdout,"\t") < 0) return -1; else len += layout->tabwidth; } } else if (len > width) width = len; if (output_string(fdout,"%s", entity->base.symbol->string, "",0) < 0) return -1; type = entity->declaration.type; while (fdout && type->kind == TYPE_ARRAY) { if (amgc_dprintf( *fdout, type->array.size ? "[%zu]" : "[]", type->array.size) < 0) return -1; type = type->array.element_type; } if (fdout && amgc_dprintf(*fdout,";\n") < 0) return -1; if (!ftabs && fdout && entity->base.next) if (amgc_dprintf(*fdout,"\n") < 0) return -1; } if (!fdout) return width; if (--depth) { for (i=0; isymwidth) return output_compound(aentity->entity,0,layout,&fdout); 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,&fdout) < 0) return -1; return 0; } int amgc_output_compound( const struct amgc_driver_ctx * dctx, const struct amgc_unit_ctx * uctx, const struct amgc_entity * aentity, const struct amgc_layout * layout) { union entity_t const * entity; entity = aentity->entity; return ((entity->kind == ENTITY_STRUCT) || (entity->kind == ENTITY_UNION)) ? output_compound_entity(dctx,uctx,aentity,layout) : -1; } int amgc_output_struct( const struct amgc_driver_ctx * dctx, const struct amgc_unit_ctx * uctx, const struct amgc_entity * aentity, const struct amgc_layout * layout) { union entity_t const * entity; entity = aentity->entity; return (entity->kind == ENTITY_STRUCT) ? output_compound_entity(dctx,uctx,aentity,layout) : -1; } int amgc_output_union( const struct amgc_driver_ctx * dctx, const struct amgc_unit_ctx * uctx, const struct amgc_entity * aentity, const struct amgc_layout * layout) { union entity_t const * entity; entity = aentity->entity; return (entity->kind == ENTITY_UNION) ? output_compound_entity(dctx,uctx,aentity,layout) : -1; } int amgc_output_unit_structs( const struct amgc_driver_ctx * dctx, const struct amgc_unit_ctx * uctx, const struct amgc_layout * layout) { const struct amgc_entity * aentity; for (aentity=uctx->entities->structs; aentity->entity; aentity++) if (output_compound_entity(dctx,uctx,aentity,layout) < 0) return -1; return 0; } int amgc_output_unit_unions( const struct amgc_driver_ctx * dctx, const struct amgc_unit_ctx * uctx, const struct amgc_layout * layout) { const struct amgc_entity * aentity; for (aentity=uctx->entities->unions; aentity->entity; aentity++) if (output_compound_entity(dctx,uctx,aentity,layout) < 0) return -1; return 0; }