#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
+#include <errno.h>
#include <getopt.h>
#include "readline.h"
#include "cdecl.h"
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];
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;
}