#include <gettext.h>
#define _(x) gettext(x)
+enum { INPUT_C, INPUT_ENGLISH };
+enum { OUTPUT_C, OUTPUT_ENGLISH };
+
int run_command(const char *line, int batch);
-int run_command_simplify(const char *arg);
-int run_command_explain(const char *arg);
-int run_command_declare(const char *cmdarg);
+int run_command_cdecl(const char *s, int input_mode, int output_mode);
void print_error(const char *fmt, ...);
#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;
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;
}
}
switch (c->cmd) {
- case cmd_help: return run_cmd_help();
- case cmd_declare: case cmd_type: return run_command_declare(cmd);
- case cmd_simplify: return run_command_simplify(arg);
- case cmd_explain: return run_command_explain(arg);
- case cmd_quit: return 1;
+ case cmd_help:
+ return run_cmd_help();
+ case cmd_declare: case cmd_type:
+ return run_command_cdecl(cmd, INPUT_ENGLISH, OUTPUT_C);
+ case cmd_simplify:
+ return run_command_cdecl(arg, INPUT_C, OUTPUT_C);
+ case cmd_explain:
+ return run_command_cdecl(arg, INPUT_C, OUTPUT_ENGLISH);
+ case cmd_quit:
+ return 1;
}
assert(0);