X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=src%2Fgenconf%2Fparse_confnode.c;h=382bfde92a7379c7e5c62734149a8d17414fbdfe;hb=0a09866300194a46a58ff4dc0b837e01305f4444;hp=5c8202bdf99e694df64e31211e3fe0d6faf8050f;hpb=5dbaf53aa2c6187d464108e360621ebfff6e0bc4;p=libcmdline.git diff --git a/src/genconf/parse_confnode.c b/src/genconf/parse_confnode.c index 5c8202b..382bfde 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,47 +90,8 @@ 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) +parse_conf_node(cmdline_parse_token_hdr_t *tk, const char *buf, void *res, + unsigned ressize) { struct token_conf_node *tk2 = (struct token_conf_node *)tk; struct token_conf_node_data *tkd = &tk2->conf_node_data; @@ -144,6 +100,9 @@ parse_conf_node(cmdline_parse_token_hdr_t *tk, const char *buf, void *res) unsigned int token_len = 0; char token[CMDLINE_MAX_TOKEN_SIZE]; + if (res && ressize < sizeof(struct confnode *)) + return -1; + /* if token is too big... */ token_len = snprintf(token, sizeof(token), "%s", buf); if (token_len >= sizeof(token)) @@ -174,28 +133,103 @@ parse_conf_node(cmdline_parse_token_hdr_t *tk, const char *buf, void *res) if (res) *(struct confnode **)res = TAILQ_FIRST(&l); - return token_len; + return 0; } -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, + __attribute__((unused)) const char *tokstr, + 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); + *opaque = NULL; + cb = malloc(sizeof(*cb)); + if (cb == NULL) + return -1; + *opaque = cb; + + n = get_next_node(*tkd->cur, NULL, flags, mask); + if (n == NULL) + return -1; /* no completion */ + + cb->start = *tkd->cur; + cb->cur = n; + 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) @@ -205,9 +239,24 @@ 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) +{ + if (*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, +}; +