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
${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 "<module>_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 "</docs>" >> "${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}"
<!ELEMENT managerEventInstance (since?,synopsis?,syntax?,description?,see-also?)*>
<!ATTLIST managerEventInstance class CDATA #REQUIRED>
+ <!ATTLIST managerEventInstance module CDATA #IMPLIED>
<!ELEMENT configInfo (synopsis?,description?,configFile+)>
<!ATTLIST configInfo name CDATA #REQUIRED>
<!ATTLIST info name CDATA #REQUIRED>
<!ATTLIST info language CDATA #REQUIRED>
<!ATTLIST info tech CDATA #REQUIRED>
+ <!ATTLIST info module CDATA #IMPLIED>
<!ELEMENT see-also (ref|xi:include)*>
* 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
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 */
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
*/
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).
#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);
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);
"%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,
);
ast_free(synopsis);
+ ast_free(provided_by);
ast_free(since);
ast_free(description);
ast_free(syntax);
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;
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);
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;
}
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,
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' */
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);
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);
#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"));
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;
}
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,
free_docs:
ast_free(synopsis);
+ ast_free(provided_by);
ast_free(since);
ast_free(description);
ast_free(syntax);
{
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) {
#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);
#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"));
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;
}
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,
free_docs:
ast_free(synopsis);
+ ast_free(provided_by);
ast_free(since);
ast_free(description);
ast_free(syntax);
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);
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 \<enum\> node.
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;
}
tech = ast_xml_get_attribute(node, "tech");
+ provided_by = ast_xml_get_attribute(node, "module");
+
if (tech) {
- ast_str_append(buffer, 0, "%s<note>Technology: %s</note>\n", internaltabs, tech);
+ ast_str_append(buffer, 0, "%s<note>Technology: %s Provided by: %s</note>\n", internaltabs, tech,
+ S_OR(provided_by, "unknown"));
ast_xml_free_attr(tech);
}
}
ast_free(doc->synopsis);
+ ast_free(doc->provided_by);
ast_free(doc->since);
ast_free(doc->description);
ast_free(doc->syntax);
}
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))
{
struct ast_xml_doc_item *item;
char *synopsis;
+ char *provided_by;
char *since;
char *description;
char *syntax;
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);
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);
}
}
ast_free(synopsis);
+ ast_free(provided_by);
ast_free(since);
ast_free(description);
ast_free(syntax);
char *seealso;
char *arguments;
char *synopsis;
+ char *provided_by;
char *description;
if (!item || !item->node) {
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) {
ast_free(seealso);
ast_free(arguments);
ast_free(synopsis);
+ ast_free(provided_by);
ast_free(description);
ast_xml_free_attr(name);
return 0;