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