diff options
Diffstat (limited to 'src/logic/amgc_unit_entities.c')
-rw-r--r-- | src/logic/amgc_unit_entities.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/logic/amgc_unit_entities.c b/src/logic/amgc_unit_entities.c new file mode 100644 index 0000000..b528a19 --- /dev/null +++ b/src/logic/amgc_unit_entities.c @@ -0,0 +1,161 @@ +/**********************************************************/ +/* 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 <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; + struct amgc_unit_entities_impl *entities; + size_t ndefs; + size_t nelements; + + 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: + uentities->enumvals[meta->nenumvals++].entity = entity; + break; + + case ENTITY_TYPEDEF: + uentities->typedefs[meta->ntypedefs++].entity = entity; + 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); + } +} |