diff --git a/arguments.c b/arguments.c index 52cdeea9c..5c53b3cf5 100644 --- a/arguments.c +++ b/arguments.c @@ -53,9 +53,11 @@ struct args { /* Prepared command state. */ struct args_command_state { - struct cmd_list *cmdlist; + struct cmd_parse_tree *tree; char *cmd; struct cmd_parse_input pi; + char *error; + int parse_input; }; static struct args_entry *args_find(struct args *, u_char); @@ -747,51 +749,51 @@ args_string(struct args *args, u_int idx) } /* Make a command now. */ -struct cmd_list * -args_make_commands_now(struct cmd *self, struct cmdq_item *item, u_int idx, +struct cmdq_item * +args_command_now(struct cmd *self, struct cmdq_item *item, u_int idx, int expand) { struct args_command_state *state; + struct cmdq_item *new_item; + struct cmdq_state *cs = cmdq_get_state(item); char *error; - struct cmd_list *cmdlist; - state = args_make_commands_prepare(self, item, idx, NULL, 0, expand); - cmdlist = args_make_commands(state, 0, NULL, &error); - if (cmdlist == NULL) { + state = args_command_prepare(self, item, idx, NULL, expand); + new_item = args_command_get(state, 0, NULL, cs, &error); + if (new_item == NULL) { cmdq_error(item, "%s", error); free(error); } - else - cmdlist->references++; - args_make_commands_free(state); - return (cmdlist); + args_command_free(state); + return (new_item); } /* Save bits to make a command later. */ struct args_command_state * -args_make_commands_prepare(struct cmd *self, struct cmdq_item *item, u_int idx, - const char *default_command, int wait, int expand) +args_command_prepare(struct cmd *self, struct cmdq_item *item, u_int idx, + const char *default_command, int expand) { struct args *args = cmd_get_args(self); struct args_value *value; struct args_command_state *state; - const char *cmd; + const char *cmd = NULL; const char *file; state = xcalloc(1, sizeof *state); + state->pi.flags = cmd_get_parse_flags(self); + + cmd_get_source(self, &file, &state->pi.line); + if (file != NULL) + state->pi.file = xstrdup(file); if (idx < args->count) { value = &args->values[idx]; if (value->type == ARGS_COMMANDS) { -#if 0 /* XXX: command parser conversion */ - state->cmdlist = value->cmdlist; - state->cmdlist->references++; + state->tree = cmd_parse_add_ref(value->cmd); return (state); -#else - fatalx("XXX: command parser conversion not done for " - "ARGS_COMMANDS"); -#endif } + if (value->type != ARGS_STRING) + fatalx("argument not string or commands"); cmd = value->string; } else { if (default_command == NULL) @@ -806,101 +808,91 @@ args_make_commands_prepare(struct cmd *self, struct cmdq_item *item, u_int idx, state->cmd = xstrdup(cmd); log_debug("%s: %s", __func__, state->cmd); -#if 0 /* XXX: command parser conversion */ - if (wait) - state->pi.item = item; - cmd_get_source(self, &file, &state->pi.line); - if (file != NULL) - state->pi.file = xstrdup(file); - state->pi.c = cmdq_get_target_client(item); - if (state->pi.c != NULL) - state->pi.c->references++; - cmd_find_copy_state(&state->pi.fs, cmdq_get_target(item)); -#else - (void)wait; - cmd_get_source(self, &file, &state->pi.line); - if (file != NULL) - state->pi.file = xstrdup(file); -#endif + if (strcmp(state->cmd, "%1") == 0) + state->parse_input = 1; + else { + state->tree = cmd_parse_from_string(state->cmd, &state->pi, + &state->error); + } return (state); } -/* Return argument as command. */ -struct cmd_list * -args_make_commands(struct args_command_state *state, int argc, char **argv, - char **error) +/* Return argument as command queue item. */ +struct cmdq_item * +args_command_get(struct args_command_state *state, int argc, char **argv, + struct cmdq_state *qstate, char **error) { - if (state->cmdlist != NULL) { - if (argc == 0) - return (state->cmdlist); - return (cmd_list_copy(state->cmdlist, argc, argv)); - } + struct cmd_invoke_input ci = { 0 }; + struct cmd_parse_tree *tree; + struct cmdq_item *item; + int free_tree = 0; -#if 0 /* XXX: command parser conversion */ - struct cmd_parse_result *pr; - char *cmd, *new_cmd; - int i; - - cmd = xstrdup(state->cmd); - log_debug("%s: %s", __func__, cmd); - cmd_log_argv(argc, argv, __func__); - for (i = 0; i < argc; i++) { - new_cmd = cmd_template_replace(cmd, argv[i], i + 1); - log_debug("%s: %%%u %s: %s", __func__, i + 1, argv[i], new_cmd); - free(cmd); - cmd = new_cmd; - } - log_debug("%s: %s", __func__, cmd); - - pr = cmd_parse_from_string(cmd, &state->pi); - free(cmd); - switch (pr->status) { - case CMD_PARSE_ERROR: - *error = pr->error; + if (state->error != NULL) { + *error = xstrdup(state->error); return (NULL); - case CMD_PARSE_SUCCESS: - return (pr->cmdlist); } - fatalx("invalid parse return state"); -#else - (void)error; - fatalx("XXX: command parser conversion not done for ARGS_COMMANDS"); -#endif + + ci.file = state->pi.file; + ci.flags = state->pi.flags; + + if (state->parse_input) { + if (argc == 0 || argv[0] == NULL) { + *error = xstrdup("missing command"); + return (NULL); + } + tree = cmd_parse_from_string(argv[0], &state->pi, error); + if (tree == NULL) + return (NULL); + free_tree = 1; + } else { + if (state->tree == NULL) + fatalx("no command tree"); + tree = state->tree; + ci.argc = argc; + ci.argv = argv; + } + + item = cmd_invoke_get(tree, qstate, &ci); + if (free_tree) + cmd_parse_free(tree); + return (item); } /* Free commands state. */ void -args_make_commands_free(struct args_command_state *state) +args_command_free(struct args_command_state *state) { - if (state->cmdlist != NULL) - cmd_list_free(state->cmdlist); -#if 0 /* XXX: command parser conversion */ - if (state->pi.c != NULL) - server_client_unref(state->pi.c); -#endif + if (state->tree != NULL) + cmd_parse_free(state->tree); free((void *)state->pi.file); free(state->cmd); + free(state->error); free(state); } /* Get prepared command. */ char * -args_make_commands_get_command(struct args_command_state *state) +args_command_get_command(struct args_command_state *state) { - struct cmd *first; - int n; - char *s; + int n; + char *s, *tmp; - if (state->cmdlist != NULL) { - first = cmd_list_first(state->cmdlist); - if (first == NULL) - return (xstrdup("")); - return (xstrdup(cmd_get_entry(first)->name)); + if (state->parse_input) + return (xstrdup("")); + if (state->cmd == NULL && state->tree != NULL) { + tmp = cmd_parse_print(state->tree); + n = strcspn(tmp, " ,"); + xasprintf(&s, "%.*s", n, tmp); + free(tmp); + return (s); } - n = strcspn(state->cmd, " ,"); - xasprintf(&s, "%.*s", n, state->cmd); - return (s); + if (state->cmd != NULL) { + n = strcspn(state->cmd, " ,"); + xasprintf(&s, "%.*s", n, state->cmd); + return (s); + } + return (xstrdup("")); } /* Get first value in argument. */ diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c index 045ef0b12..0d07c94bd 100644 --- a/cmd-command-prompt.c +++ b/cmd-command-prompt.c @@ -107,12 +107,12 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item) cdata->item = item; if (pane) cdata->wp = wp; - cdata->state = args_make_commands_prepare(self, item, 0, "%1", wait, + cdata->state = args_command_prepare(self, item, 0, "%1", args_has(args, 'F')); if ((s = args_get(args, 'p')) == NULL) { if (count != 0) { - tmp = args_make_commands_get_command(cdata->state); + tmp = args_command_get_command(cdata->state); xasprintf(&prompts, "(%s)", tmp); free(tmp); } else { @@ -201,7 +201,7 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s, struct cmd_command_prompt_cdata *cdata = data; char *error; struct cmdq_item *item = cdata->item, *new_item; - struct cmd_list *cmdlist; + struct cmdq_state *cs; struct cmd_command_prompt_prompt *prompt; int argc = 0; char **argv = NULL; @@ -235,15 +235,15 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s, cdata->argv = cmd_copy_argv(argc, argv); } - cmdlist = args_make_commands(cdata->state, argc, argv, &error); - if (cmdlist == NULL) { + if (item != NULL) + cs = cmdq_get_state(item); + new_item = args_command_get(cdata->state, argc, argv, cs, &error); + if (new_item == NULL) { cmdq_append(c, cmdq_get_error(error)); free(error); } else if (item == NULL) { - new_item = cmdq_get_command(cmdlist, NULL); cmdq_append(c, new_item); } else { - new_item = cmdq_get_command(cmdlist, cmdq_get_state(item)); cmdq_insert_after(item, new_item); } cmd_free_argv(argc, argv); @@ -281,6 +281,6 @@ cmd_command_prompt_free(void *data) } free(cdata->prompts); cmd_free_argv(cdata->argc, cdata->argv); - args_make_commands_free(cdata->state); + args_command_free(cdata->state); free(cdata); } diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c index 54bc9a2a1..9c6326947 100644 --- a/cmd-confirm-before.c +++ b/cmd-confirm-before.c @@ -50,10 +50,10 @@ const struct cmd_entry cmd_confirm_before_entry = { }; struct cmd_confirm_before_data { - struct cmdq_item *item; - struct cmd_list *cmdlist; - u_char confirm_key; - int default_yes; + struct cmdq_item *item; + struct args_command_state *state; + u_char confirm_key; + int default_yes; }; static enum args_parse_type @@ -71,15 +71,12 @@ cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item) struct client *tc = cmdq_get_target_client(item); struct cmd_find_state *target = cmdq_get_target(item); char *new_prompt; - const char *confirm_key, *prompt, *cmd; + const char *confirm_key, *prompt; + char *cmd; int wait = !args_has(args, 'b'); cdata = xcalloc(1, sizeof *cdata); - cdata->cmdlist = args_make_commands_now(self, item, 0, 1); - if (cdata->cmdlist == NULL) { - free(cdata); - return (CMD_RETURN_ERROR); - } + cdata->state = args_command_prepare(self, item, 0, NULL, 1); if (wait) cdata->item = item; @@ -92,7 +89,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_list_free(cdata->cmdlist); + args_command_free(cdata->state); free(cdata); return (CMD_RETURN_ERROR); } @@ -103,9 +100,10 @@ cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item) if ((prompt = args_get(args, 'p')) != NULL) xasprintf(&new_prompt, "%s ", prompt); else { - cmd = cmd_get_entry(cmd_list_first(cdata->cmdlist))->name; + cmd = args_command_get_command(cdata->state); xasprintf(&new_prompt, "Confirm '%s'? (%c/n) ", cmd, cdata->confirm_key); + free(cmd); } status_prompt_set(tc, target, new_prompt, NULL, @@ -124,6 +122,7 @@ cmd_confirm_before_callback(struct client *c, void *data, const char *s, { struct cmd_confirm_before_data *cdata = data; struct cmdq_item *item = cdata->item, *new_item; + char *error; int retcode = 1; if (c->flags & CLIENT_DEAD) @@ -136,11 +135,22 @@ cmd_confirm_before_callback(struct client *c, void *data, const char *s, retcode = 0; if (item == NULL) { - new_item = cmdq_get_command(cdata->cmdlist, NULL); + new_item = args_command_get(cdata->state, 0, NULL, NULL, + &error); + if (new_item == NULL) { + cmdq_append(c, cmdq_get_error(error)); + free(error); + goto out; + } cmdq_append(c, new_item); } else { - new_item = cmdq_get_command(cdata->cmdlist, - cmdq_get_state(item)); + new_item = args_command_get(cdata->state, 0, NULL, + cmdq_get_state(item), &error); + if (new_item == NULL) { + cmdq_error(item, "%s", error); + free(error); + goto out; + } cmdq_insert_after(item, new_item); } @@ -159,6 +169,6 @@ cmd_confirm_before_free(void *data) { struct cmd_confirm_before_data *cdata = data; - cmd_list_free(cdata->cmdlist); + args_command_free(cdata->state); free(cdata); } diff --git a/cmd-display-panes.c b/cmd-display-panes.c index f8991dfe1..b2f56c488 100644 --- a/cmd-display-panes.c +++ b/cmd-display-panes.c @@ -297,7 +297,7 @@ cmd_display_panes_free(__unused struct client *c, void *data) if (cdata->item != NULL) cmdq_continue(cdata->item); - args_make_commands_free(cdata->state); + args_command_free(cdata->state); free(cdata); } @@ -307,7 +307,7 @@ cmd_display_panes_key(struct client *c, void *data, struct key_event *event) struct cmd_display_panes_data *cdata = data; char *expanded, *error; struct cmdq_item *item = cdata->item, *new_item; - struct cmd_list *cmdlist; + struct cmdq_state *cs = NULL; struct window *w = c->session->curw->window; struct window_pane *wp; u_int index; @@ -331,16 +331,18 @@ cmd_display_panes_key(struct client *c, void *data, struct key_event *event) xasprintf(&expanded, "%%%u", wp->id); - cmdlist = args_make_commands(cdata->state, 1, &expanded, &error); - if (cmdlist == NULL) { + if (item != NULL) + cs = cmdq_get_state(item); + new_item = args_command_get(cdata->state, 1, &expanded, cs, + &error); + if (new_item == NULL) { cmdq_append(c, cmdq_get_error(error)); free(error); - } else if (item == NULL) { - new_item = cmdq_get_command(cmdlist, NULL); - cmdq_append(c, new_item); } else { - new_item = cmdq_get_command(cmdlist, cmdq_get_state(item)); - cmdq_insert_after(item, new_item); + if (item == NULL) + cmdq_append(c, new_item); + else + cmdq_insert_after(item, new_item); } free(expanded); @@ -374,8 +376,8 @@ cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item) cdata = xcalloc(1, sizeof *cdata); if (wait) cdata->item = item; - cdata->state = args_make_commands_prepare(self, item, 0, - "select-pane -t \"%%%\"", wait, 0); + cdata->state = args_command_prepare(self, item, 0, + "select-pane -t \"%%%\"", 0); if (args_has(args, 'N')) { server_client_set_overlay(tc, delay, NULL, NULL, diff --git a/cmd-if-shell.c b/cmd-if-shell.c index f0c3637cc..3cd9829ad 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -79,35 +79,32 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) char *shellcmd; struct client *tc = cmdq_get_target_client(item); struct session *s = target->s; - struct cmd_list *cmdlist; u_int count = args_count(args); int wait = !args_has(args, 'b'); shellcmd = format_single_from_target(item, args_string(args, 0)); if (args_has(args, 'F')) { if (*shellcmd != '0' && *shellcmd != '\0') - cmdlist = args_make_commands_now(self, item, 1, 0); + new_item = args_command_now(self, item, 1, 0); else if (count == 3) - cmdlist = args_make_commands_now(self, item, 2, 0); + new_item = args_command_now(self, item, 2, 0); else { free(shellcmd); return (CMD_RETURN_NORMAL); } free(shellcmd); - if (cmdlist == NULL) + if (new_item == NULL) return (CMD_RETURN_ERROR); - new_item = cmdq_get_command(cmdlist, cmdq_get_state(item)); cmdq_insert_after(item, new_item); return (CMD_RETURN_NORMAL); } cdata = xcalloc(1, sizeof *cdata); - cdata->cmd_if = args_make_commands_prepare(self, item, 1, NULL, wait, - 0); + cdata->cmd_if = args_command_prepare(self, item, 1, NULL, 0); if (count == 3) { - cdata->cmd_else = args_make_commands_prepare(self, item, 2, - NULL, wait, 0); + cdata->cmd_else = args_command_prepare(self, item, 2, + NULL, 0); } if (wait) { @@ -140,8 +137,8 @@ cmd_if_shell_callback(struct job *job) struct cmd_if_shell_data *cdata = job_get_data(job); struct client *c = cdata->client; struct cmdq_item *item = cdata->item, *new_item; + struct cmdq_state *cs = NULL; struct args_command_state *state; - struct cmd_list *cmdlist; char *error; int status; @@ -153,20 +150,22 @@ cmd_if_shell_callback(struct job *job) if (state == NULL) goto out; - cmdlist = args_make_commands(state, 0, NULL, &error); - if (cmdlist == NULL) { - if (cdata->item == NULL) { + if (item != NULL) + cs = cmdq_get_state(item); + new_item = args_command_get(state, 0, NULL, cs, &error); + if (new_item == NULL) { + if (cdata->item != NULL) + cmdq_error(cdata->item, "%s", error); + else { *error = toupper((u_char)*error); status_message_set(c, -1, 1, 0, 0, "%s", error); - } else - cmdq_error(cdata->item, "%s", error); + } free(error); - } else if (item == NULL) { - new_item = cmdq_get_command(cmdlist, NULL); - cmdq_append(c, new_item); } else { - new_item = cmdq_get_command(cmdlist, cmdq_get_state(item)); - cmdq_insert_after(item, new_item); + if (item == NULL) + cmdq_append(c, new_item); + else + cmdq_insert_after(item, new_item); } out: @@ -183,8 +182,8 @@ cmd_if_shell_free(void *data) server_client_unref(cdata->client); if (cdata->cmd_else != NULL) - args_make_commands_free(cdata->cmd_else); - args_make_commands_free(cdata->cmd_if); + args_command_free(cdata->cmd_else); + args_command_free(cdata->cmd_if); free(cdata); } diff --git a/cmd-run-shell.c b/cmd-run-shell.c index 6114f68a1..547c44b95 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -144,8 +144,8 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item) format_free(ft); } } else { - cdata->state = args_make_commands_prepare(self, item, 0, NULL, - wait, 1); + cdata->state = args_command_prepare(self, item, 0, NULL, + 1); } if (args_has(args, 't') && wp != NULL) @@ -195,7 +195,7 @@ cmd_run_shell_timer(__unused int fd, __unused short events, void* arg) struct client *c = cdata->client; const char *cmd = cdata->cmd; struct cmdq_item *item = cdata->item, *new_item; - struct cmd_list *cmdlist; + struct cmdq_state *cs = NULL; char *error; if (cdata->state == NULL) { @@ -221,20 +221,22 @@ cmd_run_shell_timer(__unused int fd, __unused short events, void* arg) return; } - cmdlist = args_make_commands(cdata->state, 0, NULL, &error); - if (cmdlist == NULL) { - if (cdata->item == NULL) { + if (item != NULL) + cs = cmdq_get_state(item); + new_item = args_command_get(cdata->state, 0, NULL, cs, &error); + if (new_item == NULL) { + if (cdata->item != NULL) + cmdq_error(cdata->item, "%s", error); + else { *error = toupper((u_char)*error); status_message_set(c, -1, 1, 0, 0, "%s", error); - } else - cmdq_error(cdata->item, "%s", error); + } free(error); - } else if (item == NULL) { - new_item = cmdq_get_command(cmdlist, NULL); - cmdq_append(c, new_item); } else { - new_item = cmdq_get_command(cmdlist, cmdq_get_state(item)); - cmdq_insert_after(item, new_item); + if (item == NULL) + cmdq_append(c, new_item); + else + cmdq_insert_after(item, new_item); } if (cdata->item != NULL) @@ -304,7 +306,7 @@ cmd_run_shell_free(void *data) if (cdata->client != NULL) server_client_unref(cdata->client); if (cdata->state != NULL) - args_make_commands_free(cdata->state); + args_command_free(cdata->state); free(cdata->cwd); free(cdata->cmd); free(cdata); diff --git a/tmux.h b/tmux.h index 1fbddd7c5..dd2dd60c0 100644 --- a/tmux.h +++ b/tmux.h @@ -2898,14 +2898,14 @@ u_int args_count(struct args *); struct args_value *args_values(struct args *); struct args_value *args_value(struct args *, u_int); const char *args_string(struct args *, u_int); -struct cmd_list *args_make_commands_now(struct cmd *, struct cmdq_item *, +struct cmdq_item *args_command_now(struct cmd *, struct cmdq_item *, u_int, int); -struct args_command_state *args_make_commands_prepare(struct cmd *, - struct cmdq_item *, u_int, const char *, int, int); -struct cmd_list *args_make_commands(struct args_command_state *, int, char **, - char **); -void args_make_commands_free(struct args_command_state *); -char *args_make_commands_get_command(struct args_command_state *); +struct args_command_state *args_command_prepare(struct cmd *, + struct cmdq_item *, u_int, const char *, int); +struct cmdq_item *args_command_get(struct args_command_state *, int, char **, + struct cmdq_state *, char **); +void args_command_free(struct args_command_state *); +char *args_command_get_command(struct args_command_state *); struct args_value *args_first_value(struct args *, u_char); struct args_value *args_next_value(struct args_value *); long long args_strtonum(struct args *, u_char, long long, long long,