From d0e2b015f25d53498da258d3ee988a101bc597fa Mon Sep 17 00:00:00 2001 From: Thomas Albers Date: Sun, 6 Aug 2023 12:15:56 +0200 Subject: Add parse_args --- repl.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 106 insertions(+), 13 deletions(-) (limited to 'repl.c') diff --git a/repl.c b/repl.c index 32f2bee..edac70f 100644 --- a/repl.c +++ b/repl.c @@ -69,13 +69,6 @@ syntax_error: 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) { @@ -159,12 +152,6 @@ repl_echo(int fd, const struct param *param, int argc, char **args) 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) { @@ -183,6 +170,112 @@ interrupt_handler(int signal) } */ +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
[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 -- cgit v1.2.3