Annotation of src/usr.bin/tmux/options.c, Revision 1.14
1.14 ! nicm 1: /* $OpenBSD: options.c,v 1.13 2015/10/27 15:58:42 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
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:
37: int options_cmp(struct options_entry *, struct options_entry *);
38: RB_PROTOTYPE(options_tree, options_entry, entry, options_cmp);
1.7 nicm 39: RB_GENERATE(options_tree, options_entry, entry, options_cmp);
1.1 nicm 40:
41: int
42: options_cmp(struct options_entry *o1, struct options_entry *o2)
43: {
44: return (strcmp(o1->name, o2->name));
45: }
46:
1.13 nicm 47: struct options *
48: options_create(struct options *parent)
1.1 nicm 49: {
1.13 nicm 50: struct options *oo;
51:
52: oo = xcalloc(1, sizeof *oo);
1.7 nicm 53: RB_INIT(&oo->tree);
1.1 nicm 54: oo->parent = parent;
1.13 nicm 55: return (oo);
1.1 nicm 56: }
57:
58: void
59: options_free(struct options *oo)
60: {
61: struct options_entry *o;
62:
1.7 nicm 63: while (!RB_EMPTY(&oo->tree)) {
64: o = RB_ROOT(&oo->tree);
65: RB_REMOVE(options_tree, &oo->tree, o);
1.8 nicm 66: free(o->name);
1.1 nicm 67: if (o->type == OPTIONS_STRING)
1.8 nicm 68: free(o->str);
69: free(o);
1.1 nicm 70: }
1.13 nicm 71: free(oo);
72: }
73:
74: struct options_entry *
75: options_first(struct options *oo)
76: {
77: return (RB_MIN(options_tree, &oo->tree));
78: }
79:
80: struct options_entry *
81: options_next(struct options_entry *o)
82: {
83: return (RB_NEXT(options_tree, &oo->tree, o));
1.1 nicm 84: }
85:
86: struct options_entry *
87: options_find1(struct options *oo, const char *name)
88: {
89: struct options_entry p;
90:
91: p.name = (char *) name;
1.7 nicm 92: return (RB_FIND(options_tree, &oo->tree, &p));
1.1 nicm 93: }
94:
95: struct options_entry *
96: options_find(struct options *oo, const char *name)
97: {
98: struct options_entry *o, p;
99:
100: p.name = (char *) name;
1.7 nicm 101: o = RB_FIND(options_tree, &oo->tree, &p);
1.1 nicm 102: while (o == NULL) {
103: oo = oo->parent;
104: if (oo == NULL)
105: break;
1.7 nicm 106: o = RB_FIND(options_tree, &oo->tree, &p);
1.1 nicm 107: }
108: return (o);
109: }
110:
1.2 nicm 111: void
1.1 nicm 112: options_remove(struct options *oo, const char *name)
113: {
114: struct options_entry *o;
115:
116: if ((o = options_find1(oo, name)) == NULL)
1.2 nicm 117: return;
1.1 nicm 118:
1.7 nicm 119: RB_REMOVE(options_tree, &oo->tree, o);
1.8 nicm 120: free(o->name);
1.1 nicm 121: if (o->type == OPTIONS_STRING)
1.8 nicm 122: free(o->str);
123: free(o);
1.1 nicm 124: }
125:
1.11 nicm 126: struct options_entry *
1.1 nicm 127: options_set_string(struct options *oo, const char *name, const char *fmt, ...)
128: {
129: struct options_entry *o;
130: va_list ap;
131:
132: if ((o = options_find1(oo, name)) == NULL) {
133: o = xmalloc(sizeof *o);
134: o->name = xstrdup(name);
1.7 nicm 135: RB_INSERT(options_tree, &oo->tree, o);
1.10 nicm 136: memcpy(&o->style, &grid_default_cell, sizeof o->style);
1.1 nicm 137: } else if (o->type == OPTIONS_STRING)
1.8 nicm 138: free(o->str);
1.1 nicm 139:
140: va_start(ap, fmt);
141: o->type = OPTIONS_STRING;
1.3 nicm 142: xvasprintf(&o->str, fmt, ap);
1.1 nicm 143: va_end(ap);
1.4 nicm 144: return (o);
1.1 nicm 145: }
146:
147: char *
148: options_get_string(struct options *oo, const char *name)
149: {
150: struct options_entry *o;
151:
152: if ((o = options_find(oo, name)) == NULL)
1.14 ! nicm 153: log_fatalx("missing option %s", name);
1.1 nicm 154: if (o->type != OPTIONS_STRING)
1.14 ! nicm 155: log_fatalx("option %s not a string", name);
1.3 nicm 156: return (o->str);
1.1 nicm 157: }
158:
1.4 nicm 159: struct options_entry *
1.1 nicm 160: options_set_number(struct options *oo, const char *name, long long value)
161: {
162: struct options_entry *o;
163:
164: if ((o = options_find1(oo, name)) == NULL) {
165: o = xmalloc(sizeof *o);
166: o->name = xstrdup(name);
1.7 nicm 167: RB_INSERT(options_tree, &oo->tree, o);
1.10 nicm 168: memcpy(&o->style, &grid_default_cell, sizeof o->style);
1.1 nicm 169: } else if (o->type == OPTIONS_STRING)
1.8 nicm 170: free(o->str);
1.1 nicm 171:
172: o->type = OPTIONS_NUMBER;
1.3 nicm 173: o->num = value;
1.4 nicm 174: return (o);
1.1 nicm 175: }
176:
177: long long
178: options_get_number(struct options *oo, const char *name)
179: {
180: struct options_entry *o;
181:
182: if ((o = options_find(oo, name)) == NULL)
1.14 ! nicm 183: log_fatalx("missing option %s", name);
1.1 nicm 184: if (o->type != OPTIONS_NUMBER)
1.14 ! nicm 185: log_fatalx("option %s not a number", name);
1.3 nicm 186: return (o->num);
1.10 nicm 187: }
188:
189: struct options_entry *
190: options_set_style(struct options *oo, const char *name, const char *value,
191: int append)
192: {
193: struct options_entry *o;
1.12 nicm 194: struct grid_cell tmpgc;
1.10 nicm 195:
1.12 nicm 196: o = options_find1(oo, name);
197: if (o == NULL || !append)
198: memcpy(&tmpgc, &grid_default_cell, sizeof tmpgc);
199: else
200: memcpy(&tmpgc, &o->style, sizeof tmpgc);
201:
202: if (style_parse(&grid_default_cell, &tmpgc, value) == -1)
203: return (NULL);
204:
205: if (o == NULL) {
1.10 nicm 206: o = xmalloc(sizeof *o);
207: o->name = xstrdup(name);
208: RB_INSERT(options_tree, &oo->tree, o);
209: } else if (o->type == OPTIONS_STRING)
210: free(o->str);
211:
212: o->type = OPTIONS_STYLE;
1.12 nicm 213: memcpy(&o->style, &tmpgc, sizeof o->style);
1.10 nicm 214: return (o);
215: }
216:
217: struct grid_cell *
218: options_get_style(struct options *oo, const char *name)
219: {
220: struct options_entry *o;
221:
222: if ((o = options_find(oo, name)) == NULL)
1.14 ! nicm 223: log_fatalx("missing option %s", name);
1.10 nicm 224: if (o->type != OPTIONS_STYLE)
1.14 ! nicm 225: log_fatalx("option %s not a style", name);
1.10 nicm 226: return (&o->style);
1.1 nicm 227: }