|
|
397226 |
/**********************************************************/
|
|
|
397226 |
/* apimagic: cparser-based API normalization utility */
|
|
|
397226 |
/* Copyright (C) 2015--2016 Z. Gilboa */
|
|
|
397226 |
/* Released under GPLv2 and GPLv3; see COPYING.APIMAGIC. */
|
|
|
397226 |
/**********************************************************/
|
|
|
397226 |
|
|
|
397226 |
#include <stdio.h>
|
|
|
397226 |
|
|
|
397226 |
#include <cparser/ast/ast_t.h>
|
|
|
397226 |
#include <cparser/ast/type.h>
|
|
|
397226 |
#include <cparser/ast/type_t.h>
|
|
|
397226 |
#include <cparser/ast/entity_t.h>
|
|
|
397226 |
#include <cparser/ast/symbol_t.h>
|
|
|
397226 |
|
|
|
397226 |
#include <apimagic/apimagic.h>
|
|
|
397226 |
#include "apimagic_driver_impl.h"
|
|
|
397226 |
|
|
|
397226 |
static int output_string(
|
|
|
397226 |
FILE * fout,
|
|
|
397226 |
const char * fmt,
|
|
|
397226 |
const char * string,
|
|
|
397226 |
const char * brace,
|
|
|
397226 |
int * len)
|
|
|
397226 |
{
|
|
|
397226 |
int ret = fout
|
|
|
397226 |
? fprintf(fout,fmt,string,brace)
|
|
|
397226 |
: snprintf(0,0,fmt,string,brace);
|
|
|
397226 |
|
|
|
397226 |
if (len && (ret > 0))
|
|
|
397226 |
*len += ret;
|
|
|
397226 |
|
|
|
397226 |
return ret;
|
|
|
397226 |
}
|
|
|
397226 |
|
|
|
397226 |
static int output_compound(
|
|
|
397226 |
union entity_t const * entity,
|
|
|
397226 |
int depth,
|
|
|
397226 |
const struct amgc_layout * layout,
|
|
|
397226 |
FILE * fout)
|
|
|
397226 |
{
|
|
|
397226 |
struct compound_t const * compound;
|
|
|
397226 |
type_qualifiers_t tquals;
|
|
|
397226 |
union entity_t const * subentity;
|
|
|
397226 |
const union type_t * type;
|
|
|
397226 |
const struct declaration_t * decl;
|
|
|
397226 |
const char * fmt;
|
|
|
397226 |
const char * name;
|
|
|
397226 |
const char * brace;
|
|
|
397226 |
bool ftabs;
|
|
|
397226 |
bool fspace;
|
|
|
397226 |
int len;
|
|
|
397226 |
int width;
|
|
|
397226 |
int ptrdepth;
|
|
|
397226 |
int symwidth;
|
|
|
397226 |
int i;
|
|
|
397226 |
|
|
|
397226 |
if (entity->base.symbol && (depth == 0)) {
|
|
|
397226 |
name = entity->base.symbol->string;
|
|
|
397226 |
brace = " {";
|
|
|
397226 |
} else {
|
|
|
397226 |
name = "";
|
|
|
397226 |
brace = "{";
|
|
|
397226 |
}
|
|
|
397226 |
|
|
|
397226 |
compound = 0;
|
|
|
397226 |
|
|
|
397226 |
if (entity->kind == ENTITY_STRUCT)
|
|
|
397226 |
fmt = "struct %s%s\n";
|
|
|
397226 |
else if (entity->kind == ENTITY_UNION)
|
|
|
397226 |
fmt = "union %s%s\n";
|
|
|
397226 |
else if (entity->kind != ENTITY_COMPOUND_MEMBER)
|
|
|
397226 |
return -1;
|
|
|
397226 |
else if (entity->declaration.type->kind == TYPE_COMPOUND_STRUCT)
|
|
|
397226 |
fmt = "struct %s%s\n";
|
|
|
397226 |
else if (entity->declaration.type->kind == TYPE_COMPOUND_UNION)
|
|
|
397226 |
fmt = "union %s%s\n";
|
|
|
397226 |
else if (entity->declaration.type->kind == TYPE_POINTER) {
|
|
|
397226 |
type = entity->declaration.type;
|
|
|
397226 |
|
|
|
397226 |
for (; type->kind == TYPE_POINTER; )
|
|
|
397226 |
type = type->pointer.points_to;
|
|
|
397226 |
|
|
|
397226 |
compound = type->compound.compound;
|
|
|
397226 |
entity = compound->members.first_entity;
|
|
|
397226 |
|
|
|
397226 |
if (type->kind == TYPE_COMPOUND_STRUCT)
|
|
|
397226 |
fmt = "struct %s%s\n";
|
|
|
397226 |
else if (type->kind == TYPE_COMPOUND_UNION)
|
|
|
397226 |
fmt = "union %s%s\n";
|
|
|
397226 |
else
|
|
|
397226 |
return -1;
|
|
|
397226 |
} else
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
|
|
|
397226 |
if (compound)
|
|
|
397226 |
(void)0;
|
|
|
397226 |
else if (entity->kind == ENTITY_COMPOUND_MEMBER) {
|
|
|
397226 |
compound = entity->declaration.type->compound.compound;
|
|
|
397226 |
entity = compound->members.first_entity;
|
|
|
397226 |
} else {
|
|
|
397226 |
compound = &entity->compound;
|
|
|
397226 |
entity = compound->members.first_entity;
|
|
|
397226 |
}
|
|
|
397226 |
|
|
|
397226 |
|
|
|
397226 |
if (depth && fout && (fputc('\n',fout) < 0))
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
for (i=0; i
|
|
|
397226 |
if (output_string(fout,"\t","","",0) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
if (output_string(fout,fmt,name,brace,&len) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
|
|
|
397226 |
for (width=0,depth++; entity; entity=entity->base.next) {
|
|
|
397226 |
type = entity->declaration.type;
|
|
|
397226 |
len = 0;
|
|
|
397226 |
|
|
|
397226 |
while (type->kind == TYPE_ARRAY)
|
|
|
397226 |
type = type->array.element_type;
|
|
|
397226 |
|
|
|
397226 |
for (ptrdepth=0; type->kind==TYPE_POINTER; ptrdepth++)
|
|
|
397226 |
type = type->pointer.points_to;
|
|
|
397226 |
|
|
|
397226 |
tquals = type->base.qualifiers;
|
|
|
397226 |
ftabs = true;
|
|
|
397226 |
|
|
|
397226 |
switch (type->kind) {
|
|
|
397226 |
case TYPE_TYPEDEF:
|
|
|
397226 |
fmt = "%s ";
|
|
|
397226 |
name = type->typedeft.typedefe->base.symbol->string;
|
|
|
397226 |
break;
|
|
|
397226 |
|
|
|
397226 |
case TYPE_ATOMIC:
|
|
|
397226 |
fmt = "%s ";
|
|
|
397226 |
name = get_atomic_kind_name(type->atomic.akind);
|
|
|
397226 |
break;
|
|
|
397226 |
|
|
|
397226 |
case TYPE_COMPOUND_STRUCT:
|
|
|
397226 |
case TYPE_COMPOUND_UNION:
|
|
|
397226 |
compound = type->compound.compound;
|
|
|
397226 |
subentity = compound->members.first_entity;
|
|
|
397226 |
decl = type->typedeft.typedefe;
|
|
|
397226 |
|
|
|
397226 |
if (!subentity || decl->base.symbol) {
|
|
|
397226 |
name = decl->base.symbol->string;
|
|
|
397226 |
fmt = (type->kind == TYPE_COMPOUND_STRUCT)
|
|
|
397226 |
? "struct %s " : "union %s ";
|
|
|
397226 |
} else {
|
|
|
397226 |
ftabs = false;
|
|
|
397226 |
name = "";
|
|
|
397226 |
fmt = "";
|
|
|
397226 |
|
|
|
397226 |
if (output_compound(
|
|
|
397226 |
entity,depth,
|
|
|
397226 |
layout,fout) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
}
|
|
|
397226 |
|
|
|
397226 |
break;
|
|
|
397226 |
|
|
|
397226 |
case TYPE_VOID:
|
|
|
397226 |
fmt = "%s ";
|
|
|
397226 |
name = "void";
|
|
|
397226 |
break;
|
|
|
397226 |
|
|
|
397226 |
default:
|
|
|
397226 |
fmt = "";
|
|
|
397226 |
name = "";
|
|
|
397226 |
|
|
|
397226 |
if (fout)
|
|
|
397226 |
fprintf(fout,"UNHANDLED TYPE! %d ",
|
|
|
397226 |
type->kind);
|
|
|
397226 |
|
|
|
397226 |
break;
|
|
|
397226 |
}
|
|
|
397226 |
|
|
|
397226 |
if (ftabs)
|
|
|
397226 |
for (i=0; i
|
|
|
397226 |
if (output_string(fout,"\t","","",0) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
if (tquals & TYPE_QUALIFIER_CONST)
|
|
|
397226 |
if (output_string(fout,"const ","","",&len) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
if (output_string(fout,fmt,name,"",&len) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
for (fspace=ptrdepth; ptrdepth; ptrdepth--) {
|
|
|
397226 |
type = entity->declaration.type;
|
|
|
397226 |
|
|
|
397226 |
while (type->kind == TYPE_ARRAY)
|
|
|
397226 |
type = type->array.element_type;
|
|
|
397226 |
|
|
|
397226 |
for (i=0; i
|
|
|
397226 |
type = type->pointer.points_to;
|
|
|
397226 |
|
|
|
397226 |
if (type->base.qualifiers & TYPE_QUALIFIER_CONST)
|
|
|
397226 |
if (type->kind == TYPE_POINTER)
|
|
|
397226 |
if (output_string(fout," const ",
|
|
|
397226 |
"","",&len) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
if (output_string(fout,"*","","",&len) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
}
|
|
|
397226 |
|
|
|
397226 |
if (fspace)
|
|
|
397226 |
len++;
|
|
|
397226 |
|
|
|
397226 |
if (fout) {
|
|
|
397226 |
symwidth = layout->symwidth;
|
|
|
397226 |
|
|
|
397226 |
symwidth += layout->tabwidth;
|
|
|
397226 |
symwidth &= (~(layout->tabwidth-1));
|
|
|
397226 |
|
|
|
397226 |
len &= (~(layout->tabwidth-1));
|
|
|
397226 |
|
|
|
397226 |
while (len < symwidth) {
|
|
|
397226 |
if (fputc('\t',fout) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
else
|
|
|
397226 |
len += layout->tabwidth;
|
|
|
397226 |
}
|
|
|
397226 |
} else if (len > width)
|
|
|
397226 |
width = len;
|
|
|
397226 |
|
|
|
397226 |
if (output_string(fout,"%s",
|
|
|
397226 |
entity->base.symbol->string,
|
|
|
397226 |
"",0) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
type = entity->declaration.type;
|
|
|
397226 |
|
|
|
397226 |
while (fout && type->kind == TYPE_ARRAY) {
|
|
|
397226 |
if (fprintf(fout,
|
|
|
397226 |
type->array.size ? "[%zu]" : "[]",
|
|
|
397226 |
type->array.size) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
type = type->array.element_type;
|
|
|
397226 |
}
|
|
|
397226 |
|
|
|
397226 |
if (fout && fputs(";\n",fout) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
if (!ftabs && fout && entity->base.next)
|
|
|
397226 |
if (fputc('\n',fout) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
}
|
|
|
397226 |
|
|
|
397226 |
if (!fout)
|
|
|
397226 |
return width;
|
|
|
397226 |
|
|
|
397226 |
if (--depth) {
|
|
|
397226 |
for (i=0; i
|
|
|
397226 |
if (output_string(fout,"\t","","",0) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
if (output_string(fout,"} ","","",0) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
} else {
|
|
|
397226 |
if (output_string(fout,"};\n","","",0) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
}
|
|
|
397226 |
|
|
|
397226 |
return 0;
|
|
|
397226 |
}
|
|
|
397226 |
|
|
|
d1ebf8 |
static int output_compound_entity(
|
|
|
397226 |
const struct amgc_unit_ctx * uctx,
|
|
|
397226 |
const struct amgc_entity * aentity,
|
|
|
397226 |
const struct amgc_layout * layout,
|
|
|
397226 |
FILE * fout)
|
|
|
397226 |
{
|
|
|
397226 |
struct amgc_layout elayout;
|
|
|
397226 |
|
|
|
397226 |
if (layout && layout->symwidth)
|
|
|
397226 |
return output_compound(aentity->entity,0,layout,fout);
|
|
|
397226 |
|
|
|
397226 |
if (layout)
|
|
|
397226 |
memcpy(&elayout,layout,sizeof(elayout));
|
|
|
397226 |
else
|
|
|
397226 |
memset(&elayout,0,sizeof(elayout));
|
|
|
397226 |
|
|
|
397226 |
if ((elayout.symwidth = output_compound(aentity->entity,0,layout,0)) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
if (elayout.tabwidth == 0)
|
|
|
397226 |
elayout.tabwidth = AMGC_TAB_WIDTH;
|
|
|
397226 |
|
|
|
397226 |
if (output_compound(aentity->entity,0,&elayout,fout) < 0)
|
|
|
397226 |
return -1;
|
|
|
397226 |
|
|
|
397226 |
return 0;
|
|
|
397226 |
}
|
|
|
d1ebf8 |
|
|
|
d1ebf8 |
int amgc_output_compound(
|
|
|
d1ebf8 |
const struct amgc_unit_ctx * uctx,
|
|
|
d1ebf8 |
const struct amgc_entity * aentity,
|
|
|
d1ebf8 |
const struct amgc_layout * layout,
|
|
|
d1ebf8 |
FILE * fout)
|
|
|
d1ebf8 |
{
|
|
|
d1ebf8 |
union entity_t const * entity;
|
|
|
d1ebf8 |
|
|
|
d1ebf8 |
entity = aentity->entity;
|
|
|
d1ebf8 |
|
|
|
d1ebf8 |
if ((entity->kind == ENTITY_STRUCT) || (entity->kind == ENTITY_UNION))
|
|
|
d1ebf8 |
return output_compound_entity(uctx,aentity,layout,fout);
|
|
|
d1ebf8 |
else
|
|
|
d1ebf8 |
return -1;
|
|
|
d1ebf8 |
}
|
|
|
ca3de4 |
|
|
|
ca3de4 |
int amgc_output_struct(
|
|
|
ca3de4 |
const struct amgc_unit_ctx * uctx,
|
|
|
ca3de4 |
const struct amgc_entity * aentity,
|
|
|
ca3de4 |
const struct amgc_layout * layout,
|
|
|
ca3de4 |
FILE * fout)
|
|
|
ca3de4 |
{
|
|
|
ca3de4 |
union entity_t const * entity;
|
|
|
ca3de4 |
|
|
|
ca3de4 |
entity = aentity->entity;
|
|
|
ca3de4 |
|
|
|
ca3de4 |
if (entity->kind == ENTITY_STRUCT)
|
|
|
ca3de4 |
return output_compound_entity(uctx,aentity,layout,fout);
|
|
|
ca3de4 |
else
|
|
|
ca3de4 |
return -1;
|
|
|
ca3de4 |
}
|
|
|
ca3de4 |
|
|
|
ca3de4 |
int amgc_output_union(
|
|
|
ca3de4 |
const struct amgc_unit_ctx * uctx,
|
|
|
ca3de4 |
const struct amgc_entity * aentity,
|
|
|
ca3de4 |
const struct amgc_layout * layout,
|
|
|
ca3de4 |
FILE * fout)
|
|
|
ca3de4 |
{
|
|
|
ca3de4 |
union entity_t const * entity;
|
|
|
ca3de4 |
|
|
|
ca3de4 |
entity = aentity->entity;
|
|
|
ca3de4 |
|
|
|
ca3de4 |
if (entity->kind == ENTITY_UNION)
|
|
|
ca3de4 |
return output_compound_entity(uctx,aentity,layout,fout);
|
|
|
ca3de4 |
else
|
|
|
ca3de4 |
return -1;
|
|
|
ca3de4 |
}
|
|
|
0c91ec |
|
|
|
0c91ec |
int amgc_output_unit_structs(
|
|
|
0c91ec |
const struct amgc_unit_ctx * uctx,
|
|
|
0c91ec |
const struct amgc_layout * layout,
|
|
|
0c91ec |
FILE * fout)
|
|
|
0c91ec |
{
|
|
|
0c91ec |
const struct amgc_entity * aentity;
|
|
|
0c91ec |
|
|
|
0c91ec |
for (aentity=uctx->entities->structs; aentity->entity; aentity++)
|
|
|
0c91ec |
if (output_compound_entity(uctx,aentity,layout,fout))
|
|
|
0c91ec |
return -1;
|
|
|
0c91ec |
|
|
|
0c91ec |
return 0;
|
|
|
0c91ec |
}
|
|
|
0c91ec |
|
|
|
0c91ec |
int amgc_output_unit_unions(
|
|
|
0c91ec |
const struct amgc_unit_ctx * uctx,
|
|
|
0c91ec |
const struct amgc_layout * layout,
|
|
|
0c91ec |
FILE * fout)
|
|
|
0c91ec |
{
|
|
|
0c91ec |
const struct amgc_entity * aentity;
|
|
|
0c91ec |
|
|
|
0c91ec |
for (aentity=uctx->entities->unions; aentity->entity; aentity++)
|
|
|
0c91ec |
if (output_compound_entity(uctx,aentity,layout,fout))
|
|
|
0c91ec |
return -1;
|
|
|
0c91ec |
|
|
|
0c91ec |
return 0;
|
|
|
0c91ec |
}
|