summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/app_fax.c4
-rw-r--r--doc/appdocsxml.dtd2
-rw-r--r--include/asterisk/module.h8
-rw-r--r--include/asterisk/xmldoc.h15
-rw-r--r--main/loader.c9
-rw-r--r--main/manager.c10
-rw-r--r--main/pbx.c28
-rw-r--r--main/xmldoc.c108
-rw-r--r--res/res_agi.c8
-rw-r--r--res/res_fax.c6
10 files changed, 136 insertions, 62 deletions
diff --git a/apps/app_fax.c b/apps/app_fax.c
index e2085cbbb..5285ba833 100644
--- a/apps/app_fax.c
+++ b/apps/app_fax.c
@@ -46,7 +46,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/manager.h"
/*** DOCUMENTATION
- <application name="SendFAX" language="en_US">
+ <application name="SendFAX" language="en_US" module="app_fax">
<synopsis>
Send a Fax
</synopsis>
@@ -91,7 +91,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
</variablelist>
</description>
</application>
- <application name="ReceiveFAX" language="en_US">
+ <application name="ReceiveFAX" language="en_US" module="app_fax">
<synopsis>
Receive a Fax
</synopsis>
diff --git a/doc/appdocsxml.dtd b/doc/appdocsxml.dtd
index 1de0ea452..328752c30 100644
--- a/doc/appdocsxml.dtd
+++ b/doc/appdocsxml.dtd
@@ -14,10 +14,12 @@
<!ELEMENT application (synopsis?,syntax?,description?,see-also?)>
<!ATTLIST application name CDATA #REQUIRED>
<!ATTLIST application language CDATA #REQUIRED>
+ <!ATTLIST application module CDATA #IMPLIED>
<!ELEMENT function (synopsis?,syntax?,description?,see-also?)>
<!ATTLIST function name CDATA #REQUIRED>
<!ATTLIST function language CDATA #REQUIRED>
+ <!ATTLIST function module CDATA #IMPLIED>
<!ELEMENT agi (synopsis?,syntax?,description?,see-also?)>
<!ATTLIST agi name CDATA #REQUIRED>
diff --git a/include/asterisk/module.h b/include/asterisk/module.h
index aaa8cbef3..db9c5b465 100644
--- a/include/asterisk/module.h
+++ b/include/asterisk/module.h
@@ -175,6 +175,14 @@ char *ast_module_helper(const char *line, const char *word, int pos, int state,
struct ast_module;
+/*!
+ * \brief Get the name of a module.
+ * \param mod A pointer to the module.
+ * \return the name of the module
+ * \retval NULL if mod or mod->info is NULL
+ */
+const char *ast_module_name(const struct ast_module *mod);
+
/* User count routines keep track of which channels are using a given module
resource. They can help make removing modules safer, particularly if
they're in use at the time they have been requested to be removed */
diff --git a/include/asterisk/xmldoc.h b/include/asterisk/xmldoc.h
index c876b46da..4256dc1e9 100644
--- a/include/asterisk/xmldoc.h
+++ b/include/asterisk/xmldoc.h
@@ -36,29 +36,32 @@ enum ast_doc_src {
* \brief Get the syntax for a specified application or function.
* \param type Application, Function or AGI ?
* \param name Name of the application or function.
+ * \param module The module the item is in (optional, can be NULL)
* \retval NULL on error.
* \retval The generated syntax in a ast_malloc'ed string.
*/
-char *ast_xmldoc_build_syntax(const char *type, const char *name);
+char *ast_xmldoc_build_syntax(const char *type, const char *name, const char *module);
/*!
* \brief Parse the <see-also> node content.
* \param type 'application', 'function' or 'agi'.
* \param name Application or functions name.
+ * \param module The module the item is in (optional, can be NULL)
* \retval NULL on error.
* \retval Content of the see-also node.
*/
-char *ast_xmldoc_build_seealso(const char *type, const char *name);
+char *ast_xmldoc_build_seealso(const char *type, const char *name, const char *module);
/*!
* \brief Generate the [arguments] tag based on type of node ('application',
* 'function' or 'agi') and name.
* \param type 'application', 'function' or 'agi' ?
* \param name Name of the application or function to build the 'arguments' tag.
+ * \param module The module the item is in (optional, can be NULL)
* \retval NULL on error.
* \retval Output buffer with the [arguments] tag content.
*/
-char *ast_xmldoc_build_arguments(const char *type, const char *name);
+char *ast_xmldoc_build_arguments(const char *type, const char *name, const char *module);
/*!
* \brief Colorize and put delimiters (instead of tags) to the xmldoc output.
@@ -73,19 +76,21 @@ char *ast_xmldoc_printable(const char *bwinput, int withcolors);
* \brief Generate synopsis 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 synopsis.
*/
-char *ast_xmldoc_build_synopsis(const char *type, const char *name);
+char *ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module);
/*!
* \brief Generate description 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 formatted description.
*/
-char *ast_xmldoc_build_description(const char *type, const char *name);
+char *ast_xmldoc_build_description(const char *type, const char *name, const char *module);
#endif /* AST_XML_DOCS */
diff --git a/main/loader.c b/main/loader.c
index 5fe84449f..6cd5ffbdb 100644
--- a/main/loader.c
+++ b/main/loader.c
@@ -96,6 +96,15 @@ struct ast_module {
static AST_LIST_HEAD_STATIC(module_list, ast_module);
+const char *ast_module_name(const struct ast_module *mod)
+{
+ if (!mod || !mod->info) {
+ return NULL;
+ }
+
+ return mod->info->name;
+}
+
/*
* module_list is cleared by its constructor possibly after
* we start accumulating embedded modules, so we need to
diff --git a/main/manager.c b/main/manager.c
index d4b1b9577..3beb815ac 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -5225,23 +5225,23 @@ int ast_manager_register2(const char *action, int auth, int (*func)(struct manse
cur->func = func;
#ifdef AST_XML_DOCS
if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
- tmpxml = ast_xmldoc_build_synopsis("manager", action);
+ tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL);
ast_string_field_set(cur, synopsis, tmpxml);
ast_free(tmpxml);
- tmpxml = ast_xmldoc_build_syntax("manager", action);
+ tmpxml = ast_xmldoc_build_syntax("manager", action, NULL);
ast_string_field_set(cur, syntax, tmpxml);
ast_free(tmpxml);
- tmpxml = ast_xmldoc_build_description("manager", action);
+ tmpxml = ast_xmldoc_build_description("manager", action, NULL);
ast_string_field_set(cur, description, tmpxml);
ast_free(tmpxml);
- tmpxml = ast_xmldoc_build_seealso("manager", action);
+ tmpxml = ast_xmldoc_build_seealso("manager", action, NULL);
ast_string_field_set(cur, seealso, tmpxml);
ast_free(tmpxml);
- tmpxml = ast_xmldoc_build_arguments("manager", action);
+ tmpxml = ast_xmldoc_build_arguments("manager", action, NULL);
ast_string_field_set(cur, arguments, tmpxml);
ast_free(tmpxml);
diff --git a/main/pbx.c b/main/pbx.c
index 0e528fd4f..a10293d77 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -3552,27 +3552,27 @@ static int acf_retrieve_docs(struct ast_custom_function *acf)
}
/* load synopsis */
- tmpxml = ast_xmldoc_build_synopsis("function", acf->name);
+ tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
ast_string_field_set(acf, synopsis, tmpxml);
ast_free(tmpxml);
/* load description */
- tmpxml = ast_xmldoc_build_description("function", acf->name);
+ tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
ast_string_field_set(acf, desc, tmpxml);
ast_free(tmpxml);
/* load syntax */
- tmpxml = ast_xmldoc_build_syntax("function", acf->name);
+ tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
ast_string_field_set(acf, syntax, tmpxml);
ast_free(tmpxml);
/* load arguments */
- tmpxml = ast_xmldoc_build_arguments("function", acf->name);
+ tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
ast_string_field_set(acf, arguments, tmpxml);
ast_free(tmpxml);
/* load seealso */
- tmpxml = ast_xmldoc_build_seealso("function", acf->name);
+ tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
ast_string_field_set(acf, seealso, tmpxml);
ast_free(tmpxml);
@@ -5842,31 +5842,35 @@ int ast_register_application2(const char *app, int (*execute)(struct ast_channel
return -1;
}
+ strcpy(tmp->name, app);
+ tmp->execute = execute;
+ tmp->module = mod;
+
#ifdef AST_XML_DOCS
/* Try to lookup the docs in our XML documentation database */
if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
/* load synopsis */
- tmpxml = ast_xmldoc_build_synopsis("application", app);
+ tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module));
ast_string_field_set(tmp, synopsis, tmpxml);
ast_free(tmpxml);
/* load description */
- tmpxml = ast_xmldoc_build_description("application", app);
+ tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module));
ast_string_field_set(tmp, description, tmpxml);
ast_free(tmpxml);
/* load syntax */
- tmpxml = ast_xmldoc_build_syntax("application", app);
+ tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module));
ast_string_field_set(tmp, syntax, tmpxml);
ast_free(tmpxml);
/* load arguments */
- tmpxml = ast_xmldoc_build_arguments("application", app);
+ tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module));
ast_string_field_set(tmp, arguments, tmpxml);
ast_free(tmpxml);
/* load seealso */
- tmpxml = ast_xmldoc_build_seealso("application", app);
+ tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module));
ast_string_field_set(tmp, seealso, tmpxml);
ast_free(tmpxml);
tmp->docsrc = AST_XML_DOC;
@@ -5879,10 +5883,6 @@ int ast_register_application2(const char *app, int (*execute)(struct ast_channel
}
#endif
- strcpy(tmp->name, app);
- tmp->execute = execute;
- tmp->module = mod;
-
/* Store in alphabetical order */
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
if (strcasecmp(tmp->name, cur->name) < 0) {
diff --git a/main/xmldoc.c b/main/xmldoc.c
index bbbb590e4..6dfca7192 100644
--- a/main/xmldoc.c
+++ b/main/xmldoc.c
@@ -456,46 +456,96 @@ static void xmldoc_string_cleanup(const char *text, struct ast_str **output, int
}
/*! \internal
+ * \brief Check if the given attribute on the given node matches the given value.
+ * \param node the node to match
+ * \param attr the name of the attribute
+ * \param value the expected value of the attribute
+ * \retval true if the given attribute contains the given value
+ * \retval false if the given attribute does not exist or does not contain the given value
+ */
+static int xmldoc_attribute_match(struct ast_xml_node *node, const char *attr, const char *value)
+{
+ const char *attr_value = ast_xml_get_attribute(node, attr);
+ int match = attr_value && !strcmp(attr_value, value);
+ ast_xml_free_attr(attr_value);
+ return match;
+}
+
+/*! \internal
* \brief Get the application/function node for 'name' application/function with language 'language'
- * if we don't find any, get the first application with 'name' no matter which language with.
+ * and module 'module' if we don't find any, get the first application
+ * with 'name' no matter which language or module.
* \param type 'application', 'function', ...
* \param name Application or Function name.
+ * \param module Module item is in.
* \param language Try to get this language (if not found try with en_US)
* \retval NULL on error.
* \retval A node of type ast_xml_node.
*/
-static struct ast_xml_node *xmldoc_get_node(const char *type, const char *name, const char *language)
+static struct ast_xml_node *xmldoc_get_node(const char *type, const char *name, const char *module, const char *language)
{
struct ast_xml_node *node = NULL;
+ struct ast_xml_node *first_match = NULL;
+ struct ast_xml_node *lang_match = NULL;
struct documentation_tree *doctree;
- const char *lang;
AST_RWLIST_RDLOCK(&xmldoc_tree);
AST_LIST_TRAVERSE(&xmldoc_tree, doctree, entry) {
/* the core xml documents have priority over thirdparty document. */
node = ast_xml_get_root(doctree->doc);
+ if (!node) {
+ break;
+ }
+
+ node = ast_xml_node_get_children(node);
while ((node = ast_xml_find_element(node, type, "name", name))) {
+ if (!ast_xml_node_get_children(node)) {
+ /* ignore empty nodes */
+ node = ast_xml_node_get_next(node);
+ continue;
+ }
+
+ if (!first_match) {
+ first_match = node;
+ }
+
/* Check language */
- lang = ast_xml_get_attribute(node, "language");
- if (lang && !strcmp(lang, language)) {
- ast_xml_free_attr(lang);
- break;
- } else if (lang) {
- ast_xml_free_attr(lang);
+ if (xmldoc_attribute_match(node, "language", language)) {
+ if (!lang_match) {
+ lang_match = node;
+ }
+
+ /* if module is empty we have a match */
+ if (ast_strlen_zero(module)) {
+ break;
+ }
+
+ /* Check module */
+ if (xmldoc_attribute_match(node, "module", module)) {
+ break;
+ }
}
+
+ node = ast_xml_node_get_next(node);
}
- if (node && ast_xml_node_get_children(node)) {
+ /* if we matched lang and module return this match */
+ if (node) {
break;
}
- /* We didn't find the application documentation for the specified language,
- so, try to load documentation for any language */
- node = ast_xml_get_root(doctree->doc);
- if (ast_xml_node_get_children(node)) {
- if ((node = ast_xml_find_element(ast_xml_node_get_children(node), type, "name", name))) {
- break;
- }
+ /* we didn't match lang and module, just return the first
+ * result with a matching language if we have one */
+ if (lang_match) {
+ node = lang_match;
+ break;
+ }
+
+ /* we didn't match with only the language, just return the
+ * first match */
+ if (first_match) {
+ node = first_match;
+ break;
}
}
AST_RWLIST_UNLOCK(&xmldoc_tree);
@@ -1077,12 +1127,12 @@ static enum syntaxtype xmldoc_get_syntax_type(const char *type)
return FUNCTION_SYNTAX;
}
-char *ast_xmldoc_build_syntax(const char *type, const char *name)
+char *ast_xmldoc_build_syntax(const char *type, const char *name, const char *module)
{
struct ast_xml_node *node;
char *syntax = NULL;
- node = xmldoc_get_node(type, name, documentation_language);
+ node = xmldoc_get_node(type, name, module, documentation_language);
if (!node) {
return NULL;
}
@@ -1383,7 +1433,7 @@ static int xmldoc_parse_variablelist(struct ast_xml_node *node, const char *tabs
return ret;
}
-char *ast_xmldoc_build_seealso(const char *type, const char *name)
+char *ast_xmldoc_build_seealso(const char *type, const char *name, const char *module)
{
struct ast_str *outputstr;
char *output;
@@ -1397,7 +1447,7 @@ char *ast_xmldoc_build_seealso(const char *type, const char *name)
}
/* get the application/function root node. */
- node = xmldoc_get_node(type, name, documentation_language);
+ node = xmldoc_get_node(type, name, module, documentation_language);
if (!node || !ast_xml_node_get_children(node)) {
return NULL;
}
@@ -1677,7 +1727,7 @@ static void xmldoc_parse_parameter(struct ast_xml_node *fixnode, const char *tab
ast_free(internaltabs);
}
-char *ast_xmldoc_build_arguments(const char *type, const char *name)
+char *ast_xmldoc_build_arguments(const char *type, const char *name, const char *module)
{
struct ast_xml_node *node;
struct ast_str *ret = ast_str_create(128);
@@ -1687,7 +1737,7 @@ char *ast_xmldoc_build_arguments(const char *type, const char *name)
return NULL;
}
- node = xmldoc_get_node(type, name, documentation_language);
+ node = xmldoc_get_node(type, name, module, documentation_language);
if (!node || !ast_xml_node_get_children(node)) {
return NULL;
@@ -1772,7 +1822,7 @@ static struct ast_str *xmldoc_get_formatted(struct ast_xml_node *node, int raw_o
* \retval NULL On error.
* \retval Field text content on success.
*/
-static char *xmldoc_build_field(const char *type, const char *name, const char *var, int raw)
+static char *xmldoc_build_field(const char *type, const char *name, const char *module, const char *var, int raw)
{
struct ast_xml_node *node;
char *ret = NULL;
@@ -1783,7 +1833,7 @@ static char *xmldoc_build_field(const char *type, const char *name, const char *
return ret;
}
- node = xmldoc_get_node(type, name, documentation_language);
+ node = xmldoc_get_node(type, name, module, documentation_language);
if (!node) {
ast_log(LOG_WARNING, "Couldn't find %s %s in XML documentation\n", type, name);
@@ -1806,14 +1856,14 @@ static char *xmldoc_build_field(const char *type, const char *name, const char *
return ret;
}
-char *ast_xmldoc_build_synopsis(const char *type, const char *name)
+char *ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
{
- return xmldoc_build_field(type, name, "synopsis", 1);
+ return xmldoc_build_field(type, name, module, "synopsis", 1);
}
-char *ast_xmldoc_build_description(const char *type, const char *name)
+char *ast_xmldoc_build_description(const char *type, const char *name, const char *module)
{
- return xmldoc_build_field(type, name, "description", 0);
+ return xmldoc_build_field(type, name, module, "description", 0);
}
#if !defined(HAVE_GLOB_NOMAGIC) || !defined(HAVE_GLOB_BRACE) || defined(DEBUG_NONGNU)
diff --git a/res/res_agi.c b/res/res_agi.c
index d9c45e94d..edb7b9c38 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -3147,10 +3147,10 @@ int AST_OPTIONAL_API_NAME(ast_agi_register)(struct ast_module *mod, agi_command
*((enum ast_doc_src *) &cmd->docsrc) = AST_STATIC_DOC;
if (ast_strlen_zero(cmd->summary) && ast_strlen_zero(cmd->usage)) {
#ifdef AST_XML_DOCS
- *((char **) &cmd->summary) = ast_xmldoc_build_synopsis("agi", fullcmd);
- *((char **) &cmd->usage) = ast_xmldoc_build_description("agi", fullcmd);
- *((char **) &cmd->syntax) = ast_xmldoc_build_syntax("agi", fullcmd);
- *((char **) &cmd->seealso) = ast_xmldoc_build_seealso("agi", fullcmd);
+ *((char **) &cmd->summary) = ast_xmldoc_build_synopsis("agi", fullcmd, NULL);
+ *((char **) &cmd->usage) = ast_xmldoc_build_description("agi", fullcmd, NULL);
+ *((char **) &cmd->syntax) = ast_xmldoc_build_syntax("agi", fullcmd, NULL);
+ *((char **) &cmd->seealso) = ast_xmldoc_build_seealso("agi", fullcmd, NULL);
*((enum ast_doc_src *) &cmd->docsrc) = AST_XML_DOC;
#endif
#ifndef HAVE_NULLSAFE_PRINTF
diff --git a/res/res_fax.c b/res/res_fax.c
index c3c5a2ed6..468a2de6b 100644
--- a/res/res_fax.c
+++ b/res/res_fax.c
@@ -84,7 +84,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/translate.h"
/*** DOCUMENTATION
- <application name="ReceiveFAX" language="en_US">
+ <application name="ReceiveFAX" language="en_US" module="res_fax">
<synopsis>
Receive a FAX and save as a TIFF/F file.
</synopsis>
@@ -116,7 +116,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<ref type="function">FAXOPT</ref>
</see-also>
</application>
- <application name="SendFAX" language="en_US">
+ <application name="SendFAX" language="en_US" module="res_fax">
<synopsis>
Sends a specified TIFF/F file as a FAX.
</synopsis>
@@ -155,7 +155,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<ref type="function">FAXOPT</ref>
</see-also>
</application>
- <function name="FAXOPT" language="en_US">
+ <function name="FAXOPT" language="en_US" module="res_fax">
<synopsis>
Gets/sets various pieces of information about a fax session.
</synopsis>