From b3bb8bbd9f64e59d836acac890a26c276848aa62 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 30 Jun 2026 17:57:38 +0100 Subject: [PATCH] Options and hooks updates. --- cmd-confirm-before.c | 3 +- cmd-parse.y | 10 ++--- cmd-queue.c | 8 ++-- notify.c | 14 +++---- options.c | 89 ++++++++++++++------------------------------ server-client.c | 19 ++-------- tmux-parser.h | 6 +-- tmux.h | 6 +-- 8 files changed, 53 insertions(+), 102 deletions(-) diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c index 2548bd44c..df9bf5c8b 100644 --- a/cmd-confirm-before.c +++ b/cmd-confirm-before.c @@ -100,8 +100,7 @@ cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item) cdata->confirm_key = confirm_key[0]; else { cmdq_error(item, "invalid confirm key"); - cmd_parse_free(cdata->tree); - free(cdata); + cmd_confirm_before_free(cdata); return (CMD_RETURN_ERROR); } } diff --git a/cmd-parse.y b/cmd-parse.y index 10fcb1aa9..806156845 100644 --- a/cmd-parse.y +++ b/cmd-parse.y @@ -791,12 +791,10 @@ cmd_parse_add_ref(struct cmd_parse_tree *tree) void cmd_parse_free(struct cmd_parse_tree *tree) { - if (tree == NULL) - return; - if (--tree->references != 0) - return; - cmd_parse_free_node(tree->root); - free(tree); + if (tree != NULL && --tree->references == 0) { + cmd_parse_free_node(tree->root); + free(tree); + } } struct cmd_parse_node * diff --git a/cmd-queue.c b/cmd-queue.c index c47dcbb42..804195ca9 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -369,7 +369,7 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item, struct cmdq_state *new_state; struct options_entry *o; struct options_array_item *a; - struct cmd_list *cmdlist; + struct cmd_parse_tree *tree; if (item->state->flags & CMDQ_STATE_NOHOOKS) return; @@ -429,9 +429,9 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item, a = options_array_first(o); while (a != NULL) { - cmdlist = options_array_item_value(a)->cmdlist; - if (cmdlist != NULL) { - new_item = cmdq_get_command(cmdlist, new_state); + tree = options_array_item_value(a)->cmd; + if (tree != NULL) { + new_item = cmd_invoke_get(tree, new_state, NULL); if (item != NULL) item = cmdq_insert_after(item, new_item); else diff --git a/notify.c b/notify.c index c8a9066e8..bb3283a75 100644 --- a/notify.c +++ b/notify.c @@ -37,19 +37,19 @@ struct notify_entry { static struct cmdq_item * notify_insert_one_hook(struct cmdq_item *item, struct notify_entry *ne, - struct cmd_list *cmdlist, struct cmdq_state *state) + struct cmd_parse_tree *tree, struct cmdq_state *state) { struct cmdq_item *new_item; char *s; - if (cmdlist == NULL) + if (tree == NULL) return (item); if (log_get_level() != 0) { - s = cmd_list_print(cmdlist, 0); + s = cmd_parse_print(tree); log_debug("%s: hook %s is: %s", __func__, ne->name, s); free(s); } - new_item = cmdq_get_command(cmdlist, state); + new_item = cmd_invoke_get(tree, state, NULL); return (cmdq_insert_after(item, new_item)); } @@ -61,7 +61,7 @@ notify_insert_hook(struct cmdq_item *item, struct notify_entry *ne) struct cmdq_state *state; struct options_entry *o; struct options_array_item *a; - struct cmd_list *cmdlist; + struct cmd_parse_tree *tree; log_debug("%s: inserting hook %s", __func__, ne->name); @@ -116,8 +116,8 @@ notify_insert_hook(struct cmdq_item *item, struct notify_entry *ne) } else { a = options_array_first(o); while (a != NULL) { - cmdlist = options_array_item_value(a)->cmdlist; - item = notify_insert_one_hook(item, ne, cmdlist, state); + tree = options_array_item_value(a)->cmd; + item = notify_insert_one_hook(item, ne, tree, state); a = options_array_next(a); } } diff --git a/options.c b/options.c index dede366fd..631b27663 100644 --- a/options.c +++ b/options.c @@ -125,8 +125,8 @@ options_value_free(struct options_entry *o, union options_value *ov) { if (OPTIONS_IS_STRING(o)) free(ov->string); - if (OPTIONS_IS_COMMAND(o) && ov->cmdlist != NULL) - cmd_list_free(ov->cmdlist); + if (OPTIONS_IS_COMMAND(o)) + cmd_parse_free(ov->cmd); } static char * @@ -136,7 +136,7 @@ options_value_to_string(struct options_entry *o, union options_value *ov, char *s; if (OPTIONS_IS_COMMAND(o)) - return (cmd_list_print(ov->cmdlist, 0)); + return (cmd_parse_print(ov->cmd)); if (OPTIONS_IS_NUMBER(o)) { switch (o->tableentry->type) { case OPTIONS_TABLE_NUMBER: @@ -259,6 +259,7 @@ options_default(struct options *oo, const struct options_table_entry *oe) { struct options_entry *o; union options_value *ov; + char *error = NULL; u_int i; o = options_empty(oo, oe); @@ -279,22 +280,9 @@ options_default(struct options *oo, const struct options_table_entry *oe) ov->string = xstrdup(oe->default_str); break; case OPTIONS_TABLE_COMMAND: -#if 0 /* XXX: command parser conversion */ - struct cmd_parse_result *pr; - - pr = cmd_parse_from_string(oe->default_str, NULL); - switch (pr->status) { - case CMD_PARSE_ERROR: - free(pr->error); - break; - case CMD_PARSE_SUCCESS: - ov->cmdlist = pr->cmdlist; - break; - } -#else - log_debug("XXX: command parser conversion not done for command option default %s", - oe->name); -#endif + ov->cmd = cmd_parse_from_string(oe->default_str, NULL, &error); + if (ov->cmd == NULL) + fatalx("bad default option %s", oe->name); break; default: ov->number = oe->default_num; @@ -443,6 +431,8 @@ options_array_set(struct options_entry *o, u_int idx, const char *value, struct options_array_item *a; char *new; long long number; + struct cmd_parse_tree *tree; + char *error = NULL; if (!OPTIONS_IS_ARRAY(o)) { if (cause != NULL) @@ -458,19 +448,13 @@ options_array_set(struct options_entry *o, u_int idx, const char *value, } if (OPTIONS_IS_COMMAND(o)) { -#if 0 /* XXX: command parser conversion */ - struct cmd_parse_result *pr; - - pr = cmd_parse_from_string(value, NULL); - switch (pr->status) { - case CMD_PARSE_ERROR: + tree = cmd_parse_from_string(value, NULL, &error); + if (tree == NULL) { if (cause != NULL) - *cause = pr->error; + *cause = error; else - free(pr->error); + free(error); return (-1); - case CMD_PARSE_SUCCESS: - break; } a = options_array_item(o, idx); @@ -478,15 +462,8 @@ options_array_set(struct options_entry *o, u_int idx, const char *value, a = options_array_new(o, idx); else options_value_free(o, &a->value); - a->value.cmdlist = pr->cmdlist; + a->value.cmd = tree; return (0); -#else - if (cause != NULL) { - xasprintf(cause, - "XXX: command parser conversion not done for command option array"); - } - return (-1); -#endif } if (OPTIONS_IS_STRING(o)) { @@ -776,7 +753,7 @@ options_get_number(struct options *oo, const char *name) return (o->value.number); } -struct cmd_list * +struct cmd_parse_tree * options_get_command(struct options *oo, const char *name) { struct options_entry *o; @@ -786,7 +763,7 @@ options_get_command(struct options *oo, const char *name) fatalx("missing option %s", name); if (!OPTIONS_IS_COMMAND(o)) fatalx("option %s is not a command", name); - return (o->value.cmdlist); + return (o->value.cmd); } struct options_entry * @@ -852,7 +829,7 @@ options_set_number(struct options *oo, const char *name, long long value) struct options_entry * options_set_command(struct options *oo, const char *name, - struct cmd_list *value) + struct cmd_parse_tree *value) { struct options_entry *o; @@ -868,9 +845,8 @@ options_set_command(struct options *oo, const char *name, if (!OPTIONS_IS_COMMAND(o)) fatalx("option %s is not a command", name); - if (o->value.cmdlist != NULL) - cmd_list_free(o->value.cmdlist); - o->value.cmdlist = value; + cmd_parse_free(o->value.cmd); + o->value.cmd = cmd_parse_add_ref(value); return (o); } @@ -1146,6 +1122,8 @@ options_from_string(struct options *oo, const struct options_table_entry *oe, const char *errstr, *new; char *old; key_code key; + struct cmd_parse_tree *tree; + struct cmd_parse_input pi = { 0 }; if (oe != NULL) { if (value == NULL && @@ -1203,25 +1181,14 @@ options_from_string(struct options *oo, const struct options_table_entry *oe, return (options_from_string_flag(oo, name, value, cause)); case OPTIONS_TABLE_CHOICE: return (options_from_string_choice(oe, oo, name, value, cause)); - case OPTIONS_TABLE_COMMAND: -#if 0 /* XXX: command parser conversion */ - struct cmd_parse_result *pr; - - pr = cmd_parse_from_string(value, NULL); - switch (pr->status) { - case CMD_PARSE_ERROR: - *cause = pr->error; + case OPTIONS_TABLE_COMMAND: { + tree = cmd_parse_from_string(value, &pi, cause); + if (tree == NULL) return (-1); - case CMD_PARSE_SUCCESS: - options_set_command(oo, name, pr->cmdlist); - return (0); - } - break; -#else - xasprintf(cause, - "XXX: command parser conversion not done for command option"); - return (-1); -#endif + options_set_command(oo, name, tree); + cmd_parse_free(tree); + return (0); + } } return (-1); } diff --git a/server-client.c b/server-client.c index 0a20f3502..28b510bfe 100644 --- a/server-client.c +++ b/server-client.c @@ -2527,28 +2527,15 @@ bad: proc_kill_peer(c->peer); } -/* Callback when command is not allowed. */ -static enum cmd_retval -server_client_read_only(struct cmdq_item *item, __unused void *data) -{ - cmdq_error(item, "client is read-only"); - return (CMD_RETURN_ERROR); -} - /* Callback for default command. */ static enum cmd_retval server_client_default_command(struct cmdq_item *item, __unused void *data) { - struct client *c = cmdq_get_client(item); - struct cmd_list *cmdlist; + struct cmd_parse_tree *tree; struct cmdq_item *new_item; - cmdlist = options_get_command(global_options, "default-client-command"); - if ((c->flags & CLIENT_READONLY) && - !cmd_list_all_have(cmdlist, CMD_READONLY)) - new_item = cmdq_get_callback(server_client_read_only, NULL); - else - new_item = cmdq_get_command(cmdlist, NULL); + tree = options_get_command(global_options, "default-client-command"); + new_item = cmd_invoke_get(tree, NULL, NULL); cmdq_insert_after(item, new_item); return (CMD_RETURN_NORMAL); } diff --git a/tmux-parser.h b/tmux-parser.h index df363f553..444521a61 100644 --- a/tmux-parser.h +++ b/tmux-parser.h @@ -43,9 +43,9 @@ struct args_value; struct cmd_parse_input { int flags; #define CMD_PARSE_QUIET 0x1 -#define CMD_PARSE_PARSEONLY 0x2 /* XXX */ -#define CMD_PARSE_NOALIAS 0x4 /* XXX */ -#define CMD_PARSE_VERBOSE 0x8 /* XXX */ +#define CMD_PARSE_PARSEONLY 0x2 +#define CMD_PARSE_NOALIAS 0x4 +#define CMD_PARSE_VERBOSE 0x8 #define CMD_PARSE_ONEGROUP 0x10 const char *file; diff --git a/tmux.h b/tmux.h index bffda3a44..7ead86b11 100644 --- a/tmux.h +++ b/tmux.h @@ -2340,7 +2340,7 @@ union options_value { long long number; struct style style; struct options_array array; - struct cmd_list *cmdlist; + struct cmd_parse_tree *cmd; }; /* Option table entries. */ @@ -2673,13 +2673,13 @@ struct options_entry *options_match_get(struct options *, const char *, int *, int, int *); const char *options_get_string(struct options *, const char *); long long options_get_number(struct options *, const char *); -struct cmd_list *options_get_command(struct options *, const char *); +struct cmd_parse_tree *options_get_command(struct options *, const char *); struct options_entry * printflike(4, 5) options_set_string(struct options *, const char *, int, const char *, ...); struct options_entry *options_set_number(struct options *, const char *, long long); struct options_entry *options_set_command(struct options *, const char *, - struct cmd_list *); + struct cmd_parse_tree *); int options_scope_from_name(struct args *, int, const char *, struct cmd_find_state *, struct options **, char **);