1 /* grecs - Gray's Extensible Configuration System
2    Copyright (C) 2007-2016 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 <errno.h>
29 #include <limits.h>
30 #include <string.h>
31 #include "grecs.h"
32 
33 struct grecs_sockaddr_hints *grecs_sockaddr_hints;
34 
35 void
grecs_value_free_content(struct grecs_value * val)36 grecs_value_free_content(struct grecs_value *val)
37 {
38 	int i;
39 
40 	if (!val)
41 		return;
42 	switch (val->type) {
43 	case GRECS_TYPE_STRING:
44 		grecs_free(val->v.string);
45 		break;
46 
47 	case GRECS_TYPE_LIST:
48 		grecs_list_free(val->v.list);
49 		break;
50 
51 	case GRECS_TYPE_ARRAY:
52 		for (i = 0; i < val->v.arg.c; i++)
53 			grecs_value_free(val->v.arg.v[i]);
54 		free(val->v.arg.v);
55 	}
56 }
57 
58 void
grecs_value_free(struct grecs_value * val)59 grecs_value_free(struct grecs_value *val)
60 {
61 	grecs_value_free_content(val);
62 	grecs_free(val);
63 }
64 
65 const char *
grecs_value_type_string(int t)66 grecs_value_type_string(int t)
67 {
68 	static const char *types[] = {
69 		[GRECS_TYPE_STRING] = N_("string"),
70 		[GRECS_TYPE_LIST]   = N_("list"),
71 		[GRECS_TYPE_ARRAY]  = N_("one or more arguments")
72 	};
73 	if (t >= 0 && t < sizeof(types) / sizeof(types[0]))
74 		return types[t];
75 	return N_("unrecognized type; please report");
76 }
77 
78 struct grecs_node *
grecs_node_create(enum grecs_node_type type,grecs_locus_t * loc)79 grecs_node_create(enum grecs_node_type type, grecs_locus_t *loc)
80 {
81 	struct grecs_node *np = grecs_zalloc(sizeof(*np));
82 	np->type = type;
83 	if (loc)
84 		np->locus = *loc;
85 	return np;
86 }
87 
88 struct grecs_node *
grecs_node_create_points(enum grecs_node_type type,struct grecs_locus_point beg,struct grecs_locus_point end)89 grecs_node_create_points(enum grecs_node_type type,
90 			 struct grecs_locus_point beg,
91 			 struct grecs_locus_point end)
92 {
93 	grecs_locus_t loc;
94 
95 	loc.beg = beg;
96 	loc.end = end;
97 	return grecs_node_create(type, &loc);
98 }
99 
100 void
grecs_node_bind(struct grecs_node * master,struct grecs_node * node,int dn)101 grecs_node_bind(struct grecs_node *master, struct grecs_node *node, int dn)
102 {
103 	struct grecs_node *np;
104 
105 	if (!node)
106 		return;
107 	if (dn) {
108 		if (!master->down) {
109 			master->down = node;
110 			node->prev = NULL;
111 		} else {
112 			for (np = master->down; np->next; np = np->next)
113 				;
114 			np->next = node;
115 			node->prev = np;
116 		}
117 		for (; node; node = node->next)
118 			node->up = master;
119 	} else {
120 		if (!master->next) {
121 			master->next = node;
122 			node->prev = master;
123 		} else {
124 			for (np = master->next; np->next; np = np->next)
125 				;
126 			np->next = node;
127 			node->prev = np;
128 		}
129 		node->up = master->up;
130 	}
131 }
132 
133 int
grecs_node_unlink(struct grecs_node * node)134 grecs_node_unlink(struct grecs_node *node)
135 {
136 	if (node->prev)
137 		node->prev->next = node->next;
138 	else if (node->up)
139 		node->up->down = node->next;
140 	else
141 		return 1;
142 	if (node->next)
143 		node->next->prev = node->prev;
144 	node->up = node->prev = node->next = NULL;
145 	return 0;
146 }
147 
148 static void
listel_dispose(void * el)149 listel_dispose(void *el)
150 {
151 	grecs_free(el);
152 }
153 
154 struct grecs_list *
_grecs_simple_list_create(int dispose)155 _grecs_simple_list_create(int dispose)
156 {
157 	struct grecs_list *lp = grecs_list_create();
158 	if (dispose)
159 		lp->free_entry = listel_dispose;
160 	return lp;
161 }
162 
163 
164 
165 
166 static enum grecs_tree_recurse_res
_tree_recurse(struct grecs_node * node,grecs_tree_recursor_t recfun,void * data)167 _tree_recurse(struct grecs_node *node, grecs_tree_recursor_t recfun,
168 	      void *data)
169 {
170 	enum grecs_tree_recurse_res res;
171 #define CKRES()						\
172 	switch (res) {					\
173         case grecs_tree_recurse_fail:			\
174         case grecs_tree_recurse_stop:			\
175 		return res;				\
176 	default:					\
177 		break;					\
178 	}
179 
180 	while (node) {
181 		struct grecs_node *next = node->next;
182 		if (node->type == grecs_node_stmt) {
183 			res = recfun(grecs_tree_recurse_set, node, data);
184 			CKRES();
185 		} else {
186 			switch (recfun(grecs_tree_recurse_pre, node, data)) {
187 			case grecs_tree_recurse_ok:
188 				res = _tree_recurse(node->down, recfun, data);
189 				CKRES();
190 				res = recfun(grecs_tree_recurse_post, node,
191 					     data);
192 				CKRES();
193 				break;
194 			case grecs_tree_recurse_fail:
195 				return grecs_tree_recurse_fail;
196 			case grecs_tree_recurse_stop:
197 				return grecs_tree_recurse_stop;
198 			case grecs_tree_recurse_skip:
199 				break;
200 			}
201 		}
202 		node = next;
203 	}
204 	return grecs_tree_recurse_ok;
205 #undef CKRES
206 }
207 
208 int
grecs_tree_recurse(struct grecs_node * node,grecs_tree_recursor_t recfun,void * data)209 grecs_tree_recurse(struct grecs_node *node, grecs_tree_recursor_t recfun,
210 		   void *data)
211 {
212 	switch (_tree_recurse(node, recfun, data)) {
213 	case grecs_tree_recurse_ok:
214 	case grecs_tree_recurse_stop:
215 		return 0;
216 	default:
217 		break;
218 	}
219 	return 1;
220 }
221 
222 void
grecs_node_free(struct grecs_node * node)223 grecs_node_free(struct grecs_node *node)
224 {
225 	if (!node)
226 		return;
227 	switch (node->type) {
228 	case grecs_node_root:
229 		grecs_symtab_free(node->v.texttab);
230 		break;
231 	default:
232 		grecs_value_free(node->v.value);
233 	}
234 	grecs_free(node->ident);
235 	grecs_free(node);
236 }
237 
238 static enum grecs_tree_recurse_res
freeproc(enum grecs_tree_recurse_op op,struct grecs_node * node,void * data)239 freeproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data)
240 {
241 	switch (op) {
242 	case grecs_tree_recurse_set:
243 	case grecs_tree_recurse_post:
244 		grecs_node_unlink(node);
245 		grecs_node_free(node);
246 		break;
247 	case grecs_tree_recurse_pre:
248 		/* descend into the subtree */
249 		break;
250 	}
251 	return grecs_tree_recurse_ok;
252 }
253 
254 int
grecs_tree_free(struct grecs_node * node)255 grecs_tree_free(struct grecs_node *node)
256 {
257 	if (!node)
258 		return 0;
259 	if (node->type != grecs_node_root) {
260 		errno = EINVAL;
261 		return 1;
262 	}
263 	grecs_tree_recurse(node, freeproc, NULL);
264 	return 0;
265 }
266 
267 
268 
269 static int
fake_callback(enum grecs_callback_command cmd,grecs_node_t * node,void * varptr,void * cb_data)270 fake_callback(
271 #if GRECS_TREE_API
272 	enum grecs_callback_command cmd,
273 	grecs_node_t *node,
274 	void *varptr,
275 	void *cb_data
276 #else
277 	enum grecs_callback_command cmd,
278 	grecs_locus_t *locus,
279 	void *varptr,
280 	grecs_value_t *value,
281 	void *cb_data
282 #endif
283 	)
284 {
285 	return 0;
286 }
287 
288 static struct grecs_keyword fake = {
289 	"*",
290 	NULL,
291 	NULL,
292 	grecs_type_void,
293 	GRECS_DFLT,
294 	NULL,
295 	0,
296 	fake_callback,
297 	NULL,
298 	&fake
299 };
300 
301 static struct grecs_keyword *
find_keyword(struct grecs_keyword * cursect,grecs_node_t * node)302 find_keyword(struct grecs_keyword *cursect, grecs_node_t *node)
303 {
304 	if (cursect && cursect->kwd && cursect != &fake) {
305 		struct grecs_keyword *found = NULL, *kwp;
306 		char const *msg;
307 
308 		for (kwp = cursect->kwd; kwp->ident; kwp++) {
309 			if (strcmp(kwp->ident, node->ident) == 0) {
310 				found = kwp;
311 				if (kwp->callback
312 				    || (node->down
313 				         ? kwp->type == grecs_type_section
314 					: kwp->type != grecs_type_section))
315 					return kwp;
316 			}
317 		}
318 		if (found) {
319 			if (found->type == grecs_type_section) {
320 				msg = N_("section keyword used as a scalar");
321 			} else {
322 				msg = N_("scalar keyword used as a section");
323 			}
324 		} else {
325 			msg = N_("unknown keyword");
326 		}
327 		grecs_error(&node->idloc, 0, "%s", gettext(msg));
328 	} else {
329 		return &fake;
330 	}
331 	return NULL;
332 }
333 
334 static void *
target_ptr(struct grecs_keyword * kwp,char * base)335 target_ptr(struct grecs_keyword *kwp, char *base)
336 {
337 	if (kwp->varptr)
338 		base = (char*) kwp->varptr + kwp->offset;
339 	else if (base)
340 		base += kwp->offset;
341 
342 	return base;
343 }
344 
345 static int
string_to_bool(const char * string,int * pval,grecs_locus_t const * locus)346 string_to_bool(const char *string, int *pval, grecs_locus_t const *locus)
347 {
348 	if (strcmp(string, "yes") == 0
349 	    || strcmp(string, "true") == 0
350 	    || strcmp(string, "t") == 0
351 	    || strcmp(string, "1") == 0)
352 		*pval = 1;
353 	else if (strcmp(string, "no") == 0
354 		 || strcmp(string, "false") == 0
355 		 || strcmp(string, "nil") == 0
356 		 || strcmp(string, "0") == 0)
357 		*pval = 0;
358 	else {
359 		grecs_error(locus, 0,
360 			     _("%s: not a valid boolean value"),
361 			     string);
362 		return 1;
363 	}
364 	return 0;
365 }
366 
367 static int
string_to_host(struct in_addr * in,const char * string,grecs_locus_t const * locus)368 string_to_host(struct in_addr *in, const char *string,
369 	       grecs_locus_t const *locus)
370 {
371 	if (inet_aton(string, in) == 0) {
372 		struct hostent *hp;
373 
374 		hp = gethostbyname(string);
375 		if (hp == NULL)
376 			return 1;
377 		memcpy(in, hp->h_addr, sizeof(struct in_addr));
378 	}
379 	return 0;
380 }
381 
382 #if !GRECS_SOCKADDR_LIST
383 static int
string_to_sockaddr(struct grecs_sockaddr * sp,const char * string,grecs_locus_t const * locus)384 string_to_sockaddr(struct grecs_sockaddr *sp, const char *string,
385 		   grecs_locus_t const *locus)
386 {
387 	if (string[0] == '/') {
388 		struct sockaddr_un s_un;
389 		if (strlen(string) >= sizeof(s_un.sun_path)) {
390 			grecs_error(locus, 0,
391 				     _("%s: UNIX socket name too long"),
392 				     string);
393 			return 1;
394 		}
395 		s_un.sun_family = AF_UNIX;
396 		strcpy(s_un.sun_path, string);
397 		sp->len = sizeof(s_un);
398 		sp->sa = grecs_malloc(sp->len);
399 		memcpy(sp->sa, &s_un, sp->len);
400 	} else {
401 		char *p = strchr(string, ':');
402 		size_t len;
403 		struct sockaddr_in sa;
404 
405 		sa.sin_family = AF_INET;
406 		if (p)
407 			len = p - string;
408 		else
409 			len = strlen(string);
410 
411 		if (len == 0)
412 			sa.sin_addr.s_addr = INADDR_ANY;
413 		else {
414 			char *host = grecs_malloc(len + 1);
415 			memcpy(host, string, len);
416 			host[len] = 0;
417 
418 			if (string_to_host(&sa.sin_addr, host, locus)) {
419 				grecs_error(locus, 0,
420 					     _("%s: not a valid IP address or hostname"),
421 					     host);
422 				grecs_free(host);
423 				return 1;
424 			}
425 			grecs_free(host);
426 		}
427 
428 		if (p) {
429 			struct servent *serv;
430 
431 			p++;
432 			serv = getservbyname(p, "tcp");
433 			if (serv != NULL)
434 				sa.sin_port = serv->s_port;
435 			else {
436 				unsigned long l;
437 				char *q;
438 
439 				/* Not in services, maybe a number? */
440 				l = strtoul(p, &q, 0);
441 
442 				if (*q || l > USHRT_MAX) {
443 					grecs_error(locus, 0,
444 						     _("%s: not a valid port number"), p);
445 					return 1;
446 				}
447 				sa.sin_port = htons(l);
448 			}
449 		} else if (grecs_default_port)
450 			sa.sin_port = grecs_default_port;
451 		else {
452 			grecs_error(locus, 0, _("missing port number"));
453 			return 1;
454 		}
455 		sp->len = sizeof(sa);
456 		sp->sa = grecs_malloc(sp->len);
457 		memcpy(sp->sa, &sa, sp->len);
458 	}
459 	return 0;
460 }
461 #endif
462 
463 /* The TYPE_* defines come from gnulib's intprops.h */
464 
465 /* True if the arithmetic type T is signed.  */
466 # define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
467 
468 /* The maximum and minimum values for the integer type T.  These
469    macros have undefined behavior if T is signed and has padding bits. */
470 # define TYPE_MINIMUM(t) \
471   ((t) (! TYPE_SIGNED(t) \
472         ? (t) 0 \
473         : TYPE_SIGNED_MAGNITUDE(t) \
474         ? ~ (t) 0 \
475         : ~ TYPE_MAXIMUM(t)))
476 # define TYPE_MAXIMUM(t) \
477   ((t) (! TYPE_SIGNED(t) \
478         ? (t) -1 \
479         : ((((t) 1 << (sizeof(t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
480 # define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
481 
482 
483 #define STRTONUM(s, type, base, res, limit, loc)			\
484   {									\
485     type sum = 0;							\
486     									\
487     for (; *s; s++)							\
488       {									\
489 	type x;								\
490 									\
491 	if ('0' <= *s && *s <= '9')					\
492 	  x = sum * base + *s - '0';					\
493 	else if (base == 16 && 'a' <= *s && *s <= 'f')			\
494 	  x = sum * base + *s - 'a';					\
495 	else if (base == 16 && 'A' <= *s && *s <= 'F')			\
496 	  x = sum * base + *s - 'A';					\
497 	else								\
498 	  break;							\
499 	if (x <= sum)							\
500 	  {								\
501 	    grecs_error(loc, 0, _("numeric overflow"));		        \
502 	    return 1;							\
503 	  }								\
504 	else if (limit && x > limit)					\
505 	  {								\
506 	    grecs_error(loc, 0, _("value out of allowed range"));	\
507 	    return 1;							\
508 	  }								\
509 	sum = x;							\
510       }									\
511     res = sum;								\
512   }
513 
514 #define STRxTONUM(s, type, res, limit, loc)				\
515   {									\
516     int base;								\
517     if (*s == '0')							\
518       {									\
519 	s++;								\
520 	if (*s == 0)							\
521 	  base = 10;							\
522 	else if (*s == 'x' || *s == 'X')				\
523 	  {								\
524 	    s++;							\
525 	    base = 16;							\
526 	  }								\
527 	else								\
528 	  base = 8;							\
529       } else								\
530       base = 10;							\
531     STRTONUM(s, type, base, res, limit, loc);				\
532   }
533 
534 #define GETUNUM(str, type, res, loc)					\
535   {									\
536     type tmpres;							\
537     const char *s = str;						\
538     STRxTONUM(s, type, tmpres, 0, loc);				\
539     if (*s)								\
540       {									\
541 	grecs_error(loc, 0, _("not a number (stopped near `%s')"),	\
542 		     s);						\
543 	return 1;							\
544       }									\
545     res = tmpres;							\
546   }
547 
548 #define GETSNUM(str, type, res, loc)					\
549   {									\
550     unsigned type tmpres;						\
551     const char *s = str;						\
552     int sign;							        \
553     unsigned type limit;						\
554     									\
555     if (*s == '-')							\
556       {									\
557 	sign = 1;							\
558 	s++;								\
559 	limit = TYPE_MINIMUM(type);					\
560 	limit = - limit;						\
561       }									\
562     else								\
563       {									\
564 	sign = 0;							\
565 	limit = TYPE_MAXIMUM(type);					\
566       }									\
567     									\
568     STRxTONUM(s, unsigned type, tmpres, limit, loc);			\
569     if (*s)								\
570       {									\
571 	grecs_error(loc, 0, _("not a number (stopped near `%s')"), s);	\
572 	return 1;							\
573       }									\
574     res = sign ? - tmpres : tmpres;					\
575   }
576 
577 
578 int
grecs_string_convert(void * target,enum grecs_data_type type,const char * string,grecs_locus_t const * locus)579 grecs_string_convert(void *target, enum grecs_data_type type,
580 		     const char *string, grecs_locus_t const *locus)
581 {
582   switch (type) {
583   case grecs_type_void:
584 	  abort();
585 
586   case grecs_type_null:
587 	  break;
588 
589   case grecs_type_string:
590 	  *(char**)target = grecs_strdup(string);
591 	  break;
592 
593   case grecs_type_short:
594 	  GETUNUM(string, short, *(short*)target, locus);
595 	  break;
596 
597   case grecs_type_ushort:
598 	  GETUNUM(string, unsigned short, *(unsigned short*)target, locus);
599 	  break;
600 
601   case grecs_type_bool:
602 	  return string_to_bool(string, (int*)target, locus);
603 
604   case grecs_type_int:
605 	  GETSNUM(string, int, *(int*)target, locus);
606 	  break;
607 
608   case grecs_type_uint:
609 	  GETUNUM(string, unsigned int, *(unsigned int*)target, locus);
610 	  break;
611 
612   case grecs_type_long:
613 	  GETSNUM(string, long, *(long*)target, locus);
614 	  break;
615 
616   case grecs_type_ulong:
617 	  GETUNUM(string, unsigned long, *(unsigned long*)target, locus);
618 	  break;
619 
620   case grecs_type_size:
621 	  GETUNUM(string, size_t, *(size_t*)target, locus);
622 	  break;
623 	  /*FIXME
624   case grecs_type_off:
625           GETSNUM(string, off_t, *(off_t*)target, locus);
626 	  break;
627 	  */
628   case grecs_type_time:
629 	  /*FIXME: Use getdate */
630 	  GETUNUM(string, time_t, *(time_t*)target, locus);
631 	  break;
632 
633   case grecs_type_ipv4:
634 	  if (inet_aton(string, (struct in_addr *)target)) {
635 		  grecs_error(locus, 0, _("%s: not a valid IP address"),
636 			       string);
637 		  return 1;
638 	  }
639 	  break;
640 
641   case grecs_type_host:
642 	  if (string_to_host((struct in_addr *)target, string, locus)) {
643 		  grecs_error(locus, 0,
644 			       _("%s: not a valid IP address or hostname"),
645 			       string);
646 		  return 1;
647 	  }
648 	  break;
649 
650   case grecs_type_sockaddr:
651 #if GRECS_SOCKADDR_LIST
652 	  return grecs_str_to_sockaddr((struct grecs_sockaddr **)target,
653 				       string, grecs_sockaddr_hints,
654 				       locus);
655 #else
656 	  return string_to_sockaddr((struct grecs_sockaddr *)target, string,
657 				    locus);
658 #endif
659 
660   case grecs_type_cidr:
661 	  return grecs_str_to_cidr((struct grecs_cidr *)target, string, locus);
662 
663   case grecs_type_section:
664 	  grecs_error(locus, 0,
665 		       _("invalid use of block statement"));
666 	  return 1;
667   }
668   return 0;
669 }
670 
671 struct grecs_prop
672 {
673 	size_t size;
674 	int (*cmp)(const void *, const void *);
675 };
676 
677 static int
string_cmp(const void * elt1,const void * elt2)678 string_cmp(const void *elt1, const void *elt2)
679 {
680 	return strcmp((const char *)elt1,(const char *)elt2);
681 }
682 
683 #define __grecs_name_cat__(a,b) a ## b
684 #define NUMCMP(type) __grecs_name_cat__(type,_cmp)
685 #define __DECL_NUMCMP(type,ctype)			\
686   static int						\
687   NUMCMP(type)(const void *elt1, const void *elt2)	\
688   {							\
689     return memcmp(elt1, elt2, sizeof(ctype));		\
690   }
691 #define DECL_NUMCMP(type) __DECL_NUMCMP(type,type)
692 
693 DECL_NUMCMP(short)
DECL_NUMCMP(int)694 DECL_NUMCMP(int)
695 DECL_NUMCMP(long)
696 DECL_NUMCMP(size_t)
697 /*FIXME DECL_NUMCMP(off_t)*/
698 DECL_NUMCMP(time_t)
699 __DECL_NUMCMP(in_addr, struct in_addr)
700 __DECL_NUMCMP(grecs_sockaddr, struct grecs_sockaddr)
701 
702 static int
703 cidr_cmp(const void *elt1, const void *elt2)
704 {
705 	struct grecs_cidr const *cp1 = elt1, *cp2 = elt2;
706 	return !(cp1->family == cp2->family
707 		 && cp1->len == cp2->len
708 		 && memcmp(cp1->address, cp2->address, cp1->len) == 0
709 		 && memcmp(cp1->netmask, cp2->netmask, cp1->len) == 0);
710 }
711 
712 struct grecs_prop grecs_prop_tab[] = {
713 	{ 0, NULL },                                 /* grecs_type_void */
714 	{ sizeof(char*), string_cmp },               /* grecs_type_string */
715 	{ sizeof(short), NUMCMP(short) },            /* grecs_type_short */
716 	{ sizeof(unsigned short), NUMCMP(short) },   /* grecs_type_ushort */
717 	{ sizeof(int), NUMCMP(int) },                /* grecs_type_int */
718 	{ sizeof(unsigned int), NUMCMP(int) },       /* grecs_type_uint */
719 	{ sizeof(long), NUMCMP(long) },              /* grecs_type_long */
720 	{ sizeof(unsigned long), NUMCMP(long) },     /* grecs_type_ulong */
721 	{ sizeof(size_t), NUMCMP(size_t) },          /* grecs_type_size */
722 #if 0
723 	FIXME
724 	{ sizeof(off_t), NUMCMP(off_t) },            /* grecs_type_off */
725 #endif
726 	{ sizeof(time_t), NUMCMP(time_t) },          /* grecs_type_time */
727 	{ sizeof(int), NUMCMP(int) },                /* grecs_type_bool */
728 	{ sizeof(struct in_addr), NUMCMP(in_addr) }, /* grecs_type_ipv4 */
729 	{ sizeof(struct grecs_cidr), cidr_cmp },     /* grecs_type_cidr */
730 	{ sizeof(struct in_addr), NUMCMP(in_addr) }, /* grecs_type_host */
731 	{ sizeof(struct grecs_sockaddr), NUMCMP(grecs_sockaddr) },
732                                                	      /* grecs_type_sockaddr */
733 	{ 0, NULL },                                  /* grecs_type_section */
734 	{ 0, NULL }                                   /* grecs_type_null */
735 };
736 #define grecs_prop_count \
737  (sizeof(grecs_prop_tab) / sizeof(grecs_prop_tab[0]))
738 
739 void
grecs_process_ident(struct grecs_keyword * kwp,grecs_value_t * value,void * base,grecs_locus_t * locus)740 grecs_process_ident(struct grecs_keyword *kwp, grecs_value_t *value,
741 		     void *base, grecs_locus_t *locus)
742 {
743 	void *target;
744 
745 	if (!kwp)
746 		return;
747 
748 	target = target_ptr(kwp, (char *) base);
749 
750 	if (kwp->callback) {
751 #if GRECS_TREE_API
752 		struct grecs_node node = { 0 };
753 		node.locus = *locus;
754 		node.v.value = value;
755 		node.ident = (char*) kwp->ident;
756 		kwp->callback(grecs_callback_set_value,
757 			      &node,
758 			      target,
759 			      &kwp->callback_data);
760 #else
761 		kwp->callback(grecs_callback_set_value,
762 			      locus,
763 			      target,
764 			      value,
765 			      &kwp->callback_data);
766 #endif
767 	} else if (kwp->type == grecs_type_void || target == NULL)
768 		return;
769 	else if (!value) {
770 		grecs_error(locus, 0, "%s has no value", kwp->ident);
771 		return;
772 	} else if (value->type == GRECS_TYPE_ARRAY) {
773 		grecs_error(locus, 0,
774 			     _("too many arguments to `%s'; missing semicolon?"),
775 			     kwp->ident);
776 		return;
777 	} else if (value->type == GRECS_TYPE_LIST) {
778 		if (kwp->flags & GRECS_LIST) {
779 			struct grecs_list_entry *ep;
780 			enum grecs_data_type type = kwp->type;
781 			int num = 1;
782 			struct grecs_list *list;
783 			size_t size;
784 
785 			if (type >= grecs_prop_count
786 			    || (size = grecs_prop_tab[type].size) == 0) {
787 				grecs_error(locus, 0,
788 					     _("INTERNAL ERROR at %s:%d: "
789 					       "unhandled data type %d"),
790 					     __FILE__, __LINE__, type);
791 				abort();
792 			}
793 
794 			list = _grecs_simple_list_create(
795 				     type == grecs_type_string);
796 			list->cmp = grecs_prop_tab[type].cmp;
797 
798 			for (ep = value->v.list->head; ep; ep = ep->next) {
799 				const grecs_value_t *vp = ep->data;
800 
801 				if (vp->type != GRECS_TYPE_STRING)
802 					grecs_error(&vp->locus, 0,
803 			     _("%s: incompatible data type in list item #%d"),
804 						     kwp->ident, num);
805 				else if (type == grecs_type_string)
806 					grecs_list_append(list,
807 							  grecs_strdup(vp->v.string));
808 				else {
809 					void *ptr = grecs_malloc(size);
810 					if (grecs_string_convert(ptr,
811 								 type,
812 								 vp->v.string,
813 								 &vp->locus)
814 					    == 0)
815 						grecs_list_append(list, ptr);
816 					else
817 						grecs_free(ptr);
818 				}
819 			}
820 			*(struct grecs_list**)target = list;
821 		} else {
822 			grecs_error(locus, 0,
823 				     _("incompatible data type for `%s'"),
824 				     kwp->ident);
825 			return;
826 		}
827 	} else if (kwp->flags & GRECS_LIST) {
828 		struct grecs_list *list;
829 		enum grecs_data_type type = kwp->type;
830 		size_t size;
831 		void *ptr;
832 
833 		if (type >= grecs_prop_count
834 		    || (size = grecs_prop_tab[type].size) == 0) {
835 			grecs_error(locus, 0,
836 				     _("INTERNAL ERROR at %s:%d: unhandled data type %d"),
837 				     __FILE__, __LINE__, type);
838 			abort();
839 		}
840 
841 		list = _grecs_simple_list_create(1);
842 		list->cmp = grecs_prop_tab[type].cmp;
843 		if (type == grecs_type_string)
844 			grecs_list_append(list,
845 					  grecs_strdup(value->v.string));
846 		else {
847 			ptr = grecs_malloc(size);
848 			if (grecs_string_convert(ptr, type,
849 						 value->v.string,
850 						 &value->locus)) {
851 				grecs_free(ptr);
852 				grecs_list_free(list);
853 				return;
854 			}
855 			grecs_list_append(list, ptr);
856 		}
857 		*(struct grecs_list**)target = list;
858 	} else {
859 		if (kwp->type == grecs_type_string
860 		    && !(kwp->flags & GRECS_CONST))
861 			free(*(char**)target);
862 		grecs_string_convert(target, kwp->type,
863 				     value->v.string,
864 				     &value->locus);
865 	}
866 	kwp->flags &= ~GRECS_CONST;
867 }
868 
869 
870 struct nodeproc_closure {
871 	struct grecs_keyword *cursect;
872 	struct grecs_list *sections;
873 	int flags;
874 };
875 #define CURRENT_BASE(clos) \
876 	((char*)((clos)->cursect ? (clos)->cursect->callback_data : NULL))
877 
878 static void
stmt_begin(struct nodeproc_closure * clos,struct grecs_keyword * kwp,struct grecs_node * node)879 stmt_begin(struct nodeproc_closure *clos,
880 	   struct grecs_keyword *kwp, struct grecs_node *node)
881 {
882 	void *target;
883 
884 	grecs_list_push(clos->sections, clos->cursect);
885 	if (kwp) {
886 		target = target_ptr(kwp, CURRENT_BASE(clos));
887 		clos->cursect = kwp;
888 		if (kwp->callback) {
889 #if GRECS_TREE_API
890 			if (kwp->callback(grecs_callback_section_begin,
891 					  node,
892 					  target,
893 					  &kwp->callback_data))
894 #else
895 			if (kwp->callback(grecs_callback_section_begin,
896 					  &node->locus,
897 					  target,
898 					  node->v.value,
899 					  &kwp->callback_data))
900 #endif
901 				clos->cursect = &fake;
902 		} else
903 			kwp->callback_data = target;
904 	} else
905 		/* install an "ignore-all" section */
906 		clos->cursect = kwp;
907 }
908 
909 static void
stmt_end(struct nodeproc_closure * clos,struct grecs_node * node)910 stmt_end(struct nodeproc_closure *clos, struct grecs_node *node)
911 {
912 	grecs_callback_fn callback = NULL;
913 	void *dataptr = NULL;
914 	struct grecs_keyword *kwp = clos->cursect;
915 
916 	if (clos->cursect && clos->cursect->callback) {
917 		callback = clos->cursect->callback;
918 		dataptr = &clos->cursect->callback_data;
919 	}
920 
921 	clos->cursect = (struct grecs_keyword *)grecs_list_pop(clos->sections);
922 	if (!clos->cursect)
923 		abort();
924 	if (callback)
925 #if GRECS_TREE_API
926 		callback(grecs_callback_section_end,
927 			 node,
928 			 kwp ? target_ptr(kwp, CURRENT_BASE(clos)) : NULL,
929 			 dataptr);
930 #else
931 		callback(grecs_callback_section_end,
932 			 &node->locus,
933 			 kwp ? target_ptr(kwp, CURRENT_BASE(clos)) : NULL,
934 			 NULL,
935 			 dataptr);
936 #endif
937 	if (kwp)
938 		kwp->callback_data = NULL;
939 }
940 
941 static enum grecs_tree_recurse_res
nodeproc(enum grecs_tree_recurse_op op,struct grecs_node * node,void * data)942 nodeproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data)
943 {
944 	struct nodeproc_closure *clos = data;
945 	struct grecs_keyword *kwp;
946 
947 	switch (op) {
948 	case grecs_tree_recurse_set:
949 		kwp = find_keyword(clos->cursect, node);
950 		if (!kwp)
951 			return grecs_tree_recurse_skip;
952 		grecs_process_ident(kwp, node->v.value, CURRENT_BASE(clos),
953 				    &node->idloc);
954 		break;
955 
956 	case grecs_tree_recurse_pre:
957 		kwp = find_keyword(clos->cursect, node);
958 		if (!kwp)
959 			return grecs_tree_recurse_skip;
960 		stmt_begin(clos, kwp, node);
961 		break;
962 
963 	case grecs_tree_recurse_post:
964 		stmt_end(clos, node);
965 		break;
966 	}
967 	return grecs_tree_recurse_ok;
968 }
969 
970 int
grecs_tree_process(struct grecs_node * node,struct grecs_keyword * kwd)971 grecs_tree_process(struct grecs_node *node, struct grecs_keyword *kwd)
972 {
973 	int rc;
974 	struct nodeproc_closure clos;
975 	struct grecs_keyword config_keywords;
976 
977 	memset(&config_keywords, 0, sizeof(config_keywords));
978 	config_keywords.kwd = kwd;
979 	clos.cursect = &config_keywords;
980 	clos.sections = grecs_list_create();
981 	if (node->type == grecs_node_root)
982 		node = node->down;
983 	rc = grecs_tree_recurse(node, nodeproc, &clos);
984 	grecs_list_free(clos.sections);
985 	return rc;
986 }
987 
988 
989 int
grecs_node_eq(struct grecs_node * a,struct grecs_node * b)990 grecs_node_eq(struct grecs_node *a, struct grecs_node *b)
991 {
992 	if (a->type != b->type)
993 		return 1;
994 	if (a->type == grecs_node_root)
995 		return 0;
996 	if (strcmp(a->ident, b->ident))
997 		return 1;
998 	if (a->type == grecs_node_block &&
999 	    !grecs_value_eq(a->v.value, b->v.value))
1000 		return 1;
1001 	return 0;
1002 }
1003 
1004 static void
free_value_entry(void * ptr)1005 free_value_entry(void *ptr)
1006 {
1007 	struct grecs_value *v = ptr;
1008 	grecs_value_free(v);
1009 }
1010 
1011 struct grecs_list *
grecs_value_list_create()1012 grecs_value_list_create()
1013 {
1014 	struct grecs_list *list = grecs_list_create();
1015 	list->free_entry = free_value_entry;
1016 	return list;
1017 }
1018 
1019 static void
value_to_list(struct grecs_value * val)1020 value_to_list(struct grecs_value *val)
1021 {
1022 	struct grecs_list *list;
1023 	int i;
1024 
1025 	if (val->type == GRECS_TYPE_LIST)
1026 		return;
1027 	list = grecs_value_list_create();
1028 	switch (val->type) {
1029 	case GRECS_TYPE_STRING:
1030 		grecs_list_append(list, grecs_value_ptr_from_static(val));
1031 		break;
1032 
1033 	case GRECS_TYPE_ARRAY:
1034 		for (i = 0; i < val->v.arg.c; i++)
1035 			grecs_list_append(list, val->v.arg.v[i]);
1036 	}
1037 	val->type = GRECS_TYPE_LIST;
1038 	val->v.list = list;
1039 }
1040 
1041 static void
value_to_array(struct grecs_value * val)1042 value_to_array(struct grecs_value *val)
1043 {
1044 	if (val->type == GRECS_TYPE_ARRAY)
1045 		return;
1046 	else {
1047 		struct grecs_value **vp;
1048 		vp = grecs_calloc(1, sizeof(*vp));
1049 		vp[0] = grecs_value_ptr_from_static(val);
1050 		val->type = GRECS_TYPE_ARRAY;
1051 		val->v.arg.c = 1;
1052 		val->v.arg.v = vp;
1053 	}
1054 }
1055 
1056 static void
array_add(struct grecs_value * vx,struct grecs_value * vy)1057 array_add(struct grecs_value *vx, struct grecs_value *vy)
1058 {
1059 	size_t i;
1060 
1061 	vx->v.arg.v = grecs_realloc(vx->v.arg.v,
1062 				    (vx->v.arg.c + vy->v.arg.c) *
1063 				       sizeof(vx->v.arg.v[0]));
1064 	for (i = 0; i < vy->v.arg.c; i++)
1065 		vx->v.arg.v[i + vy->v.arg.c] = vy->v.arg.v[i];
1066 	grecs_free(vy->v.arg.v);
1067 	vy->v.arg.v = NULL;
1068 	vy->v.arg.c = 0;
1069 }
1070 
1071 static void
node_aggregate_stmt(struct grecs_node * dst,struct grecs_node * src,int islist)1072 node_aggregate_stmt(struct grecs_node *dst, struct grecs_node *src, int islist)
1073 {
1074 	if (islist) {
1075 		struct grecs_list *t;
1076 		/* Coerce both arguments to lists */
1077 		value_to_list(dst->v.value);
1078 		value_to_list(src->v.value);
1079 		/* Aggregate two lists in order */
1080 		grecs_list_add(src->v.value->v.list, dst->v.value->v.list);
1081 		/* Swap them */
1082 		t = dst->v.value->v.list;
1083 		dst->v.value->v.list = src->v.value->v.list;
1084 		src->v.value->v.list = t;
1085 	} else {
1086 		value_to_array(dst->v.value);
1087 		value_to_array(src->v.value);
1088 		array_add(dst->v.value, src->v.value);
1089 	}
1090 }
1091 
1092 static void
node_merge_stmt(struct grecs_node * to_node,struct grecs_node * from_node,struct grecs_keyword * kwp,int flags)1093 node_merge_stmt(struct grecs_node *to_node, struct grecs_node *from_node,
1094 		struct grecs_keyword *kwp, int flags)
1095 {
1096 	if (kwp &&
1097 	    (flags & GRECS_AGGR) ^ (kwp->flags & GRECS_AGGR) &&
1098 	    ((kwp->flags & GRECS_LIST) || kwp->callback))
1099 		node_aggregate_stmt(to_node, from_node,
1100 				    kwp->flags & GRECS_LIST);
1101 	else {
1102 		grecs_value_free(from_node->v.value);
1103 		from_node->v.value = NULL;
1104 	}
1105 }
1106 
1107 static void
node_merge_block(struct grecs_node * to_node,struct grecs_node * from_node,struct grecs_keyword * kwp)1108 node_merge_block(struct grecs_node *to_node, struct grecs_node *from_node,
1109 		 struct grecs_keyword *kwp)
1110 {
1111 	struct grecs_node *sp;
1112 
1113 	if (!from_node->down)
1114 		return;
1115 	for (sp = from_node->down; ; sp = sp->next) {
1116 		sp->up = to_node;
1117 		if (!sp->next)
1118 			break;
1119 	}
1120 
1121 	sp->next = to_node->down;
1122 	to_node->down->prev = sp;
1123 
1124 	to_node->down = from_node->down;
1125 	from_node->down = NULL;
1126 }
1127 
1128 static int
node_reduce(struct grecs_node * node,struct grecs_keyword * kwp,int flags)1129 node_reduce(struct grecs_node *node, struct grecs_keyword *kwp, int flags)
1130 {
1131 	struct grecs_node *p;
1132 
1133 	for (p = node->next; p; p = p->next)
1134 		if (grecs_node_eq(p, node) == 0)
1135 			break;
1136 	if (p) {
1137 		switch (node->type) {
1138 		case grecs_node_root:
1139 			return 0;
1140 		case grecs_node_stmt:
1141 			node_merge_stmt(p, node, kwp, flags);
1142 			break;
1143 		case grecs_node_block:
1144 			node_merge_block(p, node, kwp);
1145 			break;
1146 		}
1147 		grecs_node_unlink(node);
1148 		grecs_node_free(node);
1149 		return 1;
1150 	}
1151 	return 0;
1152 }
1153 
1154 static enum grecs_tree_recurse_res
reduceproc(enum grecs_tree_recurse_op op,struct grecs_node * node,void * data)1155 reduceproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data)
1156 {
1157 	struct nodeproc_closure *clos = data;
1158 
1159 	if (op == grecs_tree_recurse_post) {
1160 		if (clos->sections)
1161 			clos->cursect = (struct grecs_keyword *)
1162 				           grecs_list_pop(clos->sections);
1163 	} else {
1164 		struct grecs_keyword *kwp = NULL;
1165 		if (clos->cursect) {
1166 			kwp = find_keyword(clos->cursect, node);
1167 			if (!kwp)
1168 				return grecs_tree_recurse_skip;
1169 			if (kwp->flags & GRECS_INAC)
1170 				return grecs_tree_recurse_skip;
1171 			if (!(kwp->flags & GRECS_MULT) &&
1172 			    node_reduce(node, kwp, clos->flags))
1173 				return grecs_tree_recurse_skip;
1174 			if (op == grecs_tree_recurse_pre) {
1175 				grecs_list_push(clos->sections, clos->cursect);
1176 				clos->cursect = kwp;
1177 			}
1178 		} else if (node_reduce(node, kwp, clos->flags))
1179 			return grecs_tree_recurse_skip;
1180 	}
1181 	return grecs_tree_recurse_ok;
1182 }
1183 
1184 int
grecs_tree_reduce(struct grecs_node * node,struct grecs_keyword * kwd,int flags)1185 grecs_tree_reduce(struct grecs_node *node, struct grecs_keyword *kwd,
1186 		  int flags)
1187 {
1188 	int rc;
1189 	struct nodeproc_closure clos;
1190 	struct grecs_keyword config_keywords;
1191 
1192 	memset(&config_keywords, 0, sizeof(config_keywords));
1193 	config_keywords.kwd = kwd;
1194 	if (kwd) {
1195 		clos.cursect = &config_keywords;
1196 		clos.sections = grecs_list_create();
1197 	} else {
1198 		clos.cursect = NULL;
1199 		clos.sections = NULL;
1200 	}
1201 	clos.flags = flags;
1202 	rc = grecs_tree_recurse(node->down, reduceproc, &clos);
1203 	grecs_list_free(clos.sections);
1204 	return rc;
1205 }
1206 
1207 
1208 struct grecs_node *
grecs_tree_first_node(struct grecs_node * tree)1209 grecs_tree_first_node(struct grecs_node *tree)
1210 {
1211 	if (tree->type == grecs_node_root)
1212 		return tree->down;
1213 	return tree;
1214 }
1215 
1216 struct grecs_node *
grecs_next_node(struct grecs_node * node)1217 grecs_next_node(struct grecs_node *node)
1218 {
1219 	if (!node)
1220 		return NULL;
1221 	if (node->down)
1222 		return node->down;
1223 	while (!node->next) {
1224 		node = node->up;
1225 		if (!node || node->type == grecs_node_root)
1226 			return NULL;
1227 	}
1228 	return node->next;
1229 }
1230