diff options
Diffstat (limited to 'src/output')
-rw-r--r-- | src/output/amgc_output_enum.c | 126 |
1 files changed, 126 insertions, 0 deletions
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); +} |