diff options
Diffstat (limited to 'repl.c')
-rw-r--r-- | repl.c | 356 |
1 files changed, 0 insertions, 356 deletions
@@ -1,356 +0,0 @@ -#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 -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_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); -} -*/ - -enum args_type { - A_END, - A_BYTE, - A_DBYTE, - A_QBYTE, - A_OBYTE, - A_STRING, - A_OPTIONAL = 16 -}; - -struct command; - -typedef int (*fptr)(int, const struct command *, struct param *, int, char **); - -struct command { - char alias; - const char *name; - int *args_spec; - const char *usage; - fptr fptr; - int quit; -}; - -static int -parse_args(const struct command *cmd, int argc, char **args, ...) -{ - int i = 0; - int opt = 0; - int err = 0; - va_list ap; - va_start(ap, args); - - void *ptr = NULL; - int *p = cmd->args_spec; - - for ( ; *p != A_END; ++p) { - // Avoid runaway p - assert(i < MAX_ARGS); - - if (*p == A_OPTIONAL) { - opt = 1; - continue; - } - - if (i == argc && !opt) - goto syntax_error; - - ptr = va_arg(ap, void *); - errno = 0; - char *end = NULL; - - switch (*p) { - case A_BYTE: - *((uint8_t *)ptr) = strtoul(args[i], &end, 16); - break; - - case A_DBYTE: - *((uint16_t *)ptr) = strtoul(args[i], &end, 16); - break; - - case A_STRING: - *((const char **)ptr) = args[i]; - break; - } - - if (errno || args[i] == end) { - fprintf(stderr, "Invalid argument: %s\n", args[i]); - goto syntax_error; - } - - ++i; - } - - va_end(ap); - return i; - -syntax_error: - va_end(ap); - fputs(cmd->usage, stderr); - return -1; -} - -#define ARGS(...) (int []){__VA_ARGS__} - -static int -repl_io_read(int fd, const struct param *param, int argc, char **args) -{ - uint8_t bank; - uint16_t address; - const char *filename = NULL; - - struct command cmd = { - .alias = 'i', - .name = "io_read", - .usage = "", - .fptr = NULL, - .quit = 0, - .args_spec = ARGS(A_BYTE, A_DBYTE, A_OPTIONAL, A_STRING, A_END), - .usage = "Usage: read <bank> <address> <length> [pathname]\n" - }; - - parse_args(&cmd, argc, args, &bank, &address, &filename); - printf("result: %hhx %hx %s\n", bank, address, filename); - return 0; -} - -// 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 - } -} |