From 5f32b7d9613e9ef3f8198302379a42630323da6a Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 20 Aug 2021 19:50:16 +0000 Subject: [PATCH] Hide struct args behind a couple of accessor functions. --- arguments.c | 62 ++++++++++----- cmd-bind-key.c | 20 +++-- cmd-command-prompt.c | 33 ++++---- cmd-confirm-before.c | 12 +-- cmd-display-menu.c | 52 +++++++------ cmd-display-message.c | 13 ++-- cmd-display-panes.c | 4 +- cmd-find-window.c | 2 +- cmd-if-shell.c | 21 +++-- cmd-list-keys.c | 17 ++--- cmd-load-buffer.c | 2 +- cmd-new-session.c | 14 ++-- cmd-new-window.c | 13 ++-- cmd-pipe-pane.c | 4 +- cmd-queue.c | 6 +- cmd-refresh-client.c | 5 +- cmd-rename-session.c | 2 +- cmd-rename-window.c | 2 +- cmd-resize-pane.c | 5 +- cmd-resize-window.c | 5 +- cmd-respawn-pane.c | 10 ++- cmd-respawn-window.c | 10 ++- cmd-run-shell.c | 7 +- cmd-save-buffer.c | 2 +- cmd-select-layout.c | 18 ++--- cmd-send-keys.c | 10 +-- cmd-set-buffer.c | 6 +- cmd-set-environment.c | 19 ++--- cmd-set-option.c | 20 +++-- cmd-show-environment.c | 8 +- cmd-show-options.c | 4 +- cmd-source-file.c | 20 ++--- cmd-split-window.c | 17 +++-- cmd-unbind-key.c | 10 +-- cmd-wait-for.c | 8 +- cmd.c | 7 +- tmux.h | 10 +-- window-buffer.c | 4 +- window-client.c | 4 +- window-copy.c | 169 +++++++++++++++++++++-------------------- window-tree.c | 4 +- 41 files changed, 355 insertions(+), 306 deletions(-) diff --git a/arguments.c b/arguments.c index 142f86d8..0867f815 100644 --- a/arguments.c +++ b/arguments.c @@ -38,6 +38,12 @@ struct args_entry { RB_ENTRY(args_entry) entry; }; +struct args { + struct args_tree tree; + int argc; + char **argv; +}; + static struct args_entry *args_find(struct args *, u_char); static int args_cmp(struct args_entry *, struct args_entry *); @@ -73,7 +79,7 @@ args_create(void) /* Parse an argv and argc into a new argument set. */ struct args * -args_parse(const char *template, int argc, char **argv) +args_parse(const char *template, int argc, char **argv, int lower, int upper) { struct args *args; int opt; @@ -99,6 +105,10 @@ args_parse(const char *template, int argc, char **argv) args->argc = argc; args->argv = cmd_copy_argv(argc, argv); + if ((lower != -1 && argc < lower) || (upper != -1 && argc > upper)) { + args_free(args); + return (NULL); + } return (args); } @@ -126,6 +136,14 @@ args_free(struct args *args) free(args); } +/* Convert arguments to vector. */ +void +args_vector(struct args *args, int *argc, char ***argv) +{ + *argc = args->argc; + *argv = cmd_copy_argv(args->argc, args->argv); +} + /* Add to string. */ static void printflike(3, 4) args_print_add(char **buf, size_t *len, const char *fmt, ...) @@ -145,23 +163,6 @@ args_print_add(char **buf, size_t *len, const char *fmt, ...) free(s); } -/* Add value to string. */ -static void -args_print_add_value(char **buf, size_t *len, struct args_entry *entry, - struct args_value *value) -{ - char *escaped; - - if (**buf != '\0') - args_print_add(buf, len, " -%c ", entry->flag); - else - args_print_add(buf, len, "-%c ", entry->flag); - - escaped = args_escape(value->value); - args_print_add(buf, len, "%s", escaped); - free(escaped); -} - /* Add argument to string. */ static void args_print_add_argument(char **buf, size_t *len, const char *argument) @@ -203,8 +204,13 @@ args_print(struct args *args) /* Then the flags with arguments. */ RB_FOREACH(entry, args_tree, &args->tree) { - TAILQ_FOREACH(value, &entry->values, entry) - args_print_add_value(&buf, &len, entry, value); + TAILQ_FOREACH(value, &entry->values, entry) { + if (*buf != '\0') + args_print_add(&buf, &len, " -%c", entry->flag); + else + args_print_add(&buf, &len, "-%c", entry->flag); + args_print_add_argument(&buf, &len, value->value); + } } /* And finally the argument vector. */ @@ -330,6 +336,22 @@ args_next(struct args_entry **entry) return ((*entry)->flag); } +/* Get argument count. */ +u_int +args_count(struct args *args) +{ + return (args->argc); +} + +/* Return argument as string. */ +const char * +args_string(struct args *args, u_int idx) +{ + if (idx >= (u_int)args->argc) + return (NULL); + return (args->argv[idx]); +} + /* Get first value in argument. */ struct args_value * args_first_value(struct args *args, u_char flag) diff --git a/cmd-bind-key.c b/cmd-bind-key.c index b4e4167c..87dd3cf7 100644 --- a/cmd-bind-key.c +++ b/cmd-bind-key.c @@ -48,12 +48,13 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item) key_code key; const char *tablename, *note = args_get(args, 'N'); struct cmd_parse_result *pr; - char **argv = args->argv; - int argc = args->argc, repeat; + char **argv; + int argc, repeat; + u_int count = args_count(args); - key = key_string_lookup_string(argv[0]); + key = key_string_lookup_string(args_string(args, 0)); if (key == KEYC_NONE || key == KEYC_UNKNOWN) { - cmdq_error(item, "unknown key: %s", argv[0]); + cmdq_error(item, "unknown key: %s", args_string(args, 0)); return (CMD_RETURN_ERROR); } @@ -65,11 +66,14 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item) tablename = "prefix"; repeat = args_has(args, 'r'); - if (argc != 1) { - if (argc == 2) - pr = cmd_parse_from_string(argv[1], NULL); - else + if (count != 1) { + if (count == 2) + pr = cmd_parse_from_string(args_string(args, 1), NULL); + else { + args_vector(args, &argc, &argv); pr = cmd_parse_from_arguments(argc - 1, argv + 1, NULL); + cmd_free_argv(argc, argv); + } switch (pr->status) { case CMD_PARSE_EMPTY: cmdq_error(item, "empty command"); diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c index 4943bc15..25ec6817 100644 --- a/cmd-command-prompt.c +++ b/cmd-command-prompt.c @@ -71,9 +71,10 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item) struct args *args = cmd_get_args(self); struct client *tc = cmdq_get_target_client(item); struct cmd_find_state *target = cmdq_get_target(item); - const char *inputs, *prompts, *type; + const char *inputs, *prompts, *type, *s; struct cmd_command_prompt_cdata *cdata; - char *prompt, *ptr, *input = NULL; + char *prompt, *comma, *input = NULL; + u_int count = args_count(args); size_t n; int wait = !args_has(args, 'b'); @@ -94,28 +95,30 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item) if (wait) cdata->item = item; - if (args->argc != 0 && args_has(args, 'F')) - cdata->template = format_single_from_target(item, args->argv[0]); - else if (args->argc != 0) - cdata->template = xstrdup(args->argv[0]); - else + if (count != 0) { + s = args_string(args, 0); + if (args_has(args, 'F')) + cdata->template = format_single_from_target(item, s); + else + cdata->template = xstrdup(s); + } else cdata->template = xstrdup("%1"); if ((prompts = args_get(args, 'p')) != NULL) cdata->prompts = xstrdup(prompts); - else if (args->argc != 0) { + else if (count != 0) { n = strcspn(cdata->template, " ,"); - xasprintf(&cdata->prompts, "(%.*s) ", (int) n, cdata->template); + xasprintf(&cdata->prompts, "(%.*s) ", (int)n, cdata->template); } else cdata->prompts = xstrdup(":"); /* Get first prompt. */ cdata->next_prompt = cdata->prompts; - ptr = strsep(&cdata->next_prompt, ","); + comma = strsep(&cdata->next_prompt, ","); if (prompts == NULL) - prompt = xstrdup(ptr); + prompt = xstrdup(comma); else - xasprintf(&prompt, "%s ", ptr); + xasprintf(&prompt, "%s ", comma); /* Get initial prompt input. */ if ((inputs = args_get(args, 'I')) != NULL) { @@ -157,7 +160,7 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s, int done) { struct cmd_command_prompt_cdata *cdata = data; - char *new_template, *prompt, *ptr, *error; + char *new_template, *prompt, *comma, *error; char *input = NULL; struct cmdq_item *item = cdata->item; enum cmd_parse_status status; @@ -177,8 +180,8 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s, * Check if there are more prompts; if so, get its respective input * and update the prompt data. */ - if (done && (ptr = strsep(&cdata->next_prompt, ",")) != NULL) { - xasprintf(&prompt, "%s ", ptr); + if (done && (comma = strsep(&cdata->next_prompt, ",")) != NULL) { + xasprintf(&prompt, "%s ", comma); input = strsep(&cdata->next_input, ","); status_prompt_update(c, prompt, input); diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c index 51c2fe8e..9f179aaf 100644 --- a/cmd-confirm-before.c +++ b/cmd-confirm-before.c @@ -59,22 +59,22 @@ cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item) struct cmd_confirm_before_data *cdata; struct client *tc = cmdq_get_target_client(item); struct cmd_find_state *target = cmdq_get_target(item); - char *cmd, *copy, *new_prompt, *ptr; + char *cmd, *copy, *new_prompt, *tmp; const char *prompt; int wait = !args_has(args, 'b'); + cdata = xcalloc(1, sizeof *cdata); + cdata->cmd = xstrdup(args_string(args, 0)); + if ((prompt = args_get(args, 'p')) != NULL) xasprintf(&new_prompt, "%s ", prompt); else { - ptr = copy = xstrdup(args->argv[0]); - cmd = strsep(&ptr, " \t"); + tmp = copy = xstrdup(cdata->cmd); + cmd = strsep(&tmp, " \t"); xasprintf(&new_prompt, "Confirm '%s'? (y/n) ", cmd); free(copy); } - cdata = xcalloc(1, sizeof *cdata); - cdata->cmd = xstrdup(args->argv[0]); - cmd_get_source(self, &cdata->pi.file, &cdata->pi.line); if (wait) cdata->pi.item = item; diff --git a/cmd-display-menu.c b/cmd-display-menu.c index c774284c..a8eda0d2 100644 --- a/cmd-display-menu.c +++ b/cmd-display-menu.c @@ -261,10 +261,10 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) struct client *tc = cmdq_get_target_client(item); struct menu *menu = NULL; struct menu_item menu_item; - const char *key; - char *title, *name; - int flags = 0, i; - u_int px, py; + const char *key, *name; + char *title; + int flags = 0; + u_int px, py, i, count = args_count(args); if (tc->overlay_draw != NULL) return (CMD_RETURN_NORMAL); @@ -275,24 +275,24 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) title = xstrdup(""); menu = menu_create(title); - for (i = 0; i != args->argc; /* nothing */) { - name = args->argv[i++]; + for (i = 0; i != count; /* nothing */) { + name = args_string(args, i++); if (*name == '\0') { menu_add_item(menu, NULL, item, tc, target); continue; } - if (args->argc - i < 2) { + if (count - i < 2) { cmdq_error(item, "not enough arguments"); free(title); menu_free(menu); return (CMD_RETURN_ERROR); } - key = args->argv[i++]; + key = args_string(args, i++); menu_item.name = name; menu_item.key = key_string_lookup_string(key); - menu_item.command = args->argv[i++]; + menu_item.command = args_string(args, i++); menu_add_item(menu, &menu_item, item, tc, target); } @@ -329,11 +329,10 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) struct session *s = target->s; struct client *tc = cmdq_get_target_client(item); struct tty *tty = &tc->tty; - const char *value, *shell[] = { NULL, NULL }; - const char *shellcmd = NULL; - char *cwd, *cause, **argv = args->argv; - int flags = 0, argc = args->argc; - u_int px, py, w, h; + const char *value, *shell, *shellcmd = NULL; + char *cwd, *cause, **argv = NULL; + int flags = 0, argc = 0; + u_int px, py, w, h, count = args_count(args); if (args_has(args, 'C')) { server_client_clear_overlay(tc); @@ -374,18 +373,18 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) cwd = format_single_from_target(item, value); else cwd = xstrdup(server_client_get_cwd(tc, s)); - if (argc == 0) + if (count == 0) shellcmd = options_get_string(s->options, "default-command"); - else if (argc == 1) - shellcmd = argv[0]; - if (argc <= 1 && (shellcmd == NULL || *shellcmd == '\0')) { + else if (count == 1) + shellcmd = args_string(args, 0); + if (count <= 1 && (shellcmd == NULL || *shellcmd == '\0')) { shellcmd = NULL; - shell[0] = options_get_string(s->options, "default-shell"); - if (!checkshell(shell[0])) - shell[0] = _PATH_BSHELL; - argc = 1; - argv = (char**)shell; - } + shell = options_get_string(s->options, "default-shell"); + if (!checkshell(shell)) + shell = _PATH_BSHELL; + cmd_append_argv(&argc, &argv, shell); + } else + args_vector(args, &argc, &argv); if (args_has(args, 'E') > 1) flags |= POPUP_CLOSEEXITZERO; @@ -394,7 +393,10 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) if (args_has(args, 'B')) flags |= POPUP_NOBORDER; if (popup_display(flags, item, px, py, w, h, shellcmd, argc, argv, cwd, - tc, s, NULL, NULL) != 0) + tc, s, NULL, NULL) != 0) { + cmd_free_argv(argc, argv); return (CMD_RETURN_NORMAL); + } + cmd_free_argv(argc, argv); return (CMD_RETURN_WAIT); } diff --git a/cmd-display-message.c b/cmd-display-message.c index 8fd6a8ff..f4d41e6c 100644 --- a/cmd-display-message.c +++ b/cmd-display-message.c @@ -68,9 +68,9 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item) struct window_pane *wp = target->wp; const char *template; char *msg, *cause; - int delay = -1; + int delay = -1, flags; struct format_tree *ft; - int flags; + u_int count = args_count(args); if (args_has(args, 'I')) { if (wp == NULL) @@ -83,7 +83,7 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_WAIT); } - if (args_has(args, 'F') && args->argc != 0) { + if (args_has(args, 'F') && count != 0) { cmdq_error(item, "only one of -F or argument must be given"); return (CMD_RETURN_ERROR); } @@ -97,9 +97,10 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item) } } - template = args_get(args, 'F'); - if (args->argc != 0) - template = args->argv[0]; + if (count != 0) + template = args_string(args, 0); + else + template = args_get(args, 'F'); if (template == NULL) template = DISPLAY_MESSAGE_TEMPLATE; diff --git a/cmd-display-panes.c b/cmd-display-panes.c index beadae53..59484872 100644 --- a/cmd-display-panes.c +++ b/cmd-display-panes.c @@ -276,8 +276,8 @@ cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item) delay = options_get_number(s->options, "display-panes-time"); cdata = xmalloc(sizeof *cdata); - if (args->argc != 0) - cdata->command = xstrdup(args->argv[0]); + if (args_count(args)) + cdata->command = xstrdup(args_string(args, 0)); else cdata->command = xstrdup("select-pane -t '%%'"); if (args_has(args, 'b')) diff --git a/cmd-find-window.c b/cmd-find-window.c index 43f5f9be..691baf85 100644 --- a/cmd-find-window.c +++ b/cmd-find-window.c @@ -47,7 +47,7 @@ cmd_find_window_exec(struct cmd *self, struct cmdq_item *item) struct args *args = cmd_get_args(self), *new_args; struct cmd_find_state *target = cmdq_get_target(item); struct window_pane *wp = target->wp; - const char *s = args->argv[0], *suffix = ""; + const char *s = args_string(args, 0), *suffix = ""; char *filter; int C, N, T; diff --git a/cmd-if-shell.c b/cmd-if-shell.c index f4c81074..df06a0b6 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -65,21 +65,20 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) struct cmd_find_state *target = cmdq_get_target(item); struct cmdq_state *state = cmdq_get_state(item); struct cmd_if_shell_data *cdata; - char *shellcmd, *cmd, *error; - const char *file; + char *shellcmd, *error; + const char *cmd = NULL, *file; struct client *tc = cmdq_get_target_client(item); struct session *s = target->s; struct cmd_parse_input pi; enum cmd_parse_status status; + u_int count = args_count(args); - shellcmd = format_single_from_target(item, args->argv[0]); + shellcmd = format_single_from_target(item, args_string(args, 0)); if (args_has(args, 'F')) { if (*shellcmd != '0' && *shellcmd != '\0') - cmd = args->argv[1]; - else if (args->argc == 3) - cmd = args->argv[2]; - else - cmd = NULL; + cmd = args_string(args, 1); + else if (count == 3) + cmd = args_string(args, 2); free(shellcmd); if (cmd == NULL) return (CMD_RETURN_NORMAL); @@ -101,9 +100,9 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) cdata = xcalloc(1, sizeof *cdata); - cdata->cmd_if = xstrdup(args->argv[1]); - if (args->argc == 3) - cdata->cmd_else = xstrdup(args->argv[2]); + cdata->cmd_if = xstrdup(args_string(args, 1)); + if (count == 3) + cdata->cmd_else = xstrdup(args_string(args, 2)); if (!args_has(args, 'b')) cdata->client = cmdq_get_client(item); diff --git a/cmd-list-keys.c b/cmd-list-keys.c index dbb510fb..1484af6d 100644 --- a/cmd-list-keys.c +++ b/cmd-list-keys.c @@ -150,7 +150,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item) struct args *args = cmd_get_args(self); struct key_table *table; struct key_binding *bd; - const char *tablename, *r; + const char *tablename, *r, *keystr; char *key, *cp, *tmp, *start, *empty; key_code prefix, only = KEYC_UNKNOWN; int repeat, width, tablewidth, keywidth, found = 0; @@ -159,10 +159,10 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item) if (cmd_get_entry(self) == &cmd_list_commands_entry) return (cmd_list_keys_commands(self, item)); - if (args->argc != 0) { - only = key_string_lookup_string(args->argv[0]); + if ((keystr = args_string(args, 0)) != NULL) { + only = key_string_lookup_string(keystr); if (only == KEYC_UNKNOWN) { - cmdq_error(item, "invalid key: %s", args->argv[0]); + cmdq_error(item, "invalid key: %s", keystr); return (CMD_RETURN_ERROR); } only &= (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS); @@ -243,6 +243,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item) tmpsize = 256; tmp = xmalloc(tmpsize); + table = key_bindings_first_table(); while (table != NULL) { if (tablename != NULL && strcmp(table->name, tablename) != 0) { @@ -307,7 +308,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item) out: if (only != KEYC_UNKNOWN && !found) { - cmdq_error(item, "unknown key: %s", args->argv[0]); + cmdq_error(item, "unknown key: %s", args_string(args, 0)); return (CMD_RETURN_ERROR); } return (CMD_RETURN_NORMAL); @@ -320,12 +321,9 @@ cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item) const struct cmd_entry **entryp; const struct cmd_entry *entry; struct format_tree *ft; - const char *template, *s, *command = NULL; + const char *template, *s, *command; char *line; - if (args->argc != 0) - command = args->argv[0]; - if ((template = args_get(args, 'F')) == NULL) { template = "#{command_list_name}" "#{?command_list_alias, (#{command_list_alias}),} " @@ -335,6 +333,7 @@ cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item) ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0); format_defaults(ft, NULL, NULL, NULL, NULL); + command = args_string(args, 0); for (entryp = cmd_table; *entryp != NULL; entryp++) { entry = *entryp; if (command != NULL && diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c index bca9a860..318a7467 100644 --- a/cmd-load-buffer.c +++ b/cmd-load-buffer.c @@ -105,7 +105,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item) cdata->client->references++; } - path = format_single_from_target(item, args->argv[0]); + path = format_single_from_target(item, args_string(args, 0)); file_read(cmdq_get_client(item), path, cmd_load_buffer_done, cdata); free(path); diff --git a/cmd-new-session.c b/cmd-new-session.c index 79b756bf..0cc6b9da 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -79,8 +79,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) char *cause, *cwd = NULL, *cp, *newname = NULL; char *name, *prefix = NULL; int detached, already_attached, is_control = 0; - u_int sx, sy, dsx, dsy; - struct spawn_context sc; + u_int sx, sy, dsx, dsy, count = args_count(args); + struct spawn_context sc = { 0 }; enum cmd_retval retval; struct cmd_find_state fs; struct args_value *av; @@ -93,7 +93,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_NORMAL); } - if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) { + if (args_has(args, 't') && (count != 0 || args_has(args, 'n'))) { cmdq_error(item, "command or window name given with target"); return (CMD_RETURN_ERROR); } @@ -277,15 +277,13 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) s = session_create(prefix, newname, cwd, env, oo, tiop); /* Spawn the initial window. */ - memset(&sc, 0, sizeof sc); sc.item = item; sc.s = s; if (!detached) sc.tc = c; sc.name = args_get(args, 'n'); - sc.argc = args->argc; - sc.argv = args->argv; + args_vector(args, &sc.argc, &sc.argv); sc.idx = -1; sc.cwd = args_get(args, 'c'); @@ -358,12 +356,16 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) cmd_find_from_session(&fs, s, 0); cmdq_insert_hook(s, item, &fs, "after-new-session"); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); free(cwd); free(newname); free(prefix); return (CMD_RETURN_NORMAL); fail: + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); free(cwd); free(newname); free(prefix); diff --git a/cmd-new-window.c b/cmd-new-window.c index a9156a6f..f24de8e9 100644 --- a/cmd-new-window.c +++ b/cmd-new-window.c @@ -55,12 +55,11 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item) struct client *c = cmdq_get_client(item); struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state *target = cmdq_get_target(item); - struct spawn_context sc; + struct spawn_context sc = { 0 }; struct client *tc = cmdq_get_target_client(item); struct session *s = target->s; - struct winlink *wl = target->wl; + struct winlink *wl = target->wl, *new_wl = NULL; int idx = target->idx, before; - struct winlink *new_wl = NULL; char *cause = NULL, *cp; const char *template, *name; struct cmd_find_state fs; @@ -101,14 +100,12 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item) idx = target->idx; } - memset(&sc, 0, sizeof sc); sc.item = item; sc.s = s; sc.tc = tc; sc.name = args_get(args, 'n'); - sc.argc = args->argc; - sc.argv = args->argv; + args_vector(args, &sc.argc, &sc.argv); sc.environ = environ_create(); av = args_first_value(args, 'e'); @@ -129,6 +126,8 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item) if ((new_wl = spawn_window(&sc, &cause)) == NULL) { cmdq_error(item, "create window failed: %s", cause); free(cause); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); environ_free(sc.environ); return (CMD_RETURN_ERROR); } @@ -150,6 +149,8 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item) cmd_find_from_winlink(&fs, new_wl, 0); cmdq_insert_hook(s, item, &fs, "after-new-window"); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); environ_free(sc.environ); return (CMD_RETURN_NORMAL); } diff --git a/cmd-pipe-pane.c b/cmd-pipe-pane.c index 0a518e1b..d1917bc6 100644 --- a/cmd-pipe-pane.c +++ b/cmd-pipe-pane.c @@ -82,7 +82,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item) } /* If no pipe command, that is enough. */ - if (args->argc == 0 || *args->argv[0] == '\0') + if (args_count(args) == 0 || *args_string(args, 0) == '\0') return (CMD_RETURN_NORMAL); /* @@ -112,7 +112,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item) /* Expand the command. */ ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0); format_defaults(ft, tc, s, wl, wp); - cmd = format_expand_time(ft, args->argv[0]); + cmd = format_expand_time(ft, args_string(args, 0)); format_free(ft); /* Fork the child. */ diff --git a/cmd-queue.c b/cmd-queue.c index 198a2a43..687d037f 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -357,7 +357,7 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item, struct options *oo; va_list ap; char *name, tmp[32], flag, *arguments; - int i; + u_int i; const char *value; struct cmdq_item *new_item; struct cmdq_state *new_state; @@ -394,9 +394,9 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item, cmdq_add_format(new_state, "hook_arguments", "%s", arguments); free(arguments); - for (i = 0; i < args->argc; i++) { + for (i = 0; i < args_count(args); i++) { xsnprintf(tmp, sizeof tmp, "hook_argument_%d", i); - cmdq_add_format(new_state, tmp, "%s", args->argv[i]); + cmdq_add_format(new_state, tmp, "%s", args_string(args, i)); } flag = args_first(args, &ae); while (flag != 0) { diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c index 22efb38b..93845024 100644 --- a/cmd-refresh-client.c +++ b/cmd-refresh-client.c @@ -127,10 +127,11 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item) args_has(args, 'U') || args_has(args, 'D')) { - if (args->argc == 0) + if (args_count(args) == 0) adjust = 1; else { - adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr); + adjust = strtonum(args_string(args, 0), 1, INT_MAX, + &errstr); if (errstr != NULL) { cmdq_error(item, "adjustment %s", errstr); return (CMD_RETURN_ERROR); diff --git a/cmd-rename-session.c b/cmd-rename-session.c index 49fafe33..8ec070bf 100644 --- a/cmd-rename-session.c +++ b/cmd-rename-session.c @@ -51,7 +51,7 @@ cmd_rename_session_exec(struct cmd *self, struct cmdq_item *item) struct session *s = target->s; char *newname, *tmp; - tmp = format_single_from_target(item, args->argv[0]); + tmp = format_single_from_target(item, args_string(args, 0)); newname = session_check_name(tmp); if (newname == NULL) { cmdq_error(item, "invalid session: %s", tmp); diff --git a/cmd-rename-window.c b/cmd-rename-window.c index 593e0b9e..66c119f2 100644 --- a/cmd-rename-window.c +++ b/cmd-rename-window.c @@ -50,7 +50,7 @@ cmd_rename_window_exec(struct cmd *self, struct cmdq_item *item) struct winlink *wl = target->wl; char *newname; - newname = format_single_from_target(item, args->argv[0]); + newname = format_single_from_target(item, args_string(args, 0)); window_set_name(wl->window, newname); options_set_number(wl->window->options, "automatic-rename", 0); diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c index 94e060d0..98d500db 100644 --- a/cmd-resize-pane.c +++ b/cmd-resize-pane.c @@ -95,10 +95,11 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item) } server_unzoom_window(w); - if (args->argc == 0) + if (args_count(args) == 0) adjust = 1; else { - adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr); + adjust = strtonum(args_string(args, 0), 1, INT_MAX, + &errstr); if (errstr != NULL) { cmdq_error(item, "adjustment %s", errstr); return (CMD_RETURN_ERROR); diff --git a/cmd-resize-window.c b/cmd-resize-window.c index 1ebb7aca..3e33f771 100644 --- a/cmd-resize-window.c +++ b/cmd-resize-window.c @@ -56,10 +56,11 @@ cmd_resize_window_exec(struct cmd *self, struct cmdq_item *item) u_int adjust, sx, sy; int xpixel = -1, ypixel = -1; - if (args->argc == 0) + if (args_count(args) == 0) adjust = 1; else { - adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr); + adjust = strtonum(args_string(args, 0), 1, INT_MAX, + &errstr); if (errstr != NULL) { cmdq_error(item, "adjustment %s", errstr); return (CMD_RETURN_ERROR); diff --git a/cmd-respawn-pane.c b/cmd-respawn-pane.c index 8d938c5e..14f9abf2 100644 --- a/cmd-respawn-pane.c +++ b/cmd-respawn-pane.c @@ -49,14 +49,13 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); struct cmd_find_state *target = cmdq_get_target(item); - struct spawn_context sc; + struct spawn_context sc = { 0 }; struct session *s = target->s; struct winlink *wl = target->wl; struct window_pane *wp = target->wp; char *cause = NULL; struct args_value *av; - memset(&sc, 0, sizeof sc); sc.item = item; sc.s = s; sc.wl = wl; @@ -65,8 +64,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item) sc.lc = NULL; sc.name = NULL; - sc.argc = args->argc; - sc.argv = args->argv; + args_vector(args, &sc.argc, &sc.argv); sc.environ = environ_create(); av = args_first_value(args, 'e'); @@ -85,6 +83,8 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item) if (spawn_pane(&sc, &cause) == NULL) { cmdq_error(item, "respawn pane failed: %s", cause); free(cause); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); environ_free(sc.environ); return (CMD_RETURN_ERROR); } @@ -93,6 +93,8 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item) server_redraw_window_borders(wp->window); server_status_window(wp->window); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); environ_free(sc.environ); return (CMD_RETURN_NORMAL); } diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c index da3ecee4..25288bad 100644 --- a/cmd-respawn-window.c +++ b/cmd-respawn-window.c @@ -49,22 +49,20 @@ cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); struct cmd_find_state *target = cmdq_get_target(item); - struct spawn_context sc; + struct spawn_context sc = { 0 }; struct client *tc = cmdq_get_target_client(item); struct session *s = target->s; struct winlink *wl = target->wl; char *cause = NULL; struct args_value *av; - memset(&sc, 0, sizeof sc); sc.item = item; sc.s = s; sc.wl = wl; sc.tc = tc; sc.name = NULL; - sc.argc = args->argc; - sc.argv = args->argv; + args_vector(args, &sc.argc, &sc.argv); sc.environ = environ_create(); av = args_first_value(args, 'e'); @@ -83,12 +81,16 @@ cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item) if (spawn_window(&sc, &cause) == NULL) { cmdq_error(item, "respawn window failed: %s", cause); free(cause); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); environ_free(sc.environ); return (CMD_RETURN_ERROR); } server_redraw_window(wl->window); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); environ_free(sc.environ); return (CMD_RETURN_NORMAL); } diff --git a/cmd-run-shell.c b/cmd-run-shell.c index 7bc1d7cc..a0115f0a 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -104,6 +104,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item) double d; struct timeval tv; char *end; + const char *cmd = args_string(args, 0); int wait = !args_has(args, 'b'); if ((delay = args_get(args, 'd')) != NULL) { @@ -112,12 +113,12 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item) cmdq_error(item, "invalid delay time: %s", delay); return (CMD_RETURN_ERROR); } - } else if (args->argc == 0) + } else if (args_count(args) == 0) return (CMD_RETURN_NORMAL); cdata = xcalloc(1, sizeof *cdata); - if (args->argc != 0) - cdata->cmd = format_single_from_target(item, args->argv[0]); + if (cmd != NULL) + cdata->cmd = format_single_from_target(item, cmd); cdata->shell = !args_has(args, 'C'); if (!cdata->shell) { diff --git a/cmd-save-buffer.c b/cmd-save-buffer.c index 7f161a91..f897af24 100644 --- a/cmd-save-buffer.c +++ b/cmd-save-buffer.c @@ -105,7 +105,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmdq_item *item) } path = xstrdup("-"); } else - path = format_single_from_target(item, args->argv[0]); + path = format_single_from_target(item, args_string(args, 0)); if (args_has(args, 'a')) flags = O_APPEND; else diff --git a/cmd-select-layout.c b/cmd-select-layout.c index 7069eccc..f9a29047 100644 --- a/cmd-select-layout.c +++ b/cmd-select-layout.c @@ -105,24 +105,24 @@ cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item) goto changed; } + if (args_count(args) != 0) + layoutname = args_string(args, 0); + else if (args_has(args, 'o')) + layoutname = oldlayout; + else + layoutname = NULL; + if (!args_has(args, 'o')) { - if (args->argc == 0) + if (layoutname == NULL) layout = w->lastlayout; else - layout = layout_set_lookup(args->argv[0]); + layout = layout_set_lookup(layoutname); if (layout != -1) { layout_set_select(w, layout); goto changed; } } - if (args->argc != 0) - layoutname = args->argv[0]; - else if (args_has(args, 'o')) - layoutname = oldlayout; - else - layoutname = NULL; - if (layoutname != NULL) { if (layout_parse(w, layoutname) == -1) { cmdq_error(item, "can't set layout: %s", layoutname); diff --git a/cmd-send-keys.c b/cmd-send-keys.c index c51d413b..351bd919 100644 --- a/cmd-send-keys.c +++ b/cmd-send-keys.c @@ -90,7 +90,7 @@ static struct cmdq_item * cmd_send_keys_inject_string(struct cmdq_item *item, struct cmdq_item *after, struct args *args, int i) { - const char *s = args->argv[i]; + const char *s = args_string(args, i); struct utf8_data *ud, *loop; utf8_char uc; key_code key; @@ -145,9 +145,9 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item) struct mouse_event *m = &event->m; struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes); struct cmdq_item *after = item; - int i; key_code key; - u_int np = 1; + u_int i, np = 1; + u_int count = args_count(args); char *cause = NULL; if (args_has(args, 'N')) { @@ -157,7 +157,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item) free(cause); return (CMD_RETURN_ERROR); } - if (wme != NULL && (args_has(args, 'X') || args->argc == 0)) { + if (wme != NULL && (args_has(args, 'X') || count == 0)) { if (wme->mode->command == NULL) { cmdq_error(item, "not in a mode"); return (CMD_RETURN_ERROR); @@ -203,7 +203,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item) } for (; np != 0; np--) { - for (i = 0; i < args->argc; i++) { + for (i = 0; i < count; i++) { after = cmd_send_keys_inject_string(item, after, args, i); } diff --git a/cmd-set-buffer.c b/cmd-set-buffer.c index 94d8cd52..3005e62d 100644 --- a/cmd-set-buffer.c +++ b/cmd-set-buffer.c @@ -94,11 +94,11 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_NORMAL); } - if (args->argc != 1) { + if (args_count(args) != 1) { cmdq_error(item, "no data specified"); return (CMD_RETURN_ERROR); } - if ((newsize = strlen(args->argv[0])) == 0) + if ((newsize = strlen(args_string(args, 0))) == 0) return (CMD_RETURN_NORMAL); bufsize = 0; @@ -111,7 +111,7 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item) } bufdata = xrealloc(bufdata, bufsize + newsize); - memcpy(bufdata + bufsize, args->argv[0], newsize); + memcpy(bufdata + bufsize, args_string(args, 0), newsize); bufsize += newsize; if (paste_set(bufdata, bufsize, bufname, &cause) != 0) { diff --git a/cmd-set-environment.c b/cmd-set-environment.c index f142df53..e60240a8 100644 --- a/cmd-set-environment.c +++ b/cmd-set-environment.c @@ -49,11 +49,11 @@ cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item) struct args *args = cmd_get_args(self); struct cmd_find_state *target = cmdq_get_target(item); struct environ *env; - const char *name, *value, *tflag; - char *expand = NULL; + const char *name = args_string(args, 0), *value; + const char *tflag; + char *expanded = NULL; enum cmd_retval retval = CMD_RETURN_NORMAL; - name = args->argv[0]; if (*name == '\0') { cmdq_error(item, "empty variable name"); return (CMD_RETURN_ERROR); @@ -63,13 +63,14 @@ cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_ERROR); } - if (args->argc < 2) + if (args_count(args) < 2) value = NULL; - else if (args_has(args, 'F')) - value = expand = format_single_from_target(item, args->argv[1]); else - value = args->argv[1]; - + value = args_string(args, 1); + if (value != NULL && args_has(args, 'F')) { + expanded = format_single_from_target(item, value); + value = expanded; + } if (args_has(args, 'g')) env = global_environ; else { @@ -113,6 +114,6 @@ cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item) } out: - free(expand); + free(expanded); return (retval); } diff --git a/cmd-set-option.c b/cmd-set-option.c index 70e3c54d..48e04eed 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -77,14 +77,16 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item) struct window_pane *loop; struct options *oo; struct options_entry *parent, *o, *po; - char *name, *argument, *value = NULL, *cause; + char *name, *argument, *expanded = NULL; + char *cause; + const char *value; int window, idx, already, error, ambiguous; int scope; window = (cmd_get_entry(self) == &cmd_set_window_option_entry); /* Expand argument. */ - argument = format_single_from_target(item, args->argv[0]); + argument = format_single_from_target(item, args_string(args, 0)); /* If set-hook -R, fire the hook straight away. */ if (cmd_get_entry(self) == &cmd_set_hook_entry && args_has(args, 'R')) { @@ -104,12 +106,14 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item) cmdq_error(item, "invalid option: %s", argument); goto fail; } - if (args->argc < 2) + if (args_count(args) < 2) value = NULL; - else if (args_has(args, 'F')) - value = format_single_from_target(item, args->argv[1]); else - value = xstrdup(args->argv[1]); + value = args_string(args, 1); + if (value != NULL && args_has(args, 'F')) { + expanded = format_single_from_target(item, value); + value = expanded; + } /* Get the scope and table for the option .*/ scope = options_scope_from_name(args, window, name, target, &oo, @@ -211,13 +215,13 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item) out: free(argument); - free(value); + free(expanded); free(name); return (CMD_RETURN_NORMAL); fail: free(argument); - free(value); + free(expanded); free(name); return (CMD_RETURN_ERROR); } diff --git a/cmd-show-environment.c b/cmd-show-environment.c index 3ad31400..7ea1aeec 100644 --- a/cmd-show-environment.c +++ b/cmd-show-environment.c @@ -101,7 +101,7 @@ cmd_show_environment_exec(struct cmd *self, struct cmdq_item *item) struct cmd_find_state *target = cmdq_get_target(item); struct environ *env; struct environ_entry *envent; - const char *tflag; + const char *tflag, *name = args_string(args, 0); if ((tflag = args_get(args, 't')) != NULL) { if (target->s == NULL) { @@ -124,10 +124,10 @@ cmd_show_environment_exec(struct cmd *self, struct cmdq_item *item) env = target->s->environ; } - if (args->argc != 0) { - envent = environ_find(env, args->argv[0]); + if (name != NULL) { + envent = environ_find(env, name); if (envent == NULL) { - cmdq_error(item, "unknown variable: %s", args->argv[0]); + cmdq_error(item, "unknown variable: %s", name); return (CMD_RETURN_ERROR); } cmd_show_environment_print(self, item, envent); diff --git a/cmd-show-options.c b/cmd-show-options.c index a9c5bd2a..4d0acb42 100644 --- a/cmd-show-options.c +++ b/cmd-show-options.c @@ -86,7 +86,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item) window = (cmd_get_entry(self) == &cmd_show_window_options_entry); - if (args->argc == 0) { + if (args_count(args) == 0) { scope = options_scope_from_flags(args, window, target, &oo, &cause); if (scope == OPTIONS_TABLE_NONE) { @@ -98,7 +98,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item) } return (cmd_show_options_all(self, item, scope, oo)); } - argument = format_single_from_target(item, args->argv[0]); + argument = format_single_from_target(item, args_string(args, 0)); name = options_match(argument, &idx, &ambiguous); if (name == NULL) { diff --git a/cmd-source-file.c b/cmd-source-file.c index 5509259f..edc66c3f 100644 --- a/cmd-source-file.c +++ b/cmd-source-file.c @@ -129,11 +129,11 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item) struct cmd_source_file_data *cdata; struct client *c = cmdq_get_client(item); enum cmd_retval retval = CMD_RETURN_NORMAL; - char *pattern, *cwd, *expand = NULL; + char *pattern, *cwd, *expanded = NULL; const char *path, *error; glob_t g; - int i, result; - u_int j; + int result; + u_int i, j; cdata = xcalloc(1, sizeof *cdata); cdata->item = item; @@ -147,13 +147,13 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item) utf8_stravis(&cwd, server_client_get_cwd(c, NULL), VIS_GLOB); - for (i = 0; i < args->argc; i++) { + for (i = 0; i < args_count(args); i++) { + path = args_string(args, i); if (args_has(args, 'F')) { - free(expand); - expand = format_single_from_target(item, args->argv[i]); - path = expand; - } else - path = args->argv[i]; + free(expanded); + expanded = format_single_from_target(item, path); + path = expanded; + } if (strcmp(path, "-") == 0) { cmd_source_file_add(cdata, "-"); continue; @@ -180,7 +180,7 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item) free(pattern); continue; } - free(expand); + free(expanded); free(pattern); for (j = 0; j < g.gl_pathc; j++) diff --git a/cmd-split-window.c b/cmd-split-window.c index ae36561f..baf75327 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -56,7 +56,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) struct args *args = cmd_get_args(self); struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state *target = cmdq_get_target(item); - struct spawn_context sc; + struct spawn_context sc = { 0 }; struct client *tc = cmdq_get_target_client(item); struct session *s = target->s; struct winlink *wl = target->wl; @@ -69,6 +69,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) char *cause, *cp, *copy; size_t plen; struct args_value *av; + u_int count = args_count(args); if (args_has(args, 'h')) type = LAYOUT_LEFTRIGHT; @@ -112,14 +113,14 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) size = -1; window_push_zoom(wp->window, 1, args_has(args, 'Z')); - input = (args_has(args, 'I') && args->argc == 0); + input = (args_has(args, 'I') && count == 0); flags = 0; if (args_has(args, 'b')) flags |= SPAWN_BEFORE; if (args_has(args, 'f')) flags |= SPAWN_FULLSIZE; - if (input || (args->argc == 1 && *args->argv[0] == '\0')) + if (input || (count == 1 && *args_string(args, 0) == '\0')) flags |= SPAWN_EMPTY; lc = layout_split_pane(wp, type, size, flags); @@ -128,7 +129,6 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_ERROR); } - memset(&sc, 0, sizeof sc); sc.item = item; sc.s = s; sc.wl = wl; @@ -137,8 +137,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) sc.lc = lc; sc.name = NULL; - sc.argc = args->argc; - sc.argv = args->argv; + args_vector(args, &sc.argc, &sc.argv); sc.environ = environ_create(); av = args_first_value(args, 'e'); @@ -159,6 +158,8 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) if ((new_wp = spawn_pane(&sc, &cause)) == NULL) { cmdq_error(item, "create pane failed: %s", cause); free(cause); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); environ_free(sc.environ); return (CMD_RETURN_ERROR); } @@ -168,6 +169,8 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) window_remove_pane(wp->window, new_wp); cmdq_error(item, "%s", cause); free(cause); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); environ_free(sc.environ); return (CMD_RETURN_ERROR); } @@ -188,6 +191,8 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) cmd_find_from_winlink_pane(&fs, wl, new_wp, 0); cmdq_insert_hook(s, item, &fs, "after-split-window"); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); environ_free(sc.environ); if (input) return (CMD_RETURN_WAIT); diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c index a29831af..202a07f4 100644 --- a/cmd-unbind-key.c +++ b/cmd-unbind-key.c @@ -44,11 +44,11 @@ cmd_unbind_key_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); key_code key; - const char *tablename; + const char *tablename, *keystr = args_string(args, 0); int quiet = args_has(args, 'q'); if (args_has(args, 'a')) { - if (args->argc != 0) { + if (keystr != NULL) { if (!quiet) cmdq_error(item, "key given with -a"); return (CMD_RETURN_ERROR); @@ -73,16 +73,16 @@ cmd_unbind_key_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_NORMAL); } - if (args->argc != 1) { + if (keystr == NULL) { if (!quiet) cmdq_error(item, "missing key"); return (CMD_RETURN_ERROR); } - key = key_string_lookup_string(args->argv[0]); + key = key_string_lookup_string(keystr); if (key == KEYC_NONE || key == KEYC_UNKNOWN) { if (!quiet) - cmdq_error(item, "unknown key: %s", args->argv[0]); + cmdq_error(item, "unknown key: %s", keystr); return (CMD_RETURN_ERROR); } diff --git a/cmd-wait-for.c b/cmd-wait-for.c index 807a661a..027700b4 100644 --- a/cmd-wait-for.c +++ b/cmd-wait-for.c @@ -121,11 +121,11 @@ static enum cmd_retval cmd_wait_for_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - const char *name = args->argv[0]; - struct wait_channel *wc, wc0; + const char *name = args_string(args, 0); + struct wait_channel *wc, find; - wc0.name = name; - wc = RB_FIND(wait_channels, &wait_channels, &wc0); + find.name = name; + wc = RB_FIND(wait_channels, &wait_channels, &find); if (args_has(args, 'S')) return (cmd_wait_for_signal(item, name, wc)); diff --git a/cmd.c b/cmd.c index a26c523b..4f13e90e 100644 --- a/cmd.c +++ b/cmd.c @@ -518,13 +518,10 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause) return (NULL); cmd_log_argv(argc, argv, "%s: %s", __func__, entry->name); - args = args_parse(entry->args.template, argc, argv); + args = args_parse(entry->args.template, argc, argv, entry->args.lower, + entry->args.upper); if (args == NULL) goto usage; - if (entry->args.lower != -1 && args->argc < entry->args.lower) - goto usage; - if (entry->args.upper != -1 && args->argc > entry->args.upper) - goto usage; cmd = xcalloc(1, sizeof *cmd); cmd->entry = entry; diff --git a/tmux.h b/tmux.h index ae0ffc24..a28deb74 100644 --- a/tmux.h +++ b/tmux.h @@ -1364,11 +1364,6 @@ struct args_value { /* Arguments set. */ struct args_entry; RB_HEAD(args_tree, args_entry); -struct args { - struct args_tree tree; - int argc; - char **argv; -}; /* Command find structures. */ enum cmd_find_type { @@ -2188,7 +2183,8 @@ int tty_keys_next(struct tty *); /* arguments.c */ void args_set(struct args *, u_char, const char *); struct args *args_create(void); -struct args *args_parse(const char *, int, char **); +struct args *args_parse(const char *, int, char **, int, int); +void args_vector(struct args *, int *, char ***); void args_free(struct args *); char *args_print(struct args *); char *args_escape(const char *); @@ -2196,6 +2192,8 @@ int args_has(struct args *, u_char); const char *args_get(struct args *, u_char); u_char args_first(struct args *, struct args_entry **); u_char args_next(struct args_entry **); +u_int args_count(struct args *); +const char *args_string(struct args *, u_int); 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, diff --git a/window-buffer.c b/window-buffer.c index 30bd5092..a2fa08ad 100644 --- a/window-buffer.c +++ b/window-buffer.c @@ -343,10 +343,10 @@ window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs, data->key_format = xstrdup(WINDOW_BUFFER_DEFAULT_KEY_FORMAT); else data->key_format = xstrdup(args_get(args, 'K')); - if (args == NULL || args->argc == 0) + if (args == NULL || args_count(args) == 0) data->command = xstrdup(WINDOW_BUFFER_DEFAULT_COMMAND); else - data->command = xstrdup(args->argv[0]); + data->command = xstrdup(args_string(args, 0)); data->data = mode_tree_start(wp, args, window_buffer_build, window_buffer_draw, window_buffer_search, window_buffer_menu, NULL, diff --git a/window-client.c b/window-client.c index db7c6dcc..00f36c7c 100644 --- a/window-client.c +++ b/window-client.c @@ -303,10 +303,10 @@ window_client_init(struct window_mode_entry *wme, data->key_format = xstrdup(WINDOW_CLIENT_DEFAULT_KEY_FORMAT); else data->key_format = xstrdup(args_get(args, 'K')); - if (args == NULL || args->argc == 0) + if (args == NULL || args_count(args) == 0) data->command = xstrdup(WINDOW_CLIENT_DEFAULT_COMMAND); else - data->command = xstrdup(args->argv[0]); + data->command = xstrdup(args_string(args, 0)); data->data = mode_tree_start(wp, args, window_client_build, window_client_draw, NULL, window_client_menu, NULL, diff --git a/window-copy.c b/window-copy.c index 7c342d90..3e08c039 100644 --- a/window-copy.c +++ b/window-copy.c @@ -842,26 +842,23 @@ window_copy_expand_search_string(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; - const char *argument; + const char *ss = args_string(cs->args, 1); char *expanded; - if (cs->args->argc == 2) { - argument = cs->args->argv[1]; - if (*argument != '\0') { - if (args_has(cs->args, 'F')) { - expanded = format_single(NULL, argument, NULL, - NULL, NULL, wme->wp); - if (*expanded == '\0') { - free(expanded); - return (0); - } - free(data->searchstr); - data->searchstr = expanded; - } else { - free(data->searchstr); - data->searchstr = xstrdup(argument); - } + if (ss == NULL || *ss == '\0') + return (0); + + if (args_has(cs->args, 'F')) { + expanded = format_single(NULL, ss, NULL, NULL, NULL, wme->wp); + if (*expanded == '\0') { + free(expanded); + return (0); } + free(data->searchstr); + data->searchstr = expanded; + } else { + free(data->searchstr); + data->searchstr = xstrdup(ss); } return (1); } @@ -963,24 +960,25 @@ window_copy_do_copy_end_of_line(struct window_copy_cmd_state *cs, int pipe, int cancel) { struct window_mode_entry *wme = cs->wme; - int argc = cs->args->argc; - char **argv = cs->args->argv; struct client *c = cs->c; struct session *s = cs->s; struct winlink *wl = cs->wl; struct window_pane *wp = wme->wp; + u_int count = args_count(cs->args); u_int np = wme->prefix, ocx, ocy, ooy; struct window_copy_mode_data *data = wme->data; char *prefix = NULL, *command = NULL; + const char *arg1 = args_string(cs->args, 1); + const char *arg2 = args_string(cs->args, 2); if (pipe) { - if (argc == 3) - prefix = format_single(NULL, argv[2], c, s, wl, wp); - if (s != NULL && argc > 1 && *argv[1] != '\0') - command = format_single(NULL, argv[1], c, s, wl, wp); + if (count == 3) + prefix = format_single(NULL, arg2, c, s, wl, wp); + if (s != NULL && count > 1 && *arg1 != '\0') + command = format_single(NULL, arg1, c, s, wl, wp); } else { - if (argc == 2) - prefix = format_single(NULL, argv[1], c, s, wl, wp); + if (count == 2) + prefix = format_single(NULL, arg1, c, s, wl, wp); } ocx = data->cx; @@ -1044,24 +1042,25 @@ static enum window_copy_cmd_action window_copy_do_copy_line(struct window_copy_cmd_state *cs, int pipe, int cancel) { struct window_mode_entry *wme = cs->wme; - int argc = cs->args->argc; - char **argv = cs->args->argv; struct client *c = cs->c; struct session *s = cs->s; struct winlink *wl = cs->wl; struct window_pane *wp = wme->wp; struct window_copy_mode_data *data = wme->data; + u_int count = args_count(cs->args); u_int np = wme->prefix, ocx, ocy, ooy; char *prefix = NULL, *command = NULL; + const char *arg1 = args_string(cs->args, 1); + const char *arg2 = args_string(cs->args, 2); if (pipe) { - if (argc == 3) - prefix = format_single(NULL, argv[2], c, s, wl, wp); - if (s != NULL && argc > 1 && *argv[1] != '\0') - command = format_single(NULL, argv[1], c, s, wl, wp); + if (count == 3) + prefix = format_single(NULL, arg2, c, s, wl, wp); + if (s != NULL && count > 1 && *arg1 != '\0') + command = format_single(NULL, arg1, c, s, wl, wp); } else { - if (argc == 2) - prefix = format_single(NULL, argv[1], c, s, wl, wp); + if (count == 2) + prefix = format_single(NULL, arg1, c, s, wl, wp); } ocx = data->cx; @@ -1131,9 +1130,10 @@ window_copy_cmd_copy_selection_no_clear(struct window_copy_cmd_state *cs) struct winlink *wl = cs->wl; struct window_pane *wp = wme->wp; char *prefix = NULL; + const char *arg1 = args_string(cs->args, 1); - if (cs->args->argc == 2) - prefix = format_single(NULL, cs->args->argv[1], c, s, wl, wp); + if (arg1 != NULL) + prefix = format_single(NULL, arg1, c, s, wl, wp); if (s != NULL) window_copy_copy_selection(wme, prefix); @@ -1968,14 +1968,15 @@ window_copy_cmd_copy_pipe_no_clear(struct window_copy_cmd_state *cs) struct session *s = cs->s; struct winlink *wl = cs->wl; struct window_pane *wp = wme->wp; - char *command = NULL; - char *prefix = NULL; + char *command = NULL, *prefix = NULL; + const char *arg1 = args_string(cs->args, 1); + const char *arg2 = args_string(cs->args, 2); - if (cs->args->argc == 3) - prefix = format_single(NULL, cs->args->argv[2], c, s, wl, wp); + if (arg2 != NULL) + prefix = format_single(NULL, arg2, c, s, wl, wp); - if (s != NULL && cs->args->argc > 1 && *cs->args->argv[1] != '\0') - command = format_single(NULL, cs->args->argv[1], c, s, wl, wp); + if (s != NULL && arg1 != NULL && *arg1 != '\0') + command = format_single(NULL, arg1, c, s, wl, wp); window_copy_copy_pipe(wme, s, prefix, command); free(command); @@ -2012,9 +2013,10 @@ window_copy_cmd_pipe_no_clear(struct window_copy_cmd_state *cs) struct winlink *wl = cs->wl; struct window_pane *wp = wme->wp; char *command = NULL; + const char *arg1 = args_string(cs->args, 1); - if (s != NULL && cs->args->argc > 1 && *cs->args->argv[1] != '\0') - command = format_single(NULL, cs->args->argv[1], c, s, wl, wp); + if (s != NULL && arg1 != NULL && *arg1 != '\0') + command = format_single(NULL, arg1, c, s, wl, wp); window_copy_pipe(wme, s, command); free(command); @@ -2045,10 +2047,10 @@ static enum window_copy_cmd_action window_copy_cmd_goto_line(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); - if (*argument != '\0') - window_copy_goto_line(wme, argument); + if (*arg1 != '\0') + window_copy_goto_line(wme, arg1); return (WINDOW_COPY_CMD_NOTHING); } @@ -2058,12 +2060,12 @@ window_copy_cmd_jump_backward(struct window_copy_cmd_state *cs) struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; u_int np = wme->prefix; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); - if (*argument != '\0') { + if (*arg1 != '\0') { data->jumptype = WINDOW_COPY_JUMPBACKWARD; free(data->jumpchar); - data->jumpchar = utf8_fromcstr(argument); + data->jumpchar = utf8_fromcstr(arg1); for (; np != 0; np--) window_copy_cursor_jump_back(wme); } @@ -2076,12 +2078,12 @@ window_copy_cmd_jump_forward(struct window_copy_cmd_state *cs) struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; u_int np = wme->prefix; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); - if (*argument != '\0') { + if (*arg1 != '\0') { data->jumptype = WINDOW_COPY_JUMPFORWARD; free(data->jumpchar); - data->jumpchar = utf8_fromcstr(argument); + data->jumpchar = utf8_fromcstr(arg1); for (; np != 0; np--) window_copy_cursor_jump(wme); } @@ -2094,12 +2096,12 @@ window_copy_cmd_jump_to_backward(struct window_copy_cmd_state *cs) struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; u_int np = wme->prefix; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); - if (*argument != '\0') { + if (*arg1 != '\0') { data->jumptype = WINDOW_COPY_JUMPTOBACKWARD; free(data->jumpchar); - data->jumpchar = utf8_fromcstr(argument); + data->jumpchar = utf8_fromcstr(arg1); for (; np != 0; np--) window_copy_cursor_jump_to_back(wme); } @@ -2112,12 +2114,12 @@ window_copy_cmd_jump_to_forward(struct window_copy_cmd_state *cs) struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; u_int np = wme->prefix; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); - if (*argument != '\0') { + if (*arg1 != '\0') { data->jumptype = WINDOW_COPY_JUMPTOFORWARD; free(data->jumpchar); - data->jumpchar = utf8_fromcstr(argument); + data->jumpchar = utf8_fromcstr(arg1); for (; np != 0; np--) window_copy_cursor_jump_to(wme); } @@ -2218,27 +2220,27 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); const char *ss = data->searchstr; char prefix; enum window_copy_cmd_action action = WINDOW_COPY_CMD_NOTHING; data->timeout = 0; - log_debug("%s: %s", __func__, argument); + log_debug("%s: %s", __func__, arg1); - prefix = *argument++; + prefix = *arg1++; if (data->searchx == -1 || data->searchy == -1) { data->searchx = data->cx; data->searchy = data->cy; data->searcho = data->oy; - } else if (ss != NULL && strcmp(argument, ss) != 0) { + } else if (ss != NULL && strcmp(arg1, ss) != 0) { data->cx = data->searchx; data->cy = data->searchy; data->oy = data->searcho; action = WINDOW_COPY_CMD_REDRAW; } - if (*argument == '\0') { + if (*arg1 == '\0') { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); } @@ -2248,7 +2250,7 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs) data->searchtype = WINDOW_COPY_SEARCHUP; data->searchregex = 0; free(data->searchstr); - data->searchstr = xstrdup(argument); + data->searchstr = xstrdup(arg1); if (!window_copy_search_up(wme, 0)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); @@ -2258,7 +2260,7 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs) data->searchtype = WINDOW_COPY_SEARCHDOWN; data->searchregex = 0; free(data->searchstr); - data->searchstr = xstrdup(argument); + data->searchstr = xstrdup(arg1); if (!window_copy_search_down(wme, 0)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); @@ -2273,27 +2275,27 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); const char *ss = data->searchstr; char prefix; enum window_copy_cmd_action action = WINDOW_COPY_CMD_NOTHING; data->timeout = 0; - log_debug("%s: %s", __func__, argument); + log_debug("%s: %s", __func__, arg1); - prefix = *argument++; + prefix = *arg1++; if (data->searchx == -1 || data->searchy == -1) { data->searchx = data->cx; data->searchy = data->cy; data->searcho = data->oy; - } else if (ss != NULL && strcmp(argument, ss) != 0) { + } else if (ss != NULL && strcmp(arg1, ss) != 0) { data->cx = data->searchx; data->cy = data->searchy; data->oy = data->searcho; action = WINDOW_COPY_CMD_REDRAW; } - if (*argument == '\0') { + if (*arg1 == '\0') { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); } @@ -2303,7 +2305,7 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs) data->searchtype = WINDOW_COPY_SEARCHDOWN; data->searchregex = 0; free(data->searchstr); - data->searchstr = xstrdup(argument); + data->searchstr = xstrdup(arg1); if (!window_copy_search_down(wme, 0)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); @@ -2313,7 +2315,7 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs) data->searchtype = WINDOW_COPY_SEARCHUP; data->searchregex = 0; free(data->searchstr); - data->searchstr = xstrdup(argument); + data->searchstr = xstrdup(arg1); if (!window_copy_search_up(wme, 0)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); @@ -2342,8 +2344,8 @@ window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs) static const struct { const char *command; - int minargs; - int maxargs; + u_int minargs; + u_int maxargs; enum window_copy_cmd_clear clear; enum window_copy_cmd_action (*f)(struct window_copy_cmd_state *); } window_copy_cmd_table[] = { @@ -2833,13 +2835,12 @@ window_copy_command(struct window_mode_entry *wme, struct client *c, enum window_copy_cmd_action action; enum window_copy_cmd_clear clear = WINDOW_COPY_CMD_CLEAR_NEVER; const char *command; - u_int i; + u_int i, count = args_count(args); int keys; - if (args->argc == 0) + if (count == 0) return; - command = args->argv[0]; - + command = args_string(args, 0); if (m != NULL && m->valid && !MOUSE_WHEEL(m->b)) window_copy_move_mouse(m); @@ -2854,8 +2855,8 @@ window_copy_command(struct window_mode_entry *wme, struct client *c, action = WINDOW_COPY_CMD_NOTHING; for (i = 0; i < nitems(window_copy_cmd_table); i++) { if (strcmp(window_copy_cmd_table[i].command, command) == 0) { - if (args->argc - 1 < window_copy_cmd_table[i].minargs || - args->argc - 1 > window_copy_cmd_table[i].maxargs) + if (count - 1 < window_copy_cmd_table[i].minargs || + count - 1 > window_copy_cmd_table[i].maxargs) break; clear = window_copy_cmd_table[i].clear; action = window_copy_cmd_table[i].f(&cs); @@ -5188,14 +5189,16 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme, const char *separators, int already) { struct window_copy_mode_data *data = wme->data; + struct window *w = wme->wp->window; struct screen *back_s = data->backing; struct grid_reader gr; u_int px, py, oldy, hsize; int stop_at_eol; - stop_at_eol = - options_get_number(wme->wp->window->options, "mode-keys") - == MODEKEY_EMACS; + if (options_get_number(w->options, "mode-keys") == MODEKEY_EMACS) + stop_at_eol = 1; + else + stop_at_eol = 0; px = data->cx; hsize = screen_hsize(back_s); diff --git a/window-tree.c b/window-tree.c index f8e38399..e7029d33 100644 --- a/window-tree.c +++ b/window-tree.c @@ -925,10 +925,10 @@ window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs, data->key_format = xstrdup(WINDOW_TREE_DEFAULT_KEY_FORMAT); else data->key_format = xstrdup(args_get(args, 'K')); - if (args == NULL || args->argc == 0) + if (args == NULL || args_count(args) == 0) data->command = xstrdup(WINDOW_TREE_DEFAULT_COMMAND); else - data->command = xstrdup(args->argv[0]); + data->command = xstrdup(args_string(args, 0)); data->squash_groups = !args_has(args, 'G'); data->data = mode_tree_start(wp, args, window_tree_build,