diff options
| author | Holger Hans Peter Freyther <zecke@selfish.org> | 2011-11-18 23:14:24 +0100 | 
|---|---|---|
| committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2012-07-25 11:58:58 +0200 | 
| commit | 8297c819e985ba0d46752971b274b174098afceb (patch) | |
| tree | 51ac1f236957dfa6c1ce45574f25c6b875eef822 | |
| parent | aa5d0e88944fe3258260aedfbce9101301e35b44 (diff) | |
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.
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | Makefile.am | 3 | ||||
| -rw-r--r-- | doc/vty/example.xml | 22 | ||||
| -rw-r--r-- | doc/vty/merge_doc.xsl | 37 | ||||
| -rw-r--r-- | doc/vty/vtydoc.xsd | 46 | ||||
| -rw-r--r-- | src/vty/command.c | 148 | 
6 files changed, 256 insertions, 3 deletions
| @@ -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 d0fb027a..c9b7ccd9 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 00000000..400c6340 --- /dev/null +++ b/doc/vty/example.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<vtydoc xmlns="urn:osmocom:xml:libosmocore:vty:doc:1.0"> +    <!-- test a nested hierachy --> +    <node id="mgcp" name="MGCP Node"> +	<!-- define a command --> +	<command id="foo_cmd"> +		<doc>General docs</doc> +		<params> +			<param name="do" doc="Explain do" /> +			<param name="fo" doc="Explain foo" /> +		</params> +	</command> +	<command id="foo_cmd"> +		<doc>General docs</doc> +		<params> +			<param name="do" doc="Explain do" /> +			<param name="fo" doc="Explain foo" /> +		</params> +	</command> + +    </node> +</vtydoc> diff --git a/doc/vty/merge_doc.xsl b/doc/vty/merge_doc.xsl new file mode 100644 index 00000000..6e1bab1d --- /dev/null +++ b/doc/vty/merge_doc.xsl @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" +                             xmlns:vty="urn:osmocom:xml:libosmocore:vty:doc:1.0"> +  <xsl:output method="xml" version="1.0" encoding="ISO-8859-1" indent="yes" /> +  <xsl:variable name="with" select="'additions.xml'" /> + +  <xsl:template match="@*|node()"> +    <xsl:copy> +      <xsl:apply-templates select="@*|node()" /> +    </xsl:copy> +  </xsl:template> + + +  <!-- Copy the name of the node --> +  <xsl:template match="vty:node"> +    <xsl:copy> +      <xsl:apply-templates select="@*|node()" /> +      <xsl:variable name="info" select="document($with)/vty:vtydoc/vty:node[@id=current()/@id]/." /> +      <xsl:for-each select="$info/vty:name"> +          <xsl:copy-of select="." /> +      </xsl:for-each> +    </xsl:copy> +  </xsl:template> + + +  <!-- Copy command and add nodes --> +  <xsl:template match="vty:command"> +    <xsl:copy> +      <xsl:apply-templates select="@*|node()" /> +      <xsl:variable name="info" select="document($with)/vty:vtydoc/vty:node[@id=current()/../@id]/vty:command[@id=current()/@id]/." /> +      <xsl:for-each select="$info/*"> +          <xsl:copy-of select="." /> +      </xsl:for-each> +    </xsl:copy> +  </xsl:template> +</xsl:transform> + diff --git a/doc/vty/vtydoc.xsd b/doc/vty/vtydoc.xsd new file mode 100644 index 00000000..53a67a36 --- /dev/null +++ b/doc/vty/vtydoc.xsd @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema +    xmlns="urn:osmocom:xml:libosmocore:vty:doc:1.0" +    xmlns:xs="http://www.w3.org/2001/XMLSchema" +    targetNamespace="urn:osmocom:xml:libosmocore:vty:doc:1.0" +    elementFormDefault="qualified" +    attributeFormDefault="unqualified"> + +    <xs:complexType name="ParamType"> +        <xs:attribute name="name" type="xs:string" use="required" /> +        <xs:attribute name="doc" type="xs:string" use="required" /> +    </xs:complexType> + +    <xs:complexType name="ParamsType"> +        <xs:sequence> +            <xs:element name="param" type="ParamType" maxOccurs="unbounded" /> +        </xs:sequence> +    </xs:complexType> + +    <xs:complexType name="CommandType"> +        <xs:sequence> +            <xs:element name="doc" type="xs:string" minOccurs="0" maxOccurs="1" /> +            <xs:element name="params" type="ParamsType" minOccurs="1" maxOccurs="1"/> +            <xs:element name="enter" type="xs:string" minOccurs="0" maxOccurs="unbounded" /> +        </xs:sequence> +        <xs:attribute name="id" type="xs:string" use="required" /> +    </xs:complexType> + +    <xs:complexType name="NodeType"> +	<xs:sequence> +		<xs:element name="command" type="CommandType" minOccurs="0" maxOccurs="unbounded"/> +	</xs:sequence> +        <xs:attribute name="id" type="xs:anyURI"/> +        <xs:attribute name="name" type="xs:string"/> +    </xs:complexType> + +    <!-- the main entry --> +    <xs:element name="vtydoc"> +        <xs:complexType> +            <xs:sequence> +                <xs:element name="node" type="NodeType" minOccurs="0" maxOccurs="unbounded"/> +            </xs:sequence> +        </xs:complexType> +    </xs:element> +</xs:schema> + diff --git a/src/vty/command.c b/src/vty/command.c index c84c612d..7f83a5e4 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, "    <command id='%s'>%s", xml_string, VTY_NEWLINE); +	vty_out(vty, "      <params>%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, "        <param name='%s' doc='%s' />%s", +				xml_param, xml_doc, VTY_NEWLINE); +			talloc_free(xml_param); +			talloc_free(xml_doc); +		} +	} + +	vty_out(vty, "      </params>%s", VTY_NEWLINE); +	vty_out(vty, "    </command>%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, "<vtydoc xmlns='urn:osmocom:xml:libosmocore:vty:doc:1.0'>%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, "  <node id='%d'>%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, "  </node>%s", VTY_NEWLINE); +	} + +	vty_out(vty, "</vtydoc>%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); | 
