]> git.draconx.ca Git - cdecl99.git/blobdiff - src/commands.c
cdecl99: Combine all the main command implementations.
[cdecl99.git] / src / commands.c
index faaf60785d1f69beb64005619292b0559121c38e..429ba852efff70b67470722e2cd8b012a68c9fde 100644 (file)
 #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
  *
  * 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;
 }