diff options
Diffstat (limited to 'src/logic')
-rw-r--r-- | src/logic/amgc_enum_members.c | 105 |
1 files changed, 105 insertions, 0 deletions
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 <cparser/ast/ast_t.h> +#include <cparser/ast/entity_t.h> +#include <cparser/ast/symbol_t.h> + +#include <apimagic/apimagic.h> + +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); +} |