diff --git a/build_tools/make_xml_documentation b/build_tools/make_xml_documentation index b4bc703a71..e430a1ecd4 100755 --- a/build_tools/make_xml_documentation +++ b/build_tools/make_xml_documentation @@ -205,10 +205,20 @@ for subdir in ${mod_subdirs} ; do fi fi if [ "${for_wiki}" -eq "1" ] ; then - ${PYTHON} build_tools/get_documentation.py < "${i}" >> "${output_file}" + ${PYTHON} build_tools/get_documentation.py < "${i}" > /tmp/xmldoc.tmp.xml else - ${AWK} -f "${source_tree}/build_tools/get_documentation" "${i}" >> "${output_file}" + ${AWK} -f "${source_tree}/build_tools/get_documentation" "${i}" > /tmp/xmldoc.tmp.xml fi + if [ "${subdir}" = "main" ] ; then + # Force the module to be "builtin" if the source is in the main directory. + mn="builtin" + else + # Otherwise, let's just get the basename of the module. + bn=${i##*/} + mn=${bn%%.*} + fi + # Set the module name on specific elements + ${SED} -r -e "s/<(manager|managerEvent|managerEventInstance|function|application|info)\s+([^>]+)>/<\1 \2 module=\"${mn}\">/g" /tmp/xmldoc.tmp.xml >> "${output_file}" done for i in $(${FIND} "${subdir_path}" -name '*.xml') ; do ${GREP} -q "appdocsxml.dtd" "${i}" || continue @@ -220,11 +230,36 @@ for subdir in ${mod_subdirs} ; do ${XMLSTARLET} val -e -d "${source_tree}/doc/appdocsxml.dtd" "${i}" || { echo "" ; exit 1 ; } fi fi - ${SED} -r "/^\s*(<[?]xml|<.DOCTYPE|<.?docs)/d" "${i}" >> "${output_file}" + ${SED} -r "/^\s*(<[?]xml|<.DOCTYPE|<.?docs)/d" "${i}" > /tmp/xmldoc.tmp.xml + dirname=${i%/*} + if [ "${dirname}" != "${subdir_path}" ] ; then + # If we're in a subdirectory like channels/pjsip, we need to check channels/Makefile + # to see which module xml files in this directory belong to. + bn=${dirname##*/} + mn=$(${SED} -n -r -e "s/^[$]\(call MOD_ADD_C,([^,]+),[$]\(wildcard\s+${bn}\/.*/\1/gp" "${subdir_path}/Makefile") + else + if [ "${subdir}" = "main" ] ; then + # Force the module to be "builtin" if the XML is in the main directory. + mn="builtin" + else + # Otherwise the xml should have be "_doc.xml" suffix so + # get the basename then strip the suffix. + bn=${i##*/} + mn=${bn%%_doc.xml} + fi + fi + # Set the module name on specific elements + ${SED} -r -e "s/<(manager|managerEvent|managerEventInstance|function|application|info)\s+([^>]+)>/<\1 \2 module=\"${mn}\">/g" /tmp/xmldoc.tmp.xml >> "${output_file}" done done + echo "" >> "${output_file}" echo "" +# Some entries may already have a module attribute so remove the dup. +# It's easier to do this once on the entire file rather on a source-by-source basis. +cp "${output_file}" /tmp/xmldoc.tmp.xml +${SED} -r -e 's/module="([^"]+)"\s+module="([^"]+)">/module="\1">/g' /tmp/xmldoc.tmp.xml > "${output_file}" + if [ "${for_wiki}" -eq "1" ] ; then ${PYTHON} build_tools/post_process_documentation.py -i "${output_file}" -o "${core_output_file}" diff --git a/doc/appdocsxml.dtd b/doc/appdocsxml.dtd index 85763ff24f..b1c7f49bd7 100644 --- a/doc/appdocsxml.dtd +++ b/doc/appdocsxml.dtd @@ -64,6 +64,7 @@ + @@ -95,6 +96,7 @@ + diff --git a/include/asterisk/manager.h b/include/asterisk/manager.h index 2306f33565..c956c246cf 100644 --- a/include/asterisk/manager.h +++ b/include/asterisk/manager.h @@ -181,7 +181,8 @@ struct manager_action { * function and unregistering the AMI action object. */ unsigned int registered:1; - AST_STRING_FIELD_EXTENDED(since); /*!< Documentation "since" element */ + AST_STRING_FIELD_EXTENDED(since); /*!< Documentation "since" element */ + AST_STRING_FIELD_EXTENDED(provided_by); /*!< Documentation "provided_by" element */ }; /*! \brief External routines may register/unregister manager callbacks this way diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h index 552e33344e..24481304d0 100644 --- a/include/asterisk/pbx.h +++ b/include/asterisk/pbx.h @@ -151,6 +151,7 @@ struct ast_custom_function { AST_RWLIST_ENTRY(ast_custom_function) acflist; AST_STRING_FIELD_EXTENDED(since); /*!< Since text for 'show functions' */ + AST_STRING_FIELD_EXTENDED(provided_by); /*!< Provided-by text for 'show functions' */ }; /*! \brief All switch functions have the same interface, so define a type for them */ diff --git a/include/asterisk/xmldoc.h b/include/asterisk/xmldoc.h index 5f9164fd2c..140a9544e5 100644 --- a/include/asterisk/xmldoc.h +++ b/include/asterisk/xmldoc.h @@ -80,6 +80,8 @@ struct ast_xml_doc_item { AST_LIST_ENTRY(ast_xml_doc_item) next; /*! Since tagged information, if it exists */ struct ast_str *since; + /*! The provided-by of the item */ + struct ast_str *provided_by; }; /*! \brief Execute an XPath query on the loaded XML documentation @@ -180,6 +182,18 @@ char *ast_xmldoc_printable(const char *bwinput, int withcolors); */ char *ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module); +/*! + * \brief Generate provided-by documentation from XML. + * \param type The source of documentation (application, function, etc). + * \param name The name of the application, function, etc. + * \param module The module the item is in (optional, can be NULL) + * \retval NULL on error. + * \retval A malloc'ed string with the provided-by. + * + * \note The value actually comes from the "module" attribute. + */ +char *ast_xmldoc_build_provided_by(const char *type, const char *name, const char *module); + /*! * \brief Generate description documentation from XML. * \param type The source of documentation (application, function, etc). diff --git a/main/manager.c b/main/manager.c index 98e657d4c6..ae3941e4bb 100644 --- a/main/manager.c +++ b/main/manager.c @@ -1117,6 +1117,7 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_ #ifdef AST_XML_DOCS if (cur->docsrc == AST_XML_DOC) { char *synopsis = ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1); + char *provided_by = ast_xmldoc_printable(S_OR(cur->provided_by, "Not available"), 1); char *since = ast_xmldoc_printable(S_OR(cur->since, "Not available"), 1); char *description = ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1); char *syntax = ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1); @@ -1125,9 +1126,10 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_ char *seealso = ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1); char *responses = ast_xmldoc_printable("None", 1); - if (!synopsis || !since || !description || !syntax || !arguments + if (!synopsis || !provided_by || !since || !description || !syntax || !arguments || !privilege || !seealso || !responses) { ast_free(synopsis); + ast_free(provided_by); ast_free(since); ast_free(description); ast_free(syntax); @@ -1157,9 +1159,12 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_ "%s\n\n" COLORIZE_FMT "\n" "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" COLORIZE_FMT "\n", ast_term_color(COLOR_MAGENTA, 0), cur->action, ast_term_reset(), COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis, + COLORIZE(COLOR_MAGENTA, 0, "[Provided By]"), provided_by, COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since, COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description, COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax, @@ -1199,6 +1204,7 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_ ); ast_free(synopsis); + ast_free(provided_by); ast_free(since); ast_free(description); ast_free(syntax); @@ -7839,6 +7845,11 @@ int ast_manager_register2(const char *action, int auth, int (*func)(struct manse return -1; } + if (ast_string_field_init_extended(cur, provided_by)) { + ao2_t_ref(cur, -1, "action object creation failed"); + return -1; + } + cur->action = action; cur->authority = auth; cur->func = func; @@ -7855,6 +7866,10 @@ int ast_manager_register2(const char *action, int auth, int (*func)(struct manse ast_string_field_set(cur, synopsis, tmpxml); ast_free(tmpxml); + tmpxml = ast_xmldoc_build_provided_by("manager", action, NULL); + ast_string_field_set(cur, provided_by, tmpxml); + ast_free(tmpxml); + tmpxml = ast_xmldoc_build_syntax("manager", action, NULL); ast_string_field_set(cur, syntax, tmpxml); ast_free(tmpxml); @@ -9263,16 +9278,17 @@ static char *handle_manager_show_events(struct ast_cli_entry *e, int cmd, struct static void print_event_instance(struct ast_cli_args *a, struct ast_xml_doc_item *instance) { - char *since, *syntax, *description, *synopsis, *seealso, *arguments; + char *since, *syntax, *provided_by, *description, *synopsis, *seealso, *arguments; synopsis = ast_xmldoc_printable(AS_OR(instance->synopsis, "Not available"), 1); + provided_by = ast_xmldoc_printable(AS_OR(instance->provided_by, "Not available"), 1); since = ast_xmldoc_printable(AS_OR(instance->since, "Not available"), 1); description = ast_xmldoc_printable(AS_OR(instance->description, "Not available"), 1); syntax = ast_xmldoc_printable(AS_OR(instance->syntax, "Not available"), 1); arguments = ast_xmldoc_printable(AS_OR(instance->arguments, "Not available"), 1); seealso = ast_xmldoc_printable(AS_OR(instance->seealso, "Not available"), 1); - if (!synopsis || !since || !description || !syntax || !arguments || !seealso) { + if (!synopsis || !provided_by || !since || !description || !syntax || !arguments || !seealso) { ast_cli(a->fd, "Error: Memory allocation failed\n"); goto free_docs; } @@ -9290,9 +9306,12 @@ static void print_event_instance(struct ast_cli_args *a, struct ast_xml_doc_item COLORIZE_FMT "\n" "%s\n\n" COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" "%s\n\n", ast_term_color(COLOR_MAGENTA, 0), instance->name, ast_term_reset(), COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis, + COLORIZE(COLOR_MAGENTA, 0, "[Provided By]"), provided_by, COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since, COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description, COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax, diff --git a/main/pbx_app.c b/main/pbx_app.c index a1b3f0003d..656ed7c5be 100644 --- a/main/pbx_app.c +++ b/main/pbx_app.c @@ -46,6 +46,7 @@ struct ast_app { int (*execute)(struct ast_channel *chan, const char *data); AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(synopsis); /*!< Synopsis text for 'show applications' */ + AST_STRING_FIELD(provided_by); /*!< Provided-by text for 'show applications' */ AST_STRING_FIELD(since); /*!< Since text for 'show applications' */ AST_STRING_FIELD(description); /*!< Description (help text) for 'show application <name>' */ AST_STRING_FIELD(syntax); /*!< Syntax text for 'core show applications' */ @@ -143,6 +144,11 @@ int ast_register_application2(const char *app, int (*execute)(struct ast_channel ast_string_field_set(tmp, synopsis, tmpxml); ast_free(tmpxml); + /* load provied_by */ + tmpxml = ast_xmldoc_build_provided_by("application", app, ast_module_name(tmp->module)); + ast_string_field_set(tmp, provided_by, tmpxml); + ast_free(tmpxml); + /* load since */ tmpxml = ast_xmldoc_build_since("application", app, ast_module_name(tmp->module)); ast_string_field_set(tmp, since, tmpxml); @@ -197,11 +203,12 @@ int ast_register_application2(const char *app, int (*execute)(struct ast_channel static void print_app_docs(struct ast_app *aa, int fd) { - char *synopsis = NULL, *since = NULL, *description = NULL, *syntax = NULL, *arguments = NULL, *seealso = NULL; + char *synopsis = NULL, *provided_by = NULL, *since = NULL, *description = NULL, *syntax = NULL, *arguments = NULL, *seealso = NULL; #ifdef AST_XML_DOCS if (aa->docsrc == AST_XML_DOC) { synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1); + provided_by = ast_xmldoc_printable(S_OR(aa->provided_by, "Not available"), 1); since = ast_xmldoc_printable(S_OR(aa->since, "Not available"), 1); description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1); syntax = ast_xmldoc_printable(S_OR(aa->syntax, "Not available"), 1); @@ -211,6 +218,7 @@ static void print_app_docs(struct ast_app *aa, int fd) #endif { synopsis = ast_strdup(S_OR(aa->synopsis, "Not Available")); + provided_by = ast_strdup(S_OR(aa->provided_by, "Not Available")); since = ast_strdup(S_OR(aa->since, "Not Available")); description = ast_strdup(S_OR(aa->description, "Not Available")); syntax = ast_strdup(S_OR(aa->syntax, "Not Available")); @@ -218,7 +226,7 @@ static void print_app_docs(struct ast_app *aa, int fd) seealso = ast_strdup(S_OR(aa->seealso, "Not Available")); } /* check allocated memory. */ - if (!synopsis || !since || !description || !syntax || !arguments || !seealso) { + if (!synopsis || !provided_by || !since || !description || !syntax || !arguments || !seealso) { goto free_docs; } @@ -235,9 +243,12 @@ static void print_app_docs(struct ast_app *aa, int fd) COLORIZE_FMT "\n" "%s\n\n" COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" "%s\n\n", ast_term_color(COLOR_MAGENTA, 0), aa->name, ast_term_reset(), COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis, + COLORIZE(COLOR_MAGENTA, 0, "[Provided By]"), provided_by, COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since, COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description, COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax, @@ -247,6 +258,7 @@ static void print_app_docs(struct ast_app *aa, int fd) free_docs: ast_free(synopsis); + ast_free(provided_by); ast_free(since); ast_free(description); ast_free(syntax); diff --git a/main/pbx_functions.c b/main/pbx_functions.c index 75b79ffa2a..58799449f8 100644 --- a/main/pbx_functions.c +++ b/main/pbx_functions.c @@ -144,7 +144,7 @@ static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_c { struct ast_custom_function *acf; /* Maximum number of characters added by terminal coloring is 22 */ - char *synopsis = NULL, *since = NULL, *description = NULL, *syntax = NULL, *arguments = NULL, *seealso = NULL; + char *synopsis = NULL, *provided_by = NULL, *since = NULL, *description = NULL, *syntax = NULL, *arguments = NULL, *seealso = NULL; char *rtn = CLI_SUCCESS; switch (cmd) { @@ -171,6 +171,7 @@ static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_c #ifdef AST_XML_DOCS if (acf->docsrc == AST_XML_DOC) { synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1); + provided_by = ast_xmldoc_printable(S_OR(acf->provided_by, "Not available"), 1); since = ast_xmldoc_printable(S_OR(acf->since, "Not available"), 1); description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1); syntax = ast_xmldoc_printable(S_OR(acf->syntax, "Not available"), 1); @@ -180,6 +181,7 @@ static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_c #endif { synopsis = ast_strdup(S_OR(acf->synopsis, "Not Available")); + provided_by = ast_strdup(S_OR(acf->provided_by, "Not available")); since = ast_strdup(S_OR(acf->since, "Not Available")); description = ast_strdup(S_OR(acf->desc, "Not Available")); syntax = ast_strdup(S_OR(acf->syntax, "Not Available")); @@ -187,7 +189,7 @@ static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_c seealso = ast_strdup(S_OR(acf->seealso, "Not Available")); } /* check allocated memory. */ - if (!synopsis || !since || !description || !syntax || !arguments || !seealso) { + if (!synopsis || !provided_by || !since || !description || !syntax || !arguments || !seealso) { rtn = CLI_FAILURE; goto free_docs; } @@ -205,9 +207,12 @@ static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_c COLORIZE_FMT "\n" "%s\n\n" COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" "%s\n\n", ast_term_color(COLOR_MAGENTA, 0), acf->name, ast_term_reset(), COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis, + COLORIZE(COLOR_MAGENTA, 0, "[Provided By]"), provided_by, COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since, COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description, COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax, @@ -217,6 +222,7 @@ static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_c free_docs: ast_free(synopsis); + ast_free(provided_by); ast_free(since); ast_free(description); ast_free(syntax); @@ -333,11 +339,21 @@ static int acf_retrieve_docs(struct ast_custom_function *acf) return -1; } + if (ast_string_field_init_extended(acf, provided_by)) { + ast_string_field_free_memory(acf); + return -1; + } + /* load synopsis */ tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod)); ast_string_field_set(acf, synopsis, tmpxml); ast_free(tmpxml); + /* load provided_by */ + tmpxml = ast_xmldoc_build_provided_by("function", acf->name, ast_module_name(acf->mod)); + ast_string_field_set(acf, provided_by, tmpxml); + ast_free(tmpxml); + /* load since */ tmpxml = ast_xmldoc_build_since("function", acf->name, ast_module_name(acf->mod)); ast_string_field_set(acf, since, tmpxml); diff --git a/main/xmldoc.c b/main/xmldoc.c index 85eb5a812d..68cd3223ad 100644 --- a/main/xmldoc.c +++ b/main/xmldoc.c @@ -1812,6 +1812,56 @@ char *ast_xmldoc_build_since(const char *type, const char *name, const char *mod return output; } +/*! + * \internal + * \brief Build provided-by information for an item + * + * \param node The application, function, etc. node to parse + * + * \note This method exists for when you already have the node. This + * prevents having to lock the documentation tree twice + * + * \retval A malloc'd character pointer to the provided-by information of the item + * \retval NULL on failure + * + * \note The value actually comes from the "module" attribute. + * + */ +static char *_ast_xmldoc_build_provided_by(struct ast_xml_node *node) +{ + const char *output; + + output = ast_xml_get_attribute(node, "module"); + if (ast_strlen_zero(output)) { + return NULL; + } + + return ast_strdup(output); +} + +char *ast_xmldoc_build_provided_by(const char *type, const char *name, const char *module) +{ + char *output; + struct ast_xml_node *node; + + if (ast_strlen_zero(type) || ast_strlen_zero(name)) { + return NULL; + } + + /* get the application/function root node. */ + AST_RWLIST_RDLOCK(&xmldoc_tree); + node = xmldoc_get_node(type, name, module, documentation_language); + if (!node || !ast_xml_node_get_children(node)) { + AST_RWLIST_UNLOCK(&xmldoc_tree); + return NULL; + } + + output = _ast_xmldoc_build_provided_by(node); + AST_RWLIST_UNLOCK(&xmldoc_tree); + + return output; +} + /*! * \internal * \brief Parse a \ node. @@ -2080,6 +2130,7 @@ static void xmldoc_parse_parameter(struct ast_xml_node *fixnode, const char *tab static int xmldoc_parse_info(struct ast_xml_node *node, const char *tabs, const char *posttabs, struct ast_str **buffer) { const char *tech; + const char *provided_by; char *internaltabs; int internal_ret; int ret = 0; @@ -2094,8 +2145,11 @@ static int xmldoc_parse_info(struct ast_xml_node *node, const char *tabs, const } tech = ast_xml_get_attribute(node, "tech"); + provided_by = ast_xml_get_attribute(node, "module"); + if (tech) { - ast_str_append(buffer, 0, "%sTechnology: %s\n", internaltabs, tech); + ast_str_append(buffer, 0, "%sTechnology: %s Provided by: %s\n", internaltabs, tech, + S_OR(provided_by, "unknown")); ast_xml_free_attr(tech); } @@ -2377,6 +2431,7 @@ static void ast_xml_doc_item_destructor(void *obj) } ast_free(doc->synopsis); + ast_free(doc->provided_by); ast_free(doc->since); ast_free(doc->description); ast_free(doc->syntax); @@ -2410,6 +2465,7 @@ static struct ast_xml_doc_item *ast_xml_doc_item_alloc(const char *name, const c } if ( !(item->synopsis = ast_str_create(128)) + || !(item->provided_by = ast_str_create(128)) || !(item->since = ast_str_create(128)) || !(item->description = ast_str_create(128)) || !(item->syntax = ast_str_create(128)) @@ -2475,6 +2531,7 @@ static struct ast_xml_doc_item *xmldoc_build_documentation_item(struct ast_xml_n { struct ast_xml_doc_item *item; char *synopsis; + char *provided_by; char *since; char *description; char *syntax; @@ -2487,6 +2544,7 @@ static struct ast_xml_doc_item *xmldoc_build_documentation_item(struct ast_xml_n item->node = node; synopsis = _ast_xmldoc_build_synopsis(node); + provided_by = _ast_xmldoc_build_provided_by(node); since = _ast_xmldoc_build_since(node); description = _ast_xmldoc_build_description(node); syntax = _ast_xmldoc_build_syntax(node, type, name); @@ -2496,6 +2554,9 @@ static struct ast_xml_doc_item *xmldoc_build_documentation_item(struct ast_xml_n if (synopsis) { ast_str_set(&item->synopsis, 0, "%s", synopsis); } + if (provided_by) { + ast_str_set(&item->provided_by, 0, "%s", provided_by); + } if (since) { ast_str_set(&item->since, 0, "%s", since); } @@ -2513,6 +2574,7 @@ static struct ast_xml_doc_item *xmldoc_build_documentation_item(struct ast_xml_n } ast_free(synopsis); + ast_free(provided_by); ast_free(since); ast_free(description); ast_free(syntax); @@ -2738,6 +2800,7 @@ int ast_xmldoc_regenerate_doc_item(struct ast_xml_doc_item *item) char *seealso; char *arguments; char *synopsis; + char *provided_by; char *description; if (!item || !item->node) { @@ -2753,6 +2816,7 @@ int ast_xmldoc_regenerate_doc_item(struct ast_xml_doc_item *item) seealso = _ast_xmldoc_build_seealso(item->node); arguments = _ast_xmldoc_build_arguments(item->node); synopsis = _ast_xmldoc_build_synopsis(item->node); + provided_by = _ast_xmldoc_build_provided_by(item->node); description = _ast_xmldoc_build_description(item->node); if (syntax) { @@ -2775,6 +2839,7 @@ int ast_xmldoc_regenerate_doc_item(struct ast_xml_doc_item *item) ast_free(seealso); ast_free(arguments); ast_free(synopsis); + ast_free(provided_by); ast_free(description); ast_xml_free_attr(name); return 0;