2 * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
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.
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.
34 #include <ecoli_malloc.h>
35 #include <ecoli_strvec.h>
36 #include <ecoli_keyval.h>
37 #include <ecoli_log.h>
38 #include <ecoli_node.h>
39 #include <ecoli_parsed.h>
41 struct ec_parsed *ec_node_parse(struct ec_node *node, const char *str)
43 struct ec_strvec *strvec = NULL;
44 struct ec_parsed *parsed;
51 if (ec_strvec_add(strvec, str) < 0)
54 parsed = ec_node_parse_strvec(node, strvec);
58 ec_strvec_free(strvec);
62 ec_strvec_free(strvec);
66 struct ec_parsed *ec_node_parse_strvec(struct ec_node *node,
67 const struct ec_strvec *strvec)
69 struct ec_parsed *parsed;
72 /* build the node if required */
73 if (node->type->build != NULL) {
74 if ((node->flags & EC_NODE_F_BUILT) == 0) {
75 ret = node->type->build(node);
82 node->flags |= EC_NODE_F_BUILT;
84 if (node->type->parse == NULL) {
89 parsed = node->type->parse(node, strvec);
95 struct ec_parsed *ec_parsed(void)
97 struct ec_parsed *parsed = NULL;
99 parsed = ec_calloc(1, sizeof(*parsed));
103 TAILQ_INIT(&parsed->children);
111 void ec_parsed_set_match(struct ec_parsed *parsed,
112 const struct ec_node *node, struct ec_strvec *strvec)
115 parsed->strvec = strvec;
118 void ec_parsed_free_children(struct ec_parsed *parsed)
120 struct ec_parsed *child;
125 while (!TAILQ_EMPTY(&parsed->children)) {
126 child = TAILQ_FIRST(&parsed->children);
127 TAILQ_REMOVE(&parsed->children, child, next);
128 ec_parsed_free(child);
132 void ec_parsed_free(struct ec_parsed *parsed)
137 ec_parsed_free_children(parsed);
138 ec_strvec_free(parsed->strvec);
142 static void __ec_parsed_dump(FILE *out,
143 const struct ec_parsed *parsed, size_t indent)
145 struct ec_parsed *child;
146 const struct ec_strvec *vec;
148 const char *id = "None", *typename = "None";
150 if (parsed->node != NULL) {
151 if (parsed->node->id != NULL)
152 id = parsed->node->id;
153 typename = parsed->node->type->name;
157 for (i = 0; i < indent; i++) {
164 fprintf(out, "node_type=%s id=%s vec=[", typename, id);
165 vec = ec_parsed_strvec(parsed);
166 for (i = 0; i < ec_strvec_len(vec); i++)
167 fprintf(out, "%s<%s>",
169 ec_strvec_val(vec, i));
172 TAILQ_FOREACH(child, &parsed->children, next)
173 __ec_parsed_dump(out, child, indent + 2);
176 void ec_parsed_dump(FILE *out, const struct ec_parsed *parsed)
178 fprintf(out, "------------------- parsed dump:\n"); //XXX
180 if (parsed == NULL) {
181 fprintf(out, "parsed is NULL, error in parse\n");
184 if (!ec_parsed_matches(parsed)) {
185 fprintf(out, "no match\n");
189 __ec_parsed_dump(out, parsed, 0);
192 void ec_parsed_add_child(struct ec_parsed *parsed,
193 struct ec_parsed *child)
195 TAILQ_INSERT_TAIL(&parsed->children, child, next);
198 void ec_parsed_del_child(struct ec_parsed *parsed,
199 struct ec_parsed *child)
201 TAILQ_REMOVE(&parsed->children, child, next);
204 struct ec_parsed *ec_parsed_find_first(struct ec_parsed *parsed,
207 struct ec_parsed *child, *ret;
212 if (parsed->node != NULL &&
213 parsed->node->id != NULL &&
214 !strcmp(parsed->node->id, id))
217 TAILQ_FOREACH(child, &parsed->children, next) {
218 ret = ec_parsed_find_first(child, id);
226 const struct ec_strvec *ec_parsed_strvec(const struct ec_parsed *parsed)
228 if (parsed == NULL || parsed->strvec == NULL)
231 return parsed->strvec;
234 /* number of parsed strings in the vector */
235 size_t ec_parsed_len(const struct ec_parsed *parsed)
237 if (parsed == NULL || parsed->strvec == NULL)
240 return ec_strvec_len(parsed->strvec);
243 size_t ec_parsed_matches(const struct ec_parsed *parsed)
248 if (parsed->node == NULL && TAILQ_EMPTY(&parsed->children))