]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: Break up functions, begin matcher
authorQuentin Young <qlyoung@cumulusnetworks.com>
Tue, 19 Jul 2016 21:14:27 +0000 (21:14 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Tue, 19 Jul 2016 21:14:27 +0000 (21:14 +0000)
Moved test hook out of command.c into vtysh.c,
renamed graph modules, added matching code

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
12 files changed:
lib/Makefile.am
lib/cmdtree.c [deleted file]
lib/cmdtree.h [deleted file]
lib/command.c
lib/command_graph.c [new file with mode: 0644]
lib/command_graph.h [new file with mode: 0644]
lib/command_match.c [new file with mode: 0644]
lib/command_match.h [new file with mode: 0644]
lib/command_parse.y
lib/grammar_sandbox.c
lib/grammar_sandbox.h [new file with mode: 0644]
vtysh/vtysh.c

index 126303622f81fe7445edab89ea3623b39edfd4a7..2df5ed61f434679ec5615f941b91b434cc4782a7 100644 (file)
@@ -11,7 +11,7 @@ libzebra_la_LDFLAGS = -version-info 0:0:0
 libzebra_la_SOURCES = \
        network.c pid_output.c getopt.c getopt1.c daemon.c \
        checksum.c vector.c linklist.c vty.c \
-       cmdtree.c command_parse.y command_lex.l \
+       command_graph.c command_parse.y command_lex.l command_match.c grammar_sandbox.c \
        command.c \
        sockunion.c prefix.c thread.c if.c memory.c buffer.c table.c hash.c \
        filter.c routemap.c distribute.c stream.c str.c log.c plist.c \
@@ -28,7 +28,7 @@ libzebra_la_LIBADD = @LIB_REGEX@ @LIBCAP@
 pkginclude_HEADERS = \
        buffer.h checksum.h filter.h getopt.h hash.h \
        if.h linklist.h log.h \
-       cmdtree.h \
+       command_graph.h command_match.h grammar_sandbox.h \
        command.h \
        memory.h network.h prefix.h routemap.h distribute.h sockunion.h \
        str.h stream.h table.h thread.h vector.h version.h vty.h zebra.h \
diff --git a/lib/cmdtree.c b/lib/cmdtree.c
deleted file mode 100644 (file)
index 38632dc..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Command DFA module.
- * Provides a DFA data structure and associated functions for manipulating it.
- * Used to match user command line input.
- *
- * @author Quentin Young <qlyoung@cumulusnetworks.com>
- */
-
-#include <zebra.h>
-#include "cmdtree.h"
-#include "memory.h"
-
-struct graph_node *
-add_node(struct graph_node *parent, struct graph_node *child)
-{
-  struct graph_node *p_child;
-
-  for (unsigned int i = 0; i < vector_active(parent->children); i++)
-  {
-    p_child = vector_slot(parent->children, i);
-    if (cmp_node(child, p_child))
-      return p_child;
-  }
-  vector_set(parent->children, child);
-  return child;
-}
-
-int
-cmp_node(struct graph_node *first, struct graph_node *second)
-{
-  // compare types
-  if (first->type != second->type) return 0;
-
-  switch (first->type) {
-    case WORD_GN:       // words and variables are equal if their
-    case VARIABLE_GN:   // text value is equal
-      if (first->text && second->text) {
-        if (strcmp(first->text, second->text)) return 0;
-      }
-      else if (first->text != second->text) return 0;
-      break;
-    case RANGE_GN:      // ranges are equal if their bounds are equal
-      if (first->min != second->min || first->max != second->max)
-        return 0;
-      break;
-    case NUMBER_GN:     // numbers are equal if their values are equal
-      if (first->value != second->value) return 0;
-      break;
-    /* selectors and options should be equal if all paths are equal,
-     * but the graph isomorphism problem is not solvable in polynomial
-     * time so we consider selectors and options inequal in all cases
-     */
-    case SELECTOR_GN:
-    case OPTION_GN:
-      return 0;
-    default:
-      break;
-  }
-
-  return 1;
-}
-
-struct graph_node *
-new_node(enum graph_node_type type)
-{
-  struct graph_node *node = malloc(sizeof(struct graph_node));
-  node->type = type;
-  node->children = vector_init(VECTOR_MIN_SIZE);
-  node->is_leaf = 0;
-  node->is_root = 0;
-  node->end = NULL;
-  node->text = NULL;
-  node->value = 0;
-  node->min   = 0;
-  node->max   = 0;
-  node->func = NULL;
-
-  return node;
-}
-
-void
-walk_graph(struct graph_node *start, int level)
-{
-  // print this node
-  switch (start->type) {
-    case WORD_GN:
-    case IPV4_GN:
-    case IPV4_PREFIX_GN:
-    case IPV6_GN:
-    case IPV6_PREFIX_GN:
-    case VARIABLE_GN:
-    case RANGE_GN:
-      fprintf(stderr, "%s", start->text);
-      break;
-    case NUMBER_GN:
-      fprintf(stderr, "%d", start->value);
-      break;
-    case SELECTOR_GN:
-      fprintf(stderr, "<>");
-      break;
-    case OPTION_GN:
-      fprintf(stderr, "[]");
-      break;
-    case NUL_GN:
-      fprintf(stderr, "NUL");
-      break;
-    default:
-      fprintf(stderr, "ERROR");
-  }
-  fprintf(stderr, "[%d] ", vector_active(start->children));
-
-  if (vector_active(start->children))
-    for (unsigned int i = 0; i < vector_active(start->children); i++)
-    {
-      struct graph_node *r = vector_slot(start->children, i);
-      if (!r) {
-        fprintf(stderr, "Child seems null?\n");
-        break;
-      }
-      else {
-        if (vector_active(start->children) > 1) {
-          fprintf(stderr, "\n");
-          for (int i = 0; i < level+1; i++)
-            fprintf(stderr, "    ");
-          walk_graph(r, level+1);
-        }
-        else
-          walk_graph(r, level);
-      }
-    }
-  if (level == 0)
-    fprintf(stderr, "\n");
-}
diff --git a/lib/cmdtree.h b/lib/cmdtree.h
deleted file mode 100644 (file)
index 3d2366b..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-#include "vty.h"
-#include "vector.h"
-
-enum graph_node_type
-{
-  WORD_GN,
-  IPV4_GN,
-  IPV4_PREFIX_GN,
-  IPV6_GN,
-  IPV6_PREFIX_GN,
-  VARIABLE_GN,
-  RANGE_GN,
-  NUMBER_GN,
-  SELECTOR_GN,
-  OPTION_GN,
-  NUL_GN
-};
-
-struct graph_node
-{
-  enum graph_node_type type;
-  vector children;
-  int is_root;              // true if first token in command
-  int is_leaf;              // true if last token in command
-  struct graph_node * end;  // pointer to end for selector & option
-
-  int (*func)(struct vty *, int, const char *[]);
-
-  /* various data fields for nodes */
-  char* text;       // for words and variables
-  int value;        // for numbers
-  int min, max;     // for ranges
-};
-
-/*
- * Adds a child to a node.
- * If the node already has the exact same child, nothing is done. This is
- * decided with cmp_node.
- *
- * @param[in] parent node
- * @param[in] child node
- * @return the new child, or the existing child if the parent already has the
- *         new child
- */
-extern struct graph_node *
-add_node(struct graph_node *, struct graph_node *);
-
-/*
- * Compares two nodes for parsing equivalence.
- * Equivalence in this case means that a single user input token
- * should be able to unambiguously match one of the two nodes.
- * For example, two nodes which have all fields equal except their
- * function pointers would be considered equal.
- *
- * @param[in] first node to compare
- * @param[in] second node to compare
- * @return 1 if equal, zero otherwise.
- */
-extern int
-cmp_node(struct graph_node *, struct graph_node *);
-
-/*
- * Create a new node.
- * Initializes all fields to default values and sets the node type.
- *
- * @param[in] node type
- * @return pointer to the newly allocated node
- */
-extern struct graph_node *
-new_node(enum graph_node_type);
-
-/**
- * Walks a command DFA, printing structure to stdout.
- * For debugging.
- *
- * @param[in] start node of graph to walk
- * @param[in] graph depth for recursion, caller passes 0
- */
-extern void
-walk_graph(struct graph_node *, int);
index 4b571ba75dd94025bbeef6e0e4a2bf1a46eef77e..490c2a06901a6857778ac9a9f2323e5a8a763a11 100644 (file)
@@ -34,8 +34,6 @@ Boston, MA 02111-1307, USA.  */
 #include "workqueue.h"
 #include "vrf.h"
 
-#include "grammar_sandbox.c"
-
 /* Command vector which includes some level of command lists. Normally
    each daemon maintains each own cmdvec. */
 vector cmdvec = NULL;
@@ -4077,10 +4075,6 @@ cmd_init (int terminal)
   install_element (ENABLE_NODE, &show_version_cmd);
   install_element (ENABLE_NODE, &show_commandtree_cmd);
 
-  /**/
-  grammar_sandbox_init();
-  /**/
-
   if (terminal)
     {
       install_element (ENABLE_NODE, &config_terminal_length_cmd);
diff --git a/lib/command_graph.c b/lib/command_graph.c
new file mode 100644 (file)
index 0000000..9b91eaf
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Command DFA module.
+ * Provides a DFA data structure and associated functions for manipulating it.
+ * Used to match user command line input.
+ *
+ * @author Quentin Young <qlyoung@cumulusnetworks.com>
+ */
+
+#include <zebra.h>
+#include "command_graph.h"
+#include "memory.h"
+
+struct graph_node *
+add_node(struct graph_node *parent, struct graph_node *child)
+{
+  struct graph_node *p_child;
+
+  for (unsigned int i = 0; i < vector_active(parent->children); i++)
+  {
+    p_child = vector_slot(parent->children, i);
+    if (cmp_node(child, p_child))
+      return p_child;
+  }
+  vector_set(parent->children, child);
+  return child;
+}
+
+int
+cmp_node(struct graph_node *first, struct graph_node *second)
+{
+  // compare types
+  if (first->type != second->type) return 0;
+
+  switch (first->type) {
+    case WORD_GN:       // words and variables are equal if their
+    case VARIABLE_GN:   // text value is equal
+      if (first->text && second->text) {
+        if (strcmp(first->text, second->text)) return 0;
+      }
+      else if (first->text != second->text) return 0;
+      break;
+    case RANGE_GN:      // ranges are equal if their bounds are equal
+      if (first->min != second->min || first->max != second->max)
+        return 0;
+      break;
+    case NUMBER_GN:     // numbers are equal if their values are equal
+      if (first->value != second->value) return 0;
+      break;
+    /* selectors and options should be equal if all paths are equal,
+     * but the graph isomorphism problem is not solvable in polynomial
+     * time so we consider selectors and options inequal in all cases
+     */
+    case SELECTOR_GN:
+    case OPTION_GN:
+      return 0;
+    default:
+      break;
+  }
+
+  return 1;
+}
+
+struct graph_node *
+new_node(enum graph_node_type type)
+{
+  struct graph_node *node = malloc(sizeof(struct graph_node));
+  node->type = type;
+  node->children = vector_init(VECTOR_MIN_SIZE);
+  node->is_leaf = 0;
+  node->is_root = 0;
+  node->end = NULL;
+  node->text = NULL;
+  node->value = 0;
+  node->min   = 0;
+  node->max   = 0;
+  node->func = NULL;
+
+  return node;
+}
+
+void
+walk_graph(struct graph_node *start, int level)
+{
+  // print this node
+  switch (start->type) {
+    case WORD_GN:
+    case IPV4_GN:
+    case IPV4_PREFIX_GN:
+    case IPV6_GN:
+    case IPV6_PREFIX_GN:
+    case VARIABLE_GN:
+    case RANGE_GN:
+      fprintf(stderr, "%s", start->text);
+      break;
+    case NUMBER_GN:
+      fprintf(stderr, "%d", start->value);
+      break;
+    case SELECTOR_GN:
+      fprintf(stderr, "<>");
+      break;
+    case OPTION_GN:
+      fprintf(stderr, "[]");
+      break;
+    case NUL_GN:
+      fprintf(stderr, "NUL");
+      break;
+    default:
+      fprintf(stderr, "ERROR");
+  }
+  fprintf(stderr, "[%d] ", vector_active(start->children));
+
+  if (vector_active(start->children))
+    for (unsigned int i = 0; i < vector_active(start->children); i++)
+    {
+      struct graph_node *r = vector_slot(start->children, i);
+      if (!r) {
+        fprintf(stderr, "Child seems null?\n");
+        break;
+      }
+      else {
+        if (vector_active(start->children) > 1) {
+          fprintf(stderr, "\n");
+          for (int i = 0; i < level+1; i++)
+            fprintf(stderr, "    ");
+          walk_graph(r, level+1);
+        }
+        else
+          walk_graph(r, level);
+      }
+    }
+  if (level == 0)
+    fprintf(stderr, "\n");
+}
diff --git a/lib/command_graph.h b/lib/command_graph.h
new file mode 100644 (file)
index 0000000..8d23577
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef COMMAND_GRAPH_H
+#define COMMAND_GRAPH_H
+
+#include "vty.h"
+#include "vector.h"
+
+enum graph_node_type
+{
+  WORD_GN,
+  IPV4_GN,
+  IPV4_PREFIX_GN,
+  IPV6_GN,
+  IPV6_PREFIX_GN,
+  VARIABLE_GN,
+  RANGE_GN,
+  NUMBER_GN,
+  SELECTOR_GN,
+  OPTION_GN,
+  NUL_GN
+};
+
+struct graph_node
+{
+  enum graph_node_type type;
+  vector children;
+  int is_root;              // true if first token in command
+  int is_leaf;              // true if last token in command
+  struct graph_node * end;  // pointer to end for selector & option
+
+  int (*func)(struct vty *, int, const char *[]);
+
+  /* various data fields for nodes */
+  char* text;       // for words and variables
+  int value;        // for numbers
+  int min, max;     // for ranges
+};
+
+/*
+ * Adds a child to a node.
+ * If the node already has the exact same child, nothing is done. This is
+ * decided with cmp_node.
+ *
+ * @param[in] parent node
+ * @param[in] child node
+ * @return the new child, or the existing child if the parent already has the
+ *         new child
+ */
+extern struct graph_node *
+add_node(struct graph_node *, struct graph_node *);
+
+/*
+ * Compares two nodes for parsing equivalence.
+ * Equivalence in this case means that a single user input token
+ * should be able to unambiguously match one of the two nodes.
+ * For example, two nodes which have all fields equal except their
+ * function pointers would be considered equal.
+ *
+ * @param[in] first node to compare
+ * @param[in] second node to compare
+ * @return 1 if equal, zero otherwise.
+ */
+extern int
+cmp_node(struct graph_node *, struct graph_node *);
+
+/*
+ * Create a new node.
+ * Initializes all fields to default values and sets the node type.
+ *
+ * @param[in] node type
+ * @return pointer to the newly allocated node
+ */
+extern struct graph_node *
+new_node(enum graph_node_type);
+
+/**
+ * Walks a command DFA, printing structure to stdout.
+ * For debugging.
+ *
+ * @param[in] start node of graph to walk
+ * @param[in] graph depth for recursion, caller passes 0
+ */
+extern void
+walk_graph(struct graph_node *, int);
+
+#endif
diff --git a/lib/command_match.c b/lib/command_match.c
new file mode 100644 (file)
index 0000000..bcc28bd
--- /dev/null
@@ -0,0 +1,174 @@
+#include <zebra.h>
+#include "memory.h"
+#include "command_match.h"
+
+enum match_type
+match_command (struct graph_node *start, enum filter_type filter, const char *input)
+{
+  // match input on DFA
+  return exact_match;
+}
+
+
+#define IPV4_ADDR_STR   "0123456789."
+#define IPV4_PREFIX_STR "0123456789./"
+
+enum match_type
+cmd_ipv4_match (const char *str)
+{
+  struct sockaddr_in sin_dummy;
+
+  if (str == NULL)
+    return partly_match;
+
+  if (strspn (str, IPV4_ADDR_STR) != strlen (str))
+    return no_match;
+
+  if (inet_pton(AF_INET, str, &sin_dummy.sin_addr) != 1)
+    return no_match;
+
+  return exact_match;
+}
+
+enum match_type
+cmd_ipv4_prefix_match (const char *str)
+{
+  struct sockaddr_in sin_dummy;
+  const char *delim = "/\0";
+  char *dupe, *prefix, *mask, *context, *endptr;
+  int nmask = -1;
+
+  if (str == NULL)
+    return partly_match;
+
+  if (strspn (str, IPV4_PREFIX_STR) != strlen (str))
+    return no_match;
+
+  /* tokenize to address + mask */
+  dupe = XMALLOC(MTYPE_TMP, strlen(str)+1);
+  strncpy(dupe, str, strlen(str)+1);
+  prefix = strtok_r(dupe, delim, &context);
+  mask   = strtok_r(NULL, delim, &context);
+
+  if (!mask)
+    return partly_match;
+
+  /* validate prefix */
+  if (inet_pton(AF_INET, prefix, &sin_dummy.sin_addr) != 1)
+    return no_match;
+
+  /* validate mask */
+  nmask = strtol (mask, &endptr, 10);
+  if (*endptr != '\0' || nmask < 0 || nmask > 32)
+    return no_match;
+
+  XFREE(MTYPE_TMP, dupe);
+
+  return exact_match;
+}
+
+#define IPV6_ADDR_STR   "0123456789abcdefABCDEF:."
+#define IPV6_PREFIX_STR "0123456789abcdefABCDEF:./"
+
+#ifdef HAVE_IPV6
+enum match_type
+cmd_ipv6_match (const char *str)
+{
+  struct sockaddr_in6 sin6_dummy;
+  int ret;
+
+  if (str == NULL)
+    return partly_match;
+
+  if (strspn (str, IPV6_ADDR_STR) != strlen (str))
+    return no_match;
+
+  ret = inet_pton(AF_INET6, str, &sin6_dummy.sin6_addr);
+
+  if (ret == 1)
+    return exact_match;
+
+  return no_match;
+}
+
+enum match_type
+cmd_ipv6_prefix_match (const char *str)
+{
+  struct sockaddr_in6 sin6_dummy;
+  const char *delim = "/\0";
+  char *dupe, *prefix, *mask, *context, *endptr;
+  int nmask = -1;
+
+  if (str == NULL)
+    return partly_match;
+
+  if (strspn (str, IPV6_PREFIX_STR) != strlen (str))
+    return no_match;
+
+  /* tokenize to address + mask */
+  dupe = XMALLOC(MTYPE_TMP, strlen(str)+1);
+  strncpy(dupe, str, strlen(str)+1);
+  prefix = strtok_r(dupe, delim, &context);
+  mask   = strtok_r(NULL, delim, &context);
+
+  if (!mask)
+    return partly_match;
+
+  /* validate prefix */
+  if (inet_pton(AF_INET6, prefix, &sin6_dummy.sin6_addr) != 1)
+    return no_match;
+
+  /* validate mask */
+  nmask = strtol (mask, &endptr, 10);
+  if (*endptr != '\0' || nmask < 0 || nmask > 128)
+    return no_match;
+
+  XFREE(MTYPE_TMP, dupe);
+
+  return exact_match;
+}
+#endif
+
+enum match_type
+cmd_range_match (struct graph_node *rangenode, const char *str)
+{
+  char *endptr = NULL;
+  signed long long val;
+
+  if (str == NULL)
+    return 1;
+
+  val = strtoll (str, &endptr, 10);
+  if (*endptr != '\0')
+    return 0;
+  val = llabs(val);
+
+  if (val < rangenode->min || val > rangenode->max)
+    return no_match;
+  else
+    return exact_match;
+}
+
+enum match_type
+cmd_word_match(struct graph_node *wordnode,
+               enum filter_type filter,
+               const char *word)
+{
+  if (filter == FILTER_RELAXED)
+    if (!word || !strlen(word))
+      return partly_match;
+
+  if (!word)
+    return no_match;
+
+  if (filter == FILTER_RELAXED && !strncmp(wordnode->text, word, strlen(word)))
+  {
+    if (!strcmp(wordnode->text, word))
+      return exact_match;
+    return partly_match;
+  }
+  if (filter == FILTER_STRICT && !strcmp(wordnode->text, word))
+    return exact_match;
+
+  return no_match;
+}
diff --git a/lib/command_match.h b/lib/command_match.h
new file mode 100644 (file)
index 0000000..cddeb08
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef COMMAND_MATCH_H
+#define COMMAND_MATCH_H
+
+#include "command_graph.h"
+
+/**
+ * Filter types. These tell the parser whether to allow
+ * partial matching on tokens.
+ */
+enum filter_type
+{
+  FILTER_RELAXED,
+  FILTER_STRICT
+};
+
+/**
+ * Command matcher result value.
+ */
+enum matcher_rv
+{
+  MATCHER_OK,
+  MATCHER_COMPLETE,
+  MATCHER_INCOMPLETE,
+  MATCHER_NO_MATCH,
+  MATCHER_AMBIGUOUS,
+  MATCHER_EXCEED_ARGC_MAX
+};
+
+/* Completion match types. */
+enum match_type 
+{
+  no_match,
+  partly_match,
+  exact_match 
+};
+/**
+ * Defines which matcher_rv values constitute
+ * an error. Should be used against matcher_rv
+ * return values to do basic error checking.
+ */
+#define MATCHER_ERROR(matcher_rv) \
+  (   (matcher_rv) == MATCHER_INCOMPLETE \
+   || (matcher_rv) == MATCHER_NO_MATCH \
+   || (matcher_rv) == MATCHER_AMBIGUOUS \
+   || (matcher_rv) == MATCHER_EXCEED_ARGC_MAX \
+  )
+
+enum match_type
+cmd_ipv4_match (const char *);
+
+enum match_type
+cmd_ipv4_prefix_match (const char *);
+
+enum match_type
+cmd_ipv6_match (const char *);
+
+enum match_type
+cmd_ipv6_prefix_match (const char *);
+
+enum match_type
+cmd_range_match (struct graph_node *, const char *str);
+
+enum match_type
+cmd_word_match (struct graph_node *, enum filter_type, const char *);
+
+enum match_type
+match_command (struct graph_node *, enum filter_type, const char *);
+
+#endif
index cf2cd95bddca570d946c1d8d30bc9b715cd19f53..80487af7cde4eb7684ce6677dbdb39972153e272 100644 (file)
@@ -1,5 +1,15 @@
+/*
+ * Command format string parser.
+ *
+ * Turns a command definition into a DFA that together with the functions
+ * provided in command_match.c may be used to map command line input to a
+ * function.
+ *
+ * @author Quentin Young <qlyoung@cumulusnetworks.com>
+ */
+
 %{
-#include "cmdtree.h"
+#include "command_graph.h"
 
 extern int yylex(void);
 extern void yyerror(const char *);
@@ -8,16 +18,22 @@ extern void yyerror(const char *);
 #define YYDEBUG 1
 %}
 %code provides {
-extern struct graph_node *cmd_parse_format_new(const char *, const char *, struct graph_node *);
-extern void set_buffer_string(const char *);
+extern struct
+graph_node *cmd_parse_format(const char *,
+                             const char *,
+                             struct graph_node *);
+extern void
+set_buffer_string(const char *);
 }
 
+/* valid types for tokens */
 %union{
   int integer;
   char *string;
   struct graph_node *node;
 }
 
+/* some helpful state variables */
 %{
 struct graph_node *startnode,       // command root node
                   *currnode,        // current node
@@ -66,7 +82,7 @@ sentence_root: WORD
   $$ = new_node(WORD_GN);
   $$->text = strdup(yylval.string);
   fprintf(stderr, ">>>>>>>> YYLVAL.STRING: %s\n", yylval.string);
-  fprintf(stderr, ">>>>>>>> TEXT: %s\n", $$->text);
+  fprintf(stderr, ">>>>>>>>          TEXT: %s\n", $$->text);
 
   currnode = $$;
   currnode->is_root = 1;
@@ -270,7 +286,7 @@ void yyerror(char const *message) {
 }
 
 struct graph_node *
-cmd_parse_format_new(const char *string, const char *desc, struct graph_node *start)
+cmd_parse_format(const char *string, const char *desc, struct graph_node *start)
 {
   fprintf(stderr, "parsing: %s\n", string);
 
index 807ada9d98271b9438533bac71dfb1c094dfe433..1e6a76c69cec709680dbc16d9584351866832925 100644 (file)
@@ -1,17 +1,14 @@
 #include "command.h"
+#include "command_graph.h"
 #include "command_parse.h"
-#include "cmdtree.h"
+#include "command_match.h"
 
 #define GRAMMAR_STR "CLI grammar sandbox\n"
 
 struct graph_node * nodegraph;
 
-DEFUN (grammar_test,
-       grammar_test_cmd,
-       "grammar parse .COMMAND",
-       GRAMMAR_STR
-       "command to pass to new parser\n")
-{
+/*
+char* combine_vararg(char* argv, int argc) {
   size_t linesize = 0;
   for (int i = 0; i < argc; i++)
     linesize += strlen(argv[i]) + 1;
@@ -24,8 +21,19 @@ DEFUN (grammar_test,
       strcat(cat, " ");
   }
 
-  //struct graph_node *result = new_node(NUL_GN);
-  cmd_parse_format_new((const char*) cat, "lol", nodegraph);
+  return cat;
+}
+*/
+
+DEFUN (grammar_test,
+       grammar_test_cmd,
+       "grammar parse .COMMAND",
+       GRAMMAR_STR
+       "command to pass to new parser\n")
+{
+
+  const char* command = argv_concat(argv, argc, 0);
+  cmd_parse_format(command, "lol", nodegraph);
   walk_graph(nodegraph, 0);
 
   return CMD_SUCCESS;
@@ -37,8 +45,20 @@ DEFUN (grammar_test_show,
        GRAMMAR_STR
        "print current accumulated DFA\n")
 {
-   walk_graph(nodegraph, 0);
-   return CMD_SUCCESS;
+  walk_graph(nodegraph, 0);
+  return CMD_SUCCESS;
+}
+
+DEFUN (grammar_test_match,
+       grammar_test_match_cmd,
+       "grammar match .COMMAND",
+       GRAMMAR_STR
+       "attempt to match input on DFA\n"
+       "command to match")
+{
+  const char* command = argv_concat(argv, argc, 0);
+  match_command(nodegraph, FILTER_STRICT, command);
+  return CMD_SUCCESS;
 }
 
 
@@ -48,4 +68,5 @@ void grammar_sandbox_init() {
   nodegraph = new_node(NUL_GN);
   install_element (ENABLE_NODE, &grammar_test_cmd);
   install_element (ENABLE_NODE, &grammar_test_show_cmd);
+  install_element (ENABLE_NODE, &grammar_test_match_cmd);
 }
diff --git a/lib/grammar_sandbox.h b/lib/grammar_sandbox.h
new file mode 100644 (file)
index 0000000..2b2c742
--- /dev/null
@@ -0,0 +1,2 @@
+void
+grammar_sandbox_init(void);
index ecb6c5c6ac7c75a352099e513ab06ea81eaa5f98..9d4061cfcf340db104d0f694048a332eea33ec0e 100644 (file)
@@ -42,6 +42,8 @@
 #include "bgpd/bgp_vty.h"
 #include "vrf.h"
 
+#include "lib/grammar_sandbox.h"
+
 /* Struct VTY. */
 struct vty *vty;
 
@@ -3076,4 +3078,6 @@ vtysh_init_vty (void)
   install_element (CONFIG_NODE, &vtysh_enable_password_text_cmd);
   install_element (CONFIG_NODE, &no_vtysh_enable_password_cmd);
 
+  /* grammar sandbox */
+  grammar_sandbox_init();
 }