xref: /openbsd/usr.bin/tmux/options.c (revision cca36db2)
1 /* $OpenBSD: options.c,v 1.7 2012/01/21 11:12:13 nicm Exp $ */
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>
22 #include <string.h>
23 
24 #include "tmux.h"
25 
26 /*
27  * Option handling; each option has a name, type and value and is stored in
28  * a splay tree.
29  */
30 
31 RB_GENERATE(options_tree, options_entry, entry, options_cmp);
32 
33 int
34 options_cmp(struct options_entry *o1, struct options_entry *o2)
35 {
36 	return (strcmp(o1->name, o2->name));
37 }
38 
39 void
40 options_init(struct options *oo, struct options *parent)
41 {
42 	RB_INIT(&oo->tree);
43 	oo->parent = parent;
44 }
45 
46 void
47 options_free(struct options *oo)
48 {
49 	struct options_entry	*o;
50 
51 	while (!RB_EMPTY(&oo->tree)) {
52 		o = RB_ROOT(&oo->tree);
53 		RB_REMOVE(options_tree, &oo->tree, o);
54 		xfree(o->name);
55 		if (o->type == OPTIONS_STRING)
56 			xfree(o->str);
57 		xfree(o);
58 	}
59 }
60 
61 struct options_entry *
62 options_find1(struct options *oo, const char *name)
63 {
64 	struct options_entry	p;
65 
66 	p.name = (char *) name;
67 	return (RB_FIND(options_tree, &oo->tree, &p));
68 }
69 
70 struct options_entry *
71 options_find(struct options *oo, const char *name)
72 {
73 	struct options_entry	*o, p;
74 
75 	p.name = (char *) name;
76 	o = RB_FIND(options_tree, &oo->tree, &p);
77 	while (o == NULL) {
78 		oo = oo->parent;
79 		if (oo == NULL)
80 			break;
81 		o = RB_FIND(options_tree, &oo->tree, &p);
82 	}
83 	return (o);
84 }
85 
86 void
87 options_remove(struct options *oo, const char *name)
88 {
89 	struct options_entry	*o;
90 
91 	if ((o = options_find1(oo, name)) == NULL)
92 		return;
93 
94 	RB_REMOVE(options_tree, &oo->tree, o);
95 	xfree(o->name);
96 	if (o->type == OPTIONS_STRING)
97 		xfree(o->str);
98 	xfree(o);
99 }
100 
101 struct options_entry *printflike3
102 options_set_string(struct options *oo, const char *name, const char *fmt, ...)
103 {
104 	struct options_entry	*o;
105 	va_list			 ap;
106 
107 	if ((o = options_find1(oo, name)) == NULL) {
108 		o = xmalloc(sizeof *o);
109 		o->name = xstrdup(name);
110 		RB_INSERT(options_tree, &oo->tree, o);
111 	} else if (o->type == OPTIONS_STRING)
112 		xfree(o->str);
113 
114 	va_start(ap, fmt);
115 	o->type = OPTIONS_STRING;
116 	xvasprintf(&o->str, fmt, ap);
117 	va_end(ap);
118 	return (o);
119 }
120 
121 char *
122 options_get_string(struct options *oo, const char *name)
123 {
124 	struct options_entry	*o;
125 
126 	if ((o = options_find(oo, name)) == NULL)
127 		fatalx("missing option");
128 	if (o->type != OPTIONS_STRING)
129 		fatalx("option not a string");
130 	return (o->str);
131 }
132 
133 struct options_entry *
134 options_set_number(struct options *oo, const char *name, long long value)
135 {
136 	struct options_entry	*o;
137 
138 	if ((o = options_find1(oo, name)) == NULL) {
139 		o = xmalloc(sizeof *o);
140 		o->name = xstrdup(name);
141 		RB_INSERT(options_tree, &oo->tree, o);
142 	} else if (o->type == OPTIONS_STRING)
143 		xfree(o->str);
144 
145 	o->type = OPTIONS_NUMBER;
146 	o->num = value;
147 	return (o);
148 }
149 
150 long long
151 options_get_number(struct options *oo, const char *name)
152 {
153 	struct options_entry	*o;
154 
155 	if ((o = options_find(oo, name)) == NULL)
156 		fatalx("missing option");
157 	if (o->type != OPTIONS_NUMBER)
158 		fatalx("option not a number");
159 	return (o->num);
160 }
161