10 #define PROGNAME "crossparse"
11 static const char *progname = PROGNAME;
12 static const char sopts[] = "ECVH";
13 static const struct option lopts[] = {
14 { "cdecl", 0, NULL, 'C' },
15 { "english", 0, NULL, 'E' },
16 { "version", 0, NULL, 'V' },
17 { "help", 0, NULL, 'H' },
21 static void print_usage(FILE *f)
23 fprintf(f, "Usage: %s [options]\n", progname);
26 static void print_help(void)
29 puts("Detailed help coming soon.");
37 typedef struct cdecl *parse_func(const char *);
38 typedef size_t render_func(char *, size_t, struct cdecl *);
40 char *rerender(const char *str, const char *parse_name, parse_func *parse,
41 const char *render_name, render_func *render)
43 struct cdecl *decl = NULL;
49 fprintf(stderr, "%s: %s: failed to parse input: %s\n",
50 progname, parse_name, cdecl_get_error()->str);
54 len = render(NULL, 0, decl);
55 buf = malloc_nofail(len+1);
56 if (render(buf, len+1, decl) != len) {
57 fprintf(stderr, "%s: %s: inconsistent length returned\n",
58 progname, render_name);
68 fprintf(stderr, "%s: the failed input was: %s\n", progname, str);
71 #define rerender(str, p, r) (rerender(str, #p, p, #r, r))
73 static bool test_crossparse(const char *str, int mode)
75 char *buf1 = NULL, *buf2 = NULL, *buf3 = NULL;
78 if (mode == MODE_ENGLISH) {
79 buf1 = rerender(str, cdecl_parse_english, cdecl_declare);
82 buf2 = rerender(buf1, cdecl_parse_decl, cdecl_explain);
85 buf3 = rerender(buf2, cdecl_parse_english, cdecl_declare);
89 buf1 = rerender(str, cdecl_parse_decl, cdecl_explain);
92 buf2 = rerender(buf1, cdecl_parse_english, cdecl_declare);
95 buf3 = rerender(buf2, cdecl_parse_decl, cdecl_explain);
100 if (!strcmp(buf1, buf3))
109 int main(int argc, char **argv)
111 int opt, mode = MODE_CDECL;
112 int ret = EXIT_FAILURE;
117 while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
126 test_print_version(PROGNAME);
142 for (int i = optind; i < argc; i++) {
143 if (!test_crossparse(argv[i], mode)) {
144 fprintf(stderr, "%s: failed cross-parse check of: %s\n",