fix cmd node
[protos/libecoli.git] / lib / ecoli_parsed.c
1 /*
2  * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <stdint.h>
31 #include <string.h>
32 #include <assert.h>
33 #include <errno.h>
34
35 #include <ecoli_assert.h>
36 #include <ecoli_malloc.h>
37 #include <ecoli_strvec.h>
38 #include <ecoli_keyval.h>
39 #include <ecoli_log.h>
40 #include <ecoli_node.h>
41 #include <ecoli_parsed.h>
42
43 TAILQ_HEAD(ec_parsed_list, ec_parsed);
44
45 struct ec_parsed {
46         TAILQ_ENTRY(ec_parsed) next;
47         struct ec_parsed_list children;
48         struct ec_parsed *parent;
49         const struct ec_node *node;
50         struct ec_strvec *strvec;
51         struct ec_keyval *attrs;
52 };
53
54 static int __ec_node_parse_child(const struct ec_node *node,
55                                 struct ec_parsed *state,
56                                 bool is_root, const struct ec_strvec *strvec)
57 {
58         struct ec_strvec *match_strvec;
59         struct ec_parsed *child = NULL;
60         int ret;
61
62         if (node->type->parse == NULL)
63                 return -ENOTSUP;
64
65         if (!is_root) {
66                 child = ec_parsed(node);
67                 if (child == NULL)
68                         return -ENOMEM;
69
70                 ec_parsed_add_child(state, child);
71         } else {
72                 child = state;
73         }
74         ret = node->type->parse(node, child, strvec);
75         if (ret < 0 || ret == EC_PARSED_NOMATCH)
76                 goto free;
77
78         match_strvec = ec_strvec_ndup(strvec, 0, ret);
79         if (match_strvec == NULL) {
80                 ret = -ENOMEM;
81                 goto free;
82         }
83
84         child->strvec = match_strvec;
85
86         return ret;
87
88 free:
89         if (!is_root) {
90                 ec_parsed_del_child(state, child);
91                 ec_parsed_free(child);
92         }
93         return ret;
94 }
95
96 int ec_node_parse_child(const struct ec_node *node, struct ec_parsed *state,
97                         const struct ec_strvec *strvec)
98 {
99         assert(state != NULL);
100         return __ec_node_parse_child(node, state, false, strvec);
101 }
102
103 struct ec_parsed *ec_node_parse_strvec(const struct ec_node *node,
104                                 const struct ec_strvec *strvec)
105 {
106         struct ec_parsed *parsed = ec_parsed(node);
107         int ret;
108
109         if (parsed == NULL)
110                 return NULL;
111
112         ret = __ec_node_parse_child(node, parsed, true, strvec);
113         if (ret < 0) {
114                 ec_parsed_free(parsed);
115                 return NULL;
116         }
117
118         return parsed;
119 }
120
121 struct ec_parsed *ec_node_parse(const struct ec_node *node, const char *str)
122 {
123         struct ec_strvec *strvec = NULL;
124         struct ec_parsed *parsed = NULL;
125
126         errno = ENOMEM;
127         strvec = ec_strvec();
128         if (strvec == NULL)
129                 goto fail;
130
131         if (ec_strvec_add(strvec, str) < 0)
132                 goto fail;
133
134         parsed = ec_node_parse_strvec(node, strvec);
135         if (parsed == NULL)
136                 goto fail;
137
138         ec_strvec_free(strvec);
139         return parsed;
140
141  fail:
142         ec_strvec_free(strvec);
143         ec_parsed_free(parsed);
144         return NULL;
145 }
146
147 struct ec_parsed *ec_parsed(const struct ec_node *node)
148 {
149         struct ec_parsed *parsed = NULL;
150
151         parsed = ec_calloc(1, sizeof(*parsed));
152         if (parsed == NULL)
153                 goto fail;
154
155         TAILQ_INIT(&parsed->children);
156
157         parsed->node = node;
158         parsed->attrs = ec_keyval();
159         if (parsed->attrs == NULL)
160                 goto fail;
161
162         return parsed;
163
164  fail:
165         if (parsed != NULL)
166                 ec_keyval_free(parsed->attrs);
167         ec_free(parsed);
168
169         return NULL;
170 }
171
172 static struct ec_parsed *
173 __ec_parsed_dup(const struct ec_parsed *root, const struct ec_parsed *ref,
174                 struct ec_parsed **new_ref)
175 {
176         struct ec_parsed *dup = NULL;
177         struct ec_parsed *child, *dup_child;
178         struct ec_keyval *attrs = NULL;
179
180         if (root == NULL)
181                 return NULL;
182
183         dup = ec_parsed(root->node);
184         if (dup == NULL)
185                 return NULL;
186
187         if (root == ref)
188                 *new_ref = dup;
189
190         attrs = ec_keyval_dup(root->attrs);
191         if (attrs == NULL)
192                 goto fail;
193         ec_keyval_free(dup->attrs);
194         dup->attrs = attrs;
195
196         if (root->strvec != NULL) {
197                 dup->strvec = ec_strvec_dup(root->strvec);
198                 if (dup->strvec == NULL)
199                         goto fail;
200         }
201
202         TAILQ_FOREACH(child, &root->children, next) {
203                 dup_child = __ec_parsed_dup(child, ref, new_ref);
204                 if (dup_child == NULL)
205                         goto fail;
206                 ec_parsed_add_child(dup, dup_child);
207         }
208
209         return dup;
210
211 fail:
212         ec_parsed_free(dup);
213         return NULL;
214 }
215
216 struct ec_parsed *ec_parsed_dup(struct ec_parsed *parsed) //XXX const
217 {
218         struct ec_parsed *root, *dup_root, *dup = NULL;
219
220         root = ec_parsed_get_root(parsed);
221         dup_root = __ec_parsed_dup(root, parsed, &dup);
222         if (dup_root == NULL)
223                 return NULL;
224         assert(dup != NULL);
225
226         return dup;
227 }
228
229 void ec_parsed_free_children(struct ec_parsed *parsed)
230 {
231         struct ec_parsed *child;
232
233         if (parsed == NULL)
234                 return;
235
236         while (!TAILQ_EMPTY(&parsed->children)) {
237                 child = TAILQ_FIRST(&parsed->children);
238                 TAILQ_REMOVE(&parsed->children, child, next);
239                 ec_parsed_free(child);
240         }
241 }
242
243 void ec_parsed_free(struct ec_parsed *parsed)
244 {
245         if (parsed == NULL)
246                 return;
247
248         // assert(parsed->parent == NULL); XXX
249         // or
250         // parsed = ec_parsed_get_root(parsed);
251
252         ec_parsed_free_children(parsed);
253         ec_strvec_free(parsed->strvec);
254         ec_keyval_free(parsed->attrs);
255         ec_free(parsed);
256 }
257
258 static void __ec_parsed_dump(FILE *out,
259         const struct ec_parsed *parsed, size_t indent)
260 {
261         struct ec_parsed *child;
262         const struct ec_strvec *vec;
263         size_t i;
264         const char *id = "none", *typename = "none";
265
266         if (parsed->node != NULL) {
267                 if (parsed->node->id != NULL)
268                         id = parsed->node->id;
269                 typename = parsed->node->type->name;
270         }
271
272         /* XXX enhance */
273         for (i = 0; i < indent; i++) {
274                 if (i % 2)
275                         fprintf(out, " ");
276                 else
277                         fprintf(out, "|");
278         }
279
280         fprintf(out, "node_type=%s id=%s vec=", typename, id);
281         vec = ec_parsed_strvec(parsed);
282         ec_strvec_dump(out, vec);
283
284         TAILQ_FOREACH(child, &parsed->children, next)
285                 __ec_parsed_dump(out, child, indent + 2);
286 }
287
288 void ec_parsed_dump(FILE *out, const struct ec_parsed *parsed)
289 {
290         fprintf(out, "------------------- parsed dump:\n"); //XXX
291
292         if (parsed == NULL) {
293                 fprintf(out, "parsed is NULL, error in parse\n");
294                 return;
295         }
296
297         /* only exist if it does not match (strvec == NULL) and if it
298          * does not have children: an incomplete parse, like those
299          * generated by complete() don't match but have children that
300          * may match. */
301         if (!ec_parsed_matches(parsed) && TAILQ_EMPTY(&parsed->children)) {
302                 fprintf(out, "no match\n");
303                 return;
304         }
305
306         __ec_parsed_dump(out, parsed, 0);
307 }
308
309 void ec_parsed_add_child(struct ec_parsed *parsed,
310         struct ec_parsed *child)
311 {
312         TAILQ_INSERT_TAIL(&parsed->children, child, next);
313         child->parent = parsed;
314 }
315
316 // XXX we can remove the first arg ? parsed == child->parent ?
317 void ec_parsed_del_child(struct ec_parsed *parsed, // XXX rename del in unlink?
318         struct ec_parsed *child)
319 {
320         TAILQ_REMOVE(&parsed->children, child, next);
321         child->parent = NULL;
322 }
323
324 struct ec_parsed *
325 ec_parsed_get_first_child(const struct ec_parsed *parsed)
326 {
327         return TAILQ_FIRST(&parsed->children);
328 }
329
330 struct ec_parsed *
331 ec_parsed_get_last_child(const struct ec_parsed *parsed)
332 {
333         return TAILQ_LAST(&parsed->children, ec_parsed_list);
334 }
335
336 struct ec_parsed *ec_parsed_get_next(const struct ec_parsed *parsed)
337 {
338         return TAILQ_NEXT(parsed, next);
339 }
340
341 bool ec_parsed_has_child(const struct ec_parsed *parsed)
342 {
343         return !TAILQ_EMPTY(&parsed->children);
344 }
345
346 const struct ec_node *ec_parsed_get_node(const struct ec_parsed *parsed)
347 {
348         return parsed->node;
349 }
350
351 void ec_parsed_del_last_child(struct ec_parsed *parsed) // rename in free
352 {
353         struct ec_parsed *child;
354
355         child = ec_parsed_get_last_child(parsed);
356         ec_parsed_del_child(parsed, child);
357         ec_parsed_free(child);
358 }
359
360 struct ec_parsed *ec_parsed_get_root(struct ec_parsed *parsed)
361 {
362         if (parsed == NULL)
363                 return NULL;
364
365         while (parsed->parent != NULL)
366                 parsed = parsed->parent;
367
368         return parsed;
369 }
370
371 struct ec_parsed *ec_parsed_get_parent(struct ec_parsed *parsed)
372 {
373         if (parsed == NULL)
374                 return NULL;
375
376         return parsed->parent;
377 }
378
379 struct ec_parsed *ec_parsed_iter_next(struct ec_parsed *parsed)
380 {
381         struct ec_parsed *child, *parent, *next;
382
383         child = TAILQ_FIRST(&parsed->children);
384         if (child != NULL)
385                 return child;
386         parent = parsed->parent;
387         while (parent != NULL) {
388                 next = TAILQ_NEXT(parsed, next);
389                 if (next != NULL)
390                         return next;
391                 parsed = parent;
392                 parent = parsed->parent;
393         }
394         return NULL;
395 }
396
397 struct ec_parsed *ec_parsed_find_first(struct ec_parsed *parsed,
398         const char *id)
399 {
400         struct ec_parsed *child, *ret;
401
402         if (parsed == NULL)
403                 return NULL;
404
405         if (parsed->node != NULL &&
406                         parsed->node->id != NULL &&
407                         !strcmp(parsed->node->id, id))
408                 return parsed;
409
410         TAILQ_FOREACH(child, &parsed->children, next) {
411                 ret = ec_parsed_find_first(child, id);
412                 if (ret != NULL)
413                         return ret;
414         }
415
416         return NULL;
417 }
418
419 struct ec_keyval *
420 ec_parsed_get_attrs(struct ec_parsed *parsed)
421 {
422         if (parsed == NULL)
423                 return NULL;
424
425         return parsed->attrs;
426 }
427
428 const struct ec_strvec *ec_parsed_strvec(const struct ec_parsed *parsed)
429 {
430         if (parsed == NULL || parsed->strvec == NULL)
431                 return NULL;
432
433         return parsed->strvec;
434 }
435
436 /* number of strings in the parsed vector */
437 size_t ec_parsed_len(const struct ec_parsed *parsed)
438 {
439         if (parsed == NULL || parsed->strvec == NULL)
440                 return 0;
441
442         return ec_strvec_len(parsed->strvec);
443 }
444
445 size_t ec_parsed_matches(const struct ec_parsed *parsed)
446 {
447         if (parsed == NULL)
448                 return 0;
449
450         if (parsed->strvec == NULL)
451                 return 0;
452
453         return 1;
454 }