options.c revision 1.5
1/* $OpenBSD: options.c,v 1.5 2009/09/22 12:38:10 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
31SPLAY_GENERATE(options_tree, options_entry, entry, options_cmp);
32
33int
34options_cmp(struct options_entry *o1, struct options_entry *o2)
35{
36	return (strcmp(o1->name, o2->name));
37}
38
39void
40options_init(struct options *oo, struct options *parent)
41{
42	SPLAY_INIT(&oo->tree);
43	oo->parent = parent;
44}
45
46void
47options_free(struct options *oo)
48{
49	struct options_entry	*o;
50
51	while (!SPLAY_EMPTY(&oo->tree)) {
52		o = SPLAY_ROOT(&oo->tree);
53		SPLAY_REMOVE(options_tree, &oo->tree, o);
54		xfree(o->name);
55		if (o->type == OPTIONS_STRING)
56			xfree(o->str);
57		else if (o->type == OPTIONS_DATA)
58			o->freefn(o->data);
59		xfree(o);
60	}
61}
62
63struct options_entry *
64options_find1(struct options *oo, const char *name)
65{
66	struct options_entry	p;
67
68	p.name = (char *) name;
69	return (SPLAY_FIND(options_tree, &oo->tree, &p));
70}
71
72struct options_entry *
73options_find(struct options *oo, const char *name)
74{
75	struct options_entry	*o, p;
76
77	p.name = (char *) name;
78	o = SPLAY_FIND(options_tree, &oo->tree, &p);
79	while (o == NULL) {
80		oo = oo->parent;
81		if (oo == NULL)
82			break;
83		o = SPLAY_FIND(options_tree, &oo->tree, &p);
84	}
85	return (o);
86}
87
88void
89options_remove(struct options *oo, const char *name)
90{
91	struct options_entry	*o;
92
93	if ((o = options_find1(oo, name)) == NULL)
94		return;
95
96	SPLAY_REMOVE(options_tree, &oo->tree, o);
97	xfree(o->name);
98	if (o->type == OPTIONS_STRING)
99		xfree(o->str);
100	else if (o->type == OPTIONS_DATA)
101		o->freefn(o->data);
102	xfree(o);
103}
104
105struct options_entry *printflike3
106options_set_string(struct options *oo, const char *name, const char *fmt, ...)
107{
108	struct options_entry	*o;
109	va_list			 ap;
110
111	if ((o = options_find1(oo, name)) == NULL) {
112		o = xmalloc(sizeof *o);
113		o->name = xstrdup(name);
114		SPLAY_INSERT(options_tree, &oo->tree, o);
115	} else if (o->type == OPTIONS_STRING)
116		xfree(o->str);
117	else if (o->type == OPTIONS_DATA)
118		o->freefn(o->data);
119
120	va_start(ap, fmt);
121	o->type = OPTIONS_STRING;
122	xvasprintf(&o->str, fmt, ap);
123	va_end(ap);
124	return (o);
125}
126
127char *
128options_get_string(struct options *oo, const char *name)
129{
130	struct options_entry	*o;
131
132	if ((o = options_find(oo, name)) == NULL)
133		fatalx("missing option");
134	if (o->type != OPTIONS_STRING)
135		fatalx("option not a string");
136	return (o->str);
137}
138
139struct options_entry *
140options_set_number(struct options *oo, const char *name, long long value)
141{
142	struct options_entry	*o;
143
144	if ((o = options_find1(oo, name)) == NULL) {
145		o = xmalloc(sizeof *o);
146		o->name = xstrdup(name);
147		SPLAY_INSERT(options_tree, &oo->tree, o);
148	} else if (o->type == OPTIONS_STRING)
149		xfree(o->str);
150	else if (o->type == OPTIONS_DATA)
151		o->freefn(o->data);
152
153	o->type = OPTIONS_NUMBER;
154	o->num = value;
155	return (o);
156}
157
158long long
159options_get_number(struct options *oo, const char *name)
160{
161	struct options_entry	*o;
162
163	if ((o = options_find(oo, name)) == NULL)
164		fatalx("missing option");
165	if (o->type != OPTIONS_NUMBER)
166		fatalx("option not a number");
167	return (o->num);
168}
169
170struct options_entry *
171options_set_data(
172    struct options *oo, const char *name, void *value, void (*freefn)(void *))
173{
174	struct options_entry	*o;
175
176	if ((o = options_find1(oo, name)) == NULL) {
177		o = xmalloc(sizeof *o);
178		o->name = xstrdup(name);
179		SPLAY_INSERT(options_tree, &oo->tree, o);
180	} else if (o->type == OPTIONS_STRING)
181		xfree(o->str);
182	else if (o->type == OPTIONS_DATA)
183		o->freefn(o->data);
184
185	o->type = OPTIONS_DATA;
186	o->data = value;
187	o->freefn = freefn;
188	return (o);
189}
190
191void *
192options_get_data(struct options *oo, const char *name)
193{
194	struct options_entry	*o;
195
196	if ((o = options_find(oo, name)) == NULL)
197		fatalx("missing option");
198	if (o->type != OPTIONS_DATA)
199		fatalx("option not data");
200	return (o->data);
201}
202