[asterisk-commits] mnicholson: branch 1.8 r340108 - in /branches/1.8: apps/ doc/ include/asteris...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Oct 10 09:14:55 CDT 2011


Author: mnicholson
Date: Mon Oct 10 09:14:48 2011
New Revision: 340108

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=340108
Log:
Load the proper XML documentation when multiple modules document the same application.

This patch adds an optional "module" attribute to the XML documentation spec
that allows the documentation processor to match apps with identical names from
different modules to their documentation. This patch also fixes a number of
bugs with the documentation processor and should make it a little more
efficient. Support for multiple languages has also been properly implemented.

ASTERISK-18130
Review: https://reviewboard.asterisk.org/r/1485/

Modified:
    branches/1.8/apps/app_fax.c
    branches/1.8/doc/appdocsxml.dtd
    branches/1.8/include/asterisk/module.h
    branches/1.8/include/asterisk/xmldoc.h
    branches/1.8/main/loader.c
    branches/1.8/main/manager.c
    branches/1.8/main/pbx.c
    branches/1.8/main/xmldoc.c
    branches/1.8/res/res_agi.c
    branches/1.8/res/res_fax.c

Modified: branches/1.8/apps/app_fax.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/apps/app_fax.c?view=diff&rev=340108&r1=340107&r2=340108
==============================================================================
--- branches/1.8/apps/app_fax.c (original)
+++ branches/1.8/apps/app_fax.c Mon Oct 10 09:14:48 2011
@@ -46,7 +46,7 @@
 #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 @@
 			</variablelist>
 		</description>
 	</application>
-	<application name="ReceiveFAX" language="en_US">
+	<application name="ReceiveFAX" language="en_US" module="app_fax">
 		<synopsis>
 			Receive a Fax
 		</synopsis>

Modified: branches/1.8/doc/appdocsxml.dtd
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/doc/appdocsxml.dtd?view=diff&rev=340108&r1=340107&r2=340108
==============================================================================
--- branches/1.8/doc/appdocsxml.dtd (original)
+++ branches/1.8/doc/appdocsxml.dtd Mon Oct 10 09:14:48 2011
@@ -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>

Modified: branches/1.8/include/asterisk/module.h
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/include/asterisk/module.h?view=diff&rev=340108&r1=340107&r2=340108
==============================================================================
--- branches/1.8/include/asterisk/module.h (original)
+++ branches/1.8/include/asterisk/module.h Mon Oct 10 09:14:48 2011
@@ -174,6 +174,14 @@
 /* Opaque type for module handles generated by the loader */
 
 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

Modified: branches/1.8/include/asterisk/xmldoc.h
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/include/asterisk/xmldoc.h?view=diff&rev=340108&r1=340107&r2=340108
==============================================================================
--- branches/1.8/include/asterisk/xmldoc.h (original)
+++ branches/1.8/include/asterisk/xmldoc.h Mon Oct 10 09:14:48 2011
@@ -36,29 +36,32 @@
  *  \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 @@
  *  \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 */
 

Modified: branches/1.8/main/loader.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/main/loader.c?view=diff&rev=340108&r1=340107&r2=340108
==============================================================================
--- branches/1.8/main/loader.c (original)
+++ branches/1.8/main/loader.c Mon Oct 10 09:14:48 2011
@@ -95,6 +95,15 @@
 };
 
 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

Modified: branches/1.8/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/main/manager.c?view=diff&rev=340108&r1=340107&r2=340108
==============================================================================
--- branches/1.8/main/manager.c (original)
+++ branches/1.8/main/manager.c Mon Oct 10 09:14:48 2011
@@ -5069,23 +5069,23 @@
 	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);
 

Modified: branches/1.8/main/pbx.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/main/pbx.c?view=diff&rev=340108&r1=340107&r2=340108
==============================================================================
--- branches/1.8/main/pbx.c (original)
+++ branches/1.8/main/pbx.c Mon Oct 10 09:14:48 2011
@@ -3411,27 +3411,27 @@
 	}
 
 	/* 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);
 
@@ -5682,31 +5682,35 @@
 		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;
@@ -5718,10 +5722,6 @@
 		tmp->docsrc = AST_STATIC_DOC;
 	}
 #endif
-
-	strcpy(tmp->name, app);
-	tmp->execute = execute;
-	tmp->module = mod;
 
 	/* Store in alphabetical order */
 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {

Modified: branches/1.8/main/xmldoc.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/main/xmldoc.c?view=diff&rev=340108&r1=340107&r2=340108
==============================================================================
--- branches/1.8/main/xmldoc.c (original)
+++ branches/1.8/main/xmldoc.c Mon Oct 10 09:14:48 2011
@@ -456,46 +456,96 @@
 }
 
 /*! \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 (node && ast_xml_node_get_children(node)) {
+			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 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 @@
 	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 @@
 	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 @@
 	}
 
 	/* 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 @@
 	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 @@
 		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 @@
  *  \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 @@
 		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 @@
 	return ret;
 }
 
-char *ast_xmldoc_build_synopsis(const char *type, const char *name)
-{
-	return xmldoc_build_field(type, name, "synopsis", 1);
-}
-
-char *ast_xmldoc_build_description(const char *type, const char *name)
-{
-	return xmldoc_build_field(type, name, "description", 0);
+char *ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
+{
+	return xmldoc_build_field(type, name, module, "synopsis", 1);
+}
+
+char *ast_xmldoc_build_description(const char *type, const char *name, const char *module)
+{
+	return xmldoc_build_field(type, name, module, "description", 0);
 }
 
 #if !defined(HAVE_GLOB_NOMAGIC) || !defined(HAVE_GLOB_BRACE) || defined(DEBUG_NONGNU)

Modified: branches/1.8/res/res_agi.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/res/res_agi.c?view=diff&rev=340108&r1=340107&r2=340108
==============================================================================
--- branches/1.8/res/res_agi.c (original)
+++ branches/1.8/res/res_agi.c Mon Oct 10 09:14:48 2011
@@ -3129,10 +3129,10 @@
 		*((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

Modified: branches/1.8/res/res_fax.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/res/res_fax.c?view=diff&rev=340108&r1=340107&r2=340108
==============================================================================
--- branches/1.8/res/res_fax.c (original)
+++ branches/1.8/res/res_fax.c Mon Oct 10 09:14:48 2011
@@ -64,7 +64,7 @@
 #include "asterisk/ast_version.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>
@@ -93,7 +93,7 @@
 			<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>
@@ -129,7 +129,7 @@
 			<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>




More information about the asterisk-commits mailing list