-/* $OpenBSD: arguments.c,v 1.56 2022/08/02 09:23:34 nicm Exp $ */
+/* $OpenBSD: arguments.c,v 1.57 2022/12/16 08:13:40 nicm Exp $ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
u_char flag;
struct args_values values;
u_int count;
+
+ int flags;
+#define ARGS_ENTRY_OPTIONAL_VALUE 0x1
+
RB_ENTRY(args_entry) entry;
};
return (args);
}
+/* Parse a single flag. */
+static int
+args_parse_flag_argument(struct args_value *values, u_int count, char **cause,
+ struct args *args, u_int *i, const char *string, int flag,
+ int optional_argument)
+{
+ struct args_value *argument, *new;
+ const char *s;
+
+ new = xcalloc(1, sizeof *new);
+ if (*string != '\0') {
+ new->type = ARGS_STRING;
+ new->string = xstrdup(string);
+ goto out;
+ }
+
+ if (*i == count)
+ argument = NULL;
+ else {
+ argument = &values[*i];
+ if (argument->type != ARGS_STRING) {
+ xasprintf(cause, "-%c argument must be a string", flag);
+ return (-1);
+ }
+ if (argument->string[0] == '-')
+ argument = NULL;
+ }
+ if (argument == NULL) {
+ if (optional_argument) {
+ log_debug("%s: -%c (optional)", __func__, flag);
+ args_set(args, flag, NULL, ARGS_ENTRY_OPTIONAL_VALUE);
+ return (0); /* either - or end */
+ }
+ xasprintf(cause, "-%c expects an argument", flag);
+ return (-1);
+ }
+ args_copy_value(new, argument);
+ (*i)++;
+
+out:
+ s = args_value_as_string(new);
+ log_debug("%s: -%c = %s", __func__, flag, s);
+ args_set(args, flag, new, 0);
+ return (0);
+}
+
+/* Parse flags argument. */
+static int
+args_parse_flags(const struct args_parse *parse, struct args_value *values,
+ u_int count, char **cause, struct args *args, int *i)
+{
+ struct args_value *value;
+ u_char flag;
+ const char *found, *string;
+ int optional_argument;
+
+ value = &values[*i];
+ if (value->type != ARGS_STRING)
+ return (1);
+
+ string = value->string;
+ log_debug("%s: next %s", __func__, string);
+ if (*string++ != '-' || *string == '\0')
+ return (1);
+ (*i)++;
+ if (string[0] == '-' && string[1] == '\0')
+ return (1);
+
+ for (;;) {
+ flag = *string++;
+ if (flag == '\0')
+ return (0);
+ if (flag == '?')
+ return (-1);
+ if (!isalnum(flag)) {
+ xasprintf(cause, "invalid flag -%c", flag);
+ return (-1);
+ }
+
+ found = strchr(parse->template, flag);
+ if (found == NULL) {
+ xasprintf(cause, "unknown flag -%c", flag);
+ return (-1);
+ }
+ if (*++found != ':') {
+ log_debug("%s: -%c", __func__, flag);
+ args_set(args, flag, NULL, 0);
+ continue;
+ }
+ optional_argument = (*found == ':');
+ return (args_parse_flag_argument(values, count, cause, args, i,
+ string, flag, optional_argument));
+ }
+}
+
/* Parse arguments into a new argument set. */
struct args *
args_parse(const struct args_parse *parse, struct args_value *values,
u_int i;
enum args_parse_type type;
struct args_value *value, *new;
- u_char flag;
- const char *found, *string, *s;
- int optional_argument;
+ const char *s;
+ int stop;
if (count == 0)
return (args_create());
args = args_create();
for (i = 1; i < count; /* nothing */) {
- value = &values[i];
- 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 (flag == '?') {
- args_free(args);
- return (NULL);
- }
- if (!isalnum(flag)) {
- xasprintf(cause, "invalid flag -%c", flag);
- args_free(args);
- return (NULL);
- }
- found = strchr(parse->template, flag);
- if (found == NULL) {
- xasprintf(cause, "unknown flag -%c", flag);
- args_free(args);
- return (NULL);
- }
- if (*++found != ':') {
- log_debug("%s: -%c", __func__, flag);
- args_set(args, flag, NULL);
- continue;
- }
- if (*found == ':') {
- optional_argument = 1;
- found++;
- }
- new = xcalloc(1, sizeof *new);
- if (*string != '\0') {
- new->type = ARGS_STRING;
- new->string = xstrdup(string);
- } else {
- if (i == count) {
- if (optional_argument) {
- log_debug("%s: -%c", __func__,
- flag);
- args_set(args, flag, NULL);
- continue;
- }
- xasprintf(cause,
- "-%c expects an argument",
- flag);
- args_free(args);
- return (NULL);
- }
- if (values[i].type != ARGS_STRING) {
- xasprintf(cause,
- "-%c argument must be a string",
- flag);
- args_free(args);
- return (NULL);
- }
- args_copy_value(new, &values[i++]);
- }
- s = args_value_as_string(new);
- log_debug("%s: -%c = %s", __func__, flag, s);
- args_set(args, flag, new);
- break;
+ stop = args_parse_flags(parse, values, count, cause, args, &i);
+ if (stop == -1) {
+ args_free(args);
+ return (NULL);
}
+ if (stop == 1)
+ break;
}
log_debug("%s: flags end at %u of %u", __func__, i, count);
if (i != count) {
RB_FOREACH(entry, args_tree, &args->tree) {
if (TAILQ_EMPTY(&entry->values)) {
for (i = 0; i < entry->count; i++)
- args_set(new_args, entry->flag, NULL);
+ args_set(new_args, entry->flag, NULL, 0);
continue;
}
TAILQ_FOREACH(value, &entry->values, entry) {
new_value = xcalloc(1, sizeof *new_value);
args_copy_copy_value(new_value, value, argc, argv);
- args_set(new_args, entry->flag, new_value);
+ args_set(new_args, entry->flag, new_value, 0);
}
}
if (args->count == 0)
char *buf;
u_int i, j;
struct args_entry *entry;
+ struct args_entry *last = NULL;
struct args_value *value;
len = 1;
/* Process the flags first. */
RB_FOREACH(entry, args_tree, &args->tree) {
+ if (entry->flags & ARGS_ENTRY_OPTIONAL_VALUE)
+ continue;
if (!TAILQ_EMPTY(&entry->values))
continue;
/* Then the flags with arguments. */
RB_FOREACH(entry, args_tree, &args->tree) {
+ if (entry->flags & ARGS_ENTRY_OPTIONAL_VALUE) {
+ if (*buf != '\0')
+ args_print_add(&buf, &len, " -%c", entry->flag);
+ else
+ args_print_add(&buf, &len, "-%c", entry->flag);
+ last = entry;
+ continue;
+ }
+ if (TAILQ_EMPTY(&entry->values))
+ continue;
TAILQ_FOREACH(value, &entry->values, entry) {
if (*buf != '\0')
args_print_add(&buf, &len, " -%c", entry->flag);
args_print_add(&buf, &len, "-%c", entry->flag);
args_print_add_value(&buf, &len, value);
}
+ last = entry;
}
+ if (last && (last->flags & ARGS_ENTRY_OPTIONAL_VALUE))
+ args_print_add(&buf, &len, " --");
/* And finally the argument vector. */
for (i = 0; i < args->count; i++)
/* Set argument value in the arguments tree. */
void
-args_set(struct args *args, u_char flag, struct args_value *value)
+args_set(struct args *args, u_char flag, struct args_value *value, int flags)
{
struct args_entry *entry;
entry = xcalloc(1, sizeof *entry);
entry->flag = flag;
entry->count = 1;
+ entry->flags = flags;
TAILQ_INIT(&entry->values);
RB_INSERT(args_tree, &args->tree, entry);
} else
-/* $OpenBSD: cmd-send-keys.c,v 1.72 2022/06/07 10:02:19 nicm Exp $ */
+/* $OpenBSD: cmd-send-keys.c,v 1.73 2022/12/16 08:13:40 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
.name = "send-keys",
.alias = "send",
- .args = { "FHlMN:Rt:X", 0, -1, NULL },
- .usage = "[-FHlMRX] [-N repeat-count] " CMD_TARGET_PANE_USAGE
- " key ...",
+ .args = { "c:FHKlMN:Rt:X", 0, -1, NULL },
+ .usage = "[-FHKlMRX] [-c target-client] [-N repeat-count] "
+ CMD_TARGET_PANE_USAGE " key ...",
.target = { 't', CMD_FIND_PANE, 0 },
- .flags = CMD_AFTERHOOK,
+ .flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG,
.exec = cmd_send_keys_exec
};
static struct cmdq_item *
cmd_send_keys_inject_key(struct cmdq_item *item, struct cmdq_item *after,
- key_code key)
+ struct args *args, key_code key)
{
struct cmd_find_state *target = cmdq_get_target(item);
struct client *tc = cmdq_get_target_client(item);
struct winlink *wl = target->wl;
struct window_pane *wp = target->wp;
struct window_mode_entry *wme;
- struct key_table *table;
+ struct key_table *table = NULL;
struct key_binding *bd;
+ struct key_event *event;
+
+ if (args_has(args, 'K')) {
+ event = xmalloc(sizeof *event);
+ event->key = key;
+ memset(&event->m, 0, sizeof event->m);
+ if (server_client_handle_key(tc, event) == 0)
+ free(event);
+ return (item);
+ }
wme = TAILQ_FIRST(&wp->modes);
if (wme == NULL || wme->mode->key_table == NULL) {
n = strtol(s, &endptr, 16);
if (*s =='\0' || n < 0 || n > 0xff || *endptr != '\0')
return (item);
- return (cmd_send_keys_inject_key(item, after, KEYC_LITERAL|n));
+ return (cmd_send_keys_inject_key(item, after, args,
+ KEYC_LITERAL|n));
}
literal = args_has(args, 'l');
if (!literal) {
key = key_string_lookup_string(s);
if (key != KEYC_NONE && key != KEYC_UNKNOWN) {
- after = cmd_send_keys_inject_key(item, after, key);
+ after = cmd_send_keys_inject_key(item, after, args,
+ key);
if (after != NULL)
return (after);
}
continue;
key = uc;
}
- after = cmd_send_keys_inject_key(item, after, key);
+ after = cmd_send_keys_inject_key(item, after, args,
+ key);
}
free(ud);
}
key = options_get_number(s->options, "prefix2");
else
key = options_get_number(s->options, "prefix");
- cmd_send_keys_inject_key(item, item, key);
+ cmd_send_keys_inject_key(item, item, args, key);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'N') || args_has(args, 'R'))
return (CMD_RETURN_NORMAL);
for (; np != 0; np--)
- cmd_send_keys_inject_key(item, NULL, event->key);
+ cmd_send_keys_inject_key(item, NULL, args, event->key);
return (CMD_RETURN_NORMAL);
}