From 772b3b7a06ceba64933cb3a9dfff61e56c229a74 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 23 Apr 2019 20:36:55 +0000 Subject: [PATCH 1/2] Indicate an array option with a flag rather than a special type so that in future will not have to be strings. --- cmd-set-option.c | 2 - cmd.c | 19 +++-- environ.c | 10 +-- options-table.c | 15 ++-- options.c | 209 ++++++++++++++++++++++++++--------------------- status.c | 8 +- tmux.h | 19 ++++- tty-term.c | 7 +- 8 files changed, 164 insertions(+), 125 deletions(-) diff --git a/cmd-set-option.c b/cmd-set-option.c index 96428d73..edeb8385 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -366,8 +366,6 @@ cmd_set_option_set(struct cmd *self, struct cmdq_item *item, struct options *oo, return (-1); } return (0); - case OPTIONS_TABLE_ARRAY: - break; } return (-1); } diff --git a/cmd.c b/cmd.c index eace4bbd..cf1f7496 100644 --- a/cmd.c +++ b/cmd.c @@ -321,10 +321,11 @@ cmd_try_alias(int *argc, char ***argv) { struct options_entry *o; struct options_array_item *a; + union options_value *ov; int old_argc = *argc, new_argc, i; char **old_argv = *argv, **new_argv; size_t wanted; - const char *s, *cp = NULL; + const char *cp = NULL; o = options_get_only(global_options, "command-alias"); if (o == NULL) @@ -333,14 +334,16 @@ cmd_try_alias(int *argc, char ***argv) a = options_array_first(o); while (a != NULL) { - s = options_array_item_value(a); - if (s != NULL) { - cp = strchr(s, '='); - if (cp != NULL && - (size_t)(cp - s) == wanted && - strncmp(old_argv[0], s, wanted) == 0) - break; + ov = options_array_item_value(a); + if (ov == NULL) { + a = options_array_next(a); + continue; } + cp = strchr(ov->string, '='); + if (cp != NULL && + (size_t)(cp - ov->string) == wanted && + strncmp(old_argv[0], ov->string, wanted) == 0) + break; a = options_array_next(a); } if (a == NULL) diff --git a/environ.c b/environ.c index 2764e027..301c4f29 100644 --- a/environ.c +++ b/environ.c @@ -177,20 +177,20 @@ environ_update(struct options *oo, struct environ *src, struct environ *dst) struct environ_entry *envent; struct options_entry *o; struct options_array_item *a; - const char *value; + union options_value *ov; o = options_get(oo, "update-environment"); if (o == NULL) return; a = options_array_first(o); while (a != NULL) { - value = options_array_item_value(a); - if (value == NULL) { + ov = options_array_item_value(a); + if (ov == NULL) { a = options_array_next(a); continue; } - if ((envent = environ_find(src, value)) == NULL) - environ_clear(dst, value); + if ((envent = environ_find(src, ov->string)) == NULL) + environ_clear(dst, ov->string); else environ_set(dst, envent->name, "%s", envent->value); a = options_array_next(a); diff --git a/options-table.c b/options-table.c index b30d7490..03e0dbad 100644 --- a/options-table.c +++ b/options-table.c @@ -141,8 +141,9 @@ const struct options_table_entry options_table[] = { }, { .name = "command-alias", - .type = OPTIONS_TABLE_ARRAY, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SERVER, + .flags = OPTIONS_TABLE_IS_ARRAY, .default_str = "split-pane=split-window," "splitp=split-window," "server-info=show-messages -JT," @@ -206,8 +207,9 @@ const struct options_table_entry options_table[] = { }, { .name = "terminal-overrides", - .type = OPTIONS_TABLE_ARRAY, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SERVER, + .flags = OPTIONS_TABLE_IS_ARRAY, .default_str = "xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007" ":Cs=\\E]12;%p1%s\\007:Cr=\\E]112\\007" ":Ss=\\E[%p1%d q:Se=\\E[2 q,screen*:XT", @@ -215,8 +217,9 @@ const struct options_table_entry options_table[] = { }, { .name = "user-keys", - .type = OPTIONS_TABLE_ARRAY, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SERVER, + .flags = OPTIONS_TABLE_IS_ARRAY, .default_str = "", .separator = "," }, @@ -421,8 +424,9 @@ const struct options_table_entry options_table[] = { }, { .name = "status-format", - .type = OPTIONS_TABLE_ARRAY, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SESSION, + .flags = OPTIONS_TABLE_IS_ARRAY, .default_arr = options_table_status_format_default, }, @@ -504,8 +508,9 @@ const struct options_table_entry options_table[] = { }, { .name = "update-environment", - .type = OPTIONS_TABLE_ARRAY, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SESSION, + .flags = OPTIONS_TABLE_IS_ARRAY, .default_str = "DISPLAY KRB5CCNAME SSH_ASKPASS SSH_AUTH_SOCK " "SSH_AGENT_PID SSH_CONNECTION WINDOWID XAUTHORITY" }, diff --git a/options.c b/options.c index 369776e3..0b13bca0 100644 --- a/options.c +++ b/options.c @@ -32,10 +32,9 @@ struct options_array_item { u_int index; - char *value; + union options_value value; RB_ENTRY(options_array_item) entry; }; -RB_HEAD(options_array, options_array_item); static int options_array_cmp(struct options_array_item *a1, struct options_array_item *a2) { @@ -48,19 +47,13 @@ options_array_cmp(struct options_array_item *a1, struct options_array_item *a2) RB_GENERATE_STATIC(options_array, options_array_item, entry, options_array_cmp); struct options_entry { - struct options *owner; + struct options *owner; - const char *name; - const struct options_table_entry *tableentry; + const char *name; + const struct options_table_entry *tableentry; + union options_value value; - union { - char *string; - long long number; - struct style style; - struct options_array array; - }; - - RB_ENTRY(options_entry) entry; + RB_ENTRY(options_entry) entry; }; struct options { @@ -83,9 +76,10 @@ static struct options_entry *options_add(struct options *, const char *); #define OPTIONS_IS_STYLE(o) \ ((o)->tableentry != NULL && \ (o)->tableentry->type == OPTIONS_TABLE_STYLE) -#define OPTIONS_IS_ARRAY(o) \ + +#define OPTIONS_IS_ARRAY(o) \ ((o)->tableentry != NULL && \ - (o)->tableentry->type == OPTIONS_TABLE_ARRAY) + ((o)->tableentry->flags & OPTIONS_TABLE_IS_ARRAY)) static int options_cmp(struct options_entry *, struct options_entry *); RB_GENERATE_STATIC(options_tree, options_entry, entry, options_cmp); @@ -109,6 +103,56 @@ options_parent_table_entry(struct options *oo, const char *s) return (o->tableentry); } +static void +options_value_free(struct options_entry *o, union options_value *ov) +{ + if (OPTIONS_IS_STRING(o)) + free(ov->string); +} + +static const char * +options_value_tostring(struct options_entry *o, union options_value *ov, + int numeric) +{ + static char s[1024]; + const char *tmp; + + if (OPTIONS_IS_STYLE(o)) + return (style_tostring(&ov->style)); + if (OPTIONS_IS_NUMBER(o)) { + tmp = NULL; + switch (o->tableentry->type) { + case OPTIONS_TABLE_NUMBER: + xsnprintf(s, sizeof s, "%lld", ov->number); + break; + case OPTIONS_TABLE_KEY: + tmp = key_string_lookup_key(ov->number); + break; + case OPTIONS_TABLE_COLOUR: + tmp = colour_tostring(ov->number); + break; + case OPTIONS_TABLE_FLAG: + if (numeric) + xsnprintf(s, sizeof s, "%lld", ov->number); + else + tmp = (ov->number ? "on" : "off"); + break; + case OPTIONS_TABLE_CHOICE: + tmp = o->tableentry->choices[ov->number]; + break; + case OPTIONS_TABLE_STRING: + case OPTIONS_TABLE_STYLE: + break; + } + if (tmp != NULL) + xsnprintf(s, sizeof s, "%s", tmp); + return (s); + } + if (OPTIONS_IS_STRING(o)) + return (ov->string); + return (""); +} + struct options * options_create(struct options *parent) { @@ -174,8 +218,11 @@ options_empty(struct options *oo, const struct options_table_entry *oe) o = options_add(oo, oe->name); o->tableentry = oe; - if (oe->type == OPTIONS_TABLE_ARRAY) - RB_INIT(&o->array); + if (oe->flags & OPTIONS_TABLE_IS_ARRAY) { + if (oe->type != OPTIONS_TABLE_STRING) + fatalx("arrays can only be strings"); + RB_INIT(&o->value.array); + } return (o); } @@ -183,23 +230,34 @@ options_empty(struct options *oo, const struct options_table_entry *oe) struct options_entry * options_default(struct options *oo, const struct options_table_entry *oe) { - struct options_entry *o; - u_int i; + struct options_entry *o; + union options_value *ov; + u_int i; o = options_empty(oo, oe); - if (oe->type == OPTIONS_TABLE_ARRAY) { + ov = &o->value; + + if (oe->flags & OPTIONS_TABLE_IS_ARRAY) { if (oe->default_arr != NULL) { for (i = 0; oe->default_arr[i] != NULL; i++) options_array_set(o, i, oe->default_arr[i], 0); } else options_array_assign(o, oe->default_str); - } else if (oe->type == OPTIONS_TABLE_STRING) - o->string = xstrdup(oe->default_str); - else if (oe->type == OPTIONS_TABLE_STYLE) { - style_set(&o->style, &grid_default_cell); - style_parse(&o->style, &grid_default_cell, oe->default_str); - } else - o->number = oe->default_num; + return (o); + } + + switch (oe->type) { + case OPTIONS_TABLE_STRING: + ov->string = xstrdup(oe->default_str); + break; + case OPTIONS_TABLE_STYLE: + style_set(&ov->style, &grid_default_cell); + style_parse(&ov->style, &grid_default_cell, oe->default_str); + break; + default: + ov->number = oe->default_num; + break; + } return (o); } @@ -225,11 +283,10 @@ options_remove(struct options_entry *o) { struct options *oo = o->owner; - if (OPTIONS_IS_STRING(o)) - free(o->string); - else if (OPTIONS_IS_ARRAY(o)) + if (OPTIONS_IS_ARRAY(o)) options_array_clear(o); - + else + options_value_free(o, &o->value); RB_REMOVE(options_tree, &oo->tree, o); free(o); } @@ -252,14 +309,14 @@ options_array_item(struct options_entry *o, u_int idx) struct options_array_item a; a.index = idx; - return (RB_FIND(options_array, &o->array, &a)); + return (RB_FIND(options_array, &o->value.array, &a)); } static void options_array_free(struct options_entry *o, struct options_array_item *a) { - free(a->value); - RB_REMOVE(options_array, &o->array, a); + options_value_free(o, &a->value); + RB_REMOVE(options_array, &o->value.array, a); free(a); } @@ -271,11 +328,11 @@ options_array_clear(struct options_entry *o) if (!OPTIONS_IS_ARRAY(o)) return; - RB_FOREACH_SAFE(a, options_array, &o->array, a1) + RB_FOREACH_SAFE(a, options_array, &o->value.array, a1) options_array_free(o, a); } -const char * +union options_value * options_array_get(struct options_entry *o, u_int idx) { struct options_array_item *a; @@ -285,7 +342,7 @@ options_array_get(struct options_entry *o, u_int idx) a = options_array_item(o, idx); if (a == NULL) return (NULL); - return (a->value); + return (&a->value); } int @@ -308,15 +365,15 @@ options_array_set(struct options_entry *o, u_int idx, const char *value, if (a == NULL) { a = xcalloc(1, sizeof *a); a->index = idx; - a->value = xstrdup(value); - RB_INSERT(options_array, &o->array, a); + a->value.string = xstrdup(value); + RB_INSERT(options_array, &o->value.array, a); } else { - free(a->value); + options_value_free(o, &a->value); if (a != NULL && append) - xasprintf(&new, "%s%s", a->value, value); + xasprintf(&new, "%s%s", a->value.string, value); else new = xstrdup(value); - a->value = new; + a->value.string = new; } return (0); @@ -353,13 +410,13 @@ options_array_first(struct options_entry *o) { if (!OPTIONS_IS_ARRAY(o)) return (NULL); - return (RB_MIN(options_array, &o->array)); + return (RB_MIN(options_array, &o->value.array)); } struct options_array_item * options_array_next(struct options_array_item *a) { - return (RB_NEXT(options_array, &o->array, a)); + return (RB_NEXT(options_array, &o->value.array, a)); } u_int @@ -368,10 +425,10 @@ options_array_item_index(struct options_array_item *a) return (a->index); } -const char * +union options_value * options_array_item_value(struct options_array_item *a) { - return (a->value); + return (&a->value); } int @@ -383,14 +440,12 @@ options_isarray(struct options_entry *o) int options_isstring(struct options_entry *o) { - return (OPTIONS_IS_STRING(o) || OPTIONS_IS_ARRAY(o)); + return (OPTIONS_IS_STRING(o)); } const char * options_tostring(struct options_entry *o, int idx, int numeric) { - static char s[1024]; - const char *tmp; struct options_array_item *a; if (OPTIONS_IS_ARRAY(o)) { @@ -399,43 +454,9 @@ options_tostring(struct options_entry *o, int idx, int numeric) a = options_array_item(o, idx); if (a == NULL) return (""); - return (a->value); + return (options_value_tostring(o, &a->value, numeric)); } - if (OPTIONS_IS_STYLE(o)) - return (style_tostring(&o->style)); - if (OPTIONS_IS_NUMBER(o)) { - tmp = NULL; - switch (o->tableentry->type) { - case OPTIONS_TABLE_NUMBER: - xsnprintf(s, sizeof s, "%lld", o->number); - break; - case OPTIONS_TABLE_KEY: - tmp = key_string_lookup_key(o->number); - break; - case OPTIONS_TABLE_COLOUR: - tmp = colour_tostring(o->number); - break; - case OPTIONS_TABLE_FLAG: - if (numeric) - xsnprintf(s, sizeof s, "%lld", o->number); - else - tmp = (o->number ? "on" : "off"); - break; - case OPTIONS_TABLE_CHOICE: - tmp = o->tableentry->choices[o->number]; - break; - case OPTIONS_TABLE_STRING: - case OPTIONS_TABLE_STYLE: - case OPTIONS_TABLE_ARRAY: - break; - } - if (tmp != NULL) - xsnprintf(s, sizeof s, "%s", tmp); - return (s); - } - if (OPTIONS_IS_STRING(o)) - return (o->string); - return (NULL); + return (options_value_tostring(o, &o->value, numeric)); } char * @@ -549,7 +570,7 @@ options_get_string(struct options *oo, const char *name) fatalx("missing option %s", name); if (!OPTIONS_IS_STRING(o)) fatalx("option %s is not a string", name); - return (o->string); + return (o->value.string); } long long @@ -562,7 +583,7 @@ options_get_number(struct options *oo, const char *name) fatalx("missing option %s", name); if (!OPTIONS_IS_NUMBER(o)) fatalx("option %s is not a number", name); - return (o->number); + return (o->value.number); } struct style * @@ -575,7 +596,7 @@ options_get_style(struct options *oo, const char *name) fatalx("missing option %s", name); if (!OPTIONS_IS_STYLE(o)) fatalx("option %s is not a style", name); - return (&o->style); + return (&o->value.style); } struct options_entry * @@ -592,7 +613,7 @@ options_set_string(struct options *oo, const char *name, int append, o = options_get_only(oo, name); if (o != NULL && append && OPTIONS_IS_STRING(o)) { - xasprintf(&value, "%s%s", o->string, s); + xasprintf(&value, "%s%s", o->value.string, s); free(s); } else value = s; @@ -606,8 +627,8 @@ options_set_string(struct options *oo, const char *name, int append, if (!OPTIONS_IS_STRING(o)) fatalx("option %s is not a string", name); - free(o->string); - o->string = value; + free(o->value.string); + o->value.string = value; return (o); } @@ -628,7 +649,7 @@ options_set_number(struct options *oo, const char *name, long long value) if (!OPTIONS_IS_NUMBER(o)) fatalx("option %s is not a number", name); - o->number = value; + o->value.number = value; return (o); } @@ -644,7 +665,7 @@ options_set_style(struct options *oo, const char *name, int append, o = options_get_only(oo, name); if (o != NULL && append && OPTIONS_IS_STYLE(o)) - style_copy(&sy, &o->style); + style_copy(&sy, &o->value.style); else style_set(&sy, &grid_default_cell); if (style_parse(&sy, &grid_default_cell, value) == -1) @@ -657,7 +678,7 @@ options_set_style(struct options *oo, const char *name, int append, if (!OPTIONS_IS_STYLE(o)) fatalx("option %s is not a style", name); - style_copy(&o->style, &sy); + style_copy(&o->value.style, &sy); return (o); } diff --git a/status.c b/status.c index 467db6ad..9e43b5b1 100644 --- a/status.c +++ b/status.c @@ -323,8 +323,8 @@ status_redraw(struct client *c) u_int lines, i, width = c->tty.sx; int flags, force = 0, changed = 0; struct options_entry *o; + union options_value *ov; struct format_tree *ft; - const char *fmt; char *expanded; log_debug("%s enter", __func__); @@ -370,14 +370,14 @@ status_redraw(struct client *c) for (i = 0; i < lines; i++) { screen_write_cursormove(&ctx, 0, i, 0); - fmt = options_array_get(o, i); - if (fmt == NULL) { + ov = options_array_get(o, i); + if (ov == NULL) { screen_write_clearline(&ctx, gc.bg); continue; } sle = &sl->entries[i]; - expanded = format_expand_time(ft, fmt); + expanded = format_expand_time(ft, ov->string); if (!force && sle->expanded != NULL && strcmp(expanded, sle->expanded) == 0) { diff --git a/tmux.h b/tmux.h index fc85344d..31514e84 100644 --- a/tmux.h +++ b/tmux.h @@ -1514,6 +1514,15 @@ struct key_table { }; RB_HEAD(key_tables, key_table); +/* Option data. */ +RB_HEAD(options_array, options_array_item); +union options_value { + char *string; + long long number; + struct style style; + struct options_array array; +}; + /* Option table entries. */ enum options_table_type { OPTIONS_TABLE_STRING, @@ -1522,8 +1531,7 @@ enum options_table_type { OPTIONS_TABLE_COLOUR, OPTIONS_TABLE_FLAG, OPTIONS_TABLE_CHOICE, - OPTIONS_TABLE_STYLE, - OPTIONS_TABLE_ARRAY, + OPTIONS_TABLE_STYLE }; enum options_table_scope { @@ -1533,10 +1541,13 @@ enum options_table_scope { OPTIONS_TABLE_WINDOW, }; +#define OPTIONS_TABLE_IS_ARRAY 0x1 + struct options_table_entry { const char *name; enum options_table_type type; enum options_table_scope scope; + int flags; u_int minimum; u_int maximum; @@ -1721,14 +1732,14 @@ 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 *); void options_array_clear(struct options_entry *); -const char *options_array_get(struct options_entry *, u_int); +union options_value *options_array_get(struct options_entry *, u_int); int options_array_set(struct options_entry *, u_int, const char *, int); void options_array_assign(struct options_entry *, const char *); struct options_array_item *options_array_first(struct options_entry *); struct options_array_item *options_array_next(struct options_array_item *); u_int options_array_item_index(struct options_array_item *); -const char *options_array_item_value(struct options_array_item *); +union options_value *options_array_item_value(struct options_array_item *); int options_isarray(struct options_entry *); int options_isstring(struct options_entry *); const char *options_tostring(struct options_entry *, int, int); diff --git a/tty-term.c b/tty-term.c index 9e0bb63d..47da3905 100644 --- a/tty-term.c +++ b/tty-term.c @@ -417,6 +417,7 @@ tty_term_find(char *name, int fd, char **cause) struct tty_code *code; struct options_entry *o; struct options_array_item *a; + union options_value *ov; u_int i; int n, error; const char *s, *acs; @@ -494,9 +495,9 @@ tty_term_find(char *name, int fd, char **cause) o = options_get_only(global_options, "terminal-overrides"); a = options_array_first(o); while (a != NULL) { - s = options_array_item_value(a); - if (s != NULL) - tty_term_override(term, s); + ov = options_array_item_value(a); + if (ov != NULL) + tty_term_override(term, ov->string); a = options_array_next(a); } From b9022e33eac0152850ae59be99b54cccc10f4c63 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 23 Apr 2019 20:40:03 +0000 Subject: [PATCH 2/2] Somehow missed these bits in last commit. --- status.c | 8 ++++++-- tty-keys.c | 9 +++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/status.c b/status.c index 9e43b5b1..1a11a564 100644 --- a/status.c +++ b/status.c @@ -1293,6 +1293,7 @@ status_prompt_complete_list(u_int *size, const char *s) size_t slen = strlen(s), valuelen; struct options_entry *o; struct options_array_item *a; + union options_value *ov; const char *layouts[] = { "even-horizontal", "even-vertical", "main-horizontal", "main-vertical", "tiled", NULL @@ -1321,10 +1322,13 @@ status_prompt_complete_list(u_int *size, const char *s) if (o != NULL) { a = options_array_first(o); while (a != NULL) { - value = options_array_item_value(a);; - if (value == NULL || (cp = strchr(value, '=')) == NULL) + ov = options_array_item_value(a); + if (ov == NULL) goto next; + value = ov->string; + if ((cp = strchr(value, '=')) == NULL) + goto next; valuelen = cp - value; if (slen > valuelen || strncmp(value, s, slen) != 0) goto next; diff --git a/tty-keys.c b/tty-keys.c index 7557eca0..c6dcbb56 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -399,9 +399,10 @@ tty_keys_build(struct tty *tty) const struct tty_default_key_raw *tdkr; const struct tty_default_key_code *tdkc; u_int i; - const char *s, *value; + const char *s; struct options_entry *o; struct options_array_item *a; + union options_value *ov; if (tty->key_tree != NULL) tty_keys_free(tty); @@ -427,9 +428,9 @@ tty_keys_build(struct tty *tty) if (o != NULL) { a = options_array_first(o); while (a != NULL) { - value = options_array_item_value(a); - if (value != NULL) - tty_keys_add(tty, value, KEYC_USER + i); + ov = options_array_item_value(a); + if (ov != NULL) + tty_keys_add(tty, ov->string, KEYC_USER + i); a = options_array_next(a); } }