1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016, Olivier MATZ <zer0@droids-corp.org>
12 #include <ecoli_assert.h>
13 #include <ecoli_malloc.h>
14 #include <ecoli_strvec.h>
15 #include <ecoli_keyval.h>
16 #include <ecoli_log.h>
17 #include <ecoli_node.h>
18 #include <ecoli_parse.h>
20 TAILQ_HEAD(ec_parse_list, ec_parse);
23 TAILQ_ENTRY(ec_parse) next;
24 struct ec_parse_list children;
25 struct ec_parse *parent;
26 const struct ec_node *node;
27 struct ec_strvec *strvec;
28 struct ec_keyval *attrs;
31 static int __ec_node_parse_child(const struct ec_node *node,
32 struct ec_parse *state,
33 bool is_root, const struct ec_strvec *strvec)
35 struct ec_strvec *match_strvec;
36 struct ec_parse *child = NULL;
39 if (node->type->parse == NULL)
43 child = ec_parse(node);
47 ec_parse_link_child(state, child);
51 ret = node->type->parse(node, child, strvec);
52 if (ret < 0 || ret == EC_PARSE_NOMATCH)
55 match_strvec = ec_strvec_ndup(strvec, 0, ret);
56 if (match_strvec == NULL) {
61 child->strvec = match_strvec;
67 ec_parse_unlink_child(state, child);
73 int ec_node_parse_child(const struct ec_node *node, struct ec_parse *state,
74 const struct ec_strvec *strvec)
76 assert(state != NULL);
77 return __ec_node_parse_child(node, state, false, strvec);
80 struct ec_parse *ec_node_parse_strvec(const struct ec_node *node,
81 const struct ec_strvec *strvec)
83 struct ec_parse *parse = ec_parse(node);
89 ret = __ec_node_parse_child(node, parse, true, strvec);
98 struct ec_parse *ec_node_parse(const struct ec_node *node, const char *str)
100 struct ec_strvec *strvec = NULL;
101 struct ec_parse *parse = NULL;
104 strvec = ec_strvec();
108 if (ec_strvec_add(strvec, str) < 0)
111 parse = ec_node_parse_strvec(node, strvec);
115 ec_strvec_free(strvec);
119 ec_strvec_free(strvec);
120 ec_parse_free(parse);
124 struct ec_parse *ec_parse(const struct ec_node *node)
126 struct ec_parse *parse = NULL;
128 parse = ec_calloc(1, sizeof(*parse));
132 TAILQ_INIT(&parse->children);
135 parse->attrs = ec_keyval();
136 if (parse->attrs == NULL)
143 ec_keyval_free(parse->attrs);
149 static struct ec_parse *
150 __ec_parse_dup(const struct ec_parse *root, const struct ec_parse *ref,
151 struct ec_parse **new_ref)
153 struct ec_parse *dup = NULL;
154 struct ec_parse *child, *dup_child;
155 struct ec_keyval *attrs = NULL;
160 dup = ec_parse(root->node);
167 attrs = ec_keyval_dup(root->attrs);
170 ec_keyval_free(dup->attrs);
173 if (root->strvec != NULL) {
174 dup->strvec = ec_strvec_dup(root->strvec);
175 if (dup->strvec == NULL)
179 TAILQ_FOREACH(child, &root->children, next) {
180 dup_child = __ec_parse_dup(child, ref, new_ref);
181 if (dup_child == NULL)
183 ec_parse_link_child(dup, dup_child);
193 struct ec_parse *ec_parse_dup(const struct ec_parse *parse)
195 const struct ec_parse *root;
196 struct ec_parse *dup_root, *dup = NULL;
198 root = ec_parse_get_root(parse);
199 dup_root = __ec_parse_dup(root, parse, &dup);
200 if (dup_root == NULL)
207 void ec_parse_free_children(struct ec_parse *parse)
209 struct ec_parse *child;
214 while (!TAILQ_EMPTY(&parse->children)) {
215 child = TAILQ_FIRST(&parse->children);
216 TAILQ_REMOVE(&parse->children, child, next);
217 child->parent = NULL;
218 ec_parse_free(child);
222 void ec_parse_free(struct ec_parse *parse)
227 ec_assert_print(parse->parent == NULL,
228 "parent not NULL in ec_parse_free()");
230 ec_parse_free_children(parse);
231 ec_strvec_free(parse->strvec);
232 ec_keyval_free(parse->attrs);
236 static void __ec_parse_dump(FILE *out,
237 const struct ec_parse *parse, size_t indent)
239 struct ec_parse *child;
240 const struct ec_strvec *vec;
241 const char *id, *typename = "none";
243 /* node can be null when parsing is incomplete */
244 if (parse->node != NULL) {
245 id = parse->node->id;
246 typename = parse->node->type->name;
249 fprintf(out, "%*s" "type=%s id=%s vec=",
250 (int)indent * 4, "", typename, id);
251 vec = ec_parse_strvec(parse);
252 ec_strvec_dump(out, vec);
254 TAILQ_FOREACH(child, &parse->children, next)
255 __ec_parse_dump(out, child, indent + 1);
258 void ec_parse_dump(FILE *out, const struct ec_parse *parse)
260 fprintf(out, "------------------- parse dump:\n");
263 fprintf(out, "parse is NULL\n");
267 /* only exist if it does not match (strvec == NULL) and if it
268 * does not have children: an incomplete parse, like those
269 * generated by complete() don't match but have children that
271 if (!ec_parse_matches(parse) && TAILQ_EMPTY(&parse->children)) {
272 fprintf(out, "no match\n");
276 __ec_parse_dump(out, parse, 0);
279 void ec_parse_link_child(struct ec_parse *parse,
280 struct ec_parse *child)
282 TAILQ_INSERT_TAIL(&parse->children, child, next);
283 child->parent = parse;
286 void ec_parse_unlink_child(struct ec_parse *parse,
287 struct ec_parse *child)
289 TAILQ_REMOVE(&parse->children, child, next);
290 child->parent = NULL;
294 ec_parse_get_first_child(const struct ec_parse *parse)
296 return TAILQ_FIRST(&parse->children);
300 ec_parse_get_last_child(const struct ec_parse *parse)
302 return TAILQ_LAST(&parse->children, ec_parse_list);
305 struct ec_parse *ec_parse_get_next(const struct ec_parse *parse)
307 return TAILQ_NEXT(parse, next);
310 bool ec_parse_has_child(const struct ec_parse *parse)
312 return !TAILQ_EMPTY(&parse->children);
315 const struct ec_node *ec_parse_get_node(const struct ec_parse *parse)
320 void ec_parse_del_last_child(struct ec_parse *parse)
322 struct ec_parse *child;
324 child = ec_parse_get_last_child(parse);
325 ec_parse_unlink_child(parse, child);
326 ec_parse_free(child);
329 struct ec_parse *__ec_parse_get_root(struct ec_parse *parse)
334 while (parse->parent != NULL)
335 parse = parse->parent;
340 struct ec_parse *ec_parse_get_parent(const struct ec_parse *parse)
345 return parse->parent;
348 struct ec_parse *ec_parse_iter_next(struct ec_parse *parse)
350 struct ec_parse *child, *parent, *next;
352 child = TAILQ_FIRST(&parse->children);
355 parent = parse->parent;
356 while (parent != NULL) {
357 next = TAILQ_NEXT(parse, next);
361 parent = parse->parent;
366 struct ec_parse *ec_parse_find_first(struct ec_parse *parse,
369 struct ec_parse *child, *ret;
374 if (parse->node != NULL &&
375 parse->node->id != NULL &&
376 !strcmp(parse->node->id, id))
379 TAILQ_FOREACH(child, &parse->children, next) {
380 ret = ec_parse_find_first(child, id);
389 ec_parse_get_attrs(struct ec_parse *parse)
397 const struct ec_strvec *ec_parse_strvec(const struct ec_parse *parse)
399 if (parse == NULL || parse->strvec == NULL)
402 return parse->strvec;
405 /* number of strings in the parse vector */
406 size_t ec_parse_len(const struct ec_parse *parse)
408 if (parse == NULL || parse->strvec == NULL)
411 return ec_strvec_len(parse->strvec);
414 size_t ec_parse_matches(const struct ec_parse *parse)
419 if (parse->strvec == NULL)