/**********************************************************/
/* 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;
}
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;
}
void amgc_free_enum_members(struct amgc_entity * members)
{
/* first element is a guard */
if (members)
free(--members);
}