From c4a105a804c25415eaf79588b38a5d7fc8e75d70 Mon Sep 17 00:00:00 2001 From: midipix Date: Jan 02 2016 03:50:25 +0000 Subject: amgc_get_enum_members(): initial implementation. --- diff --git a/include/apimagic/apimagic.h b/include/apimagic/apimagic.h index 81d8036..d7a61ac 100644 --- a/include/apimagic/apimagic.h +++ b/include/apimagic/apimagic.h @@ -138,6 +138,9 @@ amgc_api int amgc_init_unit_meta (const struct amgc_unit_ctx *, struct amgc_uni amgc_api int amgc_get_unit_entities (const struct amgc_unit_ctx *, struct amgc_unit_meta *, struct amgc_unit_entities **); amgc_api void amgc_free_unit_entities (struct amgc_unit_entities *); +amgc_api int amgc_get_enum_members (const struct amgc_unit_ctx *, const union entity_t *, struct amgc_entity **); +amgc_api void amgc_free_enum_members (struct amgc_entity *); + #ifdef __cplusplus } #endif diff --git a/project/common.mk b/project/common.mk index 1945a6a..d54a0f2 100644 --- a/project/common.mk +++ b/project/common.mk @@ -2,6 +2,7 @@ COMMON_SRCS = \ src/driver/amgc_driver_ctx.c \ src/driver/amgc_paradigm_meta.c \ src/driver/amgc_unit_ctx.c \ + src/logic/amgc_enum_members.c \ src/logic/amgc_init_unit_meta.c \ src/logic/amgc_map_input.c \ src/logic/amgc_unit_entities.c \ diff --git a/src/logic/amgc_enum_members.c b/src/logic/amgc_enum_members.c new file mode 100644 index 0000000..321303f --- /dev/null +++ b/src/logic/amgc_enum_members.c @@ -0,0 +1,105 @@ +/**********************************************************/ +/* apimagic: cparser-based API normalization utility */ +/* Copyright (C) 2015--2016 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.APIMAGIC. */ +/**********************************************************/ + +#include +#include +#include + +#include + +static const struct amgc_entity * enumval_vector_entity( + const struct amgc_unit_ctx * uctx, + const union entity_t * entity) +{ + const struct amgc_entity * aentity; + + aentity = uctx->entities->enumvals; + + for (; aentity->entity; aentity++) + if (aentity->entity == entity) + return aentity; + + return 0; +} + +static int enumval_cmp(const void * ptra, const void * ptrb) +{ + struct amgc_entity * entitya = (struct amgc_entity *)ptra; + struct amgc_entity * entityb = (struct amgc_entity *)ptrb; + + if (entitya->enumval == entityb->enumval) + return (strcmp( + entitya->altname + ? entitya->altname + : entitya->entity->base.symbol->string, + entityb->altname + ? entityb->altname + : entityb->entity->base.symbol->string)); + else if ((entitya->enumval <= -128) && (entityb->enumval >= 0)) + return 1; + else if ((entityb->enumval <= -128) && (entitya->enumval >= 0)) + return -1; + else if ((entitya->enumval < entityb->enumval) && (entitya->enumval > -128) && (entityb->enumval > -128)) + return -1; + else + return 1; +} + +amgc_api int amgc_get_enum_members( + const struct amgc_unit_ctx * uctx, + const union entity_t * penum, + struct amgc_entity ** pmembers) +{ + int nmembers; + struct amgc_entity * buffer; + struct amgc_entity * pentity; + const struct amgc_entity * aentity; + const union entity_t * entity; + + if (penum->base.kind != ENTITY_ENUM) + return -1; + + entity = penum->enume.first_value; + nmembers= 0; + + for (; entity && (entity->base.kind == ENTITY_ENUM_VALUE); ) { + if (!(aentity = enumval_vector_entity(uctx,entity))) + return -1; + + if (!aentity->fexclude) + nmembers++; + + entity = entity->base.next; + } + + /* use first element as a guard */ + if (!(buffer = calloc(1+nmembers+1,sizeof(*buffer)))) + return -1; + + pentity = &buffer[1]; + entity = penum->enume.first_value; + + for (; entity && (entity->base.kind == ENTITY_ENUM_VALUE); ) { + aentity = enumval_vector_entity(uctx,entity); + + if (!aentity->fexclude) + memcpy(pentity++,aentity,sizeof(*pentity)); + + entity = entity->base.next; + } + + *pmembers = &buffer[1]; + qsort(*pmembers,nmembers,sizeof(struct amgc_entity),enumval_cmp); + + return 0; +} + +amgc_api void amgc_free_enum_members(struct amgc_entity * members) +{ + /* first element is a guard */ + if (members) + free(--members); +}