Merge the rest of the FullyBooted patch
[asterisk/asterisk.git] / main / xmldoc.c
index 3185a3a..46be1f0 100644 (file)
@@ -19,6 +19,8 @@
  * \brief XML Documentation API
  *
  * \author Eliel C. Sardanons (LU1ALY) <eliels@gmail.com>
+ *
+ * \extref libxml2 http://www.xmlsoft.org/
  */
 
 #include "asterisk.h"
@@ -58,6 +60,7 @@ struct documentation_tree {
 };
 
 static char *xmldoc_get_syntax_cmd(struct ast_xml_node *fixnode, const char *name, int printname);
+static int xmldoc_parse_enumlist(struct ast_xml_node *fixnode, const char *tabs, struct ast_str **buffer);
 
 /*!
  * \brief Container of documentation trees
@@ -268,8 +271,7 @@ static char *xmldoc_string_wrap(const char *text, int columns, int maxdiff)
                                backspace = xmldoc_foundspace_backward(text, i, maxdiff);
                                if (backspace) {
                                        needtobreak = 1;
-                                       tmp->used -= backspace;
-                                       tmp->str[tmp->used] = '\0';
+                                       ast_str_truncate(tmp, -backspace);
                                        i -= backspace + 1;
                                        continue;
                                }
@@ -300,7 +302,7 @@ static char *xmldoc_string_wrap(const char *text, int columns, int maxdiff)
                ast_str_append(&tmp, 0, "%c", text[i]);
        }
 
-       ret = ast_strdup(tmp->str);
+       ret = ast_strdup(ast_str_buffer(tmp));
        ast_free(tmp);
 
        return ret;
@@ -396,14 +398,14 @@ char *ast_xmldoc_printable(const char *bwinput, int withcolors)
        }
 
        if (withcolors) {
-               ast_term_color_code(&colorized, COLOR_BRWHITE, 0);
+               ast_str_append(&colorized, 0, "%s", term_end());
                if (!colorized) {
                        return NULL;
                }
        }
 
        /* Wrap the text, notice that string wrap will avoid cutting an ESC sequence. */
-       wrapped = xmldoc_string_wrap(colorized->str, xmldoc_text_columns, xmldoc_max_diff);
+       wrapped = xmldoc_string_wrap(ast_str_buffer(colorized), xmldoc_text_columns, xmldoc_max_diff);
 
        ast_free(colorized);
 
@@ -881,7 +883,7 @@ static char *xmldoc_parse_cmd_enumlist(struct ast_xml_node *fixnode)
 
        ast_str_append(&paramname, 0, "}");
 
-       ret = ast_strdup(paramname->str);
+       ret = ast_strdup(ast_str_buffer(paramname));
        ast_free(paramname);
 
        return ret;
@@ -978,7 +980,63 @@ static char *xmldoc_get_syntax_cmd(struct ast_xml_node *fixnode, const char *nam
        }
 
        /* return a common string. */
-       ret = ast_strdup(syntax->str);
+       ret = ast_strdup(ast_str_buffer(syntax));
+       ast_free(syntax);
+
+       return ret;
+}
+
+/*! \internal
+ *  \brief Generate an AMI action syntax.
+ *  \param fixnode The manager action node pointer.
+ *  \param name The name of the manager action.
+ *  \retval The generated syntax.
+ *  \retval NULL on error.
+ */
+static char *xmldoc_get_syntax_manager(struct ast_xml_node *fixnode, const char *name)
+{
+       struct ast_str *syntax;
+       struct ast_xml_node *node = fixnode;
+       const char *paramtype, *attrname;
+       int required;
+       char *ret;
+
+       syntax = ast_str_create(128);
+       if (!syntax) {
+               return ast_strdup(name);
+       }
+
+       ast_str_append(&syntax, 0, "Action: %s", name);
+
+       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;
+               }
+
+               /* Is this parameter required? */
+               required = 0;
+               paramtype = ast_xml_get_attribute(node, "required");
+               if (paramtype) {
+                       required = ast_true(paramtype);
+                       ast_xml_free_attr(paramtype);
+               }
+
+               attrname = ast_xml_get_attribute(node, "name");
+               if (!attrname) {
+                       /* ignore this bogus parameter and continue. */
+                       continue;
+               }
+
+               ast_str_append(&syntax, 0, "\n%s%s:%s <value>",
+                       (required ? "" : "["),
+                       attrname,
+                       (required ? "" : "]"));
+
+               ast_xml_free_attr(attrname);
+       }
+
+       /* return a common string. */
+       ret = ast_strdup(ast_str_buffer(syntax));
        ast_free(syntax);
 
        return ret;
@@ -987,16 +1045,18 @@ static char *xmldoc_get_syntax_cmd(struct ast_xml_node *fixnode, const char *nam
 /*! \brief Types of syntax that we are able to generate. */
 enum syntaxtype {
        FUNCTION_SYNTAX,
+       MANAGER_SYNTAX,
        COMMAND_SYNTAX
 };
 
 /*! \brief Mapping between type of node and type of syntax to generate. */
-struct strsyntaxtype {
+static struct strsyntaxtype {
        const char *type;
        enum syntaxtype stxtype;
 } stxtype[] = {
        { "function",           FUNCTION_SYNTAX },
        { "application",        FUNCTION_SYNTAX },
+       { "manager",            MANAGER_SYNTAX  },
        { "agi",                COMMAND_SYNTAX  }
 };
 
@@ -1034,10 +1094,18 @@ char *ast_xmldoc_build_syntax(const char *type, const char *name)
        }
 
        if (node) {
-               if (xmldoc_get_syntax_type(type) == FUNCTION_SYNTAX) {
+               switch (xmldoc_get_syntax_type(type)) {
+               case FUNCTION_SYNTAX:
                        syntax = xmldoc_get_syntax_fun(node, name, "parameter", 1, 1);
-               } else {
+                       break;
+               case COMMAND_SYNTAX:
                        syntax = xmldoc_get_syntax_cmd(node, name, 1);
+                       break;
+               case MANAGER_SYNTAX:
+                       syntax = xmldoc_get_syntax_manager(node, name);
+                       break;
+               default:
+                       syntax = xmldoc_get_syntax_fun(node, name, "parameter", 1, 1);
                }
        }
        return syntax;
@@ -1084,9 +1152,9 @@ static int xmldoc_parse_para(struct ast_xml_node *node, const char *tabs, const
                        if (tmpstr) {
                                if (strcasecmp(ast_xml_node_get_name(tmp), "text")) {
                                        ast_str_append(buffer, 0, "<%s>%s</%s>", ast_xml_node_get_name(tmp),
-                                                       tmpstr->str, ast_xml_node_get_name(tmp));
+                                                       ast_str_buffer(tmpstr), ast_xml_node_get_name(tmp));
                                } else {
-                                       ast_str_append(buffer, 0, "%s", tmpstr->str);
+                                       ast_str_append(buffer, 0, "%s", ast_str_buffer(tmpstr));
                                }
                                ast_free(tmpstr);
                                ret = 2;
@@ -1245,8 +1313,8 @@ static int xmldoc_parse_variable(struct ast_xml_node *node, const char *tabs, st
                        /* Cleanup text. */
                        xmldoc_string_cleanup(tmptext, &cleanstr, 1);
                        ast_xml_free_text(tmptext);
-                       if (cleanstr && cleanstr->used > 0) {
-                               ast_str_append(buffer, 0, ":%s", cleanstr->str);
+                       if (cleanstr && ast_str_strlen(cleanstr) > 0) {
+                               ast_str_append(buffer, 0, ":%s", ast_str_buffer(cleanstr));
                        }
                        ast_free(cleanstr);
                }
@@ -1379,9 +1447,10 @@ char *ast_xmldoc_build_seealso(const char *type, const char *name)
                }
                first = 0;
                ast_xml_free_text(content);
+               ast_xml_free_attr(typename);
        }
 
-       output = ast_strdup(outputstr->str);
+       output = ast_strdup(ast_str_buffer(outputstr));
        ast_free(outputstr);
 
        return output;
@@ -1398,6 +1467,9 @@ static int xmldoc_parse_enum(struct ast_xml_node *fixnode, const char *tabs, str
 {
        struct ast_xml_node *node = fixnode;
        int ret = 0;
+       char *optiontabs;
+
+       ast_asprintf(&optiontabs, "%s    ", tabs);
 
        for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
                if ((xmldoc_parse_para(node, (ret ? tabs : " - "), "\n", buffer))) {
@@ -1405,7 +1477,12 @@ static int xmldoc_parse_enum(struct ast_xml_node *fixnode, const char *tabs, str
                } else if ((xmldoc_parse_specialtags(node, (ret ? tabs : " - "), "\n", buffer))) {
                        ret = 1;
                }
+
+               xmldoc_parse_enumlist(node, optiontabs, buffer);
        }
+
+       ast_free(optiontabs);
+
        return ret;
 }
 
@@ -1534,6 +1611,7 @@ static void xmldoc_parse_optionlist(struct ast_xml_node *fixnode, const char *ta
                if (!xmldoc_parse_option(node, tabs, buffer)) {
                        ast_str_append(buffer, 0, "\n");
                }
+               ast_str_append(buffer, 0, "\n");
                ast_xml_free_attr(optname);
                ast_xml_free_attr(hasparams);
        }
@@ -1631,13 +1709,13 @@ char *ast_xmldoc_build_arguments(const char *type, const char *name)
                xmldoc_parse_parameter(node, "", &ret);
        }
 
-       if (ret->used > 0) {
+       if (ast_str_strlen(ret) > 0) {
                /* remove last '\n' */
-               if (ret->str[ret->used - 1] == '\n') {
-                       ret->str[ret->used - 1] = '\0';
-                       ret->used--;
+               char *buf = ast_str_buffer(ret);
+               if (buf[ast_str_strlen(ret) - 1] == '\n') {
+                       ast_str_truncate(ret, -1);
                }
-               retstr = ast_strdup(ret->str);
+               retstr = ast_strdup(ast_str_buffer(ret));
        }
        ast_free(ret);
 
@@ -1677,9 +1755,9 @@ static struct ast_str *xmldoc_get_formatted(struct ast_xml_node *node, int raw_o
                }
                /* remove last '\n' */
                /* XXX Don't modify ast_str internals manually */
-               if (ret->str[ret->used-1] == '\n') {
-                       ret->str[ret->used-1] = '\0';
-                       ret->used--;
+               tmpstr = ast_str_buffer(ret);
+               if (tmpstr[ast_str_strlen(ret) - 1] == '\n') {
+                       ast_str_truncate(ret, -1);
                }
        }
        return ret;
@@ -1708,7 +1786,7 @@ static char *xmldoc_build_field(const char *type, const char *name, const char *
        node = xmldoc_get_node(type, name, documentation_language);
 
        if (!node) {
-               ast_log(LOG_WARNING, "Counldn't find %s %s in XML documentation\n", type, name);
+               ast_log(LOG_WARNING, "Couldn't find %s %s in XML documentation\n", type, name);
                return ret;
        }
 
@@ -1720,8 +1798,8 @@ static char *xmldoc_build_field(const char *type, const char *name, const char *
        }
 
        formatted = xmldoc_get_formatted(node, raw, raw);
-       if (formatted->used > 0) {
-               ret = ast_strdup(formatted->str);
+       if (ast_str_strlen(formatted) > 0) {
+               ret = ast_strdup(ast_str_buffer(formatted));
        }
        ast_free(formatted);