diff options
Diffstat (limited to 'options.c')
-rw-r--r-- | options.c | 273 |
1 files changed, 162 insertions, 111 deletions
@@ -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,13 @@ 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_COMMAND(o) \ + ((o)->tableentry != NULL && \ + (o)->tableentry->type == OPTIONS_TABLE_COMMAND) + +#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 +106,57 @@ 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); + if (OPTIONS_IS_COMMAND(o) && ov->cmdlist != NULL) + cmd_list_free(ov->cmdlist); +} + +static char * +options_value_tostring(struct options_entry *o, union options_value *ov, + int numeric) +{ + char *s; + + if (OPTIONS_IS_COMMAND(o)) + return (cmd_list_print(ov->cmdlist)); + if (OPTIONS_IS_STYLE(o)) + return (xstrdup(style_tostring(&ov->style))); + if (OPTIONS_IS_NUMBER(o)) { + switch (o->tableentry->type) { + case OPTIONS_TABLE_NUMBER: + xasprintf(&s, "%lld", ov->number); + break; + case OPTIONS_TABLE_KEY: + s = xstrdup(key_string_lookup_key(ov->number)); + break; + case OPTIONS_TABLE_COLOUR: + s = xstrdup(colour_tostring(ov->number)); + break; + case OPTIONS_TABLE_FLAG: + if (numeric) + xasprintf(&s, "%lld", ov->number); + else + s = xstrdup(ov->number ? "on" : "off"); + break; + case OPTIONS_TABLE_CHOICE: + s = xstrdup(o->tableentry->choices[ov->number]); + break; + case OPTIONS_TABLE_STRING: + case OPTIONS_TABLE_STYLE: + case OPTIONS_TABLE_COMMAND: + fatalx("not a number option type"); + } + return (s); + } + if (OPTIONS_IS_STRING(o)) + return (xstrdup(ov->string)); + return (xstrdup("")); +} + struct options * options_create(struct options *parent) { @@ -174,8 +222,8 @@ 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) + RB_INIT(&o->value.array); return (o); } @@ -183,23 +231,35 @@ 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) { - 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; + ov = &o->value; + + if (oe->flags & OPTIONS_TABLE_IS_ARRAY) { + if (oe->default_arr == NULL) { + options_array_assign(o, oe->default_str, NULL); + return (o); + } + for (i = 0; oe->default_arr[i] != NULL; i++) + options_array_set(o, i, oe->default_arr[i], 0, NULL); + 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 +285,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 +311,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 +330,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,18 +344,27 @@ 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 options_array_set(struct options_entry *o, u_int idx, const char *value, - int append) + int append, char **cause) { struct options_array_item *a; char *new; + struct cmd_list *cmdlist; - if (!OPTIONS_IS_ARRAY(o)) + if (!OPTIONS_IS_ARRAY(o)) { + *cause = xstrdup("not an array"); return (-1); + } + + if (OPTIONS_IS_COMMAND(o)) { + cmdlist = cmd_string_parse(value, NULL, 0, cause); + if (cmdlist == NULL && *cause != NULL) + return (-1); + } a = options_array_item(o, idx); if (value == NULL) { @@ -305,25 +373,29 @@ options_array_set(struct options_entry *o, u_int idx, const char *value, return (0); } - if (a == NULL) { - a = xcalloc(1, sizeof *a); - a->index = idx; - a->value = xstrdup(value); - RB_INSERT(options_array, &o->array, a); - } else { - free(a->value); + if (OPTIONS_IS_STRING(o)) { 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; } + if (a == NULL) { + a = xcalloc(1, sizeof *a); + a->index = idx; + RB_INSERT(options_array, &o->value.array, a); + } else + options_value_free(o, &a->value); + + if (OPTIONS_IS_STRING(o)) + a->value.string = new; + else if (OPTIONS_IS_COMMAND(o)) + a->value.cmdlist = cmdlist; return (0); } -void -options_array_assign(struct options_entry *o, const char *s) +int +options_array_assign(struct options_entry *o, const char *s, char **cause) { const char *separator; char *copy, *next, *string; @@ -332,7 +404,18 @@ options_array_assign(struct options_entry *o, const char *s) separator = o->tableentry->separator; if (separator == NULL) separator = " ,"; + if (*separator == '\0') { + if (*s == '\0') + return (0); + for (i = 0; i < UINT_MAX; i++) { + if (options_array_item(o, i) == NULL) + break; + } + return (options_array_set(o, i, s, 0, cause)); + } + if (*s == '\0') + return (0); copy = string = xstrdup(s); while ((next = strsep(&string, separator)) != NULL) { if (*next == '\0') @@ -343,9 +426,13 @@ options_array_assign(struct options_entry *o, const char *s) } if (i == UINT_MAX) break; - options_array_set(o, i, next, 0); + if (options_array_set(o, i, next, 0, cause) != 0) { + free(copy); + return (-1); + } } free(copy); + return (0); } struct options_array_item * @@ -353,13 +440,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 +455,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,59 +470,23 @@ 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 * +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)) { if (idx == -1) - return (NULL); + return (xstrdup("")); a = options_array_item(o, idx); if (a == NULL) - return (""); - return (a->value); + return (xstrdup("")); + 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 +600,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 +613,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 +626,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 +643,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 +657,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 +679,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 +695,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 +708,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); } |