Annotation of src/usr.bin/tmux/options.c, Revision 1.20
1.20 ! nicm 1: /* $OpenBSD: options.c,v 1.19 2016/09/26 09:02:34 nicm Exp $ */
1.1 nicm 2:
3: /*
1.18 nicm 4: * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
1.1 nicm 5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15: * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/types.h>
20:
21: #include <stdarg.h>
1.8 nicm 22: #include <stdlib.h>
1.1 nicm 23: #include <string.h>
24:
25: #include "tmux.h"
26:
27: /*
28: * Option handling; each option has a name, type and value and is stored in
1.9 nicm 29: * a red-black tree.
1.1 nicm 30: */
31:
1.13 nicm 32: struct options {
33: RB_HEAD(options_tree, options_entry) tree;
34: struct options *parent;
35: };
36:
1.17 nicm 37: static int options_cmp(struct options_entry *, struct options_entry *);
1.20 ! nicm 38: RB_GENERATE_STATIC(options_tree, options_entry, entry, options_cmp);
1.1 nicm 39:
1.17 nicm 40: static void options_free1(struct options *, struct options_entry *);
41:
42: static int
1.1 nicm 43: options_cmp(struct options_entry *o1, struct options_entry *o2)
44: {
45: return (strcmp(o1->name, o2->name));
46: }
47:
1.13 nicm 48: struct options *
49: options_create(struct options *parent)
1.1 nicm 50: {
1.16 nicm 51: struct options *oo;
1.13 nicm 52:
53: oo = xcalloc(1, sizeof *oo);
1.7 nicm 54: RB_INIT(&oo->tree);
1.1 nicm 55: oo->parent = parent;
1.13 nicm 56: return (oo);
1.1 nicm 57: }
58:
1.17 nicm 59: static void
60: options_free1(struct options *oo, struct options_entry *o)
61: {
62: RB_REMOVE(options_tree, &oo->tree, o);
63: free((char *)o->name);
64: if (o->type == OPTIONS_STRING)
65: free(o->str);
66: free(o);
67: }
68:
1.1 nicm 69: void
70: options_free(struct options *oo)
71: {
1.17 nicm 72: struct options_entry *o, *o1;
1.1 nicm 73:
1.17 nicm 74: RB_FOREACH_SAFE (o, options_tree, &oo->tree, o1)
75: options_free1(oo, o);
1.13 nicm 76: free(oo);
77: }
78:
79: struct options_entry *
80: options_first(struct options *oo)
81: {
82: return (RB_MIN(options_tree, &oo->tree));
83: }
84:
85: struct options_entry *
86: options_next(struct options_entry *o)
87: {
88: return (RB_NEXT(options_tree, &oo->tree, o));
1.1 nicm 89: }
90:
91: struct options_entry *
92: options_find1(struct options *oo, const char *name)
93: {
94: struct options_entry p;
95:
1.17 nicm 96: p.name = (char *)name;
1.7 nicm 97: return (RB_FIND(options_tree, &oo->tree, &p));
1.1 nicm 98: }
99:
100: struct options_entry *
101: options_find(struct options *oo, const char *name)
102: {
103: struct options_entry *o, p;
104:
1.17 nicm 105: p.name = (char *)name;
1.7 nicm 106: o = RB_FIND(options_tree, &oo->tree, &p);
1.1 nicm 107: while (o == NULL) {
108: oo = oo->parent;
109: if (oo == NULL)
110: break;
1.7 nicm 111: o = RB_FIND(options_tree, &oo->tree, &p);
1.1 nicm 112: }
113: return (o);
114: }
115:
1.2 nicm 116: void
1.1 nicm 117: options_remove(struct options *oo, const char *name)
118: {
119: struct options_entry *o;
120:
1.17 nicm 121: if ((o = options_find1(oo, name)) != NULL)
122: options_free1(oo, o);
1.1 nicm 123: }
124:
1.11 nicm 125: struct options_entry *
1.1 nicm 126: options_set_string(struct options *oo, const char *name, const char *fmt, ...)
127: {
128: struct options_entry *o;
129: va_list ap;
1.19 nicm 130: char *s;
1.1 nicm 131:
1.19 nicm 132: s = NULL;
1.1 nicm 133: if ((o = options_find1(oo, name)) == NULL) {
134: o = xmalloc(sizeof *o);
135: o->name = xstrdup(name);
1.7 nicm 136: RB_INSERT(options_tree, &oo->tree, o);
1.10 nicm 137: memcpy(&o->style, &grid_default_cell, sizeof o->style);
1.1 nicm 138: } else if (o->type == OPTIONS_STRING)
1.19 nicm 139: s = o->str;
1.1 nicm 140:
141: va_start(ap, fmt);
142: o->type = OPTIONS_STRING;
1.3 nicm 143: xvasprintf(&o->str, fmt, ap);
1.1 nicm 144: va_end(ap);
1.19 nicm 145:
146: free(s);
1.4 nicm 147: return (o);
1.1 nicm 148: }
149:
150: char *
151: options_get_string(struct options *oo, const char *name)
152: {
153: struct options_entry *o;
154:
155: if ((o = options_find(oo, name)) == NULL)
1.15 nicm 156: fatalx("missing option %s", name);
1.1 nicm 157: if (o->type != OPTIONS_STRING)
1.15 nicm 158: fatalx("option %s not a string", name);
1.3 nicm 159: return (o->str);
1.1 nicm 160: }
161:
1.4 nicm 162: struct options_entry *
1.1 nicm 163: options_set_number(struct options *oo, const char *name, long long value)
164: {
165: struct options_entry *o;
166:
167: if ((o = options_find1(oo, name)) == NULL) {
168: o = xmalloc(sizeof *o);
169: o->name = xstrdup(name);
1.7 nicm 170: RB_INSERT(options_tree, &oo->tree, o);
1.10 nicm 171: memcpy(&o->style, &grid_default_cell, sizeof o->style);
1.1 nicm 172: } else if (o->type == OPTIONS_STRING)
1.8 nicm 173: free(o->str);
1.1 nicm 174:
175: o->type = OPTIONS_NUMBER;
1.3 nicm 176: o->num = value;
1.4 nicm 177: return (o);
1.1 nicm 178: }
179:
180: long long
181: options_get_number(struct options *oo, const char *name)
182: {
183: struct options_entry *o;
184:
185: if ((o = options_find(oo, name)) == NULL)
1.15 nicm 186: fatalx("missing option %s", name);
1.1 nicm 187: if (o->type != OPTIONS_NUMBER)
1.15 nicm 188: fatalx("option %s not a number", name);
1.3 nicm 189: return (o->num);
1.10 nicm 190: }
191:
192: struct options_entry *
193: options_set_style(struct options *oo, const char *name, const char *value,
194: int append)
195: {
196: struct options_entry *o;
1.12 nicm 197: struct grid_cell tmpgc;
1.10 nicm 198:
1.12 nicm 199: o = options_find1(oo, name);
200: if (o == NULL || !append)
201: memcpy(&tmpgc, &grid_default_cell, sizeof tmpgc);
202: else
203: memcpy(&tmpgc, &o->style, sizeof tmpgc);
204:
205: if (style_parse(&grid_default_cell, &tmpgc, value) == -1)
206: return (NULL);
207:
208: if (o == NULL) {
1.10 nicm 209: o = xmalloc(sizeof *o);
210: o->name = xstrdup(name);
211: RB_INSERT(options_tree, &oo->tree, o);
212: } else if (o->type == OPTIONS_STRING)
213: free(o->str);
214:
215: o->type = OPTIONS_STYLE;
1.12 nicm 216: memcpy(&o->style, &tmpgc, sizeof o->style);
1.10 nicm 217: return (o);
218: }
219:
220: struct grid_cell *
221: options_get_style(struct options *oo, const char *name)
222: {
223: struct options_entry *o;
224:
225: if ((o = options_find(oo, name)) == NULL)
1.15 nicm 226: fatalx("missing option %s", name);
1.10 nicm 227: if (o->type != OPTIONS_STYLE)
1.15 nicm 228: fatalx("option %s not a style", name);
1.10 nicm 229: return (&o->style);
1.1 nicm 230: }