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.
35 struct ec_tk *ec_tk_new(const char *id, const struct ec_tk_ops *ops,
38 struct ec_tk *tk = NULL;
40 assert(size >= sizeof(*tk));
61 void ec_tk_free(struct ec_tk *tk)
66 if (tk->ops != NULL && tk->ops->free_priv != NULL)
67 tk->ops->free_priv(tk);
72 struct ec_parsed_tk *ec_tk_parse(const struct ec_tk *token, const char *str,
75 struct ec_parsed_tk *parsed_tk;
77 parsed_tk = token->ops->parse(token, str, off);
83 struct ec_parsed_tk *ec_parsed_tk_new(const struct ec_tk *tk)
85 struct ec_parsed_tk *parsed_tk;
87 parsed_tk = calloc(1, sizeof(*parsed_tk));
88 if (parsed_tk == NULL)
92 TAILQ_INIT(&parsed_tk->children);
100 void ec_parsed_tk_free(struct ec_parsed_tk *parsed_tk)
102 struct ec_parsed_tk *child;
104 if (parsed_tk == NULL)
107 while (!TAILQ_EMPTY(&parsed_tk->children)) {
108 child = TAILQ_FIRST(&parsed_tk->children);
109 TAILQ_REMOVE(&parsed_tk->children, child, next);
110 ec_parsed_tk_free(child);
112 free(parsed_tk->str);
116 static void __ec_parsed_tk_dump(const struct ec_parsed_tk *parsed_tk,
119 struct ec_parsed_tk *child;
124 for (i = 0; i < indent; i++)
126 s = ec_parsed_tk_to_string(parsed_tk);
127 printf("id=%s, s=<%s>\n", parsed_tk->tk->id, s);
129 TAILQ_FOREACH(child, &parsed_tk->children, next)
130 __ec_parsed_tk_dump(child, indent + 2);
133 void ec_parsed_tk_dump(const struct ec_parsed_tk *parsed_tk)
135 if (parsed_tk == NULL) {
136 printf("no match\n");
140 __ec_parsed_tk_dump(parsed_tk, 0);
143 void ec_parsed_tk_add_child(struct ec_parsed_tk *parsed_tk,
144 struct ec_parsed_tk *child)
146 TAILQ_INSERT_TAIL(&parsed_tk->children, child, next);
149 struct ec_parsed_tk *ec_parsed_tk_find_first(struct ec_parsed_tk *parsed_tk,
152 struct ec_parsed_tk *child, *ret;
154 if (parsed_tk == NULL)
157 if (parsed_tk->tk->id != NULL && !strcmp(parsed_tk->tk->id, id))
160 TAILQ_FOREACH(child, &parsed_tk->children, next) {
161 ret = ec_parsed_tk_find_first(child, id);
169 const char *ec_parsed_tk_to_string(const struct ec_parsed_tk *parsed_tk)
171 if (parsed_tk == NULL)
174 return parsed_tk->str;
177 struct ec_completed_tk *ec_tk_complete(const struct ec_tk *token,
178 const char *str, size_t off)
180 struct ec_completed_tk *completed_tk;
182 completed_tk = token->ops->complete(token, str, off);
187 struct ec_completed_tk *ec_completed_tk_new(void)
189 struct ec_completed_tk *completed_tk = NULL;
191 completed_tk = calloc(1, sizeof(*completed_tk));
192 if (completed_tk == NULL)
195 TAILQ_INIT(&completed_tk->elts);
196 completed_tk->count = 0;
201 struct ec_completed_tk_elt *ec_completed_tk_elt_new(const struct ec_tk *tk,
202 const char *add, const char *full)
204 struct ec_completed_tk_elt *elt = NULL;
206 elt = calloc(1, sizeof(*elt));
211 elt->add = strdup(add);
212 elt->full = strdup(full);
213 if (elt->add == NULL || elt->full == NULL) {
214 ec_completed_tk_elt_free(elt);
221 /* count the number of identical chars at the beginning of 2 strings */
222 static size_t strcmp_count(const char *s1, const char *s2)
226 while (s1[i] && s2[i] && s1[i] == s2[i])
232 void ec_completed_tk_add_elt(
233 struct ec_completed_tk *completed_tk, struct ec_completed_tk_elt *elt)
237 TAILQ_INSERT_TAIL(&completed_tk->elts, elt, next);
238 completed_tk->count++;
239 if (elt->add != NULL) {
240 if (completed_tk->smallest_start == NULL) {
241 completed_tk->smallest_start = strdup(elt->add);
243 n = strcmp_count(elt->add,
244 completed_tk->smallest_start);
245 completed_tk->smallest_start[n] = '\0';
250 void ec_completed_tk_elt_free(struct ec_completed_tk_elt *elt)
257 struct ec_completed_tk *ec_completed_tk_merge(
258 struct ec_completed_tk *completed_tk1,
259 struct ec_completed_tk *completed_tk2)
261 struct ec_completed_tk_elt *elt;
263 if (completed_tk2 == NULL)
264 return completed_tk1;
266 if (completed_tk1 == NULL)
267 return completed_tk2;
269 while (!TAILQ_EMPTY(&completed_tk2->elts)) {
270 elt = TAILQ_FIRST(&completed_tk2->elts);
271 TAILQ_REMOVE(&completed_tk2->elts, elt, next);
272 ec_completed_tk_add_elt(completed_tk1, elt);
275 ec_completed_tk_free(completed_tk2);
277 return completed_tk1;
280 void ec_completed_tk_free(struct ec_completed_tk *completed_tk)
282 struct ec_completed_tk_elt *elt;
284 if (completed_tk == NULL)
287 while (!TAILQ_EMPTY(&completed_tk->elts)) {
288 elt = TAILQ_FIRST(&completed_tk->elts);
289 TAILQ_REMOVE(&completed_tk->elts, elt, next);
290 ec_completed_tk_elt_free(elt);
292 free(completed_tk->smallest_start);
296 void ec_completed_tk_dump(const struct ec_completed_tk *completed_tk)
298 struct ec_completed_tk_elt *elt;
300 if (completed_tk == NULL || completed_tk->count == 0) {
301 printf("no completion\n");
305 printf("completion: count=%u smallest_start=<%s>\n",
306 completed_tk->count, completed_tk->smallest_start);
308 TAILQ_FOREACH(elt, &completed_tk->elts, next)
309 printf("add=<%s> full=<%s>\n", elt->add, elt->full);
312 const char *ec_completed_tk_smallest_start(
313 const struct ec_completed_tk *completed_tk)
315 if (completed_tk == NULL)
318 return completed_tk->smallest_start;
321 unsigned int ec_completed_tk_count(const struct ec_completed_tk *completed_tk)
323 struct ec_completed_tk_elt *elt;
324 unsigned int count = 0;
326 if (completed_tk == NULL)
329 TAILQ_FOREACH(elt, &completed_tk->elts, next)