summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorQuentin Young <qlyoung@cumulusnetworks.com>2016-08-01 13:18:25 +0000
committerQuentin Young <qlyoung@cumulusnetworks.com>2016-08-01 13:18:25 +0000
commit6d53a10e4cf873ff61a3dada644d15be83dd54c0 (patch)
treec5c59a7b402956be4e78a5028a93554a3141d8d1 /lib
parent3a7f5493619d20e7087536edbe694f9f2761ace5 (diff)
lib: Add partial matching support
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/.command.h.swobin0 -> 16384 bytes
-rw-r--r--lib/command_graph.c2
-rw-r--r--lib/command_lex.l2
-rw-r--r--lib/command_match.c40
-rw-r--r--lib/grammar_sandbox.c2
5 files changed, 35 insertions, 11 deletions
diff --git a/lib/.command.h.swo b/lib/.command.h.swo
new file mode 100644
index 0000000000..71a42cc20a
--- /dev/null
+++ b/lib/.command.h.swo
Binary files differ
diff --git a/lib/command_graph.c b/lib/command_graph.c
index 7c09a5cd6c..3e52f42598 100644
--- a/lib/command_graph.c
+++ b/lib/command_graph.c
@@ -92,7 +92,7 @@ struct graph_node *
copy_node (struct graph_node *node)
{
struct graph_node *new = new_node(node->type);
- new->children = vector_copy (node->children);
+ new->children = NULL;
new->is_start = node->is_start;
new->end = node->end;
new->text = node->text ? XSTRDUP(MTYPE_CMD_TOKENS, node->text) : NULL;
diff --git a/lib/command_lex.l b/lib/command_lex.l
index 5a0e76d418..ce09c5bf28 100644
--- a/lib/command_lex.l
+++ b/lib/command_lex.l
@@ -9,7 +9,7 @@ IPV4 A\.B\.C\.D
IPV4_PREFIX A\.B\.C\.D\/M
IPV6 X:X::X:X
IPV6_PREFIX X:X::X:X\/M
-VARIABLE [A-Z][A-Z_]+
+VARIABLE [A-Z][A-Z_:]+
NUMBER [0-9]{1,20}
RANGE \({NUMBER}\-{NUMBER}\)
diff --git a/lib/command_match.c b/lib/command_match.c
index f02b7c821a..7b9c5f15d8 100644
--- a/lib/command_match.c
+++ b/lib/command_match.c
@@ -13,6 +13,9 @@ match_command_r (struct graph_node *, vector, unsigned int);
static int
score_precedence (struct graph_node *);
+static enum match_type
+min_match_level(enum node_type type);
+
/* token matcher prototypes */
static enum match_type
match_ipv4 (const char *);
@@ -30,7 +33,7 @@ static enum match_type
match_range (struct graph_node *, const char *str);
static enum match_type
-match_word (struct graph_node *, enum filter_type, const char *);
+match_word (struct graph_node *, const char *, enum filter_type);
static enum match_type
match_number (struct graph_node *, const char *);
@@ -137,8 +140,11 @@ match_command (struct graph_node *start, const char *line, struct list **argv)
static struct list *
match_command_r (struct graph_node *start, vector vline, unsigned int n)
{
+ // get the minimum match level that can count as a full match
+ enum match_type minmatch = min_match_level(start->type);
+
// if we don't match this node, die
- if (match_token(start, vector_slot(vline, n), FILTER_STRICT) != exact_match)
+ if (match_token(start, vector_slot(vline, n), FILTER_RELAXED) < minmatch)
return NULL;
// arg list for this subgraph
@@ -313,12 +319,30 @@ add_nexthops(struct list *l, struct graph_node *node)
/* matching utility functions */
+/**
+ * Determines the minimum acceptable matching level
+ * for a given node type that can be accepted as a
+ * full match. Used for things like abbreviating
+ * commands, e.g. `conf t`.
+ */
+static enum match_type
+min_match_level(enum node_type type)
+{
+ switch (type) {
+ case WORD_GN:
+ return partly_match;
+ default:
+ return exact_match;
+ }
+}
+
static int
score_precedence (struct graph_node *node)
{
switch (node->type)
{
- // these should be mutually exclusive
+ // these should be mutually exclusive,
+ // or never compared
case IPV4_GN:
case IPV4_PREFIX_GN:
case IPV6_GN:
@@ -344,11 +368,11 @@ match_token (struct graph_node *node, char *token, enum filter_type filter)
case IPV4_GN:
return match_ipv4 (token);
case IPV4_PREFIX_GN:
- return match_ipv4_prefix (token, filter);
+ return match_ipv4_prefix (token);
case IPV6_GN:
- return match_ipv6 (token, filter);
+ return match_ipv6 (token);
case IPV6_PREFIX_GN:
- return match_ipv6_prefix (token, filter);
+ return match_ipv6_prefix (token);
case RANGE_GN:
return match_range (node, token);
case NUMBER_GN:
@@ -584,8 +608,8 @@ match_range (struct graph_node *rangenode, const char *str)
static enum match_type
match_word(struct graph_node *wordnode,
- enum filter_type filter,
- const char *word)
+ const char *word,
+ enum filter_type filter)
{
if (filter == FILTER_RELAXED)
{
diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c
index 2443b8471c..66e530595b 100644
--- a/lib/grammar_sandbox.c
+++ b/lib/grammar_sandbox.c
@@ -56,7 +56,7 @@ DEFUN (grammar_test_complete,
// print possible next hops, if any
for (ALL_LIST_ELEMENTS_RO(result,node,cnode)) {
if (cnode->type == END_GN)
- fprintf(stderr, "<cr>\n");
+ fprintf(stderr, "<cr> %p\n", cnode->element->func);
else
fprintf(stderr, "%s\n", describe_node(cnode, desc, 50));
}