1 #include <stdlib.h>
2 #include <string.h>
3 #include <ctype.h>
4 #include "options.h"
5
6 struct sect sect_hd = {""};
7
to_integer(const char * str,int n)8 static int to_integer(const char *str, int n)
9 {
10 int i = *str=='-';
11 if (str[i]>'0' && str[i]<='9') {
12 i++;
13 for (; i<n; i++)
14 if (!isdigit(str[i]))
15 return 0;
16 return atoi(str);
17 }
18 return 0;
19 }
20
strtoval(char * str,union val * val)21 int strtoval(char *str, union val *val)
22 {
23 int n;
24 while (isspace(*str))
25 str++;
26 n = strlen(str);
27 while (n && isspace(str[n-1]))
28 n--;
29 val->integ = 0;
30 if (n==1 && *str=='0')
31 return 0;
32 if (n >= 4) {
33 str[n] = '\0';
34 val->p = str;
35 return 2;
36 }
37 if ((val->integ = to_integer(str, n)) != 0) {
38 return 0;
39 }
40 strncpy(val->str, str, 4);
41 if (n && n<4)
42 val->str[n] = '\0';
43 return 1;
44 }
45
getsect(const char * name,struct sect ** prev)46 static struct sect *getsect(const char *name, struct sect **prev)
47 {
48 struct sect *s = §_hd;
49 if (!name[0])
50 return s;
51 while (s->next) {
52 if (!strcmp(name, s->next->name)) {
53 if (prev)
54 *prev = s;
55 return s->next;
56 }
57 s = s->next;
58 }
59 return NULL;
60 }
61
addsect(const char * name)62 struct sect *addsect(const char *name)
63 {
64 struct sect *s = getsect(name, NULL);
65 if (!s) {
66 s = malloc(sizeof(struct sect));
67 strcpy(s->name, name);
68 s->opts = NULL;
69 s->next = sect_hd.next;
70 sect_hd.next = s;
71 }
72 return s;
73 }
74
newopt(const char * key,union val val,int tp)75 static struct option *newopt(const char *key, union val val, int tp)
76 {
77 struct option *o;
78 int n = sizeof(struct option) + strlen(key) - 2;
79 int m = 0;
80 char *p;
81 if (tp == 1 && val.str[3])
82 m = 5;
83 if (tp == 2)
84 m = strlen(val.p)+1;
85 o = malloc(n+m);
86 o->val = val;
87 if (m) {
88 p = (char *) o;
89 p += n;
90 if (tp == 2) {
91 strncpy(o->val.str, val.p, 4);
92 strcpy(p, val.p);
93 } else {
94 memcpy(p, val.str, 4);
95 p[4] = '\0';
96 }
97 tp = 1;
98 }
99 o->tp_key[0] = tp;
100 strcpy(opt_key(o), key);
101 return o;
102 }
103
addopt(const char * key,union val val,int tp,struct sect * sect)104 void addopt(const char *key, union val val, int tp, struct sect *sect)
105 {
106 struct option *o = newopt(key, val, tp);
107 if (!sect)
108 sect = §_hd;
109 o->next = sect->opts;
110 sect->opts = o;
111 }
112
getoptions(const char * sect_name)113 struct option *getoptions(const char *sect_name)
114 {
115 struct sect *s = getsect(sect_name, NULL);
116 if (s)
117 return s->opts;
118 return NULL;
119 }
120
121 /* getopt might be declared in stdio.h */
get_opt(const char * sect_name,const char * key)122 static struct option *get_opt(const char *sect_name, const char *key)
123 {
124 struct option *o = getoptions(sect_name);
125 while (o) {
126 if (!strcmp(key, opt_key(o)))
127 return o;
128 o = o->next;
129 }
130 return NULL;
131 }
132
getopt_int(const char * sect_name,const char * key)133 int getopt_int(const char *sect_name, const char *key)
134 {
135 struct option *o = get_opt(sect_name, key);
136 if (o) {
137 const char *s = opt_longstr(o);
138 if (s) {
139 int d = to_integer(s, strlen(s));
140 if (d != 0)
141 return d;
142 }
143 return o->val.integ;
144 }
145 return 0;
146 }
147
getopt_str(const char * sect_name,const char * key)148 char *getopt_str(const char *sect_name, const char *key)
149 {
150 struct option *o = get_opt(sect_name, key);
151 if (o)
152 return opt_longstr(o);
153 return NULL;
154 }
155
opt_longstr(struct option * o)156 char *opt_longstr(struct option *o)
157 {
158 if (opt_isint(o))
159 return NULL;
160 if (!o->val.str[3])
161 return o->val.str;
162 return (char *) o + (sizeof(struct option) + strlen(opt_key(o)) - 2);
163 }
164
rmopt(const char * key,struct option * o)165 static void rmopt(const char *key, struct option *o)
166 {
167 struct option *p;
168 while (o->next) {
169 if (!strcmp(key, opt_key(o->next))) {
170 p = o->next;
171 o->next = p->next;
172 free(p);
173 } else
174 o = o->next;
175 }
176 }
177
setoption(const char * sect_name,const char * key,union val val,int tp)178 void setoption(const char *sect_name, const char *key, union val val, int tp)
179 {
180 struct sect *s = addsect(sect_name);
181 struct option *o;
182 if (tp==0 || tp==1 && !val.str[3]) {
183 o = s->opts;
184 while (o) {
185 if (!strcmp(key, opt_key(o))) {
186 o->val = val;
187 o->tp_key[0] = tp;
188 rmopt(key, o);
189 return;
190 }
191 o = o->next;
192 }
193 }
194 addopt(key, val, tp, s);
195 rmopt(key, s->opts);
196 }
197
unsetoption(const char * sect_name,const char * key)198 void unsetoption(const char *sect_name, const char *key)
199 {
200 struct sect *s = getsect(sect_name, NULL);
201 struct option *o;
202 if (!s || !s->opts)
203 return;
204 o = s->opts;
205 if (!strcmp(key, opt_key(o))) {
206 s->opts = o->next;
207 free(o);
208 } else
209 rmopt(key, o);
210 }
211
freeoptions(const char * sect_name)212 void freeoptions(const char *sect_name)
213 {
214 struct sect *s, *p;
215 struct option *o;
216 if (sect_name[0]) {
217 s = getsect(sect_name, &p);
218 if (!s)
219 return;
220 p->next = s->next;
221 } else {
222 while (sect_hd.next)
223 freeoptions(sect_hd.next->name);
224 s = §_hd;
225 }
226 while (o = s->opts) {
227 s->opts = o->next;
228 free(o);
229 }
230 if (sect_name[0])
231 free(s);
232 else
233 s->opts = NULL;
234 }
235