#include #include #include #include #include #include "readline.h" #include "cdecl.h" static const char *progname = "cdecl99"; static const char sopts[] = "VH"; static const struct option lopts[] = { { "version", 0, NULL, 'V' }, { "help", 0, NULL, 'H' }, { 0 } }; static void print_version(void) { puts(PACKAGE_STRING); puts("Copyright (C) 2011 Nick Bowler."); puts("License GPLv3+: GNU GPL version 3 or later ."); puts("This is free software: you are free to change and redistribute it."); puts("There is NO WARRANTY, to the extent permitted by law."); } static void print_usage(FILE *f) { fprintf(f, "Usage: %s [options]\n", progname); } static void print_help(void) { print_usage(stdout); puts("Detailed help coming soon."); } static int cmd_explain(char *cmd, char *arg) { static size_t bufsz; static char *buf; struct cdecl *decl; size_t rc; decl = cdecl_parse_decl(arg); if (!decl) goto out; retry: rc = cdecl_explain(buf, bufsz, decl); if (rc >= bufsz) { char *tmp; tmp = realloc(buf, rc + 1); if (!tmp) { fprintf(stderr, "failed to allocate memory\n"); goto out; } buf = tmp; bufsz = rc + 1; goto retry; } printf("%s\n", buf); out: cdecl_free(decl); return 1; } static int cmd_quit(char *cmd, char *arg) { return 0; } static int cmd_help(char *cmd, char *arg); static const struct command { char name[16]; int (*func)(char *cmd, char *arg); const char *blurb; } commands[] = { { "explain", cmd_explain, "Explain a C declaration." }, { "help", cmd_help, "Print this list of commands." }, { "quit", cmd_quit, "Quit the program." }, { "exit", cmd_quit, NULL } }; static const size_t ncommands = sizeof commands / sizeof commands[0]; static int cmd_help(char *cmd, char *arg) { for (size_t i = 0; i < ncommands; i++) { if (!commands[i].blurb) continue; printf("%s -- %s\n", commands[i].name, commands[i].blurb); } return 1; } static int repl(void) { char *line; int ret; print_version(); for (; (line = readline("> ")); free(line)) { char *cmd = line + strspn(line, " \t"); char *arg = cmd + strcspn(cmd, " \t"); if (cmd[0] == '\0') continue; if (arg[0] != '\0') *arg++ = '\0'; for (size_t i = 0; i < ncommands; i++) { if (strcmp(cmd, commands[i].name) != 0) continue; ret = commands[i].func(cmd, arg); if (ret <= 0) goto out; goto next; } fprintf(stderr, "Undefined command: %s\n", cmd); next: ; } ret = 0; out: free(line); return ret; } int main(int argc, char **argv) { int opt; if (argc > 0) progname = argv[0]; while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { switch (opt) { case 'V': print_version(); return EXIT_SUCCESS; case 'H': print_help(); return EXIT_SUCCESS; default: print_usage(stderr); return EXIT_FAILURE; } } if (repl() != 0) return EXIT_FAILURE; return EXIT_SUCCESS; }