Blame src/logic/amgc_enum_members.c

c4a105
/**********************************************************/
c4a105
/*  apimagic: cparser-based API normalization utility     */
c4a105
/*  Copyright (C) 2015--2016  Z. Gilboa                   */
c4a105
/*  Released under GPLv2 and GPLv3; see COPYING.APIMAGIC. */
c4a105
/**********************************************************/
c4a105
c4a105
#include <cparser/ast/ast_t.h>
c4a105
#include <cparser/ast/entity_t.h>
c4a105
#include <cparser/ast/symbol_t.h>
c4a105
c4a105
#include <apimagic/apimagic.h>
c4a105
c4a105
static const struct amgc_entity * enumval_vector_entity(
c4a105
	const struct amgc_unit_ctx *	uctx,
c4a105
	const union entity_t *		entity)
c4a105
{
c4a105
	const struct amgc_entity * aentity;
c4a105
c4a105
	aentity = uctx->entities->enumvals;
c4a105
c4a105
	for (; aentity->entity; aentity++)
c4a105
		if (aentity->entity == entity)
c4a105
			return aentity;
c4a105
c4a105
	return 0;
c4a105
}
c4a105
c4a105
static int enumval_cmp(const void * ptra, const void * ptrb)
c4a105
{
c4a105
	struct amgc_entity * entitya = (struct amgc_entity *)ptra;
c4a105
	struct amgc_entity * entityb = (struct amgc_entity *)ptrb;
c4a105
c4a105
	if (entitya->enumval == entityb->enumval)
c4a105
		return (strcmp(
c4a105
				entitya->altname
c4a105
					? entitya->altname
c4a105
					: entitya->entity->base.symbol->string,
c4a105
				entityb->altname
c4a105
					? entityb->altname
c4a105
					: entityb->entity->base.symbol->string));
c4a105
	else if ((entitya->enumval <= -128) && (entityb->enumval >= 0))
c4a105
		return 1;
c4a105
	else if ((entityb->enumval <= -128) && (entitya->enumval >= 0))
c4a105
		return -1;
c4a105
	else if ((entitya->enumval < entityb->enumval) && (entitya->enumval > -128) && (entityb->enumval > -128))
c4a105
		return -1;
c4a105
	else
c4a105
		return 1;
c4a105
}
c4a105
c4a105
amgc_api int amgc_get_enum_members(
c4a105
	const struct amgc_unit_ctx *	uctx,
c4a105
	const union entity_t *		penum,
c4a105
	struct amgc_entity **		pmembers)
c4a105
{
c4a105
	int				nmembers;
c4a105
	struct amgc_entity *		buffer;
c4a105
	struct amgc_entity *		pentity;
c4a105
	const struct amgc_entity *	aentity;
c4a105
	const union entity_t *		entity;
c4a105
c4a105
	if (penum->base.kind != ENTITY_ENUM)
c4a105
		return -1;
c4a105
c4a105
	entity	= penum->enume.first_value;
c4a105
	nmembers= 0;
c4a105
c4a105
	for (; entity && (entity->base.kind == ENTITY_ENUM_VALUE); ) {
c4a105
		if (!(aentity = enumval_vector_entity(uctx,entity)))
c4a105
			return -1;
c4a105
c4a105
		if (!aentity->fexclude)
c4a105
			nmembers++;
c4a105
c4a105
		entity = entity->base.next;
c4a105
	}
c4a105
c4a105
	/* use first element as a guard */
c4a105
	if (!(buffer = calloc(1+nmembers+1,sizeof(*buffer))))
c4a105
		return -1;
c4a105
c4a105
	pentity = &buffer[1];
c4a105
	entity	= penum->enume.first_value;
c4a105
c4a105
	for (; entity && (entity->base.kind == ENTITY_ENUM_VALUE); ) {
c4a105
		aentity = enumval_vector_entity(uctx,entity);
c4a105
c4a105
		if (!aentity->fexclude)
c4a105
			memcpy(pentity++,aentity,sizeof(*pentity));
c4a105
c4a105
		entity = entity->base.next;
c4a105
	}
c4a105
c4a105
	*pmembers = &buffer[1];
c4a105
	qsort(*pmembers,nmembers,sizeof(struct amgc_entity),enumval_cmp);
c4a105
c4a105
	return 0;
c4a105
}
c4a105
c4a105
amgc_api void amgc_free_enum_members(struct amgc_entity * members)
c4a105
{
c4a105
	/* first element is a guard */
c4a105
	if (members)
c4a105
		free(--members);
c4a105
}