summaryrefslogtreecommitdiff
path: root/lib/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/command.c')
-rw-r--r--lib/command.c42
1 files changed, 30 insertions, 12 deletions
diff --git a/lib/command.c b/lib/command.c
index 3416bcd1c7..f9c4107745 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -213,6 +213,18 @@ argv_find (struct cmd_token **argv, int argc, const char *text, int *index)
return found;
}
+static unsigned int
+cmd_hash_key (void *p)
+{
+ return (uintptr_t) p;
+}
+
+static int
+cmd_hash_cmp (const void *a, const void *b)
+{
+ return a == b;
+}
+
/* Install top node of command vector. */
void
install_node (struct cmd_node *node,
@@ -225,6 +237,7 @@ install_node (struct cmd_node *node,
// add start node
struct cmd_token *token = new_cmd_token (START_TKN, NULL, NULL);
graph_new_node (node->cmdgraph, token, (void (*)(void *)) &del_cmd_token);
+ node->cmd_hash = hash_create (cmd_hash_key, cmd_hash_cmp);
}
/* Breaking up string into each command piece. I assume given
@@ -332,8 +345,12 @@ install_element (enum node_type ntype, struct cmd_element *cmd)
/* cmd_init hasn't been called */
if (!cmdvec)
- return;
-
+ {
+ fprintf (stderr, "%s called before cmd_init, breakage likely\n",
+ __func__);
+ return;
+ }
+
cnode = vector_slot (cmdvec, ntype);
if (cnode == NULL)
@@ -342,19 +359,17 @@ install_element (enum node_type ntype, struct cmd_element *cmd)
ntype);
exit (EXIT_FAILURE);
}
-
- // add node to command graph and command vector
- // idiotic O(n) deduplication logic, should just use a merkle tree
- for (unsigned int i = 0; i < vector_active (cnode->cmd_vector); i++)
- {
- struct cmd_element *existing = vector_slot (cnode->cmd_vector, i);
- if (strmatch (existing->string, cmd->string))
+
+ if (hash_lookup (cnode->cmd_hash, cmd) != NULL)
{
- zlog_warn ("Duplicate command: %s\n", cmd->string);
+ fprintf (stderr,
+ "Multiple command installs to node %d of command:\n%s\n",
+ ntype, cmd->string);
return;
}
- }
-
+
+ assert (hash_get (cnode->cmd_hash, cmd, hash_alloc_intern));
+
command_parse_format (cnode->cmdgraph, cmd);
vector_set (cnode->cmd_vector, cmd);
@@ -2433,6 +2448,9 @@ cmd_terminate ()
// deleting the graph delets the cmd_element as well
graph_delete_graph (cmd_node->cmdgraph);
vector_free (cmd_node->cmd_vector);
+ hash_clean (cmd_node->cmd_hash, NULL);
+ hash_free (cmd_node->cmd_hash);
+ cmd_node->cmd_hash = NULL;
}
vector_free (cmdvec);