diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/command_match.c | 53 | ||||
| -rw-r--r-- | lib/command_match.h | 16 | ||||
| -rw-r--r-- | lib/command_parse.y | 1 | ||||
| -rw-r--r-- | lib/grammar_sandbox.c | 25 |
4 files changed, 76 insertions, 19 deletions
diff --git a/lib/command_match.c b/lib/command_match.c index 285a776a7c..d5efa39686 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -52,6 +52,9 @@ disambiguate_nodes (struct graph_node *, struct graph_node *, char *); static struct list * disambiguate (struct list *, struct list *, vector, unsigned int); +int +compare_completions (const void *, const void *); + /* token matcher prototypes */ static enum match_type match_token (struct graph_node *, char *); @@ -291,7 +294,7 @@ match_command_complete (struct graph_node *start, vector vline, struct list **co */ matcher_rv = - idx + 1 == vector_active(vline) && next->count ? + idx == vector_active(vline) && next->count ? MATCHER_OK : MATCHER_NO_MATCH; @@ -302,6 +305,54 @@ match_command_complete (struct graph_node *start, vector vline, struct list **co } /** + * Compare two completions. Tightly coupled to vector. + * + * @param[in] fst pointer to first item pointer in vector->index + * @param[in] snd pointer to second item poitner in vector->index + * @return integer compare code as determined by strcmp + */ +int +compare_completions (const void *fst, const void *snd) +{ + const char *first = *((char **) fst); + const char *secnd = *((char **) snd); + return strcmp (first, secnd); +} + +enum matcher_rv +match_command_complete_str (struct graph_node *start, + vector vline, + vector completions) +{ + struct list *comps; + enum matcher_rv rv = match_command_complete (start, vline, &comps); + + // quick n' dirty deduplication fn here, prolly like O(n^n) + struct listnode *ln; + struct graph_node *gn; + unsigned int i; + for (ALL_LIST_ELEMENTS_RO(comps,ln,gn)) + { + // linear search for node text in completions vector + int exists = 0; + for (i = 0; i < vector_active (completions) && !exists; i++) + exists = !strcmp (gn->text, vector_slot (completions, i)); + + if (!exists) + vector_set (completions, XSTRDUP(MTYPE_TMP, gn->text)); + } + + // sort completions + qsort (completions->index, + vector_active (completions), + sizeof (void *), + &compare_completions); + + list_delete (comps); + return rv; +} + +/** * Adds all children that are reachable by one parser hop to the given list. * NUL_GN, SELECTOR_GN, and OPTION_GN nodes are treated as transparent. * diff --git a/lib/command_match.h b/lib/command_match.h index 6804a0777a..e8a408495e 100644 --- a/lib/command_match.h +++ b/lib/command_match.h @@ -85,7 +85,7 @@ match_command (struct graph_node *start, * * @param[in] start the start node of the DFA to match against * @param[in] vline vectorized input string - * @param[in] completions pointer to possible completions + * @param[in] completions pointer to list of possible next nodes * @return matcher status */ enum matcher_rv @@ -93,4 +93,18 @@ match_command_complete (struct graph_node *start, vector vline, struct list **completions); + +/** + * Compiles possible completions for a given line of user input. + * + * @param[in] start the start node of the DFA to match against + * @param[in] vline vectorized input string + * @param[in] completions vector to fill with string completions + * @return matcher status + */ +enum matcher_rv +match_command_complete_str (struct graph_node *start, + vector vline, + vector completions); + #endif /* _ZEBRA_COMMAND_MATCH_H */ diff --git a/lib/command_parse.y b/lib/command_parse.y index 56c58fdaed..df90f64edb 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -433,6 +433,7 @@ terminate_graph (struct graph_node *startnode, { struct graph_node *end = new_node (END_GN); end->element = element; + end->text = XSTRDUP(MTYPE_CMD_TOKENS, "<cr>"); if (node_exists (finalnode, end)) yyerror (element, startnode, "Duplicate command."); else diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index 6473fc12e3..899d0469ab 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -91,31 +91,22 @@ DEFUN (grammar_test_complete, char *cmdstr = argv_concat (argv, argc, 0); vector command = cmd_make_strvec (cmdstr); - struct list *completions; - enum matcher_rv result = match_command_complete (nodegraph, command, &completions); + vector completions = vector_init (VECTOR_MIN_SIZE); + enum matcher_rv result = + match_command_complete_str (nodegraph, command, completions); // print completions or relevant error message - if (completions) + if (!MATCHER_ERROR(result)) { - struct listnode *ln; - struct graph_node *gn; - for (ALL_LIST_ELEMENTS_RO(completions,ln,gn)) - { - if (gn->type == END_GN) - zlog_info ("<cr> (%p)", gn->element->func); - else - zlog_info ("%-30s%s", gn->text, gn->doc); - } - list_delete (completions); + for (unsigned int i = 0; i < vector_active (completions); i++) + zlog_info ((char *) vector_slot (completions, i)); } else - { - assert(MATCHER_ERROR(result)); - zlog_info ("%% No match for \"%s\"", cmdstr); - } + zlog_info ("%% No match for \"%s\"", cmdstr); // free resources cmd_free_strvec (command); + cmd_free_strvec (completions); free (cmdstr); return CMD_SUCCESS; |
