From: Nick Bowler Date: Sun, 10 Jul 2011 16:25:37 +0000 (-0400) Subject: Split up interactive/noninteractive loops. X-Git-Tag: v1~137 X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/commitdiff_plain/2477f65ab0567a1b2c1c7e33cd7b66f19fd8ea2d Split up interactive/noninteractive loops. Readline isn't well suited for non-interactive loops since it tends to print stuff to standard output. So use two loops: a readline-based one and a getline-based one. --- diff --git a/src/cdecl99.c b/src/cdecl99.c index 44bcd3e..667ae03 100644 --- a/src/cdecl99.c +++ b/src/cdecl99.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "readline.h" #include "cdecl.h" @@ -180,47 +181,74 @@ static int cmd_help(char *cmd, char *arg) return 1; } -static int repl(bool interactive) +static int run_command(char *line) { - char *prompt = interactive ? "> " : NULL; - int rc, ret = 0; - char *line; + char *cmd = line + strspn(line, " \t"); + char *arg = cmd + strcspn(cmd, " \t"); - for (; (line = readline(prompt)); free(line)) { - char *cmd = line + strspn(line, " \t"); - char *arg = cmd + strcspn(cmd, " \t"); + if (cmd[0] == '\0') + return 1; + if (arg[0] != '\0') + *arg++ = '\0'; - if (cmd[0] == '\0') + for (size_t i = 0; i < ncommands; i++) { + if (strcmp(cmd, commands[i].name) != 0) continue; - if (arg[0] != '\0') - *arg++ = '\0'; - - for (size_t i = 0; i < ncommands; i++) { - if (strcmp(cmd, commands[i].name) != 0) - continue; - - rc = commands[i].func(cmd, arg); - if (!interactive && rc < 0) - ret = -1; - if (rc == 0) - goto out; - goto next; - } - fprintf(stderr, "Undefined command: %s\n", cmd); - ret = -1; - next: - ; + return commands[i].func(cmd, arg); } -out: + + fprintf(stderr, "Undefined command: %s\n", cmd); + return -1; +} + +static int repl(void) +{ + char *line; + + for (; (line = readline("> ")); free(line)) { + if (!run_command(line)) + break; + } + free(line); + return 0; +} + +static int repl_noninteractive(void) +{ + int rc, ret = 0, saved_errno; + char *line = NULL; + size_t n; + + while (getline(&line, &n, stdin) >= 0) { + char *c = strchr(line, '\n'); + if (c) + *c = '\0'; + + rc = run_command(line); + if (rc < 0) + ret = -1; + else if (rc == 0) + break; + } + + saved_errno = errno; + free(line); + + if (ferror(stdin)) { + errno = saved_errno; + perror("read error"); + return -1; + } + return ret; } int main(int argc, char **argv) { bool show_intro = true, interactive = true; - int opt; + int opt, rc; if (argc > 0) progname = argv[0]; @@ -251,8 +279,12 @@ int main(int argc, char **argv) if (interactive && show_intro) print_version(); - if (repl(interactive) != 0) - return EXIT_FAILURE; + if (interactive) + rc = repl(); + else + rc = repl_noninteractive(); + if (rc != 0) + return EXIT_FAILURE; return EXIT_SUCCESS; }