[svn-commits] eliel: branch group/appdocsxml r150561 - in /team/group/appdocsxml: ./ includ...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Oct 17 10:56:59 CDT 2008


Author: eliel
Date: Fri Oct 17 10:56:59 2008
New Revision: 150561

URL: http://svn.digium.com/view/asterisk?view=rev&rev=150561
Log:
Implements reading XML documentation from $(ASTDATADIR)/documentation & /documentation/thirdparty.
Every file named *-LANG.xml will be loaded from this directories where LANG is the actual language choice from asterisk.conf
option 'documentation_language'.
When searching for the documentation we look inside every loaded XML file.
Moved ast_load_documentation() from main/pbx.c to main/asterisk.c (this will fix the issue that appear in preloaded modules).
Fix a missing Synopsis in application 'Wait'.


Modified:
    team/group/appdocsxml/Makefile
    team/group/appdocsxml/include/asterisk/compat.h
    team/group/appdocsxml/include/asterisk/pbx.h
    team/group/appdocsxml/main/asterisk.c
    team/group/appdocsxml/main/config.c
    team/group/appdocsxml/main/pbx.c

Modified: team/group/appdocsxml/Makefile
URL: http://svn.digium.com/view/asterisk/team/group/appdocsxml/Makefile?view=diff&rev=150561&r1=150560&r2=150561
==============================================================================
--- team/group/appdocsxml/Makefile (original)
+++ team/group/appdocsxml/Makefile Fri Oct 17 10:56:59 2008
@@ -492,7 +492,7 @@
 		done ; \
 	done
 	@echo "</docs>" >> doc/core-en_US.xml
-	@echo -e "\ndoc/core-en_US.xml --> $(ASTVARLIBDIR)/core-en_US.xml"
+	@echo -e "\ndoc/core-en_US.xml --> $(ASTDATADIR)/documentation/core-en_US.xml"
 
 update: 
 	@if [ -d .svn ]; then \
@@ -542,14 +542,16 @@
 	if [ -n "$(OLDHEADERS)" ]; then \
 		rm -f $(addprefix $(DESTDIR)$(ASTHEADERDIR)/,$(OLDHEADERS)) ;\
 	fi
+	mkdir -p $(DESTDIR)$(ASTDATADIR)/documentation
+	mkdir -p $(DESTDIR)$(ASTDATADIR)/documentation/thirdparty
 	mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-csv
 	mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-custom
 	mkdir -p $(DESTDIR)$(ASTDATADIR)/keys
 	mkdir -p $(DESTDIR)$(ASTDATADIR)/firmware
 	mkdir -p $(DESTDIR)$(ASTDATADIR)/firmware/iax
 	mkdir -p $(DESTDIR)$(ASTMANDIR)/man8
-	$(INSTALL) -m 644 doc/core-*.xml $(ASTVARLIBDIR) 
-	$(INSTALL) -m 644 doc/appdocsxml.dtd $(ASTVARLIBDIR)
+	$(INSTALL) -m 644 doc/core-*.xml $(ASTDATADIR)/documentation
+	$(INSTALL) -m 644 doc/appdocsxml.dtd $(ASTVARLIBDIR)/documentation
 	$(INSTALL) -m 644 keys/iaxtel.pub $(DESTDIR)$(ASTDATADIR)/keys
 	$(INSTALL) -m 644 keys/freeworlddialup.pub $(DESTDIR)$(ASTDATADIR)/keys
 	$(INSTALL) -m 644 doc/asterisk.8 $(DESTDIR)$(ASTMANDIR)/man8

Modified: team/group/appdocsxml/include/asterisk/compat.h
URL: http://svn.digium.com/view/asterisk/team/group/appdocsxml/include/asterisk/compat.h?view=diff&rev=150561&r1=150560&r2=150561
==============================================================================
--- team/group/appdocsxml/include/asterisk/compat.h (original)
+++ team/group/appdocsxml/include/asterisk/compat.h Fri Oct 17 10:56:59 2008
@@ -182,4 +182,15 @@
 typedef unsigned long long uint64_t;
 #endif
 
+/* glob compat stuff */ 
+#if defined(__Darwin__) || defined(__CYGWIN__)
+#define GLOB_ABORTED GLOB_ABEND
 #endif
+#include <glob.h>
+#ifdef SOLARIS
+#define MY_GLOB_FLAGS   GLOB_NOCHECK
+#else
+#define MY_GLOB_FLAGS   (GLOB_NOMAGIC|GLOB_BRACE)
+#endif
+
+#endif

Modified: team/group/appdocsxml/include/asterisk/pbx.h
URL: http://svn.digium.com/view/asterisk/team/group/appdocsxml/include/asterisk/pbx.h?view=diff&rev=150561&r1=150560&r2=150561
==============================================================================
--- team/group/appdocsxml/include/asterisk/pbx.h (original)
+++ team/group/appdocsxml/include/asterisk/pbx.h Fri Oct 17 10:56:59 2008
@@ -1019,6 +1019,9 @@
 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
 unsigned int ast_hashtab_hash_contexts(const void *obj);
 
+/*! \brief Load XML documentation. */
+int ast_load_documentation(void);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: team/group/appdocsxml/main/asterisk.c
URL: http://svn.digium.com/view/asterisk/team/group/appdocsxml/main/asterisk.c?view=diff&rev=150561&r1=150560&r2=150561
==============================================================================
--- team/group/appdocsxml/main/asterisk.c (original)
+++ team/group/appdocsxml/main/asterisk.c Fri Oct 17 10:56:59 2008
@@ -117,6 +117,7 @@
 #include "asterisk/devicestate.h"
 #include "asterisk/module.h"
 #include "asterisk/dsp.h"
+#include "asterisk/xml.h"
 
 #include "asterisk/doxyref.h"		/* Doxygen documentation */
 
@@ -3328,6 +3329,11 @@
 		exit(1);
 	}
 
+#ifdef XML_DOCUMENTATION
+	/* Load XML documentation. */
+	ast_load_documentation();
+#endif
+
 	if (load_modules(1)) {		/* Load modules, pre-load only */
 		printf("%s", term_quit());
 		exit(1);

Modified: team/group/appdocsxml/main/config.c
URL: http://svn.digium.com/view/asterisk/team/group/appdocsxml/main/config.c?view=diff&rev=150561&r1=150560&r2=150561
==============================================================================
--- team/group/appdocsxml/main/config.c (original)
+++ team/group/appdocsxml/main/config.c Fri Oct 17 10:56:59 2008
@@ -38,24 +38,6 @@
 #include <math.h>	/* HUGE_VAL */
 
 #define AST_INCLUDE_GLOB 1
-
-#ifdef AST_INCLUDE_GLOB
-/* glob compat stuff - eventually this should go in compat.h or some
- * header in include/asterisk/
- */
-#if defined(__Darwin__) || defined(__CYGWIN__)
-#define GLOB_ABORTED GLOB_ABEND
-#endif
-
-#include <glob.h>
-
-#ifdef SOLARIS
-#define MY_GLOB_FLAGS	GLOB_NOCHECK
-#else
-#define MY_GLOB_FLAGS	(GLOB_NOMAGIC|GLOB_BRACE)
-#endif
-
-#endif
 
 #include "asterisk/config.h"
 #include "asterisk/cli.h"

Modified: team/group/appdocsxml/main/pbx.c
URL: http://svn.digium.com/view/asterisk/team/group/appdocsxml/main/pbx.c?view=diff&rev=150561&r1=150560&r2=150561
==============================================================================
--- team/group/appdocsxml/main/pbx.c (original)
+++ team/group/appdocsxml/main/pbx.c Fri Oct 17 10:56:59 2008
@@ -555,6 +555,7 @@
 	</application>
 	<application name="Wait" language="en_US">
 		<synopsis>
+			Waits for some time.
 		</synopsis>
 		<syntax>
 			<parameter name="seconds" required="true">
@@ -825,11 +826,16 @@
 #ifdef XML_DOCUMENTATION
 #define DEFAULT_DOCUMENTATION_LANGUAGE "en_US"
 #define XMLDOC_TEXT_COLUMNS 74
-#define XMLDOC_MAX_DIFF 5 
+#define XMLDOC_MAX_DIFF 5
 /*! \brief XML documentation language. */
 static char documentation_language[80];
 /*! \brief XML documentation tree. */
-static ast_xml_doc *documentation_tree = NULL;
+struct documentation_tree {
+	char *filename;
+	ast_xml_doc *doc;
+	AST_LIST_ENTRY(documentation_tree) entry;
+};
+static AST_LIST_HEAD_STATIC(xmldoc_tree, documentation_tree);
 #endif
 
 static int pbx_builtin_answer(struct ast_channel *, void *);
@@ -3434,49 +3440,55 @@
 /*! \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.
- *  \param doc XML documentation tree structure.
  *  \param type 'application', 'function', ...
  *  \param name Application or Function name.
  *  \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 ast_xml_node *xmldoc_get_node(ast_xml_doc *doc, const char *type, const char *name, const char *language)
+static ast_xml_node *xmldoc_get_node(const char *type, const char *name, const char *language)
 {
 	ast_xml_node *node;
+	struct documentation_tree *doctree;
 	char *lang;
 
-	node = ast_xml_get_root(doc);
-	if (!node) {
-		ast_log(LOG_ERROR, "No XML root node found while reading %s %s documentation\n", name, type);
-		return NULL;
-	}
-	node = node->AST_XML_CHILD;
-	while (node) {
-		node = ast_xml_find_element(node, type, "name", name);
-		if (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);
-			}
-			node = node->AST_XML_NEXT;
-		}
-	}
-
-	if (!node || !node->AST_XML_CHILD) {
-		/* We didn't find the application documentation for the specified language,
-		so, try to load documentation for any language */
-		node = ast_xml_get_root(documentation_tree);
-		if (node && node->AST_XML_CHILD) {
-			node = ast_xml_find_element(node->AST_XML_CHILD, type, "name", name);
-		}
-	}
-
-	return node;
+	AST_LIST_LOCK(&xmldoc_tree);
+	AST_LIST_TRAVERSE(&xmldoc_tree, doctree, entry) {
+
+		node = ast_xml_get_root(doctree->doc);
+		node = node->AST_XML_CHILD;
+		while (node) {
+			node = ast_xml_find_element(node, type, "name", name);
+			if (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);
+				}
+				node = node->AST_XML_NEXT;
+			}
+		}
+		if (!node || !node->AST_XML_CHILD) {
+			/* 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 (node->AST_XML_CHILD) {
+				if ((node = ast_xml_find_element(node->AST_XML_CHILD, type, "name", name))) {
+					AST_LIST_UNLOCK(&xmldoc_tree);
+					return node;
+				}
+			}
+		} else {
+			AST_LIST_UNLOCK(&xmldoc_tree);
+			return node;
+		}
+	}
+	AST_LIST_UNLOCK(&xmldoc_tree);
+
+	return NULL;
 }
 
 /*! \internal
@@ -3784,7 +3796,7 @@
 	ast_xml_node *node;
 	char *syntax = NULL;
 
-	node = xmldoc_get_node(documentation_tree, type, name, documentation_language);
+	node = xmldoc_get_node(type, name, documentation_language);
 	if (!node || !node->AST_XML_CHILD) {
 		return NULL;
 	}
@@ -4096,7 +4108,7 @@
 	}
 
 	/* get the application/function root node. */
-	node = xmldoc_get_node(documentation_tree, type, name, documentation_language);	
+	node = xmldoc_get_node(type, name, documentation_language);	
 	if (!node || !node->AST_XML_CHILD) {
 		return NULL;
 	}
@@ -4402,7 +4414,7 @@
 		return NULL;
 	}
 
-	node = xmldoc_get_node(documentation_tree, type, name, documentation_language);
+	node = xmldoc_get_node(type, name, documentation_language);
 	
 	if (!node || !node->AST_XML_CHILD) {
 		return NULL;
@@ -4506,20 +4518,14 @@
 	struct ast_str *formatted;
 
 	if (ast_strlen_zero(type) || ast_strlen_zero(name)) {
-		ast_log(LOG_WARNING, "Tried to look in XML tree with faulty values.\n");
+		ast_log(LOG_ERROR, "Tried to look in XML tree with faulty values.\n");
 		return ret;
 	}
 
-	/* not fully initted yet */
-	if (!documentation_tree) {
-		ast_log(LOG_DEBUG, "Parsing Documentation XML Error\n");
-		return ret; 
-	}
-
-	node = xmldoc_get_node(documentation_tree, type, name, documentation_language);
+	node = xmldoc_get_node(type, name, documentation_language);
 		
 	if (!node) {
-		ast_log(LOG_ERROR, "Counldn't find %s %s in XML documentation\n", type, name);
+		ast_log(LOG_WARNING, "Counldn't find %s %s in XML documentation\n", type, name);
 		return ret;
 	}
 
@@ -6308,59 +6314,101 @@
 }
 
 #ifdef XML_DOCUMENTATION
-
-/*! \brief Load XML Document into buffer for parsing into a list.
- *  \retval 1 on error.
- *  \retval 0 on success.
- */
-static int ast_load_documentation(void) 
+int ast_load_documentation(void) 
 {
 	ast_xml_node *root_node;
-	char *path;
-
-	documentation_tree = NULL;
-
-	/* Initialize the libxml*/
+	ast_xml_doc *tmpdoc;
+	struct documentation_tree *doc_tree;
+	char *xmlpattern;
+	struct ast_config *cfg = NULL;
+	struct ast_variable *var = NULL;
+	struct ast_flags cnfflags = { 0 };
+	int globret, i;
+	glob_t globbuf;
+
+	/* setup default XML documentation language */
+	snprintf(documentation_language, sizeof(documentation_language), DEFAULT_DOCUMENTATION_LANGUAGE);
+
+	if (!(cfg = ast_config_load("asterisk.conf", cnfflags))) {
+		ast_log(LOG_ERROR, "No asterisk.conf? That cannot be good.\n");
+	}
+
+	for (var = ast_variable_browse(cfg, "options"); var; var = var->next) {
+		if (!strcasecmp(var->name, "documentation_language")) {
+			if (!ast_strlen_zero(var->value)) {
+				snprintf(documentation_language, sizeof(documentation_language), "%s", var->value);
+			}	
+		}
+	}
+        ast_config_destroy(cfg);
+
+	/* initialize the XML library. */
 	ast_xml_init();
 
-	/* This memory is automagically freed */
-	path = alloca(strlen(ast_config_AST_DATA_DIR) + strlen(documentation_language) + strlen("/core-.xml") + 1);
-	sprintf(path, "%s/core-%s.xml", ast_config_AST_DATA_DIR, documentation_language);
-
-	documentation_tree = ast_xml_open(path);
-
-	if (!documentation_tree) {
-		ast_log(LOG_ERROR, "Could not open XML Doc at '%s'\n", path);
-		if (!strcmp(documentation_language, "en_US")) {
-			ast_xml_finish();
-			return 1;
-		}
-		path = alloca(strlen(ast_config_AST_DATA_DIR) + strlen("en_US") + strlen("/core-.xml") + 1);
-		sprintf(path, "%s/core-%s.xml", ast_config_AST_DATA_DIR, "en_US");
-		ast_log(LOG_WARNING, "Trying to load documentation XML in '%s'\n", path);
-		if (!(documentation_tree = ast_xml_open(path))) {
-			ast_log(LOG_WARNING, "Also failed trying to load default documentation\n");
-			ast_xml_finish();
-			return 1;
-		}
-		
-	}
-
-	/* Get doc root node and check if it starts with '<doc>' */
-	root_node = ast_xml_get_root(documentation_tree);
-	if (!root_node) {
-		ast_log(LOG_ERROR, "Error getting documentation root node");
-		ast_xml_close(documentation_tree);
-		ast_xml_finish();
+	/* Get every *-LANG.xml file inside $(ASTDATADIR)/documentation */
+	ast_asprintf(&xmlpattern, "%s/documentation/*-%s.xml", ast_config_AST_DATA_DIR, documentation_language);	
+	globbuf.gl_offs = 0;    /* initialize it to silence gcc */
+	globret = glob(xmlpattern, MY_GLOB_FLAGS, NULL, &globbuf);
+	if (globret == GLOB_NOSPACE) {
+		ast_log(LOG_WARNING, "Glob Expansion of pattern '%s' failed: Not enough memory\n", xmlpattern);
+		ast_free(xmlpattern);
 		return 1;
-	}
-		
-	if (strcmp((char *)root_node->AST_XML_NAME, "docs")) {
-		ast_log(LOG_ERROR, "Documentation file is not well formed!\n");
-		ast_xml_close(documentation_tree);
-		ast_xml_finish();
+	} else if (globret  == GLOB_ABORTED) {
+		ast_log(LOG_WARNING, "Glob Expansion of pattern '%s' failed: Read error\n", xmlpattern);
+		ast_free(xmlpattern);
 		return 1;
 	}
+
+	/* Get every *-LANG.xml file inside $(ASTDATADIR)/documentation/thirdparty */
+	ast_free(xmlpattern);
+	ast_asprintf(&xmlpattern, "%s/documentation/thirdparty/*-%s.xml", ast_config_AST_DATA_DIR, documentation_language);
+	globret = glob(xmlpattern, MY_GLOB_FLAGS | GLOB_APPEND, NULL, &globbuf);
+	if (globret == GLOB_NOSPACE) {
+		ast_log(LOG_WARNING, "Glob Expansion of pattern '%s' failed: Not enough memory\n", xmlpattern);
+		ast_free(xmlpattern);
+		globfree(&globbuf);
+		return 1;
+	} else if (globret  == GLOB_ABORTED) {
+		ast_log(LOG_WARNING, "Glob Expansion of pattern '%s' failed: Read error\n", xmlpattern);
+		ast_free(xmlpattern);
+		globfree(&globbuf);
+		return 1;
+	}
+	AST_LIST_LOCK(&xmldoc_tree);
+	/* loop over expanded files */
+	for (i = 0; i < globbuf.gl_pathc; i++) {
+		tmpdoc = NULL;
+		tmpdoc = ast_xml_open(globbuf.gl_pathv[i]);
+		if (!tmpdoc) {
+			ast_log(LOG_ERROR, "Could not open XML documentation at '%s'\n", globbuf.gl_pathv[i]);
+			continue;
+		}
+		/* Get doc root node and check if it starts with '<docs>' */
+		root_node = ast_xml_get_root(tmpdoc);
+		if (!root_node) {
+			ast_log(LOG_ERROR, "Error getting documentation root node");
+			ast_xml_close(tmpdoc);
+			continue;
+		}
+		/* Check root node name for malformed xmls. */
+		if (strcmp((char *)root_node->AST_XML_NAME, "docs")) {
+			ast_log(LOG_ERROR, "Documentation file is not well formed!\n");
+			ast_xml_close(tmpdoc);
+			continue;
+		}
+		doc_tree = ast_calloc(1, sizeof(*doc_tree));
+		if (!doc_tree) {
+			ast_log(LOG_ERROR, "Unable to allocate documentation_tree structure!\n");
+			continue;
+		}
+		doc_tree->doc = tmpdoc;
+		doc_tree->filename = ast_strdup(globbuf.gl_pathv[i]);
+		AST_LIST_INSERT_TAIL(&xmldoc_tree, doc_tree, entry);
+	}
+	AST_LIST_UNLOCK(&xmldoc_tree);
+
+	globfree(&globbuf);
+	ast_free(xmlpattern);
 
 	return 0;
 }
@@ -10439,32 +10487,6 @@
 int load_pbx(void)
 {
 	int x;
-#ifdef XML_DOCUMENTATION
-	struct ast_config *cfg = NULL;
-	struct ast_variable *var = NULL;
-	struct ast_flags cnfflags = { 0 };
-#endif
-
-#ifdef XML_DOCUMENTATION
-	/* setup default language */
-	snprintf(documentation_language, sizeof(documentation_language), DEFAULT_DOCUMENTATION_LANGUAGE);
-
-	if (!(cfg = ast_config_load("asterisk.conf", cnfflags))) {
-		ast_log(LOG_ERROR, "No asterisk.conf? That cannot be good.\n");
-	}
-	
-	for (var = ast_variable_browse(cfg, "options"); var; var = var->next) {
-		if (!strcasecmp(var->name, "documentation_language")) {
-			if (!ast_strlen_zero(var->value)) {
-				snprintf(documentation_language, sizeof(documentation_language), "%s", var->value);
-			}
-		}	
-	}
-	ast_config_destroy(cfg);
-
-	/* Load Documentation XML Blob */
-	ast_load_documentation();
-#endif
 
 	/* Initialize the PBX */
 	ast_verb(1, "Asterisk PBX Core Initializing\n");




More information about the svn-commits mailing list