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