summaryrefslogtreecommitdiff
path: root/src/logic
diff options
context:
space:
mode:
Diffstat (limited to 'src/logic')
-rw-r--r--src/logic/amgc_enum_members.c105
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);
+}