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 +#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 + +#include +#include +#include + +#include +#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); +}