[asterisk-commits] twilson: branch twilson/config_docs r370226 - in /team/twilson/config_docs: a...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jul 18 15:10:26 CDT 2012


Author: twilson
Date: Wed Jul 18 15:10:22 2012
New Revision: 370226

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=370226
Log:
Just a checkin before trying some...changes

Modified:
    team/twilson/config_docs/apps/app_skel.c
    team/twilson/config_docs/doc/appdocsxml.dtd
    team/twilson/config_docs/include/asterisk/_private.h
    team/twilson/config_docs/include/asterisk/config_options.h
    team/twilson/config_docs/include/asterisk/xmldoc.h
    team/twilson/config_docs/main/asterisk.c
    team/twilson/config_docs/main/config_options.c
    team/twilson/config_docs/main/xmldoc.c

Modified: team/twilson/config_docs/apps/app_skel.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_docs/apps/app_skel.c?view=diff&rev=370226&r1=370225&r2=370226
==============================================================================
--- team/twilson/config_docs/apps/app_skel.c (original)
+++ team/twilson/config_docs/apps/app_skel.c Wed Jul 18 15:10:22 2012
@@ -77,6 +77,69 @@
 		from. It shows you the basic structure to create your own Asterisk applications.</para>
 		</description>
 	</application>
+
+	<configInfo module="app_skel" language="en_US">
+		<configObject name="globals">
+			<synopsis>Options that apply globally to app_skel</synopsis>
+			<category match="true" exact="true">^general$</category>
+		</configObject>
+		<configObject name="sounds">
+			<synopsis>Prompts for SkelGuessNumber to play</synopsis>
+			<category match="true">^sounds$</category>
+		</configObject>
+		<configObject name="level">
+			<synopsis>Defined levels for the SkelGuessNumber game</synopsis>
+			<category match="false">^(general|sounds)$</category>
+		</configObject>
+
+		<configFile name="app_skel.conf">
+			<hasObject ref="globals"/>
+			<hasObject ref="sounds"/>
+			<hasObject ref="level"/>
+		</configFile>
+
+		<configOption name="games" objectType="globals" default="3">
+			<synopsis>The number of games a single execution of SkelGuessNumber will play</synopsis>
+			<dataType type="uint" min="1" max="1000"/>
+		</configOption>
+		<configOption name="cheat" objectType="globals" default="no">
+			<synopsis>Should the computer cheat?</synopsis>
+			<description><para>If enabled, the computer will ignore winning guesses.</para></description> 
+			<dataType type="boolean"/>
+		</configOption>
+		<configOption name="prompt" objectType="sounds" default="please-enter-your&amp;number&amp;queue-less-than">
+			<synopsis>A prompt directing the user to enter a number less than the max number</synopsis>
+			<dataType type="string"/>
+		</configOption>
+		<configOption name="wrong_guess" objectType="sounds" default="vm-pls-try-again">
+			<synopsis>The sound file to play when a wrong guess is made</synopsis>
+			<dataType type="string"/>
+		</configOption>
+		<configOption name="right_guess" objectType="sounds" default="auth-thankyou">
+			<synopsis>The sound file to play when a correct guess is made</synopsis>
+			<dataType type="string"/>
+		</configOption>
+		<configOption name="too_low" objectType="sounds" default="low">
+			<synopsis>The sound file to play when a guess is too low</synopsis>
+			<dataType type="string"/>
+		</configOption>
+		<configOption name="too_high" objectType="sounds" default="high">
+			<synopsis>The sound file to play when a guess is too high</synopsis>
+			<dataType type="string"/>
+		</configOption>
+		<configOption name="lose" objectType="sounds" default="vm-goodbye">
+			<synopsis>The sound file to play when a player loses</synopsis>
+			<dataType type="string"/>
+		</configOption>
+		<configOption name="max_number" objectType="level">
+			<synopsis>The maximum in the range of numbers to guess (1 is the implied minimum)</synopsis>
+			<dataType type="uint"/>
+		</configOption>
+		<configOption name="max_guesses" objectType="level">
+			<synopsis>The maximum number of guesses before a game is considered lost</synopsis>
+			<dataType type="uint"/>
+		</configOption>
+	</configInfo>
  ***/
 
 static char *app = "SkelGuessNumber";
@@ -188,6 +251,7 @@
 /*! \brief An aco_type structure to link the "general" category to the skel_global_config type */
 static struct aco_type global_option = {
 	.type = ACO_GLOBAL,
+	.name = "globals",
 	.item_offset = offsetof(struct skel_config, global),
 	.category_match = ACO_WHITELIST,
 	.category = "^general$",
@@ -198,6 +262,7 @@
 /*! \brief An aco_type structure to link the "sounds" category to the skel_global_config type */
 static struct aco_type sound_option = {
 	.type = ACO_GLOBAL,
+	.name = "sounds",
 	.item_offset = offsetof(struct skel_config, global),
 	.category_match = ACO_WHITELIST,
 	.category = "^sounds$",
@@ -208,6 +273,7 @@
 /*! \brief An aco_type structure to link the everything but the "general" and "sounds" categories to the skel_level type */
 static struct aco_type level_option = {
 	.type = ACO_ITEM,
+	.name = "level",
 	.category_match = ACO_BLACKLIST,
 	.category = "^(general|sounds)$",
 	.item_alloc = skel_level_alloc,

Modified: team/twilson/config_docs/doc/appdocsxml.dtd
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_docs/doc/appdocsxml.dtd?view=diff&rev=370226&r1=370225&r2=370226
==============================================================================
--- team/twilson/config_docs/doc/appdocsxml.dtd (original)
+++ team/twilson/config_docs/doc/appdocsxml.dtd Wed Jul 18 15:10:22 2012
@@ -1,4 +1,4 @@
-  <!ELEMENT docs (application|function|agi|manager|managerEvent)*>
+  <!ELEMENT docs (application|function|agi|manager|managerEvent|configInfo)*>
   <!ATTLIST docs xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude">
 
   <!ELEMENT xi:include (xi:fallback?) >
@@ -36,12 +36,39 @@
   <!ELEMENT managerEventInstance (synopsis?,syntax?,description?,see-also?)*>
   <!ATTLIST managerEventInstance class CDATA #REQUIRED>
 
+  <!ELEMENT configInfo (configObject*,configFile*,configOption*)>
+  <!ATTLIST configInfo module CDATA #REQUIRED>
+  <!ATTLIST configInfo language CDATA #REQUIRED>
+
+  <!ELEMENT configObject (synopsis?,category?)*>
+  <!ATTLIST configObject name ID #REQUIRED>
+
+  <!ELEMENT configOption (synopsis,description?,dataType?)*>
+  <!ATTLIST configOption name CDATA #REQUIRED>
+  <!ATTLIST configOption objectType IDREF #REQUIRED>
+  <!ATTLIST configOption default CDATA #IMPLIED>
+
+  <!ELEMENT configFile (hasObject?)*>
+  <!ATTLIST configFile name CDATA #REQUIRED>
+
+  <!ELEMENT hasObject EMPTY>
+  <!ATTLIST hasObject ref IDREF #REQUIRED>
+
   <!ELEMENT see-also (ref|xi:include)*>
 
   <!ELEMENT ref (#PCDATA)>
   <!ATTLIST ref type (application|function|astcli|link|manpage|filename|agi|manager|managerEvent) #REQUIRED>
 
   <!ELEMENT synopsis (#PCDATA)>
+
+  <!ELEMENT category (#PCDATA)>
+  <!ATTLIST category match CDATA #IMPLIED>
+  <!ATTLIST category exact CDATA #IMPLIED>
+
+  <!ELEMENT dataType EMPTY>
+  <!ATTLIST dataType type (string|uint|integer|boolean|float|enum) #REQUIRED>
+  <!ATTLIST dataType max CDATA #IMPLIED>
+  <!ATTLIST dataType min CDATA #IMPLIED>
 
   <!ELEMENT syntax (parameter|xi:include)*>
   <!ATTLIST syntax argsep CDATA ",">

Modified: team/twilson/config_docs/include/asterisk/_private.h
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_docs/include/asterisk/_private.h?view=diff&rev=370226&r1=370225&r2=370226
==============================================================================
--- team/twilson/config_docs/include/asterisk/_private.h (original)
+++ team/twilson/config_docs/include/asterisk/_private.h Wed Jul 18 15:10:22 2012
@@ -48,6 +48,7 @@
 int ast_ssl_init(void);                 /*!< Provided by ssl.c */
 int ast_test_init(void);            /*!< Provided by test.c */
 int ast_msg_init(void);             /*!< Provided by message.c */
+int aco_init(void);              /*!< Provided by config_options.c */
 
 /*!
  * \brief Reload asterisk modules.

Modified: team/twilson/config_docs/include/asterisk/config_options.h
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_docs/include/asterisk/config_options.h?view=diff&rev=370226&r1=370225&r2=370226
==============================================================================
--- team/twilson/config_docs/include/asterisk/config_options.h (original)
+++ team/twilson/config_docs/include/asterisk/config_options.h Wed Jul 18 15:10:22 2012
@@ -109,6 +109,7 @@
 struct aco_type {
 	/* common stuff */
 	enum aco_type_t type;   /*!< Whether this is a global or item type */
+	const char *name;       /*!< The name of this type (must match XML documentation) */
 	const char *category;   /*!< A regular expression for matching categories to be allowed or denied */
 	const char *matchfield; /*!< An option name to match for this type (i.e. a 'type'-like column) */
 	const char *matchvalue; /*!< The value of the option to require for matching (i.e. 'peer' for type= in sip.conf) */

Modified: team/twilson/config_docs/include/asterisk/xmldoc.h
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_docs/include/asterisk/xmldoc.h?view=diff&rev=370226&r1=370225&r2=370226
==============================================================================
--- team/twilson/config_docs/include/asterisk/xmldoc.h (original)
+++ team/twilson/config_docs/include/asterisk/xmldoc.h Wed Jul 18 15:10:22 2012
@@ -61,6 +61,8 @@
 		AST_STRING_FIELD(name);
 		/*! The type of the item */
 		AST_STRING_FIELD(type);
+		/*! Need the objectType for configInfo */
+		AST_STRING_FIELD(ref);
 	);
 	/*! The next XML documentation item that matches the same name/item type */
 	struct ast_xml_doc_item *next;

Modified: team/twilson/config_docs/main/asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_docs/main/asterisk.c?view=diff&rev=370226&r1=370225&r2=370226
==============================================================================
--- team/twilson/config_docs/main/asterisk.c (original)
+++ team/twilson/config_docs/main/asterisk.c Wed Jul 18 15:10:22 2012
@@ -4006,6 +4006,8 @@
 	ast_xmldoc_load_documentation();
 #endif
 
+	aco_init();
+
 	if (astdb_init()) {
 		printf("%s", term_quit());
 		exit(1);

Modified: team/twilson/config_docs/main/config_options.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_docs/main/config_options.c?view=diff&rev=370226&r1=370225&r2=370226
==============================================================================
--- team/twilson/config_docs/main/config_options.c (original)
+++ team/twilson/config_docs/main/config_options.c Wed Jul 18 15:10:22 2012
@@ -31,11 +31,14 @@
 
 #include <regex.h>
 
+#include "asterisk/_private.h"
 #include "asterisk/config.h"
 #include "asterisk/config_options.h"
 #include "asterisk/stringfields.h"
 #include "asterisk/acl.h"
 #include "asterisk/frame.h"
+#include "asterisk/xmldoc.h"
+#include "asterisk/cli.h"
 
 #ifdef LOW_MEMORY
 #define CONFIG_OPT_BUCKETS 5
@@ -70,6 +73,8 @@
 	intptr_t args[0];
 };
 
+static struct ao2_container *xmldocs;
+
 void *aco_pending_config(struct aco_info *info)
 {
 	if (!(info && info->internal)) {
@@ -183,12 +188,46 @@
 	return 0;
 }
 
+static int docs_exist(const char *module, struct aco_type **types, const char *name)
+{
+#ifdef AST_XML_DOCS
+	RAII_VAR(struct ast_xml_doc_item *, item, ao2_find(xmldocs, module, OBJ_KEY), ao2_cleanup);
+	struct ast_xml_doc_item *iter = item;
+	if (!item) {
+		return 0;
+	}
+
+	/* First is just the configInfo, we can skip it */
+	while ((iter = iter->next)) {
+		if (!strcasecmp(iter->name, name)) {
+			size_t x;
+			for (x = 0; types[x]; x++) {
+				if (!strcasecmp(types[x]->name, iter->ref)) {
+					return 1;
+				}
+			}
+		}
+	}
+	return 0;
+#else
+	return 1;
+#endif
+}
+
 int __aco_option_register(struct aco_info *info, const char *name, enum aco_matchtype matchtype, struct aco_type **types,
 	const char *default_val, enum aco_option_type kind, aco_option_handler handler, unsigned int flags, size_t argc, ...)
 {
 	struct aco_option *opt;
 	va_list ap;
 	int tmp;
+
+#ifdef AST_XML_DOCS
+	/* XXX If no documentation has been registered, fail with warning */
+	if (!docs_exist(info->module, types, name)) {
+		ast_log(LOG_ERROR, "XML Documentation for option '%s' in modules '%s' not found!\n", name, info->module);
+		/* return -1; */
+	}
+#endif
 
 	/* Custom option types require a handler */
 	if (!handler && kind == OPT_CUSTOM_T) {
@@ -683,6 +722,169 @@
 	return 0;
 }
 
+static char *cli_show_types(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	RAII_VAR(struct ast_xml_doc_item *, item, NULL, ao2_cleanup);
+	struct ast_xml_doc_item *tmp;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "config show types";
+		e->usage =
+			"Usage: config show types <module>\n"
+			"   Lists a module's different config object types.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 4) {
+		return CLI_SHOWUSAGE;
+	}
+
+	if (!(item = ao2_find(xmldocs, a->argv[3], OBJ_KEY))) {
+		return NULL;
+	}
+	tmp = item;
+	while ((tmp = tmp->next)) {
+		if (!strcasecmp(tmp->type, "configObject")) {
+		   	ast_cli(a->fd, "%s\n", tmp->name);
+		}
+	}
+	return CLI_SUCCESS;
+}
+
+static char *cli_show_type(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	RAII_VAR(struct ast_xml_doc_item *, item, NULL, ao2_cleanup);
+	struct ast_xml_doc_item *tmp;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "config show type";
+		e->usage =
+			"Usage: config show type <module> <type>\n"
+			"   Display detailed information about a config object type.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 5) {
+		return CLI_SHOWUSAGE;
+	}
+
+	if (!(item = ao2_find(xmldocs, a->argv[3], OBJ_KEY))) {
+		return NULL;
+	}
+	tmp = item;
+	while ((tmp = tmp->next)) {
+		if (!strcasecmp(tmp->type, "configObject") && !strcasecmp(tmp->name, a->argv[4])) {
+		   	ast_cli(a->fd, "%s\n", tmp->name);
+			ast_cli(a->fd, "Synopsis: %s\n", AS_OR(tmp->synopsis, "n/a"));
+			ast_cli(a->fd, "Description:\n\t%s\n", AS_OR(tmp->description, "n/a"));
+		}
+	}
+
+	return CLI_SUCCESS;
+}
+
+static char *cli_show_options(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	RAII_VAR(struct ast_xml_doc_item *, item, NULL, ao2_cleanup);
+	struct ast_xml_doc_item *tmp;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "config show options";
+		e->usage =
+			"Usage: config show options <module> [<type>]\n"
+			"   Lists a module's different config options.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc < 4 || a->argc > 5) {
+		return CLI_SHOWUSAGE;
+	}
+
+	if (!(item = ao2_find(xmldocs, a->argv[3], OBJ_KEY))) {
+		return NULL;
+	}
+	tmp = item;
+	while ((tmp = tmp->next)) {
+		if (!strcasecmp(tmp->type, "configOption") && (a->argc == 4 || !strcasecmp(tmp->ref, a->argv[4]))) {
+			ast_cli(a->fd, "<%s> %s\n", tmp->ref, tmp->name);
+		}
+	}
+
+	return CLI_SUCCESS;
+}
+
+static char *cli_show_option(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	RAII_VAR(struct ast_xml_doc_item *, item, NULL, ao2_cleanup);
+	struct ast_xml_doc_item *tmp;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "config show option";
+		e->usage =
+			"Usage: config show option <module> <type> <name>\n"
+			"   Display detailed information about a config option.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 6) {
+		return CLI_SHOWUSAGE;
+	}
+
+	if (!(item = ao2_find(xmldocs, a->argv[3], OBJ_KEY))) {
+		return NULL;
+	}
+	tmp = item;
+	while ((tmp = tmp->next)) {
+		if (!strcasecmp(tmp->type, "configOption") && !strcasecmp(tmp->ref, a->argv[4]) && !strcasecmp(tmp->name, a->argv[5])) {
+		   	ast_cli(a->fd, "<%s> %s\n", tmp->ref, tmp->name);
+			ast_cli(a->fd, "Synopsis: %s\n", AS_OR(tmp->synopsis, "n/a"));
+			ast_cli(a->fd, "Description:\n\t%s\n", AS_OR(tmp->description, "n/a"));
+		}
+	}
+	return CLI_SUCCESS;
+}
+
+static struct ast_cli_entry cli_aco[] = {
+	AST_CLI_DEFINE(cli_show_types, "List a module's config object types"),
+	AST_CLI_DEFINE(cli_show_type, "Display detailed information about a config object type"),
+	AST_CLI_DEFINE(cli_show_options, "List a module's config options"),
+	AST_CLI_DEFINE(cli_show_option, "Display detailed information about a config option"),
+};
+
+static void aco_deinit(void)
+{
+#ifdef AST_XML_DOCS
+	ast_cli_unregister(cli_aco);
+	ao2_cleanup(xmldocs);
+#endif
+}
+
+int aco_init(void)
+{
+
+	ast_register_atexit(aco_deinit);
+#ifdef AST_XML_DOCS
+	if (!(xmldocs = ast_xmldoc_build_documentation("configInfo"))) {
+		ast_log(LOG_ERROR, "Couldn't build config documentation\n");
+		return -1;
+	}
+	ast_cli_register_multiple(cli_aco, ARRAY_LEN(cli_aco));
+#endif
+	return 0;
+}
+
 /* Default config option handlers */
 
 /*! \brief Default option handler for signed integers

Modified: team/twilson/config_docs/main/xmldoc.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_docs/main/xmldoc.c?view=diff&rev=370226&r1=370225&r2=370226
==============================================================================
--- team/twilson/config_docs/main/xmldoc.c (original)
+++ team/twilson/config_docs/main/xmldoc.c Wed Jul 18 15:10:22 2012
@@ -475,10 +475,12 @@
 	return match;
 }
 
+
 /*! \internal
  *  \brief Get the application/function node for 'name' application/function with language 'language'
  *         and module 'module' if we don't find any, get the first application
  *         with 'name' no matter which language or module.
+ *  \param node A node to start from, otherwise look at all docroots
  *  \param type 'application', 'function', ...
  *  \param name Application or Function name.
  *  \param module Module item is in.
@@ -486,20 +488,13 @@
  *  \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 *module, const char *language)
-{
-	struct ast_xml_node *node = NULL;
-	struct ast_xml_node *first_match = NULL;
-	struct ast_xml_node *lang_match = NULL;
+static struct ast_xml_node *_xmldoc_get_node(struct ast_xml_node *node, const char *type, const char *name, const char *module, const char *language)
+{
 	struct documentation_tree *doctree;
-
-	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;
-		}
+	auto struct ast_xml_node *find_node(void); /* working around gcc bugs */
+	auto struct ast_xml_node *find_node(void) {
+		struct ast_xml_node *first_match = NULL;
+		struct ast_xml_node *lang_match = NULL;
 
 		node = ast_xml_node_get_children(node);
 		while ((node = ast_xml_find_element(node, type, "name", name))) {
@@ -535,26 +530,47 @@
 
 		/* if we matched lang and module return this match */
 		if (node) {
-			break;
+			return node;
 		}
 
 		/* 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;
+			return lang_match;
 		}
 
 		/* we didn't match with only the language, just return the
 		 * first match */
 		if (first_match) {
-			node = first_match;
+			return first_match;
+		}
+		return NULL;
+	}
+
+	/* If we know where to start looking, just return what we find */
+	if (node) {
+		return find_node();
+	}
+
+	/* We don't know where to start, so look everywhere */
+	AST_RWLIST_RDLOCK(&xmldoc_tree);
+	AST_LIST_TRAVERSE(&xmldoc_tree, doctree, entry) {
+		/* the core xml documents have priority over thirdparty document. */
+		if (!(node = ast_xml_get_root(doctree->doc))) {
 			break;
 		}
+		if ((node = find_node())) {
+			break;
+		}
 	}
 	AST_RWLIST_UNLOCK(&xmldoc_tree);
 
 	return node;
+}
+
+static struct ast_xml_node *xmldoc_get_node(const char *type, const char *name, const char *module, const char *language)
+{
+	return _xmldoc_get_node(NULL, type, name, module, language);
 }
 
 /*! \internal
@@ -1103,6 +1119,7 @@
 	FUNCTION_SYNTAX,
 	MANAGER_SYNTAX,
 	MANAGER_EVENT_SYNTAX,
+	CONFIG_INFO_SYNTAX,
 	COMMAND_SYNTAX
 };
 
@@ -1111,11 +1128,12 @@
 	const char *type;
 	enum syntaxtype stxtype;
 } stxtype[] = {
-	{ "function",		FUNCTION_SYNTAX			},
-	{ "application",	FUNCTION_SYNTAX			},
-	{ "manager",		MANAGER_SYNTAX			},
-	{ "managerEvent",	MANAGER_EVENT_SYNTAX	},
-	{ "agi",			COMMAND_SYNTAX			}
+    { "function",     FUNCTION_SYNTAX       },
+    { "application",  FUNCTION_SYNTAX       },
+    { "manager",      MANAGER_SYNTAX        },
+    { "managerEvent", MANAGER_EVENT_SYNTAX  },
+    { "configInfo",   CONFIG_INFO_SYNTAX    },
+    { "agi",          COMMAND_SYNTAX        },
 };
 
 /*! \internal
@@ -2189,6 +2207,42 @@
 				}
 				item = root;
 				break;
+			case CONFIG_INFO_SYNTAX:
+			{
+				struct ast_xml_doc_item *temp;
+				if (item) {
+					break;
+				}
+				/* Each configInfo is unique and contains other config-related elements. The first item is the one that
+				 * is hashed off of for the container, so the first item we create based on the configInfo and the module
+				 * name. */
+				/* Ignore configInfos without any information */
+				if (!ast_xml_node_get_children(node) || strcasecmp(ast_xml_node_get_name(node), "configInfo")) {
+					continue;
+				}
+				if (!(temp = xmldoc_build_documentation_item(node, ast_xml_get_attribute(node, "module"), "configInfo"))) {
+					break;
+				}
+				item = temp;
+				root = item;
+
+				for (instance = ast_xml_node_get_children(node); instance; instance = ast_xml_node_get_next(instance)) {
+					if (strncasecmp(ast_xml_node_get_name(instance), "config", 6)) {
+						continue;
+					}
+					/* Now add all of the child config-related items to the list */
+					if (!(temp = xmldoc_build_documentation_item(instance, ast_xml_get_attribute(instance, "name"), ast_xml_node_get_name(instance)))) {
+						break;
+					}
+					if (!strcasecmp(ast_xml_node_get_name(instance), "configOption")) {
+						ast_string_field_set(temp, ref, ast_xml_get_attribute(instance, "objectType"));
+					}
+					item->next = temp;
+					item = temp;
+				}
+				item = root;
+				break;
+			}
 			default:
 				item = xmldoc_build_documentation_item(node, name, type);
 			}




More information about the asterisk-commits mailing list