diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2021-08-21 18:39:08 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2021-08-21 18:39:08 +0000 |
commit | 916e63bc6665792fa593d648dcd6150f2d711adb (patch) | |
tree | 83e1f1cc1dd774c83d159b250dd6b5872ee6fb0d /usr.bin/tmux/arguments.c | |
parent | 1e7efad59e5014eb61567f9e6a9564e48c20f77c (diff) |
Pass typed arguments out of the parser into the arguments list and let
it convert them into strings.
Diffstat (limited to 'usr.bin/tmux/arguments.c')
-rw-r--r-- | usr.bin/tmux/arguments.c | 129 |
1 files changed, 105 insertions, 24 deletions
diff --git a/usr.bin/tmux/arguments.c b/usr.bin/tmux/arguments.c index eee3ba749f4..7f7d37a815e 100644 --- a/usr.bin/tmux/arguments.c +++ b/usr.bin/tmux/arguments.c @@ -1,4 +1,4 @@ -/* $OpenBSD: arguments.c,v 1.41 2021/08/21 10:28:05 nicm Exp $ */ +/* $OpenBSD: arguments.c,v 1.42 2021/08/21 18:39:07 nicm Exp $ */ /* * Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -18,9 +18,9 @@ #include <sys/types.h> +#include <ctype.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> #include <vis.h> #include "tmux.h" @@ -66,6 +66,20 @@ args_find(struct args *args, u_char flag) return (RB_FIND(args_tree, &args->tree, &entry)); } +/* Get value as string. */ +static char * +args_value_as_string(struct args_value *value) +{ + switch (value->type) { + case ARGS_NONE: + return (xstrdup("")); + case ARGS_COMMANDS: + return (cmd_list_print(value->cmdlist, 0)); + case ARGS_STRING: + return (xstrdup(value->string)); + } +} + /* Create an empty arguments set. */ struct args * args_create(void) @@ -77,42 +91,109 @@ args_create(void) return (args); } -/* Parse an argv and argc into a new argument set. */ +/* Parse arguments into a new argument set. */ struct args * -args_parse(const struct args_parse *parse, int argc, char **argv) +args_parse(const struct args_parse *parse, struct args_value *values, + u_int count) { - struct args *args; - int opt; + struct args *args; + u_int i; + struct args_value *value; + u_char flag, argument; + const char *found, *string; + char *s; - optreset = 1; - optind = 1; - optarg = NULL; + if (count == 0) + return (args_create()); args = args_create(); - while ((opt = getopt(argc, argv, parse->template)) != -1) { - if (opt < 0) - continue; - if (opt == '?' || strchr(parse->template, opt) == NULL) { - args_free(args); - return (NULL); + for (i = 1; i < count; /* nothing */) { + value = &values[i]; + + s = args_value_as_string(value); + log_debug("%s: %u = %s", __func__, i, s); + free(s); + + if (value->type != ARGS_STRING) + break; + + string = value->string; + if (*string++ != '-' || *string == '\0') + break; + i++; + if (string[0] == '-' && string[1] == '\0') + break; + + for (;;) { + flag = *string++; + if (flag == '\0') + break; + if (!isalnum(flag)) { + args_free(args); + return (NULL); + } + found = strchr(parse->template, flag); + if (found == NULL) { + args_free(args); + return (NULL); + } + argument = *++found; + if (argument != ':') { + log_debug("%s: add -%c", __func__, flag); + args_set(args, flag, NULL); + continue; + } + if (*string != '\0') + s = xstrdup(string); + else { + if (i == count) { + args_free(args); + return (NULL); + } + s = args_value_as_string(&values[i++]); + } + log_debug("%s: add -%c = %s", __func__, flag, s); + args_set(args, flag, s); + free(s); + break; + } + } + log_debug("%s: flags end at %u of %u", __func__, i, count); + if (i != count) { + for (/* nothing */; i < count; i++) { + value = &values[i]; + + s = args_value_as_string(value); + log_debug("%s: %u = %s", __func__, i, s); + cmd_append_argv(&args->argc, &args->argv, s); + free(s); } - args_set(args, opt, optarg); - optarg = NULL; } - argc -= optind; - argv += optind; - - args->argc = argc; - args->argv = cmd_copy_argv(argc, argv); - if ((parse->lower != -1 && argc < parse->lower) || - (parse->upper != -1 && argc > parse->upper)) { + if ((parse->lower != -1 && args->argc < parse->lower) || + (parse->upper != -1 && args->argc > parse->upper)) { args_free(args); return (NULL); } return (args); } +/* Free a value. */ +void +args_free_value(struct args_value *value) +{ + switch (value->type) { + case ARGS_NONE: + break; + case ARGS_STRING: + free(value->string); + break; + case ARGS_COMMANDS: + cmd_list_free(value->cmdlist); + break; + } +} + /* Free an arguments set. */ void args_free(struct args *args) |