X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/d5c6a2e654422894c528cda52e951739a6b66ae6..49dcbd9216f3513ec11731a41d4b73acaacb5949:/src/commands.c diff --git a/src/commands.c b/src/commands.c index faaf607..429ba85 100644 --- a/src/commands.c +++ b/src/commands.c @@ -23,6 +23,21 @@ #include "cdecl99.h" #include "cdecl.h" +static struct cdecl *do_parse(const char *s, int input_mode) +{ + struct cdecl *parse; + + if (input_mode == INPUT_C) + parse = cdecl_parse_decl(s); + else + parse = cdecl_parse_english(s); + + if (!parse) + print_error("%s", cdecl_get_error()->str); + + return parse; +} + /* * Format a declaration according to the given function and return a pointer * to the formatted string. The returned pointer remains valid until the @@ -30,16 +45,18 @@ * * Returns NULL on failure. */ -static const char * -do_format(size_t func(char *, size_t, struct cdecl *), struct cdecl *decl) +static const char *do_render(struct cdecl *decl, int output_mode) { static size_t bufsz; static char *buf; - size_t rc; retry: - rc = func(buf, bufsz, decl); + if (output_mode == OUTPUT_C) + rc = cdecl_declare(buf, bufsz, decl); + else + rc = cdecl_explain(buf, bufsz, decl); + if (rc >= bufsz) { char *tmp; @@ -57,93 +74,39 @@ retry: return buf; } -int run_command_explain(const char *arg) -{ - struct cdecl *decl; - const char *str; - int ret = -1; - - decl = cdecl_parse_decl(arg); - if (!decl) { - print_error("%s", cdecl_get_error()->str); - goto out; - } - - for (struct cdecl *i = decl; i; i = i->next) { - str = do_format(cdecl_explain, i); - if (!str) - goto out; - - printf("%s\n", str); - } - - ret = 0; -out: - cdecl_free(decl); - return ret; -} - -int run_command_simplify(const char *arg) +/* + * Parse the given string as either C or English (based on input_mode), + * then print the result as either C or English (based on output_mode). + */ +int run_command_cdecl(const char *s, int input_mode, int output_mode) { - struct cdecl *decl; - const char *str; + struct cdecl *i, *parse; int ret = -1; - decl = cdecl_parse_decl(arg); - if (!decl) { - print_error("%s", cdecl_get_error()->str); + if (!(parse = do_parse(s, input_mode))) goto out; - } - - for (struct cdecl *i = decl; i; i = i->next) { - struct cdecl_declspec *s = i->specifiers; - if (i != decl) { - i->specifiers = NULL; - printf(", "); - } - - str = do_format(cdecl_declare, i); - i->specifiers = s; + for (i = parse; i; i = i->next) { + const char *str; + int no_nl = 0; - if (!str) + if (!(str = do_render(i, output_mode))) goto out; - printf("%s", str); - } - - putchar('\n'); - - ret = 0; -out: - cdecl_free(decl); - return ret; -} - -int run_command_declare(const char *cmd) -{ - struct cdecl *decl; - const char *str; - int ret = -1; + /* + * In C output, only the first declarator needs specifiers + * printed, and only the last declarator needs a newline. + */ + if (output_mode == OUTPUT_C && i->next) { + i->next->specifiers = NULL; + no_nl = 1; + } - /* The name of the command is significant here. */ - decl = cdecl_parse_english(cmd); - if (!decl) { - print_error("%s", cdecl_get_error()->str); - goto out; + printf(", %s%s" + 2*!!i->specifiers, str, "\n" + no_nl); } - /* - * English parses have at most one full declarator, so no loop is - * needed here. - */ - str = do_format(cdecl_declare, decl); - if (!str) - goto out; - - printf("%s\n", str); ret = 0; out: - cdecl_free(decl); + cdecl_free(parse); return ret; }