aboutsummaryrefslogtreecommitdiff
path: root/src/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tree.c')
-rw-r--r--src/tree.c773
1 files changed, 773 insertions, 0 deletions
diff --git a/src/tree.c b/src/tree.c
new file mode 100644
index 0000000..52d38c0
--- /dev/null
+++ b/src/tree.c
@@ -0,0 +1,773 @@
1/* grecs - Gray's Extensible Configuration System
2 Copyright (C) 2007-2011 Sergey Poznyakoff
3
4 Grecs is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 3 of the License, or (at your
7 option) any later version.
8
9 Grecs is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with Grecs. If not, see <http://www.gnu.org/licenses/>. */
16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20#include <sys/types.h>
21#include <sys/socket.h>
22#include <sys/time.h>
23#include <sys/un.h>
24#include <netinet/in.h>
25#include <arpa/inet.h>
26#include <netdb.h>
27#include <stdlib.h>
28#include "grecs.h"
29
30struct grecs_node *
31grecs_node_create(enum grecs_node_type type, grecs_locus_t *loc)
32{
33 struct grecs_node *np = grecs_zalloc(sizeof(*np));
34 np->type = type;
35 if (loc)
36 np->locus = *loc;
37 return np;
38}
39
40void
41grecs_node_bind(struct grecs_node *master, struct grecs_node *node, int dn)
42{
43 struct grecs_node *np;
44
45 if (dn) {
46 if (!master->down)
47 master->down = node;
48 else {
49 for (np = master->down; np->next; np = np->next)
50 ;
51 np->next = node;
52 }
53 for (; node; node = node->next)
54 node->up = master;
55 } else {
56 if (!master->next)
57 master->next = node;
58 else {
59 for (np = master->next; np->next; np = np->next)
60 ;
61 np->next = node;
62 }
63 node->up = master->up;
64 }
65}
66
67
68static enum grecs_tree_recurse_res
69_tree_recurse(struct grecs_node *node, grecs_tree_recursor_t recfun,
70 void *data)
71{
72 enum grecs_tree_recurse_res res;
73#define CKRES() \
74 switch (res) { \
75 case grecs_tree_recurse_fail: \
76 case grecs_tree_recurse_stop: \
77 return res; \
78 default: \
79 break; \
80 }
81
82 for (; node; node = node->next) {
83 if (node->type == grecs_node_stmt) {
84 res = recfun(grecs_tree_recurse_set, node, data);
85 CKRES();
86 } else {
87 switch (recfun(grecs_tree_recurse_pre, node, data)) {
88 case grecs_tree_recurse_ok:
89 res = _tree_recurse(node->down, recfun, data);
90 CKRES();
91 res = recfun(grecs_tree_recurse_post, node,
92 data);
93 CKRES();
94 break;
95 case grecs_tree_recurse_fail:
96 return grecs_tree_recurse_fail;
97 case grecs_tree_recurse_stop:
98 return grecs_tree_recurse_stop;
99 case grecs_tree_recurse_skip:
100 break;
101 }
102 }
103 }
104 return grecs_tree_recurse_ok;
105#undef CKRES
106}
107
108int
109grecs_tree_recurse(struct grecs_node *node, grecs_tree_recursor_t recfun,
110 void *data)
111{
112 switch (_tree_recurse(node, recfun, data)) {
113 case grecs_tree_recurse_ok:
114 case grecs_tree_recurse_stop:
115 return 0;
116 default:
117 break;
118 }
119 return 1;
120}
121
122void
123grecs_node_free(struct grecs_node *node)
124{
125 /*FIXME: value*/
126 free(node);
127}
128
129void
130grecs_tree_free(struct grecs_node *node)
131{
132 while (node) {
133 struct grecs_node *next = node->next;
134 if (node->down)
135 grecs_tree_free(node->down);
136 grecs_node_free(node);
137 node = next;
138 }
139}
140
141
142
143static int
144fake_callback(enum grecs_callback_command cmd,
145 grecs_locus_t *locus,
146 void *varptr,
147 grecs_value_t *value,
148 void *cb_data)
149{
150 return 0;
151}
152
153static struct grecs_keyword fake = {
154 "*",
155 NULL,
156 NULL,
157 grecs_type_void,
158 NULL,
159 0,
160 fake_callback,
161 NULL,
162 &fake
163};
164
165static struct grecs_keyword *
166find_keyword(struct grecs_keyword *cursect, const char *ident)
167{
168 struct grecs_keyword *kwp;
169
170 if (cursect && cursect != &fake) {
171 for (kwp = cursect->kwd; kwp->ident; kwp++)
172 if (strcmp(kwp->ident, ident) == 0)
173 return kwp;
174 } else {
175 return &fake;
176 }
177 return NULL;
178}
179
180static void *
181target_ptr(struct grecs_keyword *kwp, char *base)
182{
183 if (kwp->varptr)
184 base = (char*) kwp->varptr + kwp->offset;
185 else if (base)
186 base += kwp->offset;
187
188 return base;
189}
190
191static int
192string_to_bool(const char *string, int *pval, grecs_locus_t *locus)
193{
194 if (strcmp(string, "yes") == 0
195 || strcmp(string, "true") == 0
196 || strcmp(string, "t") == 0
197 || strcmp(string, "1") == 0)
198 *pval = 1;
199 else if (strcmp(string, "no") == 0
200 || strcmp(string, "false") == 0
201 || strcmp(string, "nil") == 0
202 || strcmp(string, "0") == 0)
203 *pval = 0;
204 else {
205 grecs_error(locus, 0,
206 _("%s: not a valid boolean value"),
207 string);
208 return 1;
209 }
210 return 0;
211}
212
213static int
214string_to_host(struct in_addr *in, const char *string, grecs_locus_t *locus)
215{
216 if (inet_aton(string, in) == 0) {
217 struct hostent *hp;
218
219 hp = gethostbyname(string);
220 if (hp == NULL)
221 return 1;
222 memcpy(in, hp->h_addr, sizeof(struct in_addr));
223 }
224 return 0;
225}
226
227static int
228string_to_sockaddr(struct grecs_sockaddr *sp, const char *string,
229 grecs_locus_t *locus)
230{
231 if (string[0] == '/') {
232 struct sockaddr_un s_un;
233 if (strlen(string) >= sizeof(s_un.sun_path)) {
234 grecs_error(locus, 0,
235 _("%s: UNIX socket name too long"),
236 string);
237 return 1;
238 }
239 s_un.sun_family = AF_UNIX;
240 strcpy(s_un.sun_path, string);
241 sp->len = sizeof(s_un);
242 sp->sa = grecs_malloc(sp->len);
243 memcpy(sp->sa, &s_un, sp->len);
244 } else {
245 char *p = strchr(string, ':');
246 size_t len;
247 struct sockaddr_in sa;
248
249 sa.sin_family = AF_INET;
250 if (p)
251 len = p - string;
252 else