From 68db9584777fd40f6100e7944992a021f6e40c71 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 16 Jan 2017 14:49:14 +0000 Subject: [PATCH] getopt() has a struct option so just return to using options_entry. --- client.c | 15 +++---- cmd-set-option.c | 8 ++-- cmd-show-options.c | 16 +++---- cmd-string.c | 94 +++++++++++++++++++++++++--------------- cmd.c | 68 +++++++++++++++++++++++++++-- format.c | 2 +- key-bindings.c | 2 +- options-table.c | 7 +++ options.c | 106 ++++++++++++++++++++++----------------------- tmux.h | 53 ++++++++++++----------- 10 files changed, 230 insertions(+), 141 deletions(-) diff --git a/client.c b/client.c index 551a01b2..c7774177 100644 --- a/client.c +++ b/client.c @@ -252,16 +252,13 @@ client_main(struct event_base *base, int argc, char **argv, int flags, * flag. */ cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause); - if (cmdlist == NULL) { - fprintf(stderr, "%s\n", cause); - return (1); + if (cmdlist != NULL) { + TAILQ_FOREACH(cmd, &cmdlist->list, qentry) { + if (cmd->entry->flags & CMD_STARTSERVER) + cmdflags |= CMD_STARTSERVER; + } + cmd_list_free(cmdlist); } - cmdflags &= ~CMD_STARTSERVER; - TAILQ_FOREACH(cmd, &cmdlist->list, qentry) { - if (cmd->entry->flags & CMD_STARTSERVER) - cmdflags |= CMD_STARTSERVER; - } - cmd_list_free(cmdlist); } /* Create client process structure (starts logging). */ diff --git a/cmd-set-option.c b/cmd-set-option.c index 475b91c2..ef2ce10b 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -30,7 +30,7 @@ static enum cmd_retval cmd_set_option_exec(struct cmd *, struct cmdq_item *); static int cmd_set_option_set(struct cmd *, struct cmdq_item *, - struct options *, struct option *, const char *); + struct options *, struct options_entry *, const char *); static int cmd_set_option_flag(struct cmdq_item *, const struct options_table_entry *, struct options *, const char *); @@ -75,7 +75,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item) struct client *c; enum options_table_scope scope; struct options *oo; - struct option *parent, *o; + struct options_entry *parent, *o; const char *name, *value, *target; int window, idx, already, error, ambiguous; char *cause; @@ -256,12 +256,12 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item) static int cmd_set_option_set(struct cmd *self, struct cmdq_item *item, struct options *oo, - struct option *parent, const char *value) + struct options_entry *parent, const char *value) { const struct options_table_entry *oe; struct args *args = self->args; int append = args_has(args, 'a'); - struct option *o; + struct options_entry *o; long long number; const char *errstr; key_code key; diff --git a/cmd-show-options.c b/cmd-show-options.c index 67a70330..b9bfe5ee 100644 --- a/cmd-show-options.c +++ b/cmd-show-options.c @@ -87,7 +87,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item) static void cmd_show_options_print(struct cmd *self, struct cmdq_item *item, - struct option *o, int idx) + struct options_entry *o, int idx) { const char *name; const char *value; @@ -118,10 +118,10 @@ static enum cmd_retval cmd_show_options_one(struct cmd *self, struct cmdq_item *item, struct options *oo) { - struct args *args = self->args; - struct option *o; - int idx, ambiguous; - const char *name = args->argv[0]; + struct args *args = self->args; + struct options_entry *o; + int idx, ambiguous; + const char *name = args->argv[0]; o = options_match_get(oo, name, &idx, 1, &ambiguous); if (o == NULL) { @@ -144,9 +144,9 @@ static enum cmd_retval cmd_show_options_all(struct cmd *self, struct cmdq_item *item, struct options *oo) { - struct option *o; - const struct options_table_entry *oe; - u_int size, idx; + struct options_entry *o; + const struct options_table_entry *oe; + u_int size, idx; o = options_first(oo); while (o != NULL) { diff --git a/cmd-string.c b/cmd-string.c index 1b96b280..822d35b5 100644 --- a/cmd-string.c +++ b/cmd-string.c @@ -54,17 +54,15 @@ cmd_string_ungetc(size_t *p) (*p)--; } -struct cmd_list * -cmd_string_parse(const char *s, const char *file, u_int line, char **cause) +int +cmd_string_split(const char *s, int *rargc, char ***rargv) { - size_t p = 0; - int ch, i, argc = 0; - char **argv = NULL, *buf = NULL, *t; - const char *whitespace, *equals; - size_t len = 0; - struct cmd_list *cmdlist = NULL; + size_t p = 0; + int ch, argc = 0, append = 0; + char **argv = NULL, *buf = NULL, *t; + const char *whitespace, *equals; + size_t len = 0; - *cause = NULL; for (;;) { ch = cmd_string_getc(s, &p); switch (ch) { @@ -115,43 +113,67 @@ cmd_string_parse(const char *s, const char *file, u_int line, char **cause) argc--; memmove(argv, argv + 1, argc * (sizeof *argv)); } - if (argc == 0) - goto out; - - cmdlist = cmd_list_parse(argc, argv, file, line, cause); - goto out; + goto done; case '~': - if (buf == NULL) { - t = cmd_string_expand_tilde(s, &p); - if (t == NULL) - goto error; - cmd_string_copy(&buf, t, &len); + if (buf != NULL) { + append = 1; break; } - /* FALLTHROUGH */ - default: - if (len >= SIZE_MAX - 2) + t = cmd_string_expand_tilde(s, &p); + if (t == NULL) goto error; - - buf = xrealloc(buf, len + 1); - buf[len++] = ch; + cmd_string_copy(&buf, t, &len); + break; + default: + append = 1; break; } + if (append) { + if (len >= SIZE_MAX - 2) + goto error; + buf = xrealloc(buf, len + 1); + buf[len++] = ch; + } + append = 0; } +done: + *rargc = argc; + *rargv = argv; + + free(buf); + return (0); + +error: + if (argv != NULL) + cmd_free_argv(argc, argv); + free(buf); + return (-1); +} + +struct cmd_list * +cmd_string_parse(const char *s, const char *file, u_int line, char **cause) +{ + struct cmd_list *cmdlist = NULL; + int argc; + char **argv; + + *cause = NULL; + if (cmd_string_split(s, &argc, &argv) != 0) + goto error; + if (argc != 0) { + cmdlist = cmd_list_parse(argc, argv, file, line, cause); + if (cmdlist == NULL) { + cmd_free_argv(argc, argv); + goto error; + } + } + cmd_free_argv(argc, argv); + return (cmdlist); + error: xasprintf(cause, "invalid or unknown command: %s", s); - -out: - free(buf); - - if (argv != NULL) { - for (i = 0; i < argc; i++) - free(argv[i]); - free(argv); - } - - return (cmdlist); + return (NULL); } static void diff --git a/cmd.c b/cmd.c index 9119f7ac..07dd57bd 100644 --- a/cmd.c +++ b/cmd.c @@ -308,21 +308,74 @@ cmd_stringify_argv(int argc, char **argv) return (buf); } +static int +cmd_try_alias(int *argc, char ***argv) +{ + struct options_entry *o; + int old_argc = *argc, new_argc; + char **old_argv = *argv, **new_argv; + u_int size, idx; + int i; + size_t wanted; + const char *s, *cp = NULL; + + o = options_get_only(global_options, "command-alias"); + if (o == NULL || options_array_size(o, &size) == -1 || size == 0) + return (-1); + + wanted = strlen(old_argv[0]); + for (idx = 0; idx < size; idx++) { + s = options_array_get(o, idx); + if (s == NULL) + continue; + + cp = strchr(s, '='); + if (cp == NULL || (size_t)(cp - s) != wanted) + continue; + if (strncmp(old_argv[0], s, wanted) == 0) + break; + } + if (idx == size) + return (-1); + + if (cmd_string_split(cp + 1, &new_argc, &new_argv) != 0) + return (-1); + + *argc = new_argc + old_argc - 1; + *argv = xcalloc((*argc) + 1, sizeof **argv); + + for (i = 0; i < new_argc; i++) + (*argv)[i] = xstrdup(new_argv[i]); + for (i = 1; i < old_argc; i++) + (*argv)[new_argc + i - 1] = xstrdup(old_argv[i]); + + log_debug("alias: %s=%s", old_argv[0], cp + 1); + for (i = 0; i < *argc; i++) + log_debug("alias: argv[%d] = %s", i, (*argv)[i]); + + cmd_free_argv(new_argc, new_argv); + return (0); +} + struct cmd * cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause) { + const char *name; const struct cmd_entry **entryp, *entry; struct cmd *cmd; struct args *args; char s[BUFSIZ]; - int ambiguous = 0; + int ambiguous, allocated = 0; *cause = NULL; if (argc == 0) { xasprintf(cause, "no command"); return (NULL); } + name = argv[0]; +retry: + ambiguous = 0; entry = NULL; for (entryp = cmd_table; *entryp != NULL; entryp++) { if ((*entryp)->alias != NULL && @@ -342,10 +395,17 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause) if (strcmp(entry->name, argv[0]) == 0) break; } + if ((ambiguous || entry == NULL) && + server_proc != NULL && + !allocated && + cmd_try_alias(&argc, &argv) == 0) { + allocated = 1; + goto retry; + } if (ambiguous) goto ambiguous; if (entry == NULL) { - xasprintf(cause, "unknown command: %s", argv[0]); + xasprintf(cause, "unknown command: %s", name); return (NULL); } @@ -365,6 +425,8 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause) cmd->file = xstrdup(file); cmd->line = line; + if (allocated) + cmd_free_argv(argc, argv); return (cmd); ambiguous: @@ -378,7 +440,7 @@ ambiguous: break; } s[strlen(s) - 2] = '\0'; - xasprintf(cause, "ambiguous command: %s, could be: %s", argv[0], s); + xasprintf(cause, "ambiguous command: %s, could be: %s", name, s); return (NULL); usage: diff --git a/format.c b/format.c index 0a8c896b..3a809435 100644 --- a/format.c +++ b/format.c @@ -622,7 +622,7 @@ format_find(struct format_tree *ft, const char *key, int modifiers) struct format_entry *fe, fe_find; struct environ_entry *envent; static char s[64]; - struct option *o; + struct options_entry *o; const char *found; int idx; char *copy, *saved; diff --git a/key-bindings.c b/key-bindings.c index 65cc9b10..4cbb34ec 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -383,7 +383,7 @@ key_bindings_init(void) for (i = 0; i < nitems(defaults); i++) { cmdlist = cmd_string_parse(defaults[i], "", i, &cause); if (cmdlist == NULL) - fatalx("bad default key"); + fatalx("bad default key: %s", defaults[i]); cmdq_append(NULL, cmdq_get_command(cmdlist, NULL, NULL, 0)); cmd_list_free(cmdlist); } diff --git a/options-table.c b/options-table.c index b9559070..e61cd6ca 100644 --- a/options-table.c +++ b/options-table.c @@ -65,6 +65,13 @@ const struct options_table_entry options_table[] = { .default_num = 20 }, + { .name = "command-alias", + .type = OPTIONS_TABLE_ARRAY, + .scope = OPTIONS_TABLE_SERVER, + .default_str = "split-pane=split-window," + "splitp=split-window" + }, + { .name = "default-terminal", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SERVER, diff --git a/options.c b/options.c index 258f2981..ffea70be 100644 --- a/options.c +++ b/options.c @@ -30,7 +30,7 @@ * a red-black tree. */ -struct option { +struct options_entry { struct options *owner; const char *name; @@ -46,15 +46,15 @@ struct option { }; }; - RB_ENTRY(option) entry; + RB_ENTRY(options_entry) entry; }; struct options { - RB_HEAD(options_tree, option) tree; + RB_HEAD(options_tree, options_entry) tree; struct options *parent; }; -static struct option *options_add(struct options *, const char *); +static struct options_entry *options_add(struct options *, const char *); #define OPTIONS_ARRAY_LIMIT 1000 @@ -76,11 +76,11 @@ static struct option *options_add(struct options *, const char *); ((o)->tableentry != NULL && \ (o)->tableentry->type == OPTIONS_TABLE_ARRAY) -static int options_cmp(struct option *, struct option *); -RB_GENERATE_STATIC(options_tree, option, entry, options_cmp); +static int options_cmp(struct options_entry *, struct options_entry *); +RB_GENERATE_STATIC(options_tree, options_entry, entry, options_cmp); static int -options_cmp(struct option *lhs, struct option *rhs) +options_cmp(struct options_entry *lhs, struct options_entry *rhs) { return (strcmp(lhs->name, rhs->name)); } @@ -88,7 +88,7 @@ options_cmp(struct option *lhs, struct option *rhs) static const struct options_table_entry * options_parent_table_entry(struct options *oo, const char *s) { - struct option *o; + struct options_entry *o; if (oo->parent == NULL) fatalx("no parent options for %s", s); @@ -112,38 +112,38 @@ options_create(struct options *parent) void options_free(struct options *oo) { - struct option *o, *tmp; + struct options_entry *o, *tmp; RB_FOREACH_SAFE (o, options_tree, &oo->tree, tmp) options_remove(o); free(oo); } -struct option * +struct options_entry * options_first(struct options *oo) { return (RB_MIN(options_tree, &oo->tree)); } -struct option * -options_next(struct option *o) +struct options_entry * +options_next(struct options_entry *o) { return (RB_NEXT(options_tree, &oo->tree, o)); } -struct option * +struct options_entry * options_get_only(struct options *oo, const char *name) { - struct option o; + struct options_entry o; o.name = name; return (RB_FIND(options_tree, &oo->tree, &o)); } -struct option * +struct options_entry * options_get(struct options *oo, const char *name) { - struct option *o; + struct options_entry *o; o = options_get_only(oo, name); while (o == NULL) { @@ -155,10 +155,10 @@ options_get(struct options *oo, const char *name) return (o); } -struct option * +struct options_entry * options_empty(struct options *oo, const struct options_table_entry *oe) { - struct option *o; + struct options_entry *o; o = options_add(oo, oe->name); o->tableentry = oe; @@ -166,12 +166,12 @@ options_empty(struct options *oo, const struct options_table_entry *oe) return (o); } -struct option * +struct options_entry * options_default(struct options *oo, const struct options_table_entry *oe) { - struct option *o; - char *cp, *copy, *next; - u_int idx = 0; + struct options_entry *o; + char *cp, *copy, *next; + u_int idx = 0; o = options_empty(oo, oe); @@ -195,10 +195,10 @@ options_default(struct options *oo, const struct options_table_entry *oe) return (o); } -static struct option * +static struct options_entry * options_add(struct options *oo, const char *name) { - struct option *o; + struct options_entry *o; o = options_get_only(oo, name); if (o != NULL) @@ -213,7 +213,7 @@ options_add(struct options *oo, const char *name) } void -options_remove(struct option *o) +options_remove(struct options_entry *o) { struct options *oo = o->owner; u_int i; @@ -231,19 +231,19 @@ options_remove(struct option *o) } const char * -options_name(struct option *o) +options_name(struct options_entry *o) { return (o->name); } const struct options_table_entry * -options_table_entry(struct option *o) +options_table_entry(struct options_entry *o) { return (o->tableentry); } const char * -options_array_get(struct option *o, u_int idx) +options_array_get(struct options_entry *o, u_int idx) { if (!OPTIONS_IS_ARRAY(o)) return (NULL); @@ -253,7 +253,7 @@ options_array_get(struct option *o, u_int idx) } int -options_array_set(struct option *o, u_int idx, const char *value) +options_array_set(struct options_entry *o, u_int idx, const char *value) { u_int i; @@ -278,7 +278,7 @@ options_array_set(struct option *o, u_int idx, const char *value) } int -options_array_size(struct option *o, u_int *size) +options_array_size(struct options_entry *o, u_int *size) { if (!OPTIONS_IS_ARRAY(o)) return (-1); @@ -288,7 +288,7 @@ options_array_size(struct option *o, u_int *size) } int -options_isstring(struct option *o) +options_isstring(struct options_entry *o) { if (o->tableentry == NULL) return (1); @@ -296,7 +296,7 @@ options_isstring(struct option *o) } const char * -options_tostring(struct option *o, int idx) +options_tostring(struct options_entry *o, int idx) { static char s[1024]; const char *tmp; @@ -370,11 +370,11 @@ options_parse(const char *name, int *idx) return (copy); } -struct option * +struct options_entry * options_parse_get(struct options *oo, const char *s, int *idx, int only) { - struct option *o; - char *name; + struct options_entry *o; + char *name; name = options_parse(s, idx); if (name == NULL) @@ -426,12 +426,12 @@ options_match(const char *s, int *idx, int* ambiguous) return (xstrdup(found->name)); } -struct option * +struct options_entry * options_match_get(struct options *oo, const char *s, int *idx, int only, int* ambiguous) { - char *name; - struct option *o; + char *name; + struct options_entry *o; name = options_match(s, idx, ambiguous); if (name == NULL) @@ -455,7 +455,7 @@ options_match_get(struct options *oo, const char *s, int *idx, int only, const char * options_get_string(struct options *oo, const char *name) { - struct option *o; + struct options_entry *o; o = options_get(oo, name); if (o == NULL) @@ -468,7 +468,7 @@ options_get_string(struct options *oo, const char *name) long long options_get_number(struct options *oo, const char *name) { - struct option *o; + struct options_entry *o; o = options_get(oo, name); if (o == NULL) @@ -481,7 +481,7 @@ options_get_number(struct options *oo, const char *name) const struct grid_cell * options_get_style(struct options *oo, const char *name) { - struct option *o; + struct options_entry *o; o = options_get(oo, name); if (o == NULL) @@ -491,13 +491,13 @@ options_get_style(struct options *oo, const char *name) return (&o->style); } -struct option * +struct options_entry * options_set_string(struct options *oo, const char *name, int append, const char *fmt, ...) { - struct option *o; - va_list ap; - char *s, *value; + struct options_entry *o; + va_list ap; + char *s, *value; va_start(ap, fmt); xvasprintf(&s, fmt, ap); @@ -524,10 +524,10 @@ options_set_string(struct options *oo, const char *name, int append, return (o); } -struct option * +struct options_entry * options_set_number(struct options *oo, const char *name, long long value) { - struct option *o; + struct options_entry *o; if (*name == '@') fatalx("user option %s must be a string", name); @@ -545,11 +545,11 @@ options_set_number(struct options *oo, const char *name, long long value) return (o); } -struct option * +struct options_entry * options_set_style(struct options *oo, const char *name, int append, const char *value) { - struct option *o; + struct options_entry *o; struct grid_cell gc; if (*name == '@') @@ -619,10 +619,10 @@ options_scope_from_flags(struct args *args, int window, } void -options_style_update_new(struct options *oo, struct option *o) +options_style_update_new(struct options *oo, struct options_entry *o) { - const char *newname = o->tableentry->style; - struct option *new; + const char *newname = o->tableentry->style; + struct options_entry *new; if (newname == NULL) return; @@ -639,7 +639,7 @@ options_style_update_new(struct options *oo, struct option *o) } void -options_style_update_old(struct options *oo, struct option *o) +options_style_update_old(struct options *oo, struct options_entry *o) { char newname[128]; int size; diff --git a/tmux.h b/tmux.h index 54e20873..5f4dc4ee 100644 --- a/tmux.h +++ b/tmux.h @@ -47,6 +47,7 @@ struct input_ctx; struct mode_key_cmdstr; struct mouse_event; struct options; +struct options_entry; struct session; struct tmuxpeer; struct tmuxproc; @@ -1447,11 +1448,7 @@ struct key_table { }; RB_HEAD(key_tables, key_table); -/* - * Option table entries. The option table is the user-visible part of the - * option, as opposed to the internal options (struct option) which are just - * number or string. - */ +/* Option table entries. */ enum options_table_type { OPTIONS_TABLE_STRING, OPTIONS_TABLE_NUMBER, @@ -1607,40 +1604,43 @@ void notify_pane(const char *, struct window_pane *); /* options.c */ struct options *options_create(struct options *); void options_free(struct options *); -struct option *options_first(struct options *); -struct option *options_next(struct option *); -struct option *options_empty(struct options *, +struct options_entry *options_first(struct options *); +struct options_entry *options_next(struct options_entry *); +struct options_entry *options_empty(struct options *, const struct options_table_entry *); -struct option *options_default(struct options *, +struct options_entry *options_default(struct options *, const struct options_table_entry *); -const char *options_name(struct option *); -const struct options_table_entry *options_table_entry(struct option *); -struct option *options_get_only(struct options *, const char *); -struct option *options_get(struct options *, const char *); -void options_remove(struct option *); -const char *options_array_get(struct option *, u_int); -int options_array_set(struct option *, u_int, const char *); -int options_array_size(struct option *, u_int *); -int options_isstring(struct option *); -const char *options_tostring(struct option *, int); +const char *options_name(struct options_entry *); +const struct options_table_entry *options_table_entry(struct options_entry *); +struct options_entry *options_get_only(struct options *, const char *); +struct options_entry *options_get(struct options *, const char *); +void options_remove(struct options_entry *); +const char *options_array_get(struct options_entry *, u_int); +int options_array_set(struct options_entry *, u_int, const char *); +int options_array_size(struct options_entry *, u_int *); +int options_isstring(struct options_entry *); +const char *options_tostring(struct options_entry *, int); char *options_parse(const char *, int *); -struct option *options_parse_get(struct options *, const char *, int *, +struct options_entry *options_parse_get(struct options *, const char *, int *, int); char *options_match(const char *, int *, int *); -struct option *options_match_get(struct options *, const char *, int *, +struct options_entry *options_match_get(struct options *, const char *, int *, int, int *); const char *options_get_string(struct options *, const char *); long long options_get_number(struct options *, const char *); const struct grid_cell *options_get_style(struct options *, const char *); -struct option * printflike(4, 5) options_set_string(struct options *, +struct options_entry * printflike(4, 5) options_set_string(struct options *, const char *, int, const char *, ...); -struct option *options_set_number(struct options *, const char *, long long); -struct option *options_set_style(struct options *, const char *, int, +struct options_entry *options_set_number(struct options *, const char *, + long long); +struct options_entry *options_set_style(struct options *, const char *, int, const char *); enum options_table_scope options_scope_from_flags(struct args *, int, struct cmd_find_state *, struct options **, char **); -void options_style_update_new(struct options *, struct option *); -void options_style_update_old(struct options *, struct option *); +void options_style_update_new(struct options *, + struct options_entry *); +void options_style_update_old(struct options *, + struct options_entry *); /* options-table.c */ extern const struct options_table_entry options_table[]; @@ -1823,6 +1823,7 @@ void printflike(2, 3) cmdq_print(struct cmdq_item *, const char *, ...); void printflike(2, 3) cmdq_error(struct cmdq_item *, const char *, ...); /* cmd-string.c */ +int cmd_string_split(const char *, int *, char ***); struct cmd_list *cmd_string_parse(const char *, const char *, u_int, char **); /* cmd-wait-for.c */