X-Git-Url: http://git.droids-corp.org/?p=libcmdline.git;a=blobdiff_plain;f=src%2Fgenconf%2Fparse_confnode.c;h=21ccaacf6b594fbe18d6800c1c70128875676133;hp=b25166fce817452eba009cadb92815838c7a973f;hb=f32d30f48ddfb55b86efd695e0dd144e9d15401e;hpb=b1d5b169352e57df3fc14c51ffad4b83f3e5613f diff --git a/src/genconf/parse_confnode.c b/src/genconf/parse_confnode.c index b25166f..21ccaac 100644 --- a/src/genconf/parse_confnode.c +++ b/src/genconf/parse_confnode.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -41,15 +42,9 @@ #include "conf_htable.h" #include "parse_confnode.h" -struct cmdline_token_ops token_conf_node_ops = { - .parse = parse_conf_node, - .complete_get_nb = complete_get_nb_conf_node, - .complete_get_elt = complete_get_elt_conf_node, - .get_help = get_help_conf_node, -}; - /* return 0 if string matches pattern (string must not contain '*')*/ -static int strcmp_joker(const char *s, const char *pattern) +static int +strcmp_joker(const char *s, const char *pattern) { if (s == pattern) return 0; @@ -95,46 +90,6 @@ find_in_children(struct confnode_list *l, struct confnode *n, } static int -count_children(struct confnode *n, int flags, int mask) -{ - struct confnode *c; - int i = 0; - - TAILQ_FOREACH(c, &n->children, next) { - /* if it's a "if" node, parse children */ - if (c->flags & CONFNODE_F_INVISIBLE) - i += count_children(c, flags, mask); - else if ((c->flags & mask) == flags) - i ++; - } - return i; -} - -static struct confnode * -get_from_idx(struct confnode *n, unsigned int *cur, unsigned int idx, - int flags, int mask) -{ - struct confnode *c, *tmp; - - TAILQ_FOREACH(c, &n->children, next) { - /* if it's a "if" node, parse children */ - if (c->flags & CONFNODE_F_INVISIBLE) { - tmp = get_from_idx(c, cur, idx, flags, mask); - if (tmp) - return tmp; - } - else { - if ((c->flags & mask) != flags) - continue; - if (*cur == idx) - return c; - *cur = *cur + 1; - } - } - return NULL; -} - -int parse_conf_node(cmdline_parse_token_hdr_t *tk, const char *buf, void *res, unsigned ressize) { @@ -181,25 +136,97 @@ parse_conf_node(cmdline_parse_token_hdr_t *tk, const char *buf, void *res, return token_len; } -int complete_get_nb_conf_node(cmdline_parse_token_hdr_t *tk) +struct confnode_complete_callback { + struct confnode *start; + struct confnode *cur; +}; + + +static struct confnode *get_next_node(struct confnode *start, + struct confnode *cur, unsigned flags, + unsigned mask) +{ + struct confnode *prev; + struct confnode *parent = start; + + while (1) { + prev = cur; + + /* no more node to browse */ + if (cur == start) + return NULL; + + /* first iteration */ + if (cur == NULL) + cur = TAILQ_FIRST(&parent->children); + else + cur = TAILQ_NEXT(cur, next); + + /* no next, return to upper level */ + if (cur == NULL) { + if (prev == NULL) + return NULL; /* no node */ + cur = prev->parent; + continue; + } + + /* skip invisible nodes, and browse their contents */ + if (cur->flags & CONFNODE_F_INVISIBLE) { + parent = cur; + cur = NULL; + continue; + } + + /* check that flags match what we want */ + if ((cur->flags & mask) != flags) + continue; + + /* standard node, return it */ + return cur; + } +} + +static int +complete_conf_node_start(cmdline_parse_token_hdr_t *tk, void **opaque) { struct token_conf_node *tk2 = (struct token_conf_node *)tk; struct token_conf_node_data *tkd = &tk2->conf_node_data; + struct confnode_complete_callback *cb; + struct confnode *n; + unsigned flags = tkd->flags; + unsigned mask = tkd->mask; - return count_children(*tkd->cur, tkd->flags, tkd->mask); + cb = malloc(sizeof(*cb)); + if (cb == NULL) + return -1; + + n = get_next_node(*tkd->cur, NULL, flags, mask); + if (n == NULL) + return -1; /* no completion */ + + cb->start = *tkd->cur; + cb->cur = n; + *opaque = cb; + return 0; } -int complete_get_elt_conf_node(cmdline_parse_token_hdr_t *tk, int idx, - char *dstbuf, unsigned int size) +static int +complete_conf_node_iterate(cmdline_parse_token_hdr_t *tk, void **opaque, + char *dstbuf, unsigned int size) { struct token_conf_node *tk2 = (struct token_conf_node *)tk; struct token_conf_node_data *tkd = &tk2->conf_node_data; + struct confnode_complete_callback *cb; struct confnode *n; - unsigned int i = 0, len; + unsigned len; + unsigned flags = tkd->flags; + unsigned mask = tkd->mask; - n = get_from_idx(*tkd->cur, &i, idx, tkd->flags, tkd->mask); + cb = *opaque; + n = cb->cur; if (n == NULL) return -1; + cb->cur = get_next_node(cb->start, n, flags, mask); len = strlen(n->name) + 1; if (len > size) @@ -209,9 +236,23 @@ int complete_get_elt_conf_node(cmdline_parse_token_hdr_t *tk, int idx, return 0; } +static void +complete_conf_node_end(cmdline_parse_token_hdr_t *tk, void **opaque) +{ + free(*opaque); +} -int get_help_conf_node(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size) +int help_conf_node(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size) { snprintf(dstbuf, size, "conf-node"); return 0; } + +struct cmdline_token_ops token_conf_node_ops = { + .parse = parse_conf_node, + .complete_start = complete_conf_node_start, + .complete_iterate = complete_conf_node_iterate, + .complete_end = complete_conf_node_end, + .help = help_conf_node, +}; +