summaryrefslogtreecommitdiff
path: root/repl.c
diff options
context:
space:
mode:
Diffstat (limited to 'repl.c')
-rw-r--r--repl.c263
1 files changed, 263 insertions, 0 deletions
diff --git a/repl.c b/repl.c
new file mode 100644
index 0000000..32f2bee
--- /dev/null
+++ b/repl.c
@@ -0,0 +1,263 @@
+#include <zup.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+
+#ifdef USE_READLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif // USE_READLINE
+
+typedef int (*repl_command)(int, const struct param*, int, char**);
+
+static int
+repl_read(int fd, const struct param *param, int argc, char **args)
+{
+ int err = 0;
+ uint8_t buf[MAX_PACKET_SIZE];
+
+ uint8_t bank;
+ uint16_t address;
+ uint16_t length;
+ const char *pathname = NULL;
+
+ if (argc != 3 && argc != 4)
+ goto syntax_error;
+
+ errno = 0;
+ bank = strtoul(args[0], NULL, 16);
+ err |= errno;
+
+ errno = 0;
+ address = strtoul(args[1], NULL, 16);
+ err |= errno;
+
+ errno = 0;
+ length = strtoul(args[2], NULL, 16);
+ err |= errno;
+
+ if (argc == 4)
+ pathname = args[3];
+
+ if (err)
+ goto syntax_error;
+
+ if ((err = z_read(fd, bank, address, length, buf))) {
+ print_error(err);
+ return err;
+ }
+
+ hexdump(address, length, buf);
+
+ if (pathname) {
+ FILE *file;
+ if (!(file = fopen(pathname, "w"))) {
+ perror("File could not be opened");
+ return -1;
+ }
+ fwrite(buf, sizeof(uint8_t), length, file);
+ fclose(file);
+ }
+
+ return err;
+
+syntax_error:
+ fputs("Usage: read <bank> <address> <length> [pathname]\n", stderr);
+ return 1;
+}
+
+/*
+static int
+parse_args(const char *fname, const char *types, int argc, char **args, ...)
+{
+}
+*/
+
+static int
+repl_write(int fd, const struct param *param, int argc, char **args)
+{
+ int err;
+ char line[512];
+ uint8_t buf[MAX_PACKET_SIZE];
+
+ char *p;
+
+ uint8_t bank;
+ uint16_t address;
+ uint16_t length = 0;
+
+ do {
+ // TODO: Handle fgets error
+ fgets(line, LEN(line), stdin);
+ if (line && !strcmp("\n", line))
+ break;
+
+ p = strtok(line, " \n");
+ while (p && length < 10) {
+ errno = 0;
+ buf[length++] = strtoul(p, NULL, 16);
+ p = strtok(NULL, " \n");
+ }
+
+ if (p) {
+ fputs("WRITE: Input can't be longer than 256 bytes\n", stderr);
+ return -1;
+ }
+ } while (1);
+
+ if ((err = z_write(fd, bank, address, length, buf))) {
+ print_error(err);
+ return err;
+ }
+
+ return 0;
+}
+
+static int
+repl_echo(int fd, const struct param *param, int argc, char **args)
+{
+ int err;
+ char line[512];
+ char buf[MAX_PACKET_SIZE];
+
+ memset(line, 0, sizeof(line));
+ memset(buf, 0, sizeof(buf));
+
+ size_t length = 0;
+
+ do {
+ // TODO: Handle fgets error
+ fgets(line, LEN(line), stdin);
+ if (line && !strcmp("\n", line))
+ break;
+
+ size_t len = strlen(line);
+ if (line[len - 1] == '\n')
+ line[--len] = '\0';
+
+ if (length + len >= MAX_PACKET_SIZE) {
+ fputs("ECHO: Input can't be longer than 256 bytes\n", stderr);
+ return -1;
+ }
+
+ strcat(buf, line);
+ length += len;
+ } while (1);
+
+ if ((err = z_echo(fd, length, (uint8_t *)buf))) {
+ print_error(err);
+ return err;
+ }
+
+ fwrite(buf, sizeof(uint8_t), length, stdout);
+ putchar('\n');
+ fflush(stdout);
+
+ return 0;
+}
+
+static int
+repl_io_read(int fd, const struct param *param, int argc, char **args)
+{
+ return 0;
+}
+
+static int
+repl_io_write(int fd, const struct param *param, int argc, char **args)
+{
+ return 0;
+}
+
+/*
+static volatile sig_atomic_t quit = 0;
+
+void
+interrupt_handler(int signal)
+{
+ puts("Bye!");
+ quit = 1;
+ // fclose(stdin);
+}
+*/
+
+// TODO: Handle signals (CTRL-C)
+// TODO: Print errors when in repl and crash if from terminal
+void
+repl(int fd, struct param *param)
+{
+ struct command {
+ const char *name;
+ repl_command fptr;
+ int quit;
+ };
+
+ const struct command cmd_table[] = {
+ {"read", repl_read, 0},
+ {"write", repl_write, 0},
+ {"echo", repl_echo, 0},
+ {"io_read", repl_io_read, 0},
+ {"io_write", repl_io_write, 0},
+ {"quit", NULL, 1}
+ };
+
+ int quit = 0;
+
+#ifdef USE_READLINE
+ using_history();
+#endif
+
+ while (!quit) {
+#ifdef USE_READLINE
+ char *line = readline("* ");
+
+ if (!line)
+ break;
+
+ add_history(line);
+#else
+ size_t len = 0;
+ char line[512];
+ fputs("* ", stdout);
+
+ if (!fgets(line, sizeof(line), stdin))
+ break;
+
+ len = strlen(line);
+ if (line[len - 1] == '\n')
+ line[len - 1] = '\0';
+#endif
+ int argc = 1;
+ char *args[MAX_ARGS] = { NULL };
+
+ // Parse command
+ args[0] = strtok(line, " ");
+ if (!args[0])
+ goto skip;
+ while(argc < MAX_ARGS && (args[argc] = strtok(NULL, " ")))
+ ++argc;
+
+ // Match action
+ int cmdi;
+ for (cmdi = 0; cmdi < LEN(cmd_table); ++cmdi) {
+ if (!strcmp(args[0], cmd_table[cmdi].name))
+ break;
+ }
+
+ // Call action
+ if (cmdi == LEN(cmd_table)) {
+ fprintf(stdout, "Unknown command %s\n", args[0]);
+ } else {
+ repl_command fptr = cmd_table[cmdi].fptr;
+ if (fptr)
+ fptr(fd, param, argc - 1, &args[1]);
+ quit = cmd_table[cmdi].quit;
+ }
+ skip:
+#ifdef USE_READLINE
+ free(line);
+#endif
+ }
+}