Fix various problems.

This commit is contained in:
Nicholas Marriott
2026-07-01 07:07:24 +01:00
parent 4951eac7fa
commit db8f9b4c52
6 changed files with 60 additions and 37 deletions

View File

@@ -78,7 +78,7 @@ client_command_has_flag(int argc, char **argv, int flag)
int found; int found;
values = args_from_vector(argc, argv); values = args_from_vector(argc, argv);
tree = cmd_parse_from_arguments(values, argc); tree = cmd_parse_from_arguments(values, argc, NULL);
found = cmd_parse_any_have(tree, flag); found = cmd_parse_any_have(tree, flag);
cmd_parse_free(tree); cmd_parse_free(tree);

View File

@@ -56,11 +56,12 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
{ {
struct args *args = cmd_get_args(self); struct args *args = cmd_get_args(self);
key_code key; key_code key;
const char *tablename, *note = args_get(args, 'N'); const char *tablename, *note = args_get(args, 'N'), *file;
int repeat; int repeat;
struct args_value *value; struct args_value *value;
u_int count = args_count(args); u_int count = args_count(args);
struct cmd_parse_tree *cmd; struct cmd_parse_tree *cmd;
struct cmd_parse_input pi;
key = key_string_lookup_string(args_string(args, 0)); key = key_string_lookup_string(args_string(args, 0));
if (key == KEYC_NONE || key == KEYC_UNKNOWN) { if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
@@ -88,7 +89,13 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
cmd = cmd_parse_from_arguments(args_values(args) + 1, count - 1); memset(&pi, 0, sizeof pi);
cmd_get_source(self, &file, &pi.line);
if (file != NULL)
pi.file = file;
pi.flags = cmd_get_parse_flags(self);
cmd = cmd_parse_from_arguments(args_values(args) + 1, count - 1, &pi);
key_bindings_add(tablename, key, note, repeat, cmd); key_bindings_add(tablename, key, note, repeat, cmd);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }

View File

@@ -547,7 +547,10 @@ cmd_invoke_fire(struct cmdq_item *item, struct cmd_invoke_state *is)
break; break;
} }
if (r == -1) { if (r == -1) {
cmd_invoke_error(item, is, node, cause); if (cmdq_get_client(item) != NULL)
cmdq_error(item, "%s", cause);
else
cfg_add_cause("%s", cause);
free(cause); free(cause);
cmd_invoke_skip_sequence(is); cmd_invoke_skip_sequence(is);
break; break;

View File

@@ -103,6 +103,7 @@ static void cmd_parse_print_sequence(char **, struct cmd_parse_node *,
u_int); u_int);
static void cmd_parse_print_item(char **, struct cmd_parse_node *, u_int, static void cmd_parse_print_item(char **, struct cmd_parse_node *, u_int,
int); int);
static char *cmd_parse_make_string(struct cmd_parse_node *);
%} %}
@@ -716,16 +717,18 @@ cmd_parse_from_node(struct cmd_parse_tree *tree, struct cmd_parse_node *node)
/* Find the last command node in tree order. */ /* Find the last command node in tree order. */
static struct cmd_parse_node * static struct cmd_parse_node *
cmd_parse_last_command(struct cmd_parse_node *node) cmd_parse_last_top_level_command(struct cmd_parse_tree *tree)
{ {
struct cmd_parse_node *child, *last = NULL, *found; struct cmd_parse_node *root, *seq, *node, *last = NULL;
if (node->type == CMD_PARSE_COMMAND) root = cmd_parse_root(tree);
last = node; TAILQ_FOREACH(seq, &root->children, entry) {
TAILQ_FOREACH(child, &node->children, entry) { if (seq->type == CMD_PARSE_SEQUENCE) {
found = cmd_parse_last_command(child); TAILQ_FOREACH(node, &seq->children, entry) {
if (found != NULL) if (node->type == CMD_PARSE_COMMAND)
last = found; last = node;
}
}
} }
return (last); return (last);
} }
@@ -740,8 +743,8 @@ cmd_parse_expand_alias(struct cmd_parse_tree *src, struct cmd_parse_node *cmd,
{ {
struct cmd_parse_input pi; struct cmd_parse_input pi;
struct cmd_parse_tree *tree; struct cmd_parse_tree *tree;
struct cmd_parse_node *first, *node, *last, *loop, *copy; struct cmd_parse_node *first, *last, *loop, *copy;
char *alias; char *alias, *name;
*out = NULL; *out = NULL;
*cause = NULL; *cause = NULL;
@@ -754,15 +757,12 @@ cmd_parse_expand_alias(struct cmd_parse_tree *src, struct cmd_parse_node *cmd,
first = TAILQ_FIRST(&cmd->children); first = TAILQ_FIRST(&cmd->children);
if (first == NULL) if (first == NULL)
return (0); return (0);
if (first->type != CMD_PARSE_STRING) name = cmd_parse_make_string(first);
return (0); if (name == NULL)
node = TAILQ_FIRST(&first->children);
if (node == NULL || TAILQ_NEXT(node, entry) != NULL)
return (0);
if (node->type != CMD_PARSE_TEXT)
return (0); return (0);
alias = cmd_get_alias(node->value); alias = cmd_get_alias(name);
free(name);
if (alias == NULL) if (alias == NULL)
return (0); return (0);
@@ -771,12 +771,12 @@ cmd_parse_expand_alias(struct cmd_parse_tree *src, struct cmd_parse_node *cmd,
pi.line = cmd_parse_node_line(cmd); pi.line = cmd_parse_node_line(cmd);
pi.flags = cmd_parse_flags(src) | CMD_PARSE_NOALIAS; pi.flags = cmd_parse_flags(src) | CMD_PARSE_NOALIAS;
tree = cmd_parse_from_string(alias, &pi, cause); tree = cmd_parse_from_buffer(alias, strlen(alias), &pi, cause);
free(alias); free(alias);
if (tree == NULL) if (tree == NULL)
return (-1); return (-1);
last = cmd_parse_last_command(cmd_parse_root(tree)); last = cmd_parse_last_top_level_command(tree);
if (last != NULL) { if (last != NULL) {
loop = TAILQ_NEXT(first, entry); loop = TAILQ_NEXT(first, entry);
while (loop != NULL) { while (loop != NULL) {
@@ -824,10 +824,10 @@ cmd_parse_new_commands_node(struct cmd_parse_tree *tree, u_int line)
/* Add one argument to the current command, creating it if needed. */ /* Add one argument to the current command, creating it if needed. */
static void static void
cmd_parse_from_arguments_add(struct cmd_parse_node *seq, cmd_parse_from_arguments_add(struct cmd_parse_node *seq,
struct cmd_parse_node **cmd, struct cmd_parse_node *child) struct cmd_parse_node **cmd, struct cmd_parse_node *child, u_int line)
{ {
if (*cmd == NULL) { if (*cmd == NULL) {
*cmd = cmd_parse_new_node(CMD_PARSE_COMMAND, 0); *cmd = cmd_parse_new_node(CMD_PARSE_COMMAND, line);
TAILQ_INSERT_TAIL(&seq->children, *cmd, entry); TAILQ_INSERT_TAIL(&seq->children, *cmd, entry);
} }
TAILQ_INSERT_TAIL(&(*cmd)->children, child, entry); TAILQ_INSERT_TAIL(&(*cmd)->children, child, entry);
@@ -835,17 +835,22 @@ cmd_parse_from_arguments_add(struct cmd_parse_node *seq,
/* Build a parse tree directly from existing argument values. */ /* Build a parse tree directly from existing argument values. */
struct cmd_parse_tree * struct cmd_parse_tree *
cmd_parse_from_arguments(struct args_value *values, u_int count) cmd_parse_from_arguments(struct args_value *values, u_int count,
struct cmd_parse_input *pi)
{ {
struct cmd_parse_tree *new; struct cmd_parse_tree *new, *new_cmd;
struct cmd_parse_node *root, *seq, *cmd = NULL, *child; struct cmd_parse_node *root, *seq, *cmd = NULL, *child;
u_int i; u_int i;
char *copy; char *copy;
size_t size; size_t size;
int end; int end;
u_int line = 0;
root = cmd_parse_new_node(CMD_PARSE_ROOT, 0); if (pi != NULL)
seq = cmd_parse_new_node(CMD_PARSE_SEQUENCE, 0); line = pi->line;
root = cmd_parse_new_node(CMD_PARSE_ROOT, line);
seq = cmd_parse_new_node(CMD_PARSE_SEQUENCE, line);
TAILQ_INSERT_TAIL(&root->children, seq, entry); TAILQ_INSERT_TAIL(&root->children, seq, entry);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
@@ -865,16 +870,19 @@ cmd_parse_from_arguments(struct args_value *values, u_int count)
else else
end = 1; end = 1;
} }
if (end && size == 0) {
if (!end || size != 0) { free(copy);
child = cmd_parse_new_string_node(copy, 0); break;
cmd_parse_from_arguments_add(seq, &cmd, child);
} }
child = cmd_parse_new_string_node(copy, line);
cmd_parse_from_arguments_add(seq, &cmd, child, line);
free(copy); free(copy);
break; break;
case ARGS_COMMANDS: case ARGS_COMMANDS:
child = cmd_parse_new_commands_node(values[i].cmd, 0); new_cmd = values[i].cmd;
cmd_parse_from_arguments_add(seq, &cmd, child); child = cmd_parse_new_commands_node(new_cmd, line);
cmd_parse_from_arguments_add(seq, &cmd, child, line);
break; break;
default: default:
fatalx("unknown argument type"); fatalx("unknown argument type");
@@ -886,6 +894,10 @@ cmd_parse_from_arguments(struct args_value *values, u_int count)
new = xcalloc(1, sizeof *new); new = xcalloc(1, sizeof *new);
new->references = 1; new->references = 1;
if (pi != NULL) {
new->file = pi->file != NULL ? xstrdup(pi->file) : NULL;
new->flags = (pi->flags & ~CMD_PARSE_ONEGROUP);
}
new->root = root; new->root = root;
return (new); return (new);
} }

View File

@@ -2590,7 +2590,7 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
item = cmdq_get_callback(server_client_default_command, NULL); item = cmdq_get_callback(server_client_default_command, NULL);
else { else {
values = args_from_vector(argc, argv); values = args_from_vector(argc, argv);
tree = cmd_parse_from_arguments(values, argc); tree = cmd_parse_from_arguments(values, argc, NULL);
args_free_values(values, argc); args_free_values(values, argc);
free(values); free(values);
cmd_free_argv(argc, argv); cmd_free_argv(argc, argv);

View File

@@ -79,10 +79,11 @@ struct cmd_parse_tree *cmd_parse_from_string(const char *,
struct cmd_parse_input *, char **); struct cmd_parse_input *, char **);
struct cmd_parse_tree *cmd_parse_from_node(struct cmd_parse_tree *, struct cmd_parse_tree *cmd_parse_from_node(struct cmd_parse_tree *,
struct cmd_parse_node *); struct cmd_parse_node *);
struct cmd_parse_tree *cmd_parse_from_arguments(struct args_value *, u_int,
struct cmd_parse_input *);
int cmd_parse_expand_alias(struct cmd_parse_tree *, int cmd_parse_expand_alias(struct cmd_parse_tree *,
struct cmd_parse_node *, struct cmd_parse_tree **, struct cmd_parse_node *, struct cmd_parse_tree **,
char **); char **);
struct cmd_parse_tree *cmd_parse_from_arguments(struct args_value *, u_int);
struct cmd_parse_tree *cmd_parse_add_ref(struct cmd_parse_tree *); struct cmd_parse_tree *cmd_parse_add_ref(struct cmd_parse_tree *);
int cmd_parse_any_have(struct cmd_parse_tree *, int); int cmd_parse_any_have(struct cmd_parse_tree *, int);
void cmd_parse_free(struct cmd_parse_tree *); void cmd_parse_free(struct cmd_parse_tree *);