]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: Implement status variable
authorQuentin Young <qlyoung@cumulusnetworks.com>
Wed, 3 Aug 2016 19:22:27 +0000 (19:22 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Wed, 3 Aug 2016 19:22:27 +0000 (19:22 +0000)
Matcher now keeps track of why it failed

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
lib/.command.h.swo [deleted file]
lib/command_match.c
lib/command_match.h
lib/grammar_sandbox.c

diff --git a/lib/.command.h.swo b/lib/.command.h.swo
deleted file mode 100644 (file)
index 71a42cc..0000000
Binary files a/lib/.command.h.swo and /dev/null differ
index 6923da776bece1999afe8df3f6c50efd96af273c..5ba1c1b6e76039e5684b95c26068bb1ee8b14b91 100644 (file)
@@ -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;
index 8ad7ab05568ec2075fddd46af1a8415acaf6c249..895a678dcefa925bbaebe9dabac4d8f87e99c669 100644 (file)
@@ -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.
index c53811e0629b29f418a331761977468a18a4bdbb..0eb8d69cee2786663c6b602da7eaa96e520f6015 100644 (file)
@@ -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;