summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/apimagic/apimagic.h3
-rw-r--r--project/common.mk1
-rw-r--r--src/logic/amgc_enum_members.c105
3 files changed, 109 insertions, 0 deletions
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 <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);
+}