From 8297c819e985ba0d46752971b274b174098afceb Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 18 Nov 2011 23:14:24 +0100 Subject: [PATCH] vty: Add xsd and a command that can generate the documentation. When building the doxygen documentation do not remove the other VTY documentation files in the doc/vty folder. Create a command that can be installed to dump all nodes and commands as XML on the given VTY. Create a schema for the XML file and a XSL-T script that can merge the generated file with additional information. --- .gitignore | 3 +- Makefile.am | 3 +- doc/vty/example.xml | 22 +++++++ doc/vty/merge_doc.xsl | 37 +++++++++++ doc/vty/vtydoc.xsd | 46 +++++++++++++ src/vty/command.c | 148 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 256 insertions(+), 3 deletions(-) create mode 100644 doc/vty/example.xml create mode 100644 doc/vty/merge_doc.xsl create mode 100644 doc/vty/vtydoc.xsd 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);