diff --git a/.gitignore b/.gitignore
index 3c8afd9be..b91b5aa8c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,7 +61,8 @@ utils/osmo-auc-gen
doc/codec
doc/core
-doc/vty
+doc/vty/latex
+doc/vty/html
doc/gsm
doc/html.tar
diff --git a/Makefile.am b/Makefile.am
index d0fb027ad..c9b7ccd9e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -36,8 +36,7 @@ $(top_builddir)/doc/gsm/html/index.html: $(SOURCES) Doxyfile.gsm
$(DOXYGEN) Doxyfile.gsm
$(top_builddir)/doc/vty/html/index.html: $(SOURCES) Doxyfile.vty
- @rm -rf doc/vty
- mkdir -p doc/vty
+ @rm -rf doc/vty/{html,latex}
$(DOXYGEN) Doxyfile.vty
$(top_builddir)/doc/codec/html/index.html: $(SOURCES) Doxyfile.codec
diff --git a/doc/vty/example.xml b/doc/vty/example.xml
new file mode 100644
index 000000000..400c63400
--- /dev/null
+++ b/doc/vty/example.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ General docs
+
+
+
+
+
+
+ General docs
+
+
+
+
+
+
+
+
diff --git a/doc/vty/merge_doc.xsl b/doc/vty/merge_doc.xsl
new file mode 100644
index 000000000..6e1bab1d9
--- /dev/null
+++ b/doc/vty/merge_doc.xsl
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/vty/vtydoc.xsd b/doc/vty/vtydoc.xsd
new file mode 100644
index 000000000..53a67a367
--- /dev/null
+++ b/doc/vty/vtydoc.xsd
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/vty/command.c b/src/vty/command.c
index c84c612d7..7f83a5e43 100644
--- a/src/vty/command.c
+++ b/src/vty/command.c
@@ -405,6 +405,145 @@ const char *cmd_prompt(enum node_type node)
return cnode->prompt;
}
+static char *xml_escape(const char *inp)
+{
+ int _strlen;
+ char *out, *out_ptr;
+ int len = 0, i, j;
+
+ if (!inp)
+ return NULL;
+ _strlen = strlen(inp);
+
+ for (i = 0; i < _strlen; ++i) {
+ switch (inp[i]) {
+ case '"':
+ len += 6;
+ break;
+ case '\'':
+ len += 6;
+ break;
+ case '<':
+ len += 4;
+ break;
+ case '>':
+ len += 4;
+ break;
+ case '&':
+ len += 5;
+ break;
+ default:
+ len += 1;
+ break;
+ }
+ }
+
+ out = talloc_size(NULL, len + 1);
+ if (!out)
+ return NULL;
+
+ out_ptr = out;
+
+#define ADD(out, str) \
+ for (j = 0; j < strlen(str); ++j) \
+ *(out++) = str[j];
+
+ for (i = 0; i < _strlen; ++i) {
+ switch (inp[i]) {
+ case '"':
+ ADD(out_ptr, """);
+ break;
+ case '\'':
+ ADD(out_ptr, "'");
+ break;
+ case '<':
+ ADD(out_ptr, "<");
+ break;
+ case '>':
+ ADD(out_ptr, ">");
+ break;
+ case '&':
+ ADD(out_ptr, "&");
+ break;
+ default:
+ *(out_ptr++) = inp[i];
+ break;
+ }
+ }
+
+#undef ADD
+
+ out_ptr[0] = '\0';
+ return out;
+}
+
+/*
+ * Write one cmd_element as XML to the given VTY.
+ */
+static int vty_dump_element(struct cmd_element *cmd, struct vty *vty)
+{
+ char *xml_string = xml_escape(cmd->string);
+
+ vty_out(vty, " %s", xml_string, VTY_NEWLINE);
+ vty_out(vty, " %s", VTY_NEWLINE);
+
+ int j;
+ for (j = 0; j < vector_count(cmd->strvec); ++j) {
+ vector descvec = vector_slot(cmd->strvec, j);
+ int i;
+ for (i = 0; i < vector_active(descvec); ++i) {
+ char *xml_param, *xml_doc;
+ struct desc *desc = vector_slot(descvec, i);
+ if (desc == NULL)
+ continue;
+
+ xml_param = xml_escape(desc->cmd);
+ xml_doc = xml_escape(desc->str);
+ vty_out(vty, " %s",
+ xml_param, xml_doc, VTY_NEWLINE);
+ talloc_free(xml_param);
+ talloc_free(xml_doc);
+ }
+ }
+
+ vty_out(vty, " %s", VTY_NEWLINE);
+ vty_out(vty, " %s", VTY_NEWLINE);
+
+ talloc_free(xml_string);
+ return 0;
+}
+
+/*
+ * Dump all nodes and commands associated with a given node as XML to the VTY.
+ */
+static int vty_dump_nodes(struct vty *vty)
+{
+ int i, j;
+
+ vty_out(vty, "%s", VTY_NEWLINE);
+
+ for (i = 0; i < vector_active(cmdvec); ++i) {
+ struct cmd_node *cnode;
+ cnode = vector_slot(cmdvec, i);
+ if (!cnode)
+ continue;
+
+ vty_out(vty, " %s", i, VTY_NEWLINE);
+
+ for (j = 0; j < vector_active(cnode->cmd_vector); ++j) {
+ struct cmd_element *elem;
+ elem = vector_slot(cnode->cmd_vector, j);
+ vty_dump_element(elem, vty);
+ }
+
+ vty_out(vty, " %s", VTY_NEWLINE);
+ }
+
+ vty_out(vty, "%s", VTY_NEWLINE);
+
+ return 0;
+}
+
/*! \brief Install a command into a node
* \param[in] ntype Node Type
* \param[cmd] element to be installed
@@ -2232,6 +2371,13 @@ DEFUN(show_version,
return CMD_SUCCESS;
}
+DEFUN(show_online_help,
+ show_online_help_cmd, "show online-help", SHOW_STR "Online help\n")
+{
+ vty_dump_nodes(vty);
+ return CMD_SUCCESS;
+}
+
/* Help display function for all node. */
gDEFUN(config_help,
config_help_cmd, "help", "Description of the interactive help system\n")
@@ -3269,6 +3415,7 @@ void cmd_init(int terminal)
/* Each node's basic commands. */
install_element(VIEW_NODE, &show_version_cmd);
+ install_element(VIEW_NODE, &show_online_help_cmd);
if (terminal) {
install_element(VIEW_NODE, &config_list_cmd);
install_element(VIEW_NODE, &config_exit_cmd);
@@ -3288,6 +3435,7 @@ void cmd_init(int terminal)
}
install_element (ENABLE_NODE, &show_startup_config_cmd);
install_element(ENABLE_NODE, &show_version_cmd);
+ install_element(ENABLE_NODE, &show_online_help_cmd);
if (terminal) {
install_element(ENABLE_NODE, &config_terminal_length_cmd);