summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/vty/command.h5
-rw-r--r--src/vty/command.c47
2 files changed, 51 insertions, 1 deletions
diff --git a/include/osmocom/vty/command.h b/include/osmocom/vty/command.h
index cb2edaaf..58f248fe 100644
--- a/include/osmocom/vty/command.h
+++ b/include/osmocom/vty/command.h
@@ -123,6 +123,11 @@ struct cmd_node {
/*! Vector of this node's command list. */
vector cmd_vector;
+
+ /*! Human-readable ID of this node. Should only contain alphanumeric
+ * plus '-' and '_' characters (is used as XML ID for 'show
+ * online-help'). If left NUL, this is derived from the prompt.*/
+ char name[64];
};
enum {
diff --git a/src/vty/command.c b/src/vty/command.c
index af936ee7..8ad2e975 100644
--- a/src/vty/command.c
+++ b/src/vty/command.c
@@ -123,12 +123,40 @@ char *argv_concat(const char **argv, int argc, int shift)
return str;
}
+/* Strip all characters from a string (prompt) except for alnum, '-' and '_'.
+ * For example used to derive a node->name from node->prompt if the user didn't provide a name;
+ * in turn, this name us used for XML IDs in 'show online-help'. */
+static const char *node_name_from_prompt(const char *prompt, char *name_buf, size_t name_buf_size)
+{
+ const char *pos;
+ int dest = 0;
+
+ if (!prompt || !*prompt)
+ return "";
+
+ for (pos = prompt; *pos && dest < (name_buf_size-1); pos++) {
+ if (pos[0] == '%' && pos[1]) {
+ /* skip "%s"; loop pos++ does the second one. */
+ pos++;
+ continue;
+ }
+ if (!(isalnum(pos[0]) || pos[0] == '-' || pos[0] == '_'))
+ continue;
+ name_buf[dest] = pos[0];
+ dest++;
+ }
+ name_buf[dest] = '\0';
+ return name_buf;
+}
+
/*! Install top node of command vector. */
void install_node(struct cmd_node *node, int (*func) (struct vty *))
{
vector_set_index(cmdvec, node->node, node);
node->func = func;
node->cmd_vector = vector_init(VECTOR_MIN_SIZE);
+ if (!*node->name)
+ node_name_from_prompt(node->prompt, node->name, sizeof(node->name));
}
/* Compare two command's string. Used in sort_node (). */
@@ -608,6 +636,7 @@ static int vty_dump_element(struct cmd_element *cmd, struct vty *vty)
static int vty_dump_nodes(struct vty *vty)
{
int i, j;
+ int same_name_count;
vty_out(vty, "<vtydoc xmlns='urn:osmocom:xml:libosmocore:vty:doc:1.0'>%s", VTY_NEWLINE);
@@ -617,7 +646,23 @@ static int vty_dump_nodes(struct vty *vty)
if (!cnode)
continue;
- vty_out(vty, " <node id='%d'>%s", cnode->node, VTY_NEWLINE);
+ /* De-dup node IDs: how many times has this same name been used before? Count the first
+ * occurence as _1 and omit that first suffix, so that the first occurence is called
+ * 'name', the second becomes 'name_2', then 'name_3', ... */
+ same_name_count = 1;
+ for (j = 0; j < i; ++j) {
+ struct cmd_node *cnode2;
+ cnode2 = vector_slot(cmdvec, j);
+ if (!cnode2)
+ continue;
+ if (strcmp(cnode->name, cnode2->name) == 0)
+ same_name_count ++;
+ }
+
+ vty_out(vty, " <node id='%s", cnode->name);
+ if (same_name_count > 1 || !*cnode->name)
+ vty_out(vty, "_%d", same_name_count);
+ vty_out(vty, "'>%s", VTY_NEWLINE);
for (j = 0; j < vector_active(cnode->cmd_vector); ++j) {
struct cmd_element *elem;