mirror of https://gerrit.osmocom.org/libosmocore
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.jolly/7bit_ussd
parent
aa5d0e8894
commit
8297c819e9
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue