diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/xmldoc.c | 203 |
1 files changed, 193 insertions, 10 deletions
diff --git a/main/xmldoc.c b/main/xmldoc.c index c24a6b7a5..3a68b6cab 100644 --- a/main/xmldoc.c +++ b/main/xmldoc.c @@ -57,6 +57,8 @@ struct documentation_tree { AST_RWLIST_ENTRY(documentation_tree) entry; }; +static char *xmldoc_get_syntax_cmd(struct ast_xml_node *fixnode, const char *name, int printname); + /*! * \brief Container of documentation trees * @@ -548,17 +550,18 @@ static __attribute__((format(printf,4,5))) void xmldoc_reverse_helper(int revers } /*! \internal - * \brief Check if the passed node has <argument> tags inside it. - * \param node Root node to search argument elements. + * \brief Check if the passed node has 'what' tags inside it. + * \param node Root node to search 'what' elements. + * \param what node name to search inside node. * \retval 1 If a <argument> element is found inside 'node'. * \retval 0 If no <argument> is found inside 'node'. */ -static int xmldoc_has_arguments(struct ast_xml_node *fixnode) +static int xmldoc_has_inside(struct ast_xml_node *fixnode, const char *what) { struct ast_xml_node *node = fixnode; for (node = ast_xml_node_get_children(fixnode); node; node = ast_xml_node_get_next(node)) { - if (!strcasecmp(ast_xml_node_get_name(node), "argument")) { + if (!strcasecmp(ast_xml_node_get_name(node), what)) { return 1; } } @@ -575,7 +578,7 @@ static int xmldoc_has_arguments(struct ast_xml_node *fixnode) * \retval NULL on error. * \retval An ast_malloc'ed string with the syntax generated. */ -static char *xmldoc_get_syntax(struct ast_xml_node *rootnode, const char *rootname, const char *childname, int printparenthesis, int printrootname) +static char *xmldoc_get_syntax_fun(struct ast_xml_node *rootnode, const char *rootname, const char *childname, int printparenthesis, int printrootname) { #define GOTONEXT(__rev, __a) (__rev ? ast_xml_node_get_prev(__a) : ast_xml_node_get_next(__a)) #define ISLAST(__rev, __a) (__rev == 1 ? (ast_xml_node_get_prev(__a) ? 0 : 1) : (ast_xml_node_get_next(__a) ? 0 : 1)) @@ -679,7 +682,7 @@ static char *xmldoc_get_syntax(struct ast_xml_node *rootnode, const char *rootna } /* Get the argument name, if it is not the leaf, go inside that parameter. */ - if (xmldoc_has_arguments(node)) { + if (xmldoc_has_inside(node, "arguments")) { parenthesis = ast_xml_get_attribute(node, "hasparams"); prnparenthesis = 0; if (parenthesis) { @@ -691,7 +694,7 @@ static char *xmldoc_get_syntax(struct ast_xml_node *rootnode, const char *rootna } argname = ast_xml_get_attribute(node, "name"); if (argname) { - paramname = xmldoc_get_syntax(node, argname, "argument", prnparenthesis, prnparenthesis); + paramname = xmldoc_get_syntax_fun(node, argname, "argument", prnparenthesis, prnparenthesis); ast_xml_free_attr(argname); paramnamemalloc = 1; } else { @@ -805,6 +808,182 @@ static char *xmldoc_get_syntax(struct ast_xml_node *rootnode, const char *rootna #undef MP } +/*! \internal + * \brief Parse an enumlist inside a <parameter> to generate a COMMAND + * syntax. + * \param fixnode A pointer to the <enumlist> node. + * \retval {<unknown>} on error. + * \retval A string inside brackets {} with the enum's separated by pipes |. + */ +static char *xmldoc_parse_cmd_enumlist(struct ast_xml_node *fixnode) +{ + struct ast_xml_node *node = fixnode; + struct ast_str *paramname; + char *enumname, *ret; + int first = 1; + + paramname = ast_str_create(128); + if (!paramname) { + return ast_strdup("{<unkown>}"); + } + + ast_str_append(¶mname, 0, "{"); + + for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) { + if (strcasecmp(ast_xml_node_get_name(node), "enum")) { + continue; + } + + enumname = xmldoc_get_syntax_cmd(node, "", 0); + if (!enumname) { + continue; + } + if (!first) { + ast_str_append(¶mname, 0, "|"); + } + ast_str_append(¶mname, 0, "%s", enumname); + first = 0; + ast_free(enumname); + } + + ast_str_append(¶mname, 0, "}"); + + ret = ast_strdup(paramname->str); + ast_free(paramname); + + return ret; +} + +/*! \internal + * \brief Generate a syntax of COMMAND type. + * \param fixnode The <syntax> node pointer. + * \param name The name of the 'command'. + * \param printname Print the name of the command before the paramters? + * \retval On error, return just 'name'. + * \retval On success return the generated syntax. + */ +static char *xmldoc_get_syntax_cmd(struct ast_xml_node *fixnode, const char *name, int printname) +{ + struct ast_str *syntax; + struct ast_xml_node *tmpnode, *node = fixnode; + char *ret; + const char *paramname, *paramtype, *attrname, *literal; + int required, isenum, first = 1, isliteral; + + syntax = ast_str_create(128); + if (!syntax) { + /* at least try to return something... */ + return ast_strdup(name); + } + + /* append name to output string. */ + if (printname) { + ast_str_append(&syntax, 0, "%s", name); + first = 0; + } + + for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) { + if (strcasecmp(ast_xml_node_get_name(node), "parameter")) { + continue; + } + + if (xmldoc_has_inside(node, "parameter")) { + /* is this a recursive parameter. */ + paramname = xmldoc_get_syntax_cmd(node, "", 0); + isenum = 1; + } else if (!xmldoc_has_inside(node, "enumlist")) { + /* this is a simple parameter. */ + attrname = ast_xml_get_attribute(node, "name"); + if (!attrname) { + /* ignore this bogus parameter and continue. */ + continue; + } + paramname = ast_strdup(attrname); + ast_xml_free_attr(attrname); + isenum = 0; + } else { + /* parse enumlist (note that this is a special enumlist + that is used to describe a syntax like {<param1>|<param2>|...} */ + for (tmpnode = ast_xml_node_get_children(node); tmpnode; tmpnode = ast_xml_node_get_next(tmpnode)) { + if (!strcasecmp(ast_xml_node_get_name(tmpnode), "enumlist")) { + break; + } + } + paramname = xmldoc_parse_cmd_enumlist(tmpnode); + isenum = 1; + } + + /* Is this parameter required? */ + required = 0; + paramtype = ast_xml_get_attribute(node, "required"); + if (paramtype) { + required = ast_true(paramtype); + ast_xml_free_attr(paramtype); + } + + /* Is this a replaceable value or a fixed parameter value? */ + isliteral = 0; + literal = ast_xml_get_attribute(node, "literal"); + if (literal) { + isliteral = ast_true(literal); + ast_xml_free_attr(literal); + } + + /* if required="false" print with [...]. + * if literal="true" or is enum print without <..>. + * if not first print a space at the beginning. + */ + ast_str_append(&syntax, 0, "%s%s%s%s%s%s", + (first ? "" : " "), + (required ? "" : "["), + (isenum || isliteral ? "" : "<"), + paramname, + (isenum || isliteral ? "" : ">"), + (required ? "" : "]")); + first = 0; + ast_xml_free_attr(paramname); + } + + /* return a common string. */ + ret = ast_strdup(syntax->str); + ast_free(syntax); + + return ret; +} + +/*! \brief Types of syntax that we are able to generate. */ +enum syntaxtype { + FUNCTION_SYNTAX, + COMMAND_SYNTAX +}; + +/*! \brief Mapping between type of node and type of syntax to generate. */ +struct strsyntaxtype { + const char *type; + enum syntaxtype stxtype; +} stxtype[] = { + { "function", FUNCTION_SYNTAX }, + { "application", FUNCTION_SYNTAX }, + { "agi", COMMAND_SYNTAX } +}; + +/*! \internal + * \brief Get syntax type based on type of node. + * \param type Type of node. + * \retval The type of syntax to generate based on the type of node. + */ +static enum syntaxtype xmldoc_get_syntax_type(const char *type) +{ + int i; + for (i=0; i < ARRAY_LEN(stxtype); i++) { + if (!strcasecmp(stxtype[i].type, type)) { + return stxtype[i].stxtype; + } + } + + return FUNCTION_SYNTAX; +} + char *ast_xmldoc_build_syntax(const char *type, const char *name) { struct ast_xml_node *node; @@ -822,7 +1001,11 @@ char *ast_xmldoc_build_syntax(const char *type, const char *name) } if (node) { - syntax = xmldoc_get_syntax(node, name, "parameter", 1, 1); + if (xmldoc_get_syntax_type(type) == FUNCTION_SYNTAX) { + syntax = xmldoc_get_syntax_fun(node, name, "parameter", 1, 1); + } else { + syntax = xmldoc_get_syntax_cmd(node, name, 1); + } } return syntax; } @@ -1294,7 +1477,7 @@ static void xmldoc_parse_optionlist(struct ast_xml_node *fixnode, const char *ta continue; } - optionsyntax = xmldoc_get_syntax(node, optname, "argument", 0, 1); + optionsyntax = xmldoc_get_syntax_fun(node, optname, "argument", 0, 1); if (!optionsyntax) { continue; } @@ -1325,7 +1508,7 @@ static void xmldoc_parse_parameter(struct ast_xml_node *fixnode, const char *tab return; } - hasarguments = xmldoc_has_arguments(node); + hasarguments = xmldoc_has_inside(node, "arguments"); if (!(paramname = ast_xml_get_attribute(node, "name"))) { /* parameter MUST have an attribute name. */ return; |