summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/apimagic/apimagic.h2
-rw-r--r--project/common.mk1
-rw-r--r--src/internal/apimagic_driver_impl.h4
-rw-r--r--src/output/amgc_output_enum.c126
4 files changed, 133 insertions, 0 deletions
diff --git a/include/apimagic/apimagic.h b/include/apimagic/apimagic.h
index ac78b57..f1bec42 100644
--- a/include/apimagic/apimagic.h
+++ b/include/apimagic/apimagic.h
@@ -139,6 +139,8 @@ amgc_api int amgc_lang_std_from_string (const char * std);
/* utility api */
amgc_api int amgc_output_pad_symbol (const char *, const struct amgc_layout *, FILE *);
+amgc_api int amgc_output_unit_enum (const struct amgc_unit_ctx *, const union entity_t *, const struct amgc_layout *, FILE *);
+amgc_api int amgc_output_custom_enum (const struct amgc_entity *, const struct amgc_entity[], const struct amgc_layout *, FILE *);
/* low-level api */
amgc_api int amgc_init_unit_meta (const struct amgc_unit_ctx *, struct amgc_unit_meta *);
diff --git a/project/common.mk b/project/common.mk
index 318de8b..1f75489 100644
--- a/project/common.mk
+++ b/project/common.mk
@@ -6,6 +6,7 @@ COMMON_SRCS = \
src/logic/amgc_init_unit_meta.c \
src/logic/amgc_map_input.c \
src/logic/amgc_unit_entities.c \
+ src/output/amgc_output_enum.c \
src/output/amgc_output_pad_symbol.c \
src/skin/amgc_skin_default.c \
diff --git a/src/internal/apimagic_driver_impl.h b/src/internal/apimagic_driver_impl.h
index 659597d..be747aa 100644
--- a/src/internal/apimagic_driver_impl.h
+++ b/src/internal/apimagic_driver_impl.h
@@ -7,6 +7,10 @@
#include <apimagic/apimagic.h>
+#ifndef AMGC_TAB_WIDTH
+#define AMGC_TAB_WIDTH 8
+#endif
+
enum app_tags {
TAG_HELP,
TAG_VERSION,
diff --git a/src/output/amgc_output_enum.c b/src/output/amgc_output_enum.c
new file mode 100644
index 0000000..0a15728
--- /dev/null
+++ b/src/output/amgc_output_enum.c
@@ -0,0 +1,126 @@
+/**********************************************************/
+/* apimagic: cparser-based API normalization utility */
+/* Copyright (C) 2015--2016 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.APIMAGIC. */
+/**********************************************************/
+
+#include <stdio.h>
+
+#include <cparser/ast/ast_t.h>
+#include <cparser/ast/entity_t.h>
+#include <cparser/ast/symbol_t.h>
+
+#include <apimagic/apimagic.h>
+#include "apimagic_driver_impl.h"
+
+static int output_enum(
+ const char * symbol,
+ const struct amgc_entity enumvals[],
+ const struct amgc_layout * layout,
+ FILE * fout)
+{
+ const struct amgc_entity * enumval;
+ struct amgc_layout elayout;
+ size_t len;
+
+ if (!layout || !layout->symwidth) {
+ if (!layout)
+ memset(&elayout,0,sizeof(elayout));
+ else
+ memcpy(&elayout,layout,sizeof(elayout));
+
+ if (!elayout.tabwidth)
+ elayout.tabwidth = AMGC_TAB_WIDTH;
+
+ layout = &elayout;
+ enumval = enumvals;
+
+ for (; enumval->entity || enumval->altname; enumval++) {
+ len = strlen(enumval->altname
+ ? enumval->altname
+ : enumval->entity->base.symbol->string);
+
+ if (len > elayout.symwidth)
+ elayout.symwidth = len;
+ }
+ }
+
+ if (layout->header && (fputs(layout->header,fout) < 0))
+ return -1;
+
+ if (fprintf(fout,"enum %s {\n",symbol) < 0)
+ return -1;
+
+ for (enumval=enumvals; enumval->entity || enumval->altname; enumval++) {
+ symbol = enumval->altname
+ ? enumval->altname
+ : enumval->entity->base.symbol->string;
+
+ if (fprintf(fout,"\t%s",symbol) < 0)
+ return -1;
+
+ if (amgc_output_pad_symbol(symbol,layout,fout) < 0)
+ return -1;
+
+ if ((enumval->enumval < 0) && (enumval->enumval > -128))
+ fprintf(fout,"= (%d)",enumval->enumval);
+ else if ((enumval->enumval >= 0) && (enumval->enumval < 2048))
+ fprintf(fout,"= %d",enumval->enumval);
+ else
+ fprintf(fout,"= 0x%08x",enumval->enumval);
+
+ if (fputs(",\n",fout) < 0)
+ return -1;
+ }
+
+ if (fputs("};\n",fout) < 0)
+ return -1;
+
+ if (layout->footer && (fputs(layout->footer,fout) < 0))
+ return -1;
+
+ return 0;
+}
+
+int amgc_output_unit_enum(
+ const struct amgc_unit_ctx * uctx,
+ const union entity_t * entity,
+ const struct amgc_layout * layout,
+ FILE * fout)
+{
+ struct amgc_entity * enumvals;
+ int ret;
+
+ if (entity->base.kind != ENTITY_ENUM)
+ return -1;
+ else if (amgc_get_enum_members(uctx,entity,&enumvals))
+ return -1;
+
+ ret = output_enum(entity->base.symbol->string,enumvals,layout,fout);
+ amgc_free_enum_members(enumvals);
+
+ return ret;
+}
+
+int amgc_output_custom_enum(
+ const struct amgc_entity * penum,
+ const struct amgc_entity enumvals[],
+ const struct amgc_layout * layout,
+ FILE * fout)
+{
+ const struct amgc_entity * aentity;
+
+ if (penum->entity && penum->entity->base.kind != ENTITY_ENUM)
+ return -1;
+ else if (!penum->entity && !penum->altname)
+ return -1;
+
+ for (aentity=enumvals; aentity->entity || aentity->altname; aentity++)
+ if (aentity->entity && aentity->entity->base.kind != ENTITY_ENUM_VALUE)
+ return -1;
+
+ return output_enum(penum->entity
+ ? penum->entity->base.symbol->string
+ : penum->altname,
+ enumvals,layout,fout);
+}