/**********************************************************/
/* apimagic: cparser-based API normalization utility */
/* Copyright (C) 2015--2016 Z. Gilboa */
/* Released under GPLv2 and GPLv3; see COPYING.APIMAGIC. */
/**********************************************************/
#include <cparser/ast/ast_t.h>
#include <cparser/ast/entity_t.h>
#include <cparser/ast/type_t.h>
#include <libfirm/tv.h>
#include <apimagic/apimagic.h>
struct amgc_unit_entities_impl {
struct amgc_define * adefines;
struct amgc_entity * aentities;
struct amgc_unit_entities entities;
};
static int amgc_free_unit_entities_impl(
struct amgc_unit_entities_impl *entities,
int status)
{
if (entities->adefines)
free(entities->adefines);
if (entities->aentities)
free(entities->aentities);
free (entities);
return status;
}
int amgc_get_unit_entities(
const struct amgc_unit_ctx * uctx,
struct amgc_unit_meta * meta,
struct amgc_unit_entities ** pentities)
{
struct amgc_unit_meta umeta;
struct amgc_define * adefine;
struct amgc_entity * aentity;
struct amgc_unit_entities * uentities;
union entity_t * entity;
union type_t * etype;
struct amgc_unit_entities_impl *entities;
size_t ndefs;
size_t nelements;
int enumval;
int ptrdepth;
if (!meta)
meta = &umeta;
if (amgc_init_unit_meta(uctx,meta))
return -1;
if (!(entities = calloc(1,sizeof(*entities))))
return -1;
/* use first element as a guard */
ndefs = 1;
ndefs += meta->ndefines + 1;
nelements = 1;
nelements += meta->nenums + 1;
nelements += meta->nenumvals + 1;
nelements += meta->ntypedefs + 1;
nelements += meta->nstructs + 1;
nelements += meta->nunions + 1;
nelements += meta->nfunctions + 1;
nelements += meta->ngenerated + 1;
if (!(entities->adefines = calloc(ndefs,sizeof(struct amgc_define))))
return amgc_free_unit_entities_impl(entities,-1);
if (!(entities->aentities = calloc(nelements,sizeof(struct amgc_entity))))
return amgc_free_unit_entities_impl(entities,-1);
adefine = &entities->adefines[1];
entities->entities.defines = adefine;
aentity = &entities->aentities[1];
entities->entities.enums = aentity;
aentity += meta->nenums + 1;
entities->entities.enumvals = aentity;
aentity += meta->nenumvals + 1;
entities->entities.typedefs = aentity;
aentity += meta->ntypedefs + 1;
entities->entities.structs = aentity;
aentity += meta->nstructs + 1;
entities->entities.unions = aentity;
aentity += meta->nunions + 1;
entities->entities.functions = aentity;
aentity += meta->nfunctions + 1;
entities->entities.generated = aentity;
aentity += meta->ngenerated + 1;
meta = &umeta;
memset(meta,0,sizeof(*meta));
entity = uctx->ccunit->ast->scope.first_entity;
uentities = &entities->entities;
for (; entity; entity=entity->base.next) {
if (strcmp(*uctx->path,entity->base.pos.input_name))
continue;
if ((is_declaration(entity)) && (entity->declaration.implicit))
uentities->generated[meta->ngenerated++].entity = entity;
else {
switch (entity->kind) {
case ENTITY_ENUM:
uentities->enums[meta->nenums++].entity = entity;
break;
case ENTITY_ENUM_VALUE:
enumval = (int)get_tarval_long(entity->enum_value.tv);
uentities->enumvals[meta->nenumvals].entity = entity;
uentities->enumvals[meta->nenumvals].enumval = enumval;
meta->nenumvals++;
break;
case ENTITY_TYPEDEF:
etype = entity->declaration.type;
ptrdepth = 0;
for (; etype->kind == TYPE_POINTER; etype=etype->pointer.points_to)
ptrdepth++;
uentities->typedefs[meta->ntypedefs].entity = entity;
uentities->typedefs[meta->ntypedefs].reftype = etype;
uentities->typedefs[meta->ntypedefs].ptrdepth = ptrdepth;
meta->ntypedefs++;
break;
case ENTITY_STRUCT:
if (entity->base.symbol || entity->compound.alias)
uentities->structs[meta->nstructs++].entity = entity;
break;
case ENTITY_UNION:
if (entity->base.symbol || entity->compound.alias)
uentities->unions[meta->nunions++].entity = entity;
break;
case ENTITY_FUNCTION:
uentities->functions[meta->nfunctions++].entity = entity;
break;
default:
break;
}
}
}
*pentities = uentities;
return 0;
}
void amgc_free_unit_entities(struct amgc_unit_entities * ctx)
{
struct amgc_unit_entities_impl *ictx;
uintptr_t addr;
if (ctx) {
addr = (uintptr_t)ctx - offsetof(struct amgc_unit_entities_impl,entities);
ictx = (struct amgc_unit_entities_impl *)addr;
amgc_free_unit_entities_impl(ictx,0);
}
}