diff --git a/cmd-queue.c b/cmd-queue.c index 804195ca9..9eee5473a 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -48,7 +48,6 @@ struct cmdq_item { struct client *target_client; enum cmdq_type type; - u_int group; u_int number; time_t time; @@ -59,7 +58,6 @@ struct cmdq_item { struct cmd_find_state source; struct cmd_find_state target; - struct cmd_list *cmdlist; struct cmd *cmd; struct cmd_invoke_state *invoke_state; @@ -457,8 +455,8 @@ cmdq_remove(struct cmdq_item *item) { if (item->client != NULL) server_client_unref(item->client); - if (item->cmdlist != NULL) - cmd_list_free(item->cmdlist); + if (item->cmd != NULL) + cmd_free(item->cmd); if (item->invoke_state != NULL) cmd_invoke_state_free(item->invoke_state); cmdq_free_state(item->state); @@ -469,91 +467,28 @@ cmdq_remove(struct cmdq_item *item) free(item); } -/* Remove all subsequent items that match this item's group. */ -static void -cmdq_remove_group(struct cmdq_item *item) -{ - struct cmdq_item *this, *next; - - if (item->group == 0) - return; - this = TAILQ_NEXT(item, entry); - while (this != NULL) { - next = TAILQ_NEXT(this, entry); - if (this->group == item->group) - cmdq_remove(this); - this = next; - } -} - -/* Empty command callback. */ -static enum cmd_retval -cmdq_empty_command(__unused struct cmdq_item *item, __unused void *data) -{ - return (CMD_RETURN_NORMAL); -} - -/* Get a command for the command queue. */ -struct cmdq_item * -cmdq_get_command(struct cmd_list *cmdlist, struct cmdq_state *state) -{ - struct cmdq_item *item, *first = NULL, *last = NULL; - struct cmd *cmd; - const struct cmd_entry *entry; - int created = 0; - - if ((cmd = cmd_list_first(cmdlist)) == NULL) - return (cmdq_get_callback(cmdq_empty_command, NULL)); - - if (state == NULL) { - state = cmdq_new_state(NULL, NULL, 0); - created = 1; - } - - while (cmd != NULL) { - entry = cmd_get_entry(cmd); - - item = xcalloc(1, sizeof *item); - xasprintf(&item->name, "[%s/%p]", entry->name, item); - item->type = CMDQ_COMMAND; - - item->group = cmd_get_group(cmd); - item->state = cmdq_link_state(state); - - item->cmdlist = cmdlist; - item->cmd = cmd; - - cmdlist->references++; - log_debug("%s: %s group %u", __func__, item->name, item->group); - - if (first == NULL) - first = item; - if (last != NULL) - last->next = item; - last = item; - - cmd = cmd_list_next(cmd); - } - - if (created) - cmdq_free_state(state); - return (first); -} - /* Get a single command for command queue with invoke state. */ struct cmdq_item * cmdq_get_one_command(struct cmd *cmd, struct cmdq_state *state, struct cmd_invoke_state *invoke_state) { - struct cmd_list *cmdlist; struct cmdq_item *item; + const struct cmd_entry *entry = cmd_get_entry(cmd); - cmdlist = cmd_list_new(); - cmd_list_append(cmdlist, cmd); + item = xcalloc(1, sizeof *item); + xasprintf(&item->name, "[%s/%p]", entry->name, item); + item->type = CMDQ_COMMAND; + item->cmd = cmd; - item = cmdq_get_command(cmdlist, state); - cmd_list_free(cmdlist); - item->invoke_state = cmd_invoke_state_add_ref(invoke_state); + if (state == NULL) + item->state = cmdq_new_state(NULL, NULL, 0); + else + item->state = cmdq_link_state(state); + + if (invoke_state != NULL) + item->invoke_state = cmd_invoke_state_add_ref(invoke_state); + + log_debug("%s: %s", __func__, item->name); return (item); } @@ -566,7 +501,6 @@ cmdq_get_invoke(struct cmd_invoke_state *invoke_state, struct cmdq_state *state) item = xcalloc(1, sizeof *item); xasprintf(&item->name, "[invoke/%p]", item); item->type = CMDQ_INVOKE; - item->group = 0; if (state == NULL) item->state = cmdq_new_state(NULL, NULL, 0); else @@ -650,7 +584,7 @@ cmdq_fire_command(struct cmdq_item *item) cmdq_add_message(item); if (log_get_level() > 1) { tmp = cmd_print(cmd); - log_debug("%s %s: (%u) %s", __func__, name, item->group, tmp); + log_debug("%s %s: %s", __func__, name, tmp); free(tmp); } @@ -729,7 +663,6 @@ cmdq_get_callback1(const char *name, cmdq_cb cb, void *data) xasprintf(&item->name, "[%s/%p]", name, item); item->type = CMDQ_CALLBACK; - item->group = 0; item->state = cmdq_new_state(NULL, NULL, 0); item->cb = cb; @@ -814,12 +747,6 @@ cmdq_next(struct client *c) if (item->invoke_state != NULL) cmd_invoke_result(item->invoke_state, retval); - /* - * If a command returns an error, remove any - * subsequent commands in the same group. - */ - if (retval == CMD_RETURN_ERROR) - cmdq_remove_group(item); break; case CMDQ_CALLBACK: retval = cmdq_fire_callback(item); diff --git a/cmd.c b/cmd.c index fe7fcb196..98abc4825 100644 --- a/cmd.c +++ b/cmd.c @@ -220,18 +220,11 @@ const struct cmd_entry *cmd_table[] = { struct cmd { const struct cmd_entry *entry; struct args *args; - u_int group; char *file; u_int line; int parse_flags; - - TAILQ_ENTRY(cmd) qentry; }; -TAILQ_HEAD(cmds, cmd); - -/* Next group number for new command list. */ -static u_int cmd_list_next_group = 1; /* Log an argument vector. */ void printflike(3, 4) @@ -402,13 +395,6 @@ cmd_get_args(struct cmd *cmd) return (cmd->args); } -/* Get group for command. */ -u_int -cmd_get_group(struct cmd *cmd) -{ - return (cmd->group); -} - /* Get file and line for command. */ void cmd_get_source(struct cmd *cmd, const char **file, u_int *line) @@ -559,22 +545,6 @@ cmd_free(struct cmd *cmd) } /* Copy a command. */ -struct cmd * -cmd_copy(struct cmd *cmd, int argc, char **argv) -{ - struct cmd *new_cmd; - - new_cmd = xcalloc(1, sizeof *new_cmd); - new_cmd->entry = cmd->entry; - new_cmd->args = args_copy(cmd->args, argc, argv); - - if (cmd->file != NULL) - new_cmd->file = xstrdup(cmd->file); - new_cmd->line = cmd->line; - - return (new_cmd); -} - /* Get a command as a string. */ char * cmd_print(struct cmd *cmd) @@ -592,173 +562,6 @@ cmd_print(struct cmd *cmd) } /* Create a new command list. */ -struct cmd_list * -cmd_list_new(void) -{ - struct cmd_list *cmdlist; - - cmdlist = xcalloc(1, sizeof *cmdlist); - cmdlist->references = 1; - cmdlist->group = cmd_list_next_group++; - cmdlist->list = xcalloc(1, sizeof *cmdlist->list); - TAILQ_INIT(cmdlist->list); - return (cmdlist); -} - -/* Append a command to a command list. */ -void -cmd_list_append(struct cmd_list *cmdlist, struct cmd *cmd) -{ - cmd->group = cmdlist->group; - TAILQ_INSERT_TAIL(cmdlist->list, cmd, qentry); -} - -/* Append all commands from one list to another. */ -void -cmd_list_append_all(struct cmd_list *cmdlist, struct cmd_list *from) -{ - struct cmd *cmd; - - TAILQ_FOREACH(cmd, from->list, qentry) - cmd->group = cmdlist->group; - TAILQ_CONCAT(cmdlist->list, from->list, qentry); -} - -/* Move all commands from one command list to another. */ -void -cmd_list_move(struct cmd_list *cmdlist, struct cmd_list *from) -{ - TAILQ_CONCAT(cmdlist->list, from->list, qentry); - cmdlist->group = cmd_list_next_group++; -} - -/* Free a command list. */ -void -cmd_list_free(struct cmd_list *cmdlist) -{ - struct cmd *cmd, *cmd1; - - if (--cmdlist->references != 0) - return; - - TAILQ_FOREACH_SAFE(cmd, cmdlist->list, qentry, cmd1) { - TAILQ_REMOVE(cmdlist->list, cmd, qentry); - cmd_free(cmd); - } - free(cmdlist->list); - free(cmdlist); -} - -/* Copy a command list, expanding %s in arguments. */ -struct cmd_list * -cmd_list_copy(const struct cmd_list *cmdlist, int argc, char **argv) -{ - struct cmd *cmd; - struct cmd_list *new_cmdlist; - struct cmd *new_cmd; - u_int group = cmdlist->group; - char *s; - - s = cmd_list_print(cmdlist, 0); - log_debug("%s: %s", __func__, s); - free(s); - - new_cmdlist = cmd_list_new(); - TAILQ_FOREACH(cmd, cmdlist->list, qentry) { - if (cmd->group != group) { - new_cmdlist->group = cmd_list_next_group++; - group = cmd->group; - } - new_cmd = cmd_copy(cmd, argc, argv); - cmd_list_append(new_cmdlist, new_cmd); - } - - s = cmd_list_print(new_cmdlist, 0); - log_debug("%s: %s", __func__, s); - free(s); - - return (new_cmdlist); -} - -/* Get a command list as a string. */ -char * -cmd_list_print(const struct cmd_list *cmdlist, int flags) -{ - struct cmd *cmd, *next; - char *buf, *this; - size_t len; - const char *separator; - int escaped = flags & CMD_LIST_PRINT_ESCAPED; - int no_groups = flags & CMD_LIST_PRINT_NO_GROUPS; - const char *single_separator = escaped ? " \\; " : " ; "; - const char *double_separator = escaped ? " \\;\\; " : " ;; "; - - len = 1; - buf = xcalloc(1, len); - - TAILQ_FOREACH(cmd, cmdlist->list, qentry) { - this = cmd_print(cmd); - - len += strlen(this) + 6; - buf = xrealloc(buf, len); - - strlcat(buf, this, len); - - next = TAILQ_NEXT(cmd, qentry); - if (next != NULL) { - if (!no_groups && cmd->group != next->group) - separator = double_separator; - else - separator = single_separator; - strlcat(buf, separator, len); - } - - free(this); - } - - return (buf); -} - -/* Get first command in list. */ -struct cmd * -cmd_list_first(struct cmd_list *cmdlist) -{ - return (TAILQ_FIRST(cmdlist->list)); -} - -/* Get next command in list. */ -struct cmd * -cmd_list_next(struct cmd *cmd) -{ - return (TAILQ_NEXT(cmd, qentry)); -} - -/* Do all of the commands in this command list have this flag? */ -int -cmd_list_all_have(struct cmd_list *cmdlist, int flag) -{ - struct cmd *cmd; - - TAILQ_FOREACH(cmd, cmdlist->list, qentry) { - if (~cmd->entry->flags & flag) - return (0); - } - return (1); -} - -/* Do any of the commands in this command list have this flag? */ -int -cmd_list_any_have(struct cmd_list *cmdlist, int flag) -{ - struct cmd *cmd; - - TAILQ_FOREACH(cmd, cmdlist->list, qentry) { - if (cmd->entry->flags & flag) - return (1); - } - return (0); -} - /* Adjust current mouse position for a pane. */ int cmd_mouse_at(struct window_pane *wp, struct mouse_event *m, u_int *xp, diff --git a/fuzz/cmd-parse-fuzzer.c b/fuzz/cmd-parse-fuzzer.c index 2e1354225..046c8827a 100644 --- a/fuzz/cmd-parse-fuzzer.c +++ b/fuzz/cmd-parse-fuzzer.c @@ -36,7 +36,8 @@ int LLVMFuzzerTestOneInput(const u_char *data, size_t size) { struct cmd_parse_input pi; - struct cmd_parse_result *pr; + struct cmd_parse_tree *tree; + char *cause = NULL; if (size > 2048 || size == 0) return 0; @@ -44,17 +45,10 @@ LLVMFuzzerTestOneInput(const u_char *data, size_t size) memset(&pi, 0, sizeof pi); pi.flags = CMD_PARSE_QUIET; - pr = cmd_parse_from_buffer(data, size, &pi); - switch (pr->status) { - case CMD_PARSE_SUCCESS: - cmd_list_free(pr->cmdlist); - break; - case CMD_PARSE_ERROR: - free(pr->error); - break; - default: - break; - } + tree = cmd_parse_from_buffer(data, size, &pi, &cause); + if (tree != NULL) + cmd_parse_free(tree); + free(cause); return 0; } diff --git a/tmux-parser.h b/tmux-parser.h index 19ff20fd1..bb59020ef 100644 --- a/tmux-parser.h +++ b/tmux-parser.h @@ -28,8 +28,7 @@ * * The parser builds syntax only. It does not expand formats, environment * variables, or ~, does not evaluate %if/%elif, does not expand aliases, and - * does not build struct cmd or struct cmd_list. Those are execution-time - * operations. + * does not build struct cmd. That is an execution-time operation. * * Command failure scope is represented by CMD_PARSE_SEQUENCE: if an invoked * command or assignment fails, the invoker skips the remaining children of diff --git a/tmux.h b/tmux.h index 7ead86b11..ac36c7509 100644 --- a/tmux.h +++ b/tmux.h @@ -1924,13 +1924,6 @@ struct cmd_find_state { #define CMD_FIND_EXACT_WINDOW 0x20 #define CMD_FIND_CANFAIL 0x40 -/* List of commands. */ -struct cmd_list { - int references; - u_int group; - struct cmds *list; -}; - /* Command return values. */ enum cmd_retval { CMD_RETURN_ERROR = -1, @@ -2956,27 +2949,12 @@ char *cmd_stringify_argv(int, char **); char *cmd_get_alias(const char *); const struct cmd_entry *cmd_get_entry(struct cmd *); struct args *cmd_get_args(struct cmd *); -u_int cmd_get_group(struct cmd *); void cmd_get_source(struct cmd *, const char **, u_int *); int cmd_get_parse_flags(struct cmd *); struct cmd *cmd_parse(struct args_value *, u_int, const char *, u_int, int, char **); -struct cmd *cmd_copy(struct cmd *, int, char **); void cmd_free(struct cmd *); char *cmd_print(struct cmd *); -struct cmd_list *cmd_list_new(void); -struct cmd_list *cmd_list_copy(const struct cmd_list *, int, char **); -void cmd_list_append(struct cmd_list *, struct cmd *); -void cmd_list_append_all(struct cmd_list *, struct cmd_list *); -void cmd_list_move(struct cmd_list *, struct cmd_list *); -void cmd_list_free(struct cmd_list *); -#define CMD_LIST_PRINT_ESCAPED 0x1 -#define CMD_LIST_PRINT_NO_GROUPS 0x2 -char *cmd_list_print(const struct cmd_list *, int); -struct cmd *cmd_list_first(struct cmd_list *); -struct cmd *cmd_list_next(struct cmd *); -int cmd_list_all_have(struct cmd_list *, int); -int cmd_list_any_have(struct cmd_list *, int); int cmd_mouse_at(struct window_pane *, struct mouse_event *, u_int *, u_int *, int); struct winlink *cmd_mouse_window(struct mouse_event *, struct session **); @@ -3018,7 +2996,6 @@ struct cmd_find_state *cmdq_get_source(struct cmdq_item *); struct key_event *cmdq_get_event(struct cmdq_item *); struct cmd_find_state *cmdq_get_current(struct cmdq_item *); int cmdq_get_flags(struct cmdq_item *); -struct cmdq_item *cmdq_get_command(struct cmd_list *, struct cmdq_state *); struct cmdq_item *cmdq_get_one_command(struct cmd *, struct cmdq_state *, struct cmd_invoke_state *); struct cmdq_item *cmdq_get_invoke(struct cmd_invoke_state *,