From: Quentin Young Date: Wed, 3 Aug 2016 19:22:27 +0000 (+0000) Subject: lib: Implement status variable X-Git-Tag: frr-3.0-branchpoint~129^2~267 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=6ce82b63cd35eac37a4ddf1d0253342d5160b7af;p=matthieu%2Ffrr.git lib: Implement status variable Matcher now keeps track of why it failed Signed-off-by: Quentin Young --- diff --git a/lib/.command.h.swo b/lib/.command.h.swo deleted file mode 100644 index 71a42cc20a..0000000000 Binary files a/lib/.command.h.swo and /dev/null differ diff --git a/lib/command_match.c b/lib/command_match.c index 6923da776b..5ba1c1b6e7 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -54,46 +54,41 @@ static enum match_type match_variable (struct graph_node *, const char *); /* matching functions */ +static enum matcher_rv matcher_result_value; -struct cmd_element * -match_command (struct graph_node *start, const char *line, struct list **argv) +enum matcher_rv +match_command (struct graph_node *start, + const char *line, + struct list **argvv, + struct cmd_element **el) { + matcher_result_value = MATCHER_NO_MATCH; // parse command vector vline = cmd_make_strvec (line); for (unsigned int i = 0; i < vector_active(start->children); i++) { - // call recursive builder on each starting child - *argv = match_command_r(vector_slot(start->children, i), vline, 0); - // if any of them succeed, return their argv - // since all command DFA's must begin with a word, there can only be - // one valid return value - if (*argv) break; + // call recursive matcher on each starting child + *argvv = match_command_r(vector_slot(start->children, i), vline, 0); + if (*argvv) break; } - // walk the list, find the END_GN, return that - if (*argv) { + if (*argvv) { struct listnode *ln; struct graph_node *gn; - char buf[50]; - for (ALL_LIST_ELEMENTS_RO(*argv,ln,gn)) { - describe_node(gn, buf, 50); - fprintf(stderr, "%s[%d]\n", buf, gn->type); - if (gn->type == END_GN) - return gn->element; - } - assert(0); + for (ALL_LIST_ELEMENTS_RO(*argvv,ln,gn)) + if (gn->type == END_GN) { + *el = gn->element; + break; + } + assert(el); } - return NULL; + return matcher_result_value; } /** - * Matches a given input line against a DFA. - * - * Builds an argument list given a DFA and a matching input line. This function - * should be passed the start node of the DFA, a matching input line, and the - * index of the first token in the input line. + * Builds an argument list given a DFA and a matching input line. * * First the function determines if the node it is passed matches the first * token of input. If it does not, it returns NULL. If it does match, then it @@ -177,7 +172,7 @@ match_command_r (struct graph_node *start, vector vline, unsigned int n) else continue; } - // else recurse on node + // else recurse on candidate child node struct list *result = match_command_r (gn, vline, n+1); // save the best match, subtle logic at play here @@ -200,16 +195,23 @@ match_command_r (struct graph_node *start, vector vline, unsigned int n) } } - if (ambiguous) { - list_delete(bestmatch); - bestmatch = NULL; - } - if (bestmatch) { - // copy current node, set arg and prepend to bestmatch - struct graph_node *curr = copy_node(start); - curr->arg = XSTRDUP(MTYPE_CMD_TOKENS, token); - list_add_node_prev (bestmatch, bestmatch->head, curr); + if (ambiguous) { + list_delete(bestmatch); + bestmatch = NULL; + matcher_result_value = MATCHER_AMBIGUOUS; + } + else { + // copy current node, set arg and prepend to bestmatch + struct graph_node *curr = copy_node(start); + curr->arg = XSTRDUP(MTYPE_CMD_TOKENS, token); + list_add_node_prev (bestmatch, bestmatch->head, curr); + matcher_result_value = MATCHER_OK; + } + } + else { + if (n+1 == vector_active(vline) && matcher_result_value == MATCHER_NO_MATCH) + matcher_result_value = MATCHER_INCOMPLETE; } // cleanup @@ -271,9 +273,13 @@ match_command_complete (struct graph_node *start, const char *line) * next = set of all nodes reachable from all nodes in `matched` */ list_free (current); - cmd_free_strvec(vline); + matcher_result_value = + idx + 1 == vector_active(vline) && next->count ? + MATCHER_OK : + MATCHER_NO_MATCH; + return next; } @@ -329,13 +335,15 @@ score_precedence (enum graph_node_type type) { switch (type) { - // some of these are mutually exclusive, order is important + // some of these are mutually exclusive, so they share + // the same precedence value case IPV4_GN: case IPV4_PREFIX_GN: case IPV6_GN: case IPV6_PREFIX_GN: - case RANGE_GN: case NUMBER_GN: + return 1; + case RANGE_GN: return 2; case WORD_GN: return 3; diff --git a/lib/command_match.h b/lib/command_match.h index 8ad7ab0556..895a678dce 100644 --- a/lib/command_match.h +++ b/lib/command_match.h @@ -18,12 +18,10 @@ enum filter_type /* matcher result value. */ enum matcher_rv { - MATCHER_OK, - MATCHER_COMPLETE, - MATCHER_INCOMPLETE, MATCHER_NO_MATCH, + MATCHER_INCOMPLETE, MATCHER_AMBIGUOUS, - MATCHER_EXCEED_ARGC_MAX + MATCHER_OK, }; /* Completion match types. */ @@ -42,7 +40,6 @@ enum match_type ( (matcher_rv) == MATCHER_INCOMPLETE \ || (matcher_rv) == MATCHER_NO_MATCH \ || (matcher_rv) == MATCHER_AMBIGUOUS \ - || (matcher_rv) == MATCHER_EXCEED_ARGC_MAX \ ) /** @@ -50,11 +47,12 @@ enum match_type * * @param DFA to match against * @param input string - * @param pointer to argv pointer - * @return cmd_element found, or NULL if there is no match. + * @param pointer which will be pointed at argv upon match + * @param pointer which will be pointed at matching cmd_element upon match + * @return result of matcher run */ -struct cmd_element * -match_command (struct graph_node *, const char *, struct list **); +enum matcher_rv +match_command (struct graph_node *, const char *, struct list **, struct cmd_element **); /** * Compiles next-hops for a given line of user input. diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index c53811e062..0eb8d69cee 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -77,9 +77,11 @@ DEFUN (grammar_test_match, "attempt to match input on DFA\n" "command to match") { + const char *line = argv_concat(argv, argc, 0); + struct list *argvv = NULL; - const char *command = argv_concat(argv, argc, 0); - struct cmd_element *element = match_command (nodegraph, command, &argvv); + struct cmd_element *element = NULL; + enum matcher_rv result = match_command (nodegraph, line, &argvv, &element); if (element) { fprintf(stderr, "Matched: %s\n", element->string); @@ -89,8 +91,20 @@ DEFUN (grammar_test_match, fprintf(stderr, "%s -- %s\n", gn->text, gn->arg); } else { - fprintf(stderr, "Returned NULL\n"); - return CMD_SUCCESS; + switch (result) { + case MATCHER_NO_MATCH: + fprintf(stderr, "%% Unknown command\n"); + break; + case MATCHER_INCOMPLETE: + fprintf(stderr, "%% Incomplete command\n"); + break; + case MATCHER_AMBIGUOUS: + fprintf(stderr, "%% Ambiguous command\n"); + break; + default: + fprintf(stderr, "%% Unknown error\n"); + break; + } } return CMD_SUCCESS;