summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/command.c24
-rw-r--r--lib/command.h6
-rw-r--r--lib/command_graph.c57
-rw-r--r--lib/command_graph.h46
-rw-r--r--lib/command_lex.l14
-rw-r--r--lib/command_match.c326
-rw-r--r--lib/command_match.h15
-rw-r--r--lib/command_parse.y3
-rw-r--r--lib/grammar_sandbox.c27
9 files changed, 312 insertions, 206 deletions
diff --git a/lib/command.c b/lib/command.c
index 490c2a0690..d3c6771248 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -4191,6 +4191,30 @@ cmd_terminate_element(struct cmd_element *cmd)
}
void
+free_cmd_element(struct cmd_element *cmd)
+{
+ if (!cmd) return;
+ free ((char*) cmd->string);
+ free ((char*) cmd->doc);
+ cmd_terminate_element(cmd);
+ free (cmd);
+}
+
+struct cmd_element *
+copy_cmd_element(struct cmd_element *cmd)
+{
+ struct cmd_element *el = XMALLOC(MTYPE_CMD_TOKENS, sizeof (struct cmd_element));
+ el->string = cmd->string ? XSTRDUP(MTYPE_CMD_TOKENS, cmd->string) : NULL;
+ el->func = cmd->func;
+ el->doc = cmd->doc ? XSTRDUP(MTYPE_CMD_TOKENS, cmd->doc) : NULL;
+ el->daemon = cmd->daemon;
+ el->tokens = cmd->tokens ? vector_copy(cmd->tokens) : NULL;
+ el->attr = cmd->attr;
+ fprintf(stderr, "successful copy\n");
+ return el;
+}
+
+void
cmd_terminate ()
{
unsigned int i, j;
diff --git a/lib/command.h b/lib/command.h
index c1ef0e55bd..9a77d3b87c 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -571,6 +571,12 @@ extern int cmd_execute_command_strict (vector, struct vty *, struct cmd_element
extern void cmd_init (int);
extern void cmd_terminate (void);
+/* memory management for cmd_element */
+void
+free_cmd_element(struct cmd_element *);
+struct cmd_element *
+copy_cmd_element(struct cmd_element *cmd);
+
/* Export typical functions. */
extern struct cmd_element config_end_cmd;
extern struct cmd_element config_exit_cmd;
diff --git a/lib/command_graph.c b/lib/command_graph.c
index a5880f34a6..7c09a5cd6c 100644
--- a/lib/command_graph.c
+++ b/lib/command_graph.c
@@ -22,6 +22,7 @@ add_node(struct graph_node *parent, struct graph_node *child)
return p_child;
}
vector_set(parent->children, child);
+ child->refs++;
return child;
}
@@ -58,6 +59,7 @@ cmp_node(struct graph_node *first, struct graph_node *second)
*/
case START_GN:
case END_GN:
+ case NUL_GN:
default:
break;
}
@@ -73,29 +75,61 @@ new_node(enum graph_node_type type)
node->type = type;
node->children = vector_init(VECTOR_MIN_SIZE);
- node->is_start = 0;
node->end = NULL;
node->text = NULL;
+ node->element = NULL;
+ node->arg = NULL;
+ node->is_start = 0;
node->value = 0;
node->min = 0;
node->max = 0;
- node->element = NULL;
+ node->refs = 0;
return node;
}
+struct graph_node *
+copy_node (struct graph_node *node)
+{
+ struct graph_node *new = new_node(node->type);
+ new->children = vector_copy (node->children);
+ new->is_start = node->is_start;
+ new->end = node->end;
+ new->text = node->text ? XSTRDUP(MTYPE_CMD_TOKENS, node->text) : NULL;
+ new->value = node->value;
+ new->min = node->min;
+ new->max = node->max;
+ new->element = node->element ? copy_cmd_element(node->element) : NULL;
+ new->arg = node->arg ? XSTRDUP(MTYPE_CMD_TOKENS, node->arg) : NULL;
+ new->refs = 0;
+ return new;
+}
+
void
free_node (struct graph_node *node)
{
if (!node) return;
- free_node (node->end);
vector_free (node->children);
+ free_cmd_element (node->element);
free (node->text);
free (node->arg);
- free (node->element);
free (node);
}
+void
+free_graph (struct graph_node *start)
+{
+ if (start && start->children && vector_active(start->children) > 0) {
+ for (unsigned int i = 0; i < vector_active(start->children); i++) {
+ free_graph (vector_slot(start->children, i));
+ vector_unset(start->children, i);
+ }
+ }
+
+ if (--(start->refs) == 0)
+ free_node (start);
+}
+
char *
describe_node(struct graph_node *node, char* buffer, unsigned int bufsize)
{
@@ -166,3 +200,18 @@ walk_graph(struct graph_node *start, int level)
fprintf(stderr, "\n");
}
+void
+dump_node (struct graph_node *node)
+{
+ char buf[50];
+ describe_node(node, buf, 50);
+ fprintf(stderr, "%s[%d]\n", buf, node->type);
+ fprintf(stderr, "\t->text: %s\n", node->text);
+ fprintf(stderr, "\t->value: %ld\n", node->value);
+ fprintf(stderr, "\t->is_start: %d\n", node->is_start);
+ fprintf(stderr, "\t->element: %p\n", node->element);
+ fprintf(stderr, "\t->min: %ld\n->max: %ld\n", node->min, node->max);
+ fprintf(stderr, "\t->arg: %s\n", node->arg);
+ fprintf(stderr, "\t->refs: %d\n", node->refs);
+ fprintf(stderr, "\tnum children: %d\n", vector_active(node->children));
+}
diff --git a/lib/command_graph.h b/lib/command_graph.h
index a9ffe0f7b6..dc78475ca6 100644
--- a/lib/command_graph.h
+++ b/lib/command_graph.h
@@ -35,6 +35,9 @@ struct graph_node
struct cmd_element *element;
/* used for passing arguments to command functions */
char *arg;
+
+ /* refcount for node parents */
+ int refs;
};
/*
@@ -47,7 +50,7 @@ struct graph_node
* @param[in] child node
* @return pointer to child if it is added, pointer to existing child otherwise
*/
-extern struct graph_node *
+struct graph_node *
add_node(struct graph_node *, struct graph_node *);
/*
@@ -61,7 +64,7 @@ add_node(struct graph_node *, struct graph_node *);
* @param[in] second node to compare
* @return 1 if equal, zero otherwise.
*/
-extern int
+int
cmp_node(struct graph_node *, struct graph_node *);
/*
@@ -71,17 +74,44 @@ cmp_node(struct graph_node *, struct graph_node *);
* @param[in] node type
* @return pointer to the newly allocated node
*/
-extern struct graph_node *
+struct graph_node *
new_node(enum graph_node_type);
/**
+ * Copies a node.
+ * The children vector is copied, but the pointers the vector
+ * holds point to the same data as the original vector.
+ * The element, if it exists, is copied.
+ *
+ * @param[in] pointer to node to copy
+ * @return pointer to copied node
+ */
+struct graph_node *
+copy_node(struct graph_node *);
+
+/**
+ * Frees the data associated with a graph_node.
+ * @param[out] pointer to graph_node to free
+ */
+void
+free_node(struct graph_node *);
+
+/**
+ * Recursively calls free_node on a graph node
+ * and all its children.
+ * @param[out] graph to free
+ */
+void
+free_graph(struct graph_node *);
+
+/**
* 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
+void
walk_graph(struct graph_node *, int);
/**
@@ -90,13 +120,9 @@ walk_graph(struct graph_node *, int);
* @param[out] the buffer to write the description into
* @return pointer to description string
*/
-extern char *
+char *
describe_node(struct graph_node *, char *, unsigned int);
-/**
- * Frees the data associated with a graph_node.
- * @param[out] pointer to graph_node to free
- */
void
-free_node(struct graph_node *);
+dump_node (struct graph_node *);
#endif
diff --git a/lib/command_lex.l b/lib/command_lex.l
index 45f8f8e636..5a0e76d418 100644
--- a/lib/command_lex.l
+++ b/lib/command_lex.l
@@ -22,14 +22,14 @@ RANGE \({NUMBER}\-{NUMBER}\)
%%
[ /t] /* ignore whitespace */;
-{WORD} {yylval.string = strdup(yytext); return WORD;}
-{IPV4} {yylval.string = strdup(yytext); return IPV4;}
-{IPV4_PREFIX} {yylval.string = strdup(yytext); return IPV4_PREFIX;}
-{IPV6} {yylval.string = strdup(yytext); return IPV6;}
-{IPV6_PREFIX} {yylval.string = strdup(yytext); return IPV6_PREFIX;}
-{VARIABLE} {yylval.string = strdup(yytext); return VARIABLE;}
+{WORD} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return WORD;}
+{IPV4} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return IPV4;}
+{IPV4_PREFIX} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return IPV4_PREFIX;}
+{IPV6} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return IPV6;}
+{IPV6_PREFIX} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return IPV6_PREFIX;}
+{VARIABLE} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return VARIABLE;}
{NUMBER} {yylval.integer = atoi(yytext); return NUMBER;}
-{RANGE} {yylval.string = strdup(yytext); return RANGE;}
+{RANGE} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return RANGE;}
. {return yytext[0];}
%%
diff --git a/lib/command_match.c b/lib/command_match.c
index 023faafade..91b6069b1a 100644
--- a/lib/command_match.c
+++ b/lib/command_match.c
@@ -8,7 +8,7 @@ static int
add_nexthops(struct list *, struct graph_node *);
static struct list *
-match_build_argv_r (struct graph_node *, vector, unsigned int);
+match_command_r (struct graph_node *, vector, unsigned int);
static int
score_precedence (struct graph_node *);
@@ -43,176 +43,86 @@ match_token (struct graph_node *, char *, enum filter_type);
/* matching functions */
-struct cmd_element *
-match_command (struct graph_node *start, const char *line, enum filter_type filter)
-{
- // get all possible completions
- struct list *completions = match_command_complete (start, line, filter);
-
- // one of them should be END_GN if this command matches
- struct graph_node *gn;
- struct listnode *node;
- for (ALL_LIST_ELEMENTS_RO(completions,node,gn))
- {
- if (gn->type == END_GN)
- break;
- gn = NULL;
- }
- return gn ? gn->element : NULL;
+static void
+free_nodelist (void *node) {
+ free_node ((struct graph_node *) node);
}
-struct list *
-match_command_complete (struct graph_node *start, const char *line, enum filter_type filter)
-{
- // vectorize command line
- vector vline = cmd_make_strvec (line);
-
- // pointer to next input token to match
- 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
- struct graph_node *gn;
- struct listnode *node;
-
- // add all children of start node to list
- add_nexthops(next, start);
-
- unsigned int idx;
- for (idx = 0; idx < vector_active(vline) && next->count > 0; idx++)
- {
- list_free (current);
- current = next;
- next = list_new();
-
- token = vector_slot(vline, idx);
-
- list_delete_all_node(matched);
-
- for (ALL_LIST_ELEMENTS_RO(current,node,gn))
- {
- if (match_token(gn, token, filter) == exact_match) {
- listnode_add(matched, gn);
- add_nexthops(next, gn);
- }
- }
- }
-
- /* Variable summary
- * -----------------------------------------------------------------
- * token = last input token processed
- * idx = index in `command` of last token processed
- * current = set of all transitions from the previous input token
- * matched = set of all nodes reachable with current input
- * next = set of all nodes reachable from all nodes in `matched`
- */
- list_free (current);
- list_free (matched);
-
- cmd_free_strvec(vline);
-
- return next;
-}
-
-/**
- * Adds all children that are reachable by one parser hop
- * to the given list. NUL_GN, SELECTOR_GN, and OPTION_GN
- * nodes are treated as transparent.
- *
- * @param[out] l the list to add the children to
- * @param[in] node the node to get the children of
- * @return the number of children added to the list
- */
-static int
-add_nexthops(struct list *l, struct graph_node *node)
-{
- int added = 0;
- struct graph_node *child;
- for (unsigned int i = 0; i < vector_active(node->children); i++)
- {
- child = vector_slot(node->children, i);
- switch (child->type) {
- case OPTION_GN:
- case SELECTOR_GN:
- case NUL_GN:
- added += add_nexthops(l, child);
- break;
- default:
- listnode_add(l, child);
- added++;
- }
- }
- return added;
-}
-
-struct list *
-match_build_argv (const char *line, struct cmd_element *element)
+struct cmd_element *
+match_command (struct graph_node *start, const char *line, struct list **argv)
{
- struct list *argv = NULL;
-
// parse command
- struct graph_node *start = new_node(NUL_GN);
- parse_command_format(start, element);
-
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_build_argv_r (vector_slot(start->children, i), vline, 0);
+ *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 and these are deduplicated,
- // no need to check precedence
- if (argv) break;
+ // since all command DFA's must begin with a word, there can only be
+ // one valid return value
+ if (*argv) break;
+ }
+
+ if (*argv) {
+ // copy the nodes we need
+ 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);
}
- return argv;
+ return NULL;
}
/**
- * 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 input token in the input line.
+ * 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.
*
- * 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 saves the input token as the head of an argument list.
+ * 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
+ * saves the input token as the head of an argument list.
*
- * The next step is to see if there is further input in the input line.
- * If there is not, the current node's children are searched to see if
- * any of them are leaves (type END_GN). If this is the case, then the
- * bottom of the recursion stack has been reached, and the argument list
- * (with one node) is returned. If it is not the case, NULL is returned,
- * indicating that there is no match for the input along this path.
+ * The next step is to see if there is further input in the input line. If
+ * there is not, the current node's children are searched to see if any of them
+ * are leaves (type END_GN). If this is the case, then the bottom of the
+ * recursion stack has been reached, and the argument list (with one node) is
+ * returned. If it is not the case, NULL is returned, indicating that there is
+ * no match for the input along this path.
*
- * If there is further input, then the function recurses on each of the
- * current node's children, passing them the input line minus the token
- * that was just matched. For each child, the return value of the recursive
- * call is inspected. If it is null, then there is no match for the input along
- * the subgraph headed by that child. If it is not null, then there is at least
- * one input match in that subgraph (more on this in a moment).
+ * If there is further input, then the function recurses on each of the current
+ * node's children, passing them the input line minus the token that was just
+ * matched. For each child, the return value of the recursive call is
+ * inspected. If it is null, then there is no match for the input along the
+ * subgraph headed by that child. If it is not null, then there is at least one
+ * input match in that subgraph (more on this in a moment).
*
* If a recursive call on a child returns a non-null value, then it has matched
* the input given it on the subgraph that starts with that child. However, due
* to the flexibility of the grammar, it is sometimes the case that two or more
* child graphs match the same input (two or more of the recursive calls have
- * non-NULL return values). This is not a valid state, since only one
- * true match is possible. In order to resolve this conflict, the function
- * keeps a reference to the child node that most specifically matches the
- * input. This is done by assigning each node type a precedence. If a child is
- * found to match the remaining input, then the precedence values of the
- * current best-matching child and this new match are compared. The node with
- * higher precedence is kept, and the other match is discarded. Due to the
- * recursive nature of this function, it is only necessary to compare the
- * precedence of immediate children, since all subsequent children will already
- * have been disambiguated in this way.
+ * non-NULL return values). This is not a valid state, since only one true
+ * match is possible. In order to resolve this conflict, the function keeps a
+ * reference to the child node that most specifically matches the input. This
+ * is done by assigning each node type a precedence. If a child is found to
+ * match the remaining input, then the precedence values of the current
+ * best-matching child and this new match are compared. The node with higher
+ * precedence is kept, and the other match is discarded. Due to the recursive
+ * nature of this function, it is only necessary to compare the precedence of
+ * immediate children, since all subsequent children will already have been
+ * disambiguated in this way.
*
* In the event that two children are found to match with the same precedence,
- * then this command is totally ambiguous (how did you even match it in the first
- * place?) and NULL is returned.
+ * then the input is ambiguous for the passed cmd_element and NULL is returned.
*
* The ultimate return value is an ordered linked list of nodes that comprise
* the best match for the command, each with their `arg` fields pointing to the
@@ -224,22 +134,19 @@ match_build_argv (const char *line, struct cmd_element *element)
* callers.
*/
static struct list *
-match_build_argv_r (struct graph_node *start, vector vline, unsigned int n)
+match_command_r (struct graph_node *start, vector vline, unsigned int n)
{
// if we don't match this node, die
if (match_token(start, vector_slot(vline, n), FILTER_STRICT) != exact_match)
return NULL;
// arg list for this subgraph
- struct list *argv = list_new();
+ struct list *argv;
// pointers for iterating linklist
struct graph_node *gn;
struct listnode *ln;
- // append current arg
- listnode_add(argv, start);
-
// get all possible nexthops
struct list *next = list_new();
add_nexthops(next, start);
@@ -248,14 +155,22 @@ match_build_argv_r (struct graph_node *start, vector vline, unsigned int n)
if (n+1 == vector_active (vline)) {
for (ALL_LIST_ELEMENTS_RO(next,ln,gn)) {
if (gn->type == END_GN) {
+ // delete nexthops, we don't need them
list_delete (next);
- start->arg = XSTRDUP(MTYPE_CMD_TOKENS, vector_slot(vline, n));
- if (start->type == VARIABLE_GN)
- fprintf(stderr, "Setting variable %s->arg with text %s\n", start->text, start->arg);
+ // dupe current node, set arg field, and return
+ struct graph_node *curr = copy_node(start);
+ curr->arg = XSTRDUP(MTYPE_CMD_TOKENS, vector_slot(vline, n));
+ fprintf(stderr, ">> Matched END_GN on node %s for token %s\n", curr->text, curr->arg);
+ // initialize a new argument list
+ argv = list_new();
+ argv->del = &free_nodelist;
+ listnode_add(argv, curr);
+ listnode_add(argv, copy_node(gn));
return argv;
}
}
- list_free (next);
+ // no END_GN found, free resources and return null
+ list_delete (next);
return NULL;
}
@@ -269,7 +184,7 @@ match_build_argv_r (struct graph_node *start, vector vline, unsigned int n)
// get the result of the next node
for (unsigned int i = 0; i < n; i++) fprintf(stderr, "\t");
fprintf(stderr, "Recursing on node %s for token %s\n", gn->text, (char*) vector_slot(vline, n+1));
- struct list *result = match_build_argv_r (gn, vline, n+1);
+ struct list *result = match_command_r (gn, vline, n+1);
// compare to our current best match, and save if it's better
if (result) {
@@ -288,7 +203,7 @@ match_build_argv_r (struct graph_node *start, vector vline, unsigned int n)
fprintf(stderr, ">> Ambiguous match. Abort.\n");
list_delete (bestmatch);
list_delete (result);
- list_delete (argv);
+ list_delete (next);
return NULL;
}
}
@@ -301,19 +216,110 @@ match_build_argv_r (struct graph_node *start, vector vline, unsigned int n)
}
if (bestmatch) {
+ argv = list_new();
+ listnode_add(argv, start);
list_add_list(argv, bestmatch);
- list_delete (bestmatch);
+ list_free (bestmatch);
+ list_delete (next);
start->arg = XSTRDUP(MTYPE_CMD_TOKENS, vector_slot(vline, n));
if (start->type == VARIABLE_GN)
fprintf(stderr, "Setting variable %s->arg with text %s\n", start->text, start->arg);
return argv;
}
- else {
- list_delete (argv);
+ else
return NULL;
+}
+
+struct list *
+match_command_complete (struct graph_node *start, const char *line, enum filter_type filter)
+{
+ enum match_type minmatch = filter + 1;
+
+ // vectorize command line
+ vector vline = cmd_make_strvec (line);
+
+ // pointer to next input token to match
+ 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
+ struct graph_node *gn;
+ struct listnode *node;
+
+ // add all children of start node to list
+ add_nexthops(next, start);
+
+ unsigned int idx;
+ for (idx = 0; idx < vector_active(vline) && next->count > 0; idx++)
+ {
+ list_free (current);
+ current = next;
+ next = list_new();
+
+ 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);
+ }
+ }
}
+
+ /* Variable summary
+ * -----------------------------------------------------------------
+ * token = last input token processed
+ * idx = index in `command` of last token processed
+ * current = set of all transitions from the previous input token
+ * matched = set of all nodes reachable with current input
+ * next = set of all nodes reachable from all nodes in `matched`
+ */
+ list_free (current);
+ list_free (matched);
+
+ cmd_free_strvec(vline);
+
+ return next;
}
+/**
+ * Adds all children that are reachable by one parser hop
+ * to the given list. NUL_GN, SELECTOR_GN, and OPTION_GN
+ * nodes are treated as transparent.
+ *
+ * @param[out] l the list to add the children to
+ * @param[in] node the node to get the children of
+ * @return the number of children added to the list
+ */
+static int
+add_nexthops(struct list *l, struct graph_node *node)
+{
+ int added = 0;
+ struct graph_node *child;
+ for (unsigned int i = 0; i < vector_active(node->children); i++)
+ {
+ child = vector_slot(node->children, i);
+ switch (child->type) {
+ case OPTION_GN:
+ case SELECTOR_GN:
+ case NUL_GN:
+ added += add_nexthops(l, child);
+ break;
+ default:
+ listnode_add(l, child);
+ added++;
+ }
+ }
+ return added;
+}
+
+
/* matching utility functions */
static int
diff --git a/lib/command_match.h b/lib/command_match.h
index 24cd1287e6..a102ba9484 100644
--- a/lib/command_match.h
+++ b/lib/command_match.h
@@ -48,10 +48,13 @@ enum match_type
/**
* Attempt to find an exact command match for a line of user input.
*
+ * @param DFA to match against
+ * @param input string
+ * @param pointer to argv pointer
* @return cmd_element found, or NULL if there is no match.
*/
struct cmd_element *
-match_command (struct graph_node *, const char *, enum filter_type);
+match_command (struct graph_node *, const char *, struct list **);
/**
* Compiles next-hops for a given line of user input.
@@ -77,14 +80,4 @@ match_command (struct graph_node *, const char *, enum filter_type);
struct list *
match_command_complete (struct graph_node *, const char *, enum filter_type);
-/**
- * Builds an argument list given a cmd_element and a matching input line.
- *
- * @param[in] input line
- * @param[in] cmd_element struct
- * @return pointer to argument linked list
- */
-struct list *
-match_build_argv (const char *, struct cmd_element *);
-
#endif
diff --git a/lib/command_parse.y b/lib/command_parse.y
index 8c0584facd..cf87ca1042 100644
--- a/lib/command_parse.y
+++ b/lib/command_parse.y
@@ -91,6 +91,7 @@ start: sentence_root
yyerror("Duplicate command.");
YYABORT;
}
+ fprintf(stderr, "Added END_GN with active children: %d\n", vector_active(end->children));
}
sentence_root: WORD
@@ -323,7 +324,7 @@ parse_command_format(struct graph_node *start, struct cmd_element *cmd)
optnode_start = optnode_end = NULL;
// trace parser
- yydebug = 1;
+ yydebug = 0;
// command string
command = cmd;
// make flex read from a string
diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c
index e4617969af..2443b8471c 100644
--- a/lib/grammar_sandbox.c
+++ b/lib/grammar_sandbox.c
@@ -18,7 +18,6 @@ DEFUN (grammar_test,
struct cmd_element *cmd = malloc(sizeof(struct cmd_element));
cmd->string = command;
parse_command_format(nodegraph, cmd);
- walk_graph(nodegraph, 0);
return CMD_SUCCESS;
}
@@ -28,6 +27,10 @@ DEFUN (grammar_test_show,
GRAMMAR_STR
"print current accumulated DFA\n")
{
+ if (!nodegraph)
+ fprintf(stderr, "!nodegraph\n");
+ fprintf(stderr, "trying to print nodegraph->type\n");
+ fprintf(stderr, "%d\n", nodegraph->type);
walk_graph(nodegraph, 0);
return CMD_SUCCESS;
}
@@ -59,7 +62,7 @@ DEFUN (grammar_test_complete,
}
free(desc);
}
- list_free(result);
+ list_delete(result);
return CMD_SUCCESS;
}
@@ -71,24 +74,22 @@ DEFUN (grammar_test_match,
"attempt to match input on DFA\n"
"command to match")
{
- const char* command = argv_concat(argv, argc, 0);
- struct cmd_element *element = match_command (nodegraph, command, FILTER_STRICT);
+ struct list *argvv = NULL;
+ const char *command = argv_concat(argv, argc, 0);
+ struct cmd_element *element = match_command (nodegraph, command, &argvv);
- if (element)
+ if (element) {
fprintf(stderr, "Matched: %s\n", element->string);
- else {
- fprintf(stderr, "Returned NULL\n");
- return CMD_SUCCESS;
- }
-
- struct list *argvv = match_build_argv (command, element);
- if (!argvv) fprintf(stderr, "Failed to build argv.\n");
- else {
struct listnode *ln;
struct graph_node *gn;
for (ALL_LIST_ELEMENTS_RO(argvv,ln,gn))
fprintf(stderr, "%s -- %s\n", gn->text, gn->arg);
}
+ else {
+ fprintf(stderr, "Returned NULL\n");
+ return CMD_SUCCESS;
+ }
+
return CMD_SUCCESS;
}