From b50e1f74202e18ea10f1f2cd46e9e02a9d4f0e65 Mon Sep 17 00:00:00 2001 From: Thomas Albers Date: Sun, 6 Aug 2023 10:01:18 +0200 Subject: Rewrite for new serial protocol --- repl.c | 263 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 repl.c (limited to 'repl.c') 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 + +#include +#include +#include +#include +#include + +#ifdef USE_READLINE +#include +#include +#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
[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 + } +} -- cgit v1.2.3