match_range (struct graph_node *, const char *str);
static enum match_type
-match_word (struct graph_node *, const char *, enum filter_type);
+match_word (struct graph_node *, const char *);
static enum match_type
match_number (struct graph_node *, const char *);
match_variable (struct graph_node *, const char *);
static enum match_type
-match_token (struct graph_node *, char *, enum filter_type);
+match_token (struct graph_node *, char *);
/* matching functions */
/* Linked list data deletion callback */
static void
-free_nodelist (void *node) {
+delete_nodelist (void *node) {
free_node ((struct graph_node *) node);
}
// get the minimum match level that can count as a full match
enum match_type minmatch = min_match_level(start->type);
+ // get the current operating token
+ char *token = vector_slot(vline, n);
+
// if we don't match this node, die
- if (match_token(start, vector_slot(vline, n), FILTER_RELAXED) < minmatch)
+ if (match_token(start, token) < minmatch)
return NULL;
// pointers for iterating linklist
if (n+1 == vector_active (vline)) {
for (ALL_LIST_ELEMENTS_RO(next,ln,gn)) {
if (gn->type == END_GN) {
- struct graph_node *curr = copy_node(start);
- curr->arg = XSTRDUP(MTYPE_CMD_TOKENS, vector_slot(vline, n));
- // initialize a new argument list
+ // we have a match, so build an argv and pass it back up the chain
struct list *argv = list_new();
- argv->del = &free_nodelist;
+ argv->del = &delete_nodelist;
+ struct graph_node *curr = copy_node(start);
+ curr->arg = XSTRDUP(MTYPE_CMD_TOKENS, token);
// add the current node
- listnode_add(argv, copy_node(curr));
- // push the end node
+ listnode_add(argv, curr);
+ // add the end node
listnode_add(argv, copy_node(gn));
// clean up
list_delete (next);
}
if (bestmatch) {
+ // if we have a best match, prepend this node + matching token
+ // to argv and pass it up the chain
struct graph_node *curr = copy_node(start);
- curr->arg = XSTRDUP(MTYPE_CMD_TOKENS, vector_slot(vline, n));
+ curr->arg = XSTRDUP(MTYPE_CMD_TOKENS, token);
list_add_node_prev (bestmatch, bestmatch->head, curr);
// cleanup
list_delete (next);
}
struct list *
-match_command_complete (struct graph_node *start, const char *line, enum filter_type filter)
+match_command_complete (struct graph_node *start, const char *line)
{
- enum match_type minmatch = filter + 1;
-
// vectorize command line
vector vline = cmd_make_strvec (line);
char *token;
struct list *current = list_new(), // current nodes to match input token against
- *matched = list_new(), // current nodes that match the input token
*next = list_new(); // possible next hops to current input token
// pointers used for iterating lists
token = vector_slot(vline, idx);
- list_delete_all_node(matched);
-
for (ALL_LIST_ELEMENTS_RO(current,node,gn))
{
- if (match_token(gn, token, filter) >= minmatch) {
- listnode_add(matched, gn);
- add_nexthops(next, gn);
+ switch (match_token(gn, token)) {
+ case partly_match: // if it's a partial match, add this node to possible next hops
+ listnode_add(next, gn);
+ break;
+ case exact_match: // if it's an exact match, add this node's children to next hops
+ add_nexthops(next, gn);
+ break;
+ default: // otherwise do nothing
+ break;
}
}
}
* next = set of all nodes reachable from all nodes in `matched`
*/
list_free (current);
- list_free (matched);
cmd_free_strvec(vline);
}
static enum match_type
-match_token (struct graph_node *node, char *token, enum filter_type filter)
+match_token (struct graph_node *node, char *token)
{
switch (node->type) {
case WORD_GN:
- return match_word (node, token, filter);
+ return match_word (node, token);
case IPV4_GN:
return match_ipv4 (token);
case IPV4_PREFIX_GN:
}
static enum match_type
-match_word(struct graph_node *wordnode,
- const char *word,
- enum filter_type filter)
+match_word(struct graph_node *wordnode, const char *word)
{
- if (filter == FILTER_RELAXED)
- {
- if (!word || !strlen(word))
- return partly_match;
- else if (!strncmp(wordnode->text, word, strlen(word)))
- return !strcmp(wordnode->text, word) ? exact_match : partly_match;
- else
- return no_match;
- }
- else
- {
- if (!word)
- return no_match;
- else
- return !strcmp(wordnode->text, word) ? exact_match : no_match;
- }
+ // if the passed token is null or 0 length, partly match
+ if (!word || !strlen(word))
+ return partly_match;
+
+ // if the passed token is strictly a prefix of the full word, partly match
+ if (strlen(word) < strlen(wordnode->text))
+ return !strncmp(wordnode->text, word, strlen(word)) ? partly_match : no_match;
+
+ // if they are the same length and exactly equal, exact match
+ else if (strlen(word) == strlen(wordnode->text))
+ return !strncmp(wordnode->text, word, strlen(word)) ? exact_match : no_match;
+
+ return no_match;
}
static enum match_type