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 <string.h>
21 #include <errno.h>
22 #include <ctype.h>
23 #include "grecs.h"
24 #include "wordsplit.h"
25 #include <fnmatch.h>
26 #include <stdlib.h>
27 
28 static int
_grecs_list_eq(struct grecs_value * a,struct grecs_value * b)29 _grecs_list_eq(struct grecs_value *a, struct grecs_value *b)
30 {
31 	struct grecs_list_entry *aent, *bent;
32 	if (grecs_list_size(a->v.list) != grecs_list_size(b->v.list))
33 		return 0;
34 
35 	for (aent = a->v.list->head, bent = b->v.list->head;;
36 	     aent = aent->next, bent = bent->next) {
37 		if (!aent)
38 			return bent == NULL;
39 		if (!bent)
40 			return 0;
41 		if (!grecs_value_eq(aent->data, bent->data))
42 			return 0;
43 	}
44 	/*notreached*/
45 	return 1;
46 }
47 
48 static int
_grecs_array_eq(struct grecs_value * a,struct grecs_value * b)49 _grecs_array_eq(struct grecs_value *a, struct grecs_value *b)
50 {
51 	size_t i;
52 
53 	if (a->v.arg.c != b->v.arg.c)
54 		return 0;
55 
56 	for (i = 0; i < a->v.arg.c; i++)
57 		if (!grecs_value_eq(a->v.arg.v[i], b->v.arg.v[i]))
58 			return 0;
59 	return 1;
60 }
61 
62 /* Return 1 if configuration value A equals B */
63 int
grecs_value_eq(struct grecs_value * a,struct grecs_value * b)64 grecs_value_eq(struct grecs_value *a, struct grecs_value *b)
65 {
66 	if (a == 0 || b == 0)
67 		return a == b;
68 	if (a->type != b->type)
69 		return 0;
70 	switch (a->type) {
71 	case GRECS_TYPE_STRING:
72 		if (a->v.string == NULL)
73 			return b->v.string == NULL;
74 		return strcmp(a->v.string, b->v.string) == 0;
75 
76 	case GRECS_TYPE_LIST:
77 		return _grecs_list_eq(a, b);
78 
79 	case GRECS_TYPE_ARRAY:
80 		return _grecs_array_eq(a, b);
81     }
82   return 0;
83 }
84 
85 static int
_grecs_list_match(struct grecs_value * pat,struct grecs_value * b,int flags)86 _grecs_list_match(struct grecs_value *pat, struct grecs_value *b, int flags)
87 {
88 	struct grecs_list_entry *aent, *bent;
89 	if (grecs_list_size(pat->v.list) != grecs_list_size(b->v.list))
90 		return 0;
91 
92 	for (aent = pat->v.list->head, bent = b->v.list->head;;
93 	     aent = aent->next, bent = bent->next) {
94 		if (!aent)
95 			return bent == NULL;
96 		if (!bent)
97 			return 0;
98 		if (!grecs_value_match(aent->data, bent->data, flags))
99 			return 0;
100 	}
101 	/*notreached*/
102 	return 1;
103 }
104 
105 static int
_grecs_array_match(struct grecs_value * pat,struct grecs_value * b,int flags)106 _grecs_array_match(struct grecs_value *pat, struct grecs_value *b, int flags)
107 {
108 	size_t i;
109 
110 	if (pat->v.arg.c > b->v.arg.c)
111 		return 0;
112 
113 	for (i = 0; i < pat->v.arg.c; i++)
114 		if (!grecs_value_match(pat->v.arg.v[i], b->v.arg.v[i], flags))
115 			return 0;
116 	return 1;
117 }
118 
119 int
grecs_value_match(struct grecs_value * pat,struct grecs_value * b,int flags)120 grecs_value_match(struct grecs_value *pat, struct grecs_value *b, int flags)
121 {
122 	if (pat == 0 || b == 0)
123 		return pat == b;
124 	if (pat->type != b->type) {
125 		if (pat->type != GRECS_TYPE_STRING)
126 			return 0;
127 		switch (b->type) {
128 		case GRECS_TYPE_LIST:
129 			b = grecs_list_index(b->v.list, 0);
130 			break;
131 
132 		case GRECS_TYPE_ARRAY:
133 			b = b->v.arg.v[0];
134 		}
135 	}
136 
137 	switch (pat->type) {
138 	case GRECS_TYPE_STRING:
139 		if (pat->v.string == NULL)
140 			return b->v.string == NULL;
141 		return fnmatch(pat->v.string, b->v.string, flags) == 0;
142 
143 	case GRECS_TYPE_LIST:
144 		return _grecs_list_match(pat, b, flags);
145 
146 	case GRECS_TYPE_ARRAY:
147 		return _grecs_array_match(pat, b, flags);
148     }
149   return 0;
150 }
151 
152 
153 struct grecs_match_buf {
154 	int argc;                      /* number of path components */
155 	char **argv;                   /* array of path components */
156 	int argi;                      /* Index of the current component */
157 	struct grecs_value **labelv;   /* Component labels */
158 	struct grecs_node *root;       /* Root node */
159 	struct grecs_node *node;       /* Last found node */
160 };
161 
162 #define ISWC(c,w) ((c)[0] == (w) && (c)[1] == 0)
163 
164 grecs_match_buf_t
grecs_match_buf_create(int argc,char ** argv,struct grecs_value ** labelv)165 grecs_match_buf_create(int argc, char **argv, struct grecs_value **labelv)
166 {
167 	int i;
168 	struct grecs_match_buf *buf = grecs_zalloc(sizeof(*buf));
169 
170 	buf->argc = argc;
171 	buf->argv = argv;
172 	buf->labelv = labelv;
173 	/* Compress argv/argc by replacing contiguous sequences of *'s
174 	   with a single *. */
175 	for (i = 0; i < buf->argc; i++) {
176 		if (ISWC(buf->argv[i], '*')) {
177 			int j;
178 
179 			for (j = i + 1;
180 			     j < buf->argc && ISWC(buf->argv[j], '*'); j++) {
181 			        free(buf->argv[j]);
182 				grecs_value_free_content(buf->labelv[i]);
183 			}
184 			j -= i;
185 			if (j > 1) {
186 				memmove(&buf->argv[i+1], &buf->argv[i+j],
187 					(buf->argc - (i + j)) *
188 					sizeof(buf->argv[0]));
189 				memmove(&buf->labelv[i+1], &buf->labelv[i+j],
190 					(buf->argc - (i + j)) *
191 					sizeof(buf->labelv[0]));
192 				buf->argc -= j - 1;
193 			}
194 		}
195 	}
196 
197 	return buf;
198 }
199 
200 size_t
grecs_match_buf_get_args(grecs_match_buf_t buf,char *** argv)201 grecs_match_buf_get_args(grecs_match_buf_t buf, char ***argv)
202 {
203 	if (argv)
204 		*argv = buf->argv;
205 	return buf->argc;
206 }
207 
208 struct grecs_node *
grecs_match_buf_get_node(grecs_match_buf_t buf)209 grecs_match_buf_get_node(grecs_match_buf_t buf)
210 {
211 	return buf->node;
212 }
213 
214 struct grecs_node *
grecs_match_buf_get_root(grecs_match_buf_t buf)215 grecs_match_buf_get_root(grecs_match_buf_t buf)
216 {
217 	return buf->root;
218 }
219 
220 void
grecs_match_buf_set_root(grecs_match_buf_t buf,struct grecs_node * root)221 grecs_match_buf_set_root(grecs_match_buf_t buf, struct grecs_node *root)
222 {
223 	buf->root = root;
224 }
225 
226 static void
grecs_match_buf_free_contents(struct grecs_match_buf * buf)227 grecs_match_buf_free_contents(struct grecs_match_buf *buf)
228 {
229 	size_t i;
230 	for (i = 0; i < buf->argc; i++) {
231 		free(buf->argv[i]);
232 		grecs_value_free(buf->labelv[i]);
233 	}
234 	free(buf->argv);
235 	free(buf->labelv);
236 }
237 
238 void
grecs_match_buf_free(struct grecs_match_buf * buf)239 grecs_match_buf_free(struct grecs_match_buf *buf)
240 {
241 	if (buf) {
242 		grecs_match_buf_free_contents(buf);
243 		free(buf);
244 	}
245 }
246 
247 
248 static struct grecs_value *
parse_label(const char * str)249 parse_label(const char *str)
250 {
251 	struct grecs_value *val = NULL;
252 	size_t i;
253 	struct wordsplit ws;
254 	size_t len = strlen (str);
255 
256 	if (len > 1 && str[0] == '(' && str[len-1] == ')') {
257 		struct grecs_list *lst;
258 
259 		ws.ws_delim = ",";
260 		if (wordsplit_len (str + 1, len - 2, &ws,
261 				      WRDSF_DEFFLAGS|WRDSF_DELIM|
262 				      WRDSF_WS)) {
263 			return NULL;
264 		}
265 
266 		lst = grecs_value_list_create();
267 		for (i = 0; i < ws.ws_wordc; i++) {
268 			struct grecs_value *p = grecs_zalloc(sizeof(*p));
269 			p->type = GRECS_TYPE_STRING;
270 			p->v.string = ws.ws_wordv[i];
271 			grecs_list_append(lst, p);
272 		}
273 		val = grecs_malloc(sizeof(*val));
274 		val->type = GRECS_TYPE_LIST;
275 		val->v.list = lst;
276 	} else {
277 		if (wordsplit(str, &ws, WRDSF_DEFFLAGS))
278 			return NULL;
279 		val = grecs_zalloc(sizeof(*val));
280 		if (ws.ws_wordc == 1) {
281 			val->type = GRECS_TYPE_STRING;
282 			val->v.string = ws.ws_wordv[0];
283 		} else {
284 			val->type = GRECS_TYPE_ARRAY;
285 			val->v.arg.c = ws.ws_wordc;
286 			val->v.arg.v = grecs_calloc(ws.ws_wordc,
287 						    sizeof(val->v.arg.v[0]));
288 			for (i = 0; i < ws.ws_wordc; i++) {
289 				val->v.arg.v[i] =
290 					grecs_zalloc(sizeof(*val->v.arg.v[0]));
291 				val->v.arg.v[i]->type = GRECS_TYPE_STRING;
292 				val->v.arg.v[i]->v.string = ws.ws_wordv[i];
293 			}
294 		}
295 	}
296 	ws.ws_wordc = 0;
297 	wordsplit_free(&ws);
298 	return val;
299 }
300 
301 static int
split_cfg_path(const char * path,int * pargc,char *** pargv,grecs_value_t *** pvalv)302 split_cfg_path(const char *path, int *pargc, char ***pargv,
303 	       grecs_value_t ***pvalv)
304 {
305 	int argc;
306 	char **argv;
307 	char *delim = ".";
308 	char static_delim[2] = { 0, 0 };
309 
310 	if (path[0] == '\\') {
311 		argv = calloc(2, sizeof (*argv));
312 		if (!argv)
313 			return WRDSE_NOSPACE;
314 		argv[0] = strdup(path + 1);
315 		if (!argv[0]) {
316 			free(argv);
317 			return WRDSE_NOSPACE;
318 		}
319 		argv[1] = NULL;
320 		argc = 1;
321 	} else {
322 		int rc;
323 		struct wordsplit ws;
324 
325 		if (strchr("./:;,^~", path[0])) {
326 			delim = static_delim;
327 			delim[0] = path[0];
328 			path++;
329 		}
330 		ws.ws_delim = delim;
331 
332 		rc = wordsplit(path, &ws,
333 			       WRDSF_DELIM | WRDSF_DEFFLAGS);
334 		if (rc)
335 			return rc;
336 		argc = ws.ws_wordc;
337 		argv = ws.ws_wordv;
338 		ws.ws_wordc = 0;
339 		ws.ws_wordv = NULL;
340 		wordsplit_free(&ws);
341 	}
342 
343 	*pargv = argv;
344 	*pargc = argc;
345 	if (pvalv) {
346 		int i;
347 		grecs_value_t **valv;
348 
349 		valv = grecs_calloc(argc, sizeof(valv[0]));
350 		for (i = 0; i < argc; i++) {
351 			char *p = strchr(argv[i], '=');
352 			if (p) {
353 				*p++ = 0;
354 				valv[i] = parse_label(p);
355 			}
356 		}
357 		*pvalv = valv;
358 	}
359 	return 0;
360 }
361 
362 
363 enum grecs_tree_recurse_res
grecs_node_exact_match(enum grecs_tree_recurse_op op,struct grecs_node * node,void * data)364 grecs_node_exact_match(enum grecs_tree_recurse_op op,
365 		       struct grecs_node *node, void *data)
366 {
367 	int match = 0;
368 	struct grecs_match_buf *buf = data;
369 
370 	if (node->type == grecs_node_root)
371 		return grecs_tree_recurse_ok;
372 	if (op == grecs_tree_recurse_post) {
373 		if (buf->argi == 0)
374 			return grecs_tree_recurse_stop;
375 		--buf->argi;
376 		return grecs_tree_recurse_ok;
377 	}
378 
379 	if (strcmp(buf->argv[buf->argi], node->ident) == 0
380 	    && (!buf->labelv[buf->argi] ||
381 		grecs_value_eq(buf->labelv[buf->argi], node->v.value))) {
382 		if (buf->argi + 1 == buf->argc) {
383 			buf->node = node;
384 			return grecs_tree_recurse_stop;
385 		}
386 		match = 1;
387 	}
388 
389 	if (match) {
390 		if (op == grecs_tree_recurse_pre) {
391 			if (buf->argi + 1 == buf->argc)
392 				return grecs_tree_recurse_skip;
393 			buf->argi++;
394 		}
395 		return grecs_tree_recurse_ok;
396 	}
397 
398 	return node->type == grecs_node_block ?
399 		grecs_tree_recurse_skip : grecs_tree_recurse_ok;
400 }
401 
402 struct grecs_node *
grecs_find_node(struct grecs_node * node,const char * path)403 grecs_find_node(struct grecs_node *node, const char *path)
404 {
405 	int rc;
406 	struct grecs_match_buf buf;
407 
408 	if (strcmp(path, ".") == 0)
409 		return node;
410 	rc = split_cfg_path(path, &buf.argc, &buf.argv, &buf.labelv);
411 	if (rc || !buf.argc)
412 		return NULL;
413 	buf.argi = 0;
414 	buf.node = NULL;
415 	grecs_tree_recurse(node, grecs_node_exact_match, &buf);
416 	grecs_match_buf_free_contents(&buf);
417 	return buf.node;
418 }
419 
420 
421 static void
fixup_loci(struct grecs_node * node,grecs_locus_t const * plocus,struct grecs_locus_point const * endp)422 fixup_loci(struct grecs_node *node,
423 	   grecs_locus_t const *plocus,
424 	   struct grecs_locus_point const *endp)
425 {
426 	grecs_locus_t loc = *plocus;
427 
428 	for (; node; node = node->down) {
429 		node->idloc = loc;
430 
431 		node->locus = loc;
432 		if (endp)
433 			node->locus.end = *endp;
434 	}
435 }
436 
437 struct grecs_node *
grecs_node_from_path_locus(const char * path,const char * value,grecs_locus_t * plocus,grecs_locus_t * vallocus)438 grecs_node_from_path_locus(const char *path, const char *value,
439 			   grecs_locus_t *plocus, grecs_locus_t *vallocus)
440 {
441 	int rc;
442 	int i;
443 	int argc;
444 	char **argv;
445 	struct grecs_node *dn = NULL;
446 
447 	rc = split_cfg_path(path, &argc, &argv, NULL);
448 	if (rc)
449 		return NULL;
450 
451 	dn = grecs_node_create(grecs_node_stmt, NULL);
452 	dn->ident = argv[argc - 1];
453 	if (value) {
454 		struct grecs_value *gval = parse_label(value);
455 		if (vallocus)
456 			gval->locus = *vallocus;
457 		dn->v.value = gval;
458 	} else
459 		dn->v.value = NULL;
460 
461 	for (i = argc - 2; i >= 0; i--) {
462 		struct grecs_value *label = NULL;
463 		struct grecs_node *node;
464 		char *p, *q = argv[i];
465 
466 		do {
467 			p = strchr(q, '=');
468 			if (p && p > argv[i] && p[-1] != '\\') {
469 				*p++ = 0;
470 				label = parse_label(p);
471 				break;
472 			} else if (p)
473 				q = p + 1;
474 			else
475 				break;
476 		} while (*q);
477 
478 		node = grecs_node_create(grecs_node_block, plocus);
479 		node->ident = argv[i];
480 		if (label)
481 			node->v.value = label;
482 
483 		node->down = dn;
484 		if (dn)
485 			dn->up = node;
486 		dn = node;
487 	}
488 
489 	if (plocus)
490 		fixup_loci(dn,
491 			   plocus, vallocus ? &vallocus->end : NULL);
492 
493 	free(argv);
494 	return dn;
495 }
496 
497 struct grecs_node *
grecs_node_from_path(const char * path,const char * value)498 grecs_node_from_path(const char *path, const char *value)
499 {
500 	return grecs_node_from_path_locus(path, value, NULL, NULL);
501 }
502 
503 
504 static int
is_root(struct grecs_match_buf * buf,struct grecs_node * node)505 is_root(struct grecs_match_buf *buf, struct grecs_node *node)
506 {
507 	return (buf->root == node || node->type == grecs_node_root);
508 }
509 
510 static int
grecs_match(struct grecs_match_buf * buf)511 grecs_match(struct grecs_match_buf *buf)
512 {
513 	struct grecs_node *node;
514 	int wcard = 0;
515 
516 	buf->argi = buf->argc - 1;
517 	node = buf->node;
518 
519 	while (buf->argi >= 0) {
520 		if (ISWC(buf->argv[buf->argi], '*')) {
521 			wcard = 1;
522 			if (buf->argi-- == 0)
523 				return 1;
524 			continue;
525 		}
526 
527 		if ((ISWC(buf->argv[buf->argi], '%') ||
528 		     strcmp(buf->argv[buf->argi], node->ident) == 0)
529 		    /* FIXME: */
530 		    && (!buf->labelv[buf->argi] ||
531 			grecs_value_match(buf->labelv[buf->argi],
532 					  node->v.value, 0))) {
533 			wcard = 0;
534 			node = node->up;
535 			if (buf->argi-- == 0)
536 				return is_root(buf, node);
537 		} else if (!wcard)
538 			return 0;
539 		else
540 			node = node->up;
541 		if (is_root(buf, node))
542 			return ISWC(buf->argv[buf->argi], '*');
543 	}
544 	return 0;
545 }
546 
547 struct grecs_node *
grecs_match_next(struct grecs_match_buf * buf)548 grecs_match_next(struct grecs_match_buf *buf)
549 {
550 	if (!buf)
551 		return NULL;
552 	while ((buf->node = grecs_next_node(buf->node)))
553 		if (grecs_match(buf))
554 			break;
555 	return buf->node;
556 }
557 
558 struct grecs_node *
grecs_match_buf_first(struct grecs_match_buf * buf,struct grecs_node * tree)559 grecs_match_buf_first(struct grecs_match_buf *buf, struct grecs_node *tree)
560 {
561 	struct grecs_node *node;
562 
563 	buf->argi = 0;
564 	buf->root = tree;
565 	buf->node = grecs_tree_first_node(tree);
566 	if (!buf->node)
567 		return NULL;
568 	if (grecs_match(buf))
569 		node = buf->node;
570 	else
571 		node = grecs_match_next(buf);
572 	return node;
573 }
574 
575 struct grecs_node *
grecs_match_first(struct grecs_node * tree,const char * pattern,struct grecs_match_buf ** pbuf)576 grecs_match_first(struct grecs_node *tree, const char *pattern,
577 		  struct grecs_match_buf **pbuf)
578 {
579 	struct grecs_node *node;
580 	struct grecs_match_buf *buf;
581 
582 	if (strcmp(pattern, ".") == 0) {
583 		*pbuf = NULL;
584 		return tree;
585 	}
586 
587 	buf = grecs_zalloc(sizeof(*buf));
588 	if (split_cfg_path(pattern, &buf->argc, &buf->argv, &buf->labelv)) {
589 		free(buf);
590 		return NULL;
591 	}
592 	node = grecs_match_buf_first(buf, tree);
593 	if (node)
594 		*pbuf = buf;
595 	else {
596 		grecs_match_buf_free(buf);
597 		*pbuf = NULL;
598 	}
599 	return node;
600 }
601 
602