56 struct ast_xml_doc *
doc;
60 static
char *xmldoc_get_syntax_cmd(struct ast_xml_node *fixnode, const
char *name,
int printname);
61 static
int xmldoc_parse_enumlist(struct ast_xml_node *fixnode, const
char *tabs, struct
ast_str **buffer);
62 static
void xmldoc_parse_parameter(struct ast_xml_node *fixnode, const
char *tabs, struct
ast_str **buffer);
63 static
int xmldoc_parse_info(struct ast_xml_node *
node, const
char *tabs, const
char *posttabs, struct
ast_str **buffer);
64 static
int xmldoc_parse_para(struct ast_xml_node *node, const
char *tabs, const
char *posttabs, struct
ast_str **buffer);
65 static
int xmldoc_parse_specialtags(struct ast_xml_node *fixnode, const
char *tabs, const
char *posttabs, struct
ast_str **buffer);
82 } colorized_tags[] = {
83 {
"<",
">", COLOR_GREEN,
"<replaceable>",
"</replaceable>" },
84 {
"\'",
"\'", COLOR_BLUE,
"<literal>",
"</literal>" },
85 {
"*",
"*", COLOR_RED,
"<emphasis>",
"</emphasis>" },
86 {
"\"",
"\"", COLOR_YELLOW,
"<filename>",
"</filename>" },
87 {
"\"",
"\"", COLOR_CYAN,
"<directory>",
"</directory>" },
88 {
"${",
"}", COLOR_GREEN,
"<variable>",
"</variable>" },
89 {
"",
"", COLOR_BLUE,
"<value>",
"</value>" },
90 {
"",
"", COLOR_BLUE,
"<enum>",
"</enum>" },
91 {
"\'",
"\'", COLOR_GRAY,
"<astcli>",
"</astcli>" },
94 {
"",
"", COLOR_YELLOW,
"<note>",
"</note>" },
95 {
"",
"", COLOR_RED,
"<warning>",
"</warning>" },
96 {
"",
"", COLOR_WHITE,
"<example>",
"</example>" },
97 {
"",
"", COLOR_GRAY,
"<exampletext>",
"</exampletext>"},
105 {
"note",
"<note>NOTE:</note> ",
"" },
106 {
"warning",
"<warning>WARNING!!!:</warning> ",
"" },
107 {
"example",
"<example>Example:</example> ",
"" },
119 static int xmldoc_postbrlen(
const char *postbr)
121 int postbrreallen = 0, i;
127 postbrlen = strlen(postbr);
128 for (i = 0; i < postbrlen; i++) {
129 if (postbr[i] ==
'\t') {
130 postbrreallen += 8 - (postbrreallen % 8);
135 return postbrreallen;
147 static void xmldoc_setpostbr(
char *postbr,
size_t len,
const char *text)
149 int c, postbrlen = 0;
155 for (c = 0; c < len; c++) {
156 if (text[c] ==
'\t' || text[c] ==
' ') {
157 postbr[postbrlen++] = text[c];
162 postbr[postbrlen] =
'\0';
175 static char *xmldoc_string_wrap(
const char *text,
int columns)
178 char *ret, postbr[160];
179 int count, i, textlen, postbrlen, lastbreak;
182 if (!text || columns <= 0) {
183 ast_log(LOG_WARNING,
"Passing wrong arguments while trying to wrap the text\n");
194 xmldoc_setpostbr(postbr,
sizeof(postbr), text);
195 postbrlen = xmldoc_postbrlen(postbr);
200 textlen = strlen(text);
201 for (i = 0; i < textlen; i++) {
202 if (text[i] ==
'\n') {
203 xmldoc_setpostbr(postbr,
sizeof(postbr), &text[i] + 1);
204 postbrlen = xmldoc_postbrlen(postbr);
207 }
else if (text[i] == ESC) {
212 }
while (i < textlen && text[i] !=
'm');
214 if (text[i] ==
' ') {
220 if (count > columns) {
222 int back = i - lastbreak;
223 if (lastbreak && back > 0 && back < 30) {
244 char *wrapped = NULL;
245 int i, c, len, colorsection;
248 static const int base_fg = COLOR_CYAN;
254 bwinputlen = strlen(bwinput);
267 for (i = 0; i < bwinputlen; i++) {
270 for (c = 0; c < ARRAY_LEN(colorized_tags); c++) {
271 if (strncasecmp(bwinput + i, colorized_tags[c].inittag, strlen(colorized_tags[c].inittag))) {
275 if (!(tmp = strcasestr(bwinput + i + strlen(colorized_tags[c].inittag), colorized_tags[c].endtag))) {
279 len = tmp - (bwinput + i + strlen(colorized_tags[c].inittag));
283 if (ast_opt_light_background) {
302 ast_copy_string(buf, bwinput + i + strlen(colorized_tags[c].inittag),
sizeof(buf));
323 i += len + strlen(colorized_tags[c].endtag) + strlen(colorized_tags[c].inittag) - 1;
360 static void xmldoc_string_cleanup(
const char *text,
struct ast_str **output,
int lastspaces,
int maintain_newlines)
370 textlen = strlen(text);
374 ast_log(LOG_ERROR,
"Problem allocating output buffer\n");
378 for (i = 0; i < textlen; i++) {
379 if (text[i] ==
'\n' || text[i] ==
'\r') {
380 if (maintain_newlines) {
384 while (text[i + 1] ==
'\t' || text[i + 1] ==
'\r' || text[i + 1] ==
'\n') {
411 static int xmldoc_attribute_match(
struct ast_xml_node *
node,
const char *attr,
const char *value)
414 int match = attr_value && !strcmp(attr_value, value);
435 static struct ast_xml_node *xmldoc_get_node(
const char *type,
const char *name,
const char *module,
const char *language)
437 struct ast_xml_node *
node = NULL;
438 struct ast_xml_node *first_match = NULL;
439 struct ast_xml_node *lang_match = NULL;
462 if (xmldoc_attribute_match(node,
"language", language)) {
468 if (ast_strlen_zero(module)) {
473 if (xmldoc_attribute_match(node,
"module", module)) {
515 static void __attribute__((format(printf, 4, 5))) xmldoc_reverse_helper(
int reverse,
int *len,
char **syntax, const
char *fmt, ...)
531 tmpfmtlen = strlen(tmpfmt);
532 totlen = *len + tmpfmtlen + 1;
539 *syntax = new_syntax;
542 memmove(*syntax + tmpfmtlen, *syntax, *len);
545 strcpy(*syntax, tmpfmt);
547 (*syntax)[tmpfmtlen] = tmp;
548 (*syntax)[totlen - 1] =
'\0';
550 strcpy(*syntax + *len, tmpfmt);
567 static int xmldoc_has_inside(
struct ast_xml_node *fixnode,
const char *what)
569 struct ast_xml_node *node = fixnode;
588 static int xmldoc_has_nodes(
struct ast_xml_node *fixnode)
590 struct ast_xml_node *node = fixnode;
609 static int xmldoc_has_specialtags(
struct ast_xml_node *fixnode)
611 struct ast_xml_node *node = fixnode;
615 for (i = 0; i < ARRAY_LEN(special_tags); i++) {
637 static char *xmldoc_get_syntax_fun(
struct ast_xml_node *rootnode,
const char *rootname,
const char *childname,
int printparenthesis,
int printrootname)
639 #define GOTONEXT(__rev, __a) (__rev ? ast_xml_node_get_prev(__a) : ast_xml_node_get_next(__a))
640 #define ISLAST(__rev, __a) (__rev == 1 ? (ast_xml_node_get_prev(__a) ? 0 : 1) : (ast_xml_node_get_next(__a) ? 0 : 1))
641 #define MP(__a) ((multiple ? __a : ""))
642 struct ast_xml_node *node = NULL, *firstparam = NULL, *lastparam = NULL;
643 const char *paramtype, *multipletype, *paramnameattr, *attrargsep, *parenthesis, *argname;
644 int reverse, required, paramcount = 0, openbrackets = 0, len = 0, hasparams=0;
645 int reqfinode = 0, reqlanode = 0, optmidnode = 0, prnparenthesis, multiple;
646 char *syntax = NULL, *argsep, *paramname;
648 if (ast_strlen_zero(rootname) || ast_strlen_zero(childname)) {
649 ast_log(LOG_WARNING,
"Tried to look in XML tree with faulty rootname or childname while creating a syntax.\n");
655 if (
ast_asprintf(&syntax,
"%s%s", (printrootname ? rootname :
""), (printparenthesis ?
"()" :
"")) < 0) {
686 reqlanode = required;
691 reqfinode = required;
697 if (
ast_asprintf(&syntax,
"%s%s", (printrootname ? rootname :
""), (printparenthesis ?
"()" :
"")) < 0) {
703 if (reqfinode && reqlanode) {
709 if (node != firstparam && node != lastparam) {
722 if ((!reqfinode && reqlanode) || (reqfinode && reqlanode && optmidnode)) {
732 xmldoc_reverse_helper(reverse, &len, &syntax,
733 (printrootname ? (printrootname == 2 ?
")]" :
")"):
""));
735 xmldoc_reverse_helper(reverse, &len, &syntax,
"%s%s", (printrootname ? rootname :
""),
736 (printrootname ? (printrootname == 2 ?
"[(" :
"(") :
""));
739 for (; node; node = GOTONEXT(reverse, node)) {
745 if (xmldoc_has_inside(node,
"argument")) {
749 prnparenthesis =
ast_true(parenthesis);
750 if (!strcasecmp(parenthesis,
"optional")) {
757 paramname = xmldoc_get_syntax_fun(node, argname,
"argument", prnparenthesis, prnparenthesis);
765 if (!paramnameattr) {
766 ast_log(LOG_WARNING,
"Malformed XML %s: no %s name\n", rootname, childname);
772 if (
ast_asprintf(&syntax,
"%s%s", (printrootname ? rootname :
""), (printparenthesis ?
"()" :
"")) < 0) {
807 xmldoc_reverse_helper(reverse, &len, &syntax,
"%s%s%s%s", paramname, MP(
"["), MP(argsep), MP(
"...]"));
810 while (openbrackets > 0) {
811 xmldoc_reverse_helper(reverse, &len, &syntax, (reverse ?
"[" :
"]"));
815 xmldoc_reverse_helper(reverse, &len, &syntax,
"%s%s", paramname, argsep);
817 xmldoc_reverse_helper(reverse, &len, &syntax,
"%s%s", argsep, paramname);
819 xmldoc_reverse_helper(reverse, &len, &syntax,
"%s%s%s", MP(
"["), MP(argsep), MP(
"...]"));
824 xmldoc_reverse_helper(reverse, &len, &syntax,
"[%s%s%s%s]", paramname, MP(
"["), MP(argsep), MP(
"...]"));
826 if (ISLAST(reverse, node)) {
829 xmldoc_reverse_helper(reverse, &len, &syntax,
"[%s%s%s%s]%s", paramname,
830 MP(
"["), MP(argsep), MP(
"...]"), argsep);
832 xmldoc_reverse_helper(reverse, &len, &syntax,
"%s[%s%s%s%s]", argsep, paramname,
833 MP(
"["), MP(argsep), MP(
"...]"));
837 xmldoc_reverse_helper(reverse, &len, &syntax,
"%s%s%s%s%s]", paramname, argsep,
838 MP(
"["), MP(argsep), MP(
"...]"));
840 xmldoc_reverse_helper(reverse, &len, &syntax,
"[%s%s%s%s%s", argsep, paramname,
841 MP(
"["), MP(argsep), MP(
"...]"));
853 while (openbrackets > 0) {
854 xmldoc_reverse_helper(reverse, &len, &syntax, (reverse ?
"[" :
"]"));
860 xmldoc_reverse_helper(reverse, &len, &syntax,
"%s%s", (printrootname ? rootname :
""),
861 (printrootname ? (printrootname == 2 ?
"[(" :
"(") :
""));
863 xmldoc_reverse_helper(reverse, &len, &syntax, (printrootname ? (printrootname == 2 ?
")]" :
")") :
""));
881 static char *xmldoc_parse_cmd_enumlist(
struct ast_xml_node *fixnode)
883 struct ast_xml_node *node = fixnode;
885 char *enumname, *ret;
900 enumname = xmldoc_get_syntax_cmd(node,
"", 0);
931 static char *xmldoc_get_syntax_cmd(
struct ast_xml_node *fixnode,
const char *name,
int printname)
934 struct ast_xml_node *tmpnode, *node = fixnode;
935 char *ret, *paramname;
936 const char *paramtype, *attrname, *literal;
937 int required, isenum, first = 1, isliteral;
960 if (xmldoc_has_inside(node,
"parameter")) {
962 paramname = xmldoc_get_syntax_cmd(node,
"", 0);
973 paramname = xmldoc_parse_cmd_enumlist(tmpnode);
1010 (required ?
"" :
"["),
1011 (isenum || isliteral ?
"" :
"<"),
1013 (isenum || isliteral ?
"" :
">"),
1014 (required ?
"" :
"]"));
1016 ast_free(paramname);
1037 static char *xmldoc_get_syntax_manager(
struct ast_xml_node *fixnode,
const char *name,
const char *manager_type)
1040 struct ast_xml_node *node = fixnode;
1041 const char *paramtype, *attrname;
1062 required = !strcasecmp(manager_type,
"event") ? 1 : 0;
1076 (required ?
"" :
"["),
1078 (required ?
"" :
"]"));
1089 static char *xmldoc_get_syntax_config_object(
struct ast_xml_node *fixnode,
const char *name)
1091 struct ast_xml_node *matchinfo, *tmp;
1093 const char *attr_value;
1097 if (!syntax || !fixnode) {
1110 ast_str_set(&syntax, 0,
"category %s /%s/", match ?
"=~" :
"!~", text);
1118 ast_str_append(&syntax, 0,
" matchfield: %s = %s",
S_OR(attr_value,
"Unknown"), text);
1125 static char *xmldoc_get_syntax_config_option(
struct ast_xml_node *fixnode,
const char *name)
1128 const char *default_value;
1132 if (!syntax || !fixnode) {
1139 ast_str_set(&syntax, 0,
"%s = [%s] (Default: %s) (Regex: %s)\n",
1142 default_value ?:
"n/a",
1156 MANAGER_EVENT_SYNTAX,
1159 CONFIG_OPTION_SYNTAX,
1160 CONFIG_OBJECT_SYNTAX,
1169 {
"function", FUNCTION_SYNTAX },
1170 {
"application", FUNCTION_SYNTAX },
1171 {
"manager", MANAGER_SYNTAX },
1172 {
"managerEvent", MANAGER_EVENT_SYNTAX },
1173 {
"configInfo", CONFIG_INFO_SYNTAX },
1174 {
"configFile", CONFIG_FILE_SYNTAX },
1175 {
"configOption", CONFIG_OPTION_SYNTAX },
1176 {
"configObject", CONFIG_OBJECT_SYNTAX },
1177 {
"agi", COMMAND_SYNTAX },
1188 static enum syntaxtype xmldoc_get_syntax_type(
const char *type)
1191 for (i=0; i < ARRAY_LEN(stxtype); i++) {
1192 if (!strcasecmp(stxtype[i].type, type)) {
1193 return stxtype[i].stxtype;
1197 return FUNCTION_SYNTAX;
1215 static char *_ast_xmldoc_build_syntax(
struct ast_xml_node *root_node,
const char *type,
const char *name)
1217 char *syntax = NULL;
1218 struct ast_xml_node *node = root_node;
1226 switch (xmldoc_get_syntax_type(type)) {
1227 case FUNCTION_SYNTAX:
1228 syntax = xmldoc_get_syntax_fun(node, name,
"parameter", 1, 1);
1230 case COMMAND_SYNTAX:
1231 syntax = xmldoc_get_syntax_cmd(node, name, 1);
1233 case MANAGER_SYNTAX:
1234 syntax = xmldoc_get_syntax_manager(node, name,
"Action");
1236 case MANAGER_EVENT_SYNTAX:
1237 syntax = xmldoc_get_syntax_manager(node, name,
"Event");
1239 case CONFIG_OPTION_SYNTAX:
1240 syntax = xmldoc_get_syntax_config_option(root_node, name);
1242 case CONFIG_OBJECT_SYNTAX:
1243 syntax = xmldoc_get_syntax_config_object(node, name);
1246 syntax = xmldoc_get_syntax_fun(node, name,
"parameter", 1, 1);
1254 struct ast_xml_node *node;
1264 syntax = _ast_xmldoc_build_syntax(node, type, name);
1285 static int xmldoc_parse_common_elements(
struct ast_xml_node *node,
const char *tabs,
const char *posttabs,
struct ast_str **buffer)
1287 return (xmldoc_parse_para(node, tabs, posttabs, buffer)
1288 || xmldoc_parse_specialtags(node, tabs, posttabs, buffer)
1289 || xmldoc_parse_info(node, tabs, posttabs, buffer));
1307 static int xmldoc_parse_para(
struct ast_xml_node *node,
const char *tabs,
const char *posttabs,
struct ast_str **buffer)
1309 const char *tmptext;
1310 struct ast_xml_node *tmp;
1331 xmldoc_string_cleanup(tmptext, &tmpstr, 0, 0);
1362 static int xmldoc_parse_example(
struct ast_xml_node *fixnode,
struct ast_str **buffer)
1364 struct ast_xml_node *node = fixnode;
1365 const char *tmptext;
1367 struct ast_str *stripped_text;
1390 xmldoc_string_cleanup(tmptext, &stripped_text, 0, 1);
1391 if (stripped_text) {
1394 ast_free(stripped_text);
1415 static int xmldoc_parse_specialtags(
struct ast_xml_node *fixnode,
const char *tabs,
const char *posttabs,
struct ast_str **buffer)
1417 struct ast_xml_node *node = fixnode;
1424 for (i = 0; i < ARRAY_LEN(special_tags); i++) {
1433 if (!ast_strlen_zero(special_tags[i].init)) {
1437 if (xmldoc_parse_example(node, buffer)) {
1445 if ((xmldoc_parse_para(node,
"", posttabs, buffer) == 2)
1446 || (xmldoc_parse_info(node,
"", posttabs, buffer) == 2)) {
1451 if (!ast_strlen_zero(special_tags[i].end)) {
1452 ast_str_append(buffer, 0,
"%s%s", special_tags[i].end, posttabs);
1474 static int xmldoc_parse_argument(
struct ast_xml_node *fixnode,
int insideparameter,
const char *paramtabs,
const char *tabs,
struct ast_str **buffer)
1476 struct ast_xml_node *node = fixnode;
1477 const char *argname;
1478 int count = 0, ret = 0;
1489 if (xmldoc_has_inside(node,
"para") || xmldoc_has_inside(node,
"info") || xmldoc_has_specialtags(node)) {
1490 ast_str_append(buffer, 0,
"%s%s%s", tabs, argname, (insideparameter ?
"\n" :
""));
1498 if (xmldoc_parse_common_elements(node, (insideparameter ? paramtabs : (!count ?
" - " : tabs)),
"\n", buffer) == 2) {
1521 static int xmldoc_parse_variable(
struct ast_xml_node *node,
const char *tabs,
struct ast_str **buffer)
1523 struct ast_xml_node *tmp;
1524 const char *valname;
1525 const char *tmptext;
1527 int ret = 0, printedpara=0;
1530 if (xmldoc_parse_common_elements(tmp, (ret ? tabs :
""),
"\n", buffer)) {
1555 xmldoc_string_cleanup(tmptext, &cleanstr, 1, 0);
1582 static int xmldoc_parse_variablelist(
struct ast_xml_node *node,
const char *tabs,
struct ast_str **buffer)
1584 struct ast_xml_node *tmp;
1585 const char *varname;
1603 if (xmldoc_parse_common_elements(tmp, (ret ? tabs :
""),
"\n", buffer)) {
1612 ast_str_append(buffer, 0,
"%s<variable>%s</variable>: ", tabs, varname);
1615 xmldoc_parse_variable(tmp, vartabs, buffer);
1640 static char *_ast_xmldoc_build_seealso(
struct ast_xml_node *node)
1644 const char *
typename;
1645 const char *content;
1682 if (!strcasecmp(
typename,
"application")) {
1683 ast_str_append(&outputstr, 0,
"%s%s()", (first ?
"" :
", "), content);
1684 }
else if (!strcasecmp(
typename,
"function")) {
1685 ast_str_append(&outputstr, 0,
"%s%s", (first ?
"" :
", "), content);
1686 }
else if (!strcasecmp(
typename,
"astcli")) {
1687 ast_str_append(&outputstr, 0,
"%s<astcli>%s</astcli>", (first ?
"" :
", "), content);
1689 ast_str_append(&outputstr, 0,
"%s%s", (first ?
"" :
", "), content);
1697 ast_free(outputstr);
1705 struct ast_xml_node *node;
1707 if (ast_strlen_zero(type) || ast_strlen_zero(name)) {
1719 output = _ast_xmldoc_build_seealso(node);
1736 static int xmldoc_parse_enum(
struct ast_xml_node *fixnode,
const char *tabs,
struct ast_str **buffer)
1738 struct ast_xml_node *node = fixnode;
1747 if (xmldoc_parse_common_elements(node, (ret ? tabs :
" - "),
"\n", buffer)) {
1751 xmldoc_parse_enumlist(node, optiontabs, buffer);
1752 xmldoc_parse_parameter(node, optiontabs, buffer);
1755 ast_free(optiontabs);
1771 static int xmldoc_parse_enumlist(
struct ast_xml_node *fixnode,
const char *tabs,
struct ast_str **buffer)
1773 struct ast_xml_node *node = fixnode;
1774 const char *enumname;
1788 if ((xmldoc_parse_enum(node, tabs, buffer))) {
1810 static int xmldoc_parse_option(
struct ast_xml_node *fixnode,
const char *tabs,
struct ast_str **buffer)
1812 struct ast_xml_node *node;
1826 if (xmldoc_parse_argument(node, 0, NULL, optiontabs, buffer)) {
1832 if (xmldoc_parse_common_elements(node, (ret ? tabs :
""),
"\n", buffer)) {
1836 xmldoc_parse_variablelist(node, optiontabs, buffer);
1838 xmldoc_parse_enumlist(node, optiontabs, buffer);
1840 ast_free(optiontabs);
1854 static void xmldoc_parse_optionlist(
struct ast_xml_node *fixnode,
const char *tabs,
struct ast_str **buffer)
1856 struct ast_xml_node *node;
1857 const char *optname, *hasparams;
1875 if (hasparams && !strcasecmp(hasparams,
"optional")) {
1879 optionsyntax = xmldoc_get_syntax_fun(node, optname,
"argument", 0, optparams);
1880 if (!optionsyntax) {
1888 if (!xmldoc_parse_option(node, tabs, buffer)) {
1894 ast_free(optionsyntax);
1907 static void xmldoc_parse_parameter(
struct ast_xml_node *fixnode,
const char *tabs,
struct ast_str **buffer)
1909 const char *paramname;
1910 struct ast_xml_node *node = fixnode;
1911 int hasarguments, printed = 0;
1918 hasarguments = xmldoc_has_inside(node,
"argument");
1929 if (!hasarguments && xmldoc_has_nodes(node)) {
1937 xmldoc_parse_optionlist(node, internaltabs, buffer);
1939 xmldoc_parse_enumlist(node, internaltabs, buffer);
1941 xmldoc_parse_argument(node, 1, internaltabs, (!hasarguments ?
" " :
""), buffer);
1948 if (xmldoc_parse_para(node, internaltabs,
"\n", buffer)) {
1960 if (xmldoc_parse_info(node, internaltabs,
"\n", buffer)) {
1966 }
else if ((xmldoc_parse_specialtags(node, internaltabs,
"\n", buffer))) {
1973 ast_free(internaltabs);
1990 static int xmldoc_parse_info(
struct ast_xml_node *node,
const char *tabs,
const char *posttabs,
struct ast_str **buffer)
2002 if (!internaltabs) {
2008 ast_str_append(buffer, 0,
"%s<note>Technology: %s</note>\n", internaltabs, tech);
2016 xmldoc_parse_enumlist(node, internaltabs, buffer);
2018 xmldoc_parse_parameter(node, internaltabs, buffer);
2019 }
else if ((internal_ret = xmldoc_parse_common_elements(node, internaltabs, posttabs, buffer))) {
2020 if (internal_ret > ret) {
2025 ast_free(internaltabs);
2044 static char *_ast_xmldoc_build_arguments(
struct ast_xml_node *node)
2046 char *retstr = NULL;
2068 xmldoc_parse_parameter(node,
"", &ret);
2086 struct ast_xml_node *node;
2089 if (ast_strlen_zero(type) || ast_strlen_zero(name)) {
2101 arguments = _ast_xmldoc_build_arguments(node);
2117 static struct ast_str *xmldoc_get_formatted(
struct ast_xml_node *node,
int raw_output,
int raw_wrap)
2119 struct ast_xml_node *tmp;
2120 const char *notcleanret, *tmpstr;
2126 tmpstr = notcleanret;
2136 if (xmldoc_parse_common_elements(tmp,
"",
"\n", &ret)) {
2139 if (xmldoc_parse_variablelist(tmp,
"", &ret)) {
2142 if (xmldoc_parse_enumlist(tmp,
" ", &ret)) {
2145 if (xmldoc_parse_specialtags(tmp,
"",
"", &ret)) {
2171 static char *_xmldoc_build_field(
struct ast_xml_node *node,
const char *var,
int raw)
2182 formatted = xmldoc_get_formatted(node, raw, raw);
2186 ast_free(formatted);
2204 static char *xmldoc_build_field(
const char *type,
const char *name,
const char *module,
const char *var,
int raw)
2206 struct ast_xml_node *node;
2209 if (ast_strlen_zero(type) || ast_strlen_zero(name)) {
2210 ast_log(LOG_ERROR,
"Tried to look in XML tree with faulty values.\n");
2219 ast_log(LOG_WARNING,
"Couldn't find %s %s in XML documentation"
2220 " If this module was recently built, run 'xmldoc reload' to refresh documentation\n",
2225 field = _xmldoc_build_field(node, var, raw);
2243 static char *_ast_xmldoc_build_synopsis(
struct ast_xml_node *node)
2245 return _xmldoc_build_field(node,
"synopsis", 1);
2250 return xmldoc_build_field(type, name, module,
"synopsis", 1);
2266 static char *_ast_xmldoc_build_description(
struct ast_xml_node *node)
2268 return _xmldoc_build_field(node,
"description", 0);
2273 return xmldoc_build_field(type, name, module,
"description", 0);
2281 static void ast_xml_doc_item_destructor(
void *obj)
2310 static struct ast_xml_doc_item *ast_xml_doc_item_alloc(
const char *name,
const char *type)
2314 item = ao2_alloc_options(
sizeof(*item), ast_xml_doc_item_destructor,
2317 ast_log(AST_LOG_ERROR,
"Failed to allocate memory for ast_xml_doc_item instance\n");
2326 ast_log(AST_LOG_ERROR,
"Failed to allocate strings for ast_xml_doc_item instance\n");
2327 goto ast_xml_doc_item_failure;
2331 ast_log(AST_LOG_ERROR,
"Failed to initialize string field for ast_xml_doc_item instance\n");
2332 goto ast_xml_doc_item_failure;
2339 ast_xml_doc_item_failure:
2349 static int ast_xml_doc_item_hash(
const void *obj,
const int flags)
2352 const char *name = (flags &
OBJ_KEY) ? obj : item->
name;
2361 static int ast_xml_doc_item_cmp(
void *obj,
void *arg,
int flags)
2365 const char *match = (flags &
OBJ_KEY) ? arg : right->
name;
2381 static struct ast_xml_doc_item *xmldoc_build_documentation_item(
struct ast_xml_node *node,
const char *name,
const char *type)
2390 if (!(item = ast_xml_doc_item_alloc(name, type))) {
2395 syntax = _ast_xmldoc_build_syntax(node, type, name);
2396 seealso = _ast_xmldoc_build_seealso(node);
2397 arguments = _ast_xmldoc_build_arguments(node);
2398 synopsis = _ast_xmldoc_build_synopsis(node);
2399 description = _ast_xmldoc_build_description(node);
2419 ast_free(arguments);
2421 ast_free(description);
2442 struct ast_xml_node *
event;
2443 struct ast_xml_node *responses;
2444 struct ast_xml_node *list_elements;
2455 if (!list_elements) {
2461 struct ast_xml_node *event_instance;
2471 "managerEventInstance", NULL, NULL);
2472 new_item = xmldoc_build_documentation_item(event_instance, name,
"managerEvent");
2486 struct ast_xml_node *node;
2489 if (ast_strlen_zero(type) || ast_strlen_zero(name)) {
2501 responses = xmldoc_build_list_responses(node);
2520 static struct ast_xml_doc_item *xmldoc_build_final_response(
struct ast_xml_node *manager_action)
2522 struct ast_xml_node *responses;
2523 struct ast_xml_node *final_response_event;
2524 struct ast_xml_node *event_instance;
2527 "responses", NULL, NULL);
2533 "managerEvent", NULL, NULL);
2534 if (!final_response_event) {
2539 "managerEventInstance", NULL, NULL);
2540 if (!event_instance) {
2547 res = xmldoc_build_documentation_item(event_instance, name,
"managerEvent");
2556 struct ast_xml_node *node;
2559 if (ast_strlen_zero(type) || ast_strlen_zero(name)) {
2571 response = xmldoc_build_final_response(node);
2576 struct ast_xml_xpath_results *__attribute__((format(printf, 1, 2)))
ast_xmldoc_query(const
char *fmt, ...)
2578 struct ast_xml_xpath_results *results = NULL;
2609 struct ast_xml_node *iter;
2613 const char *iter_name;
2620 ast_log(LOG_ERROR,
"Could not build documentation for '%s:%s'\n",
ast_xml_node_get_name(iter), iter_name);
2631 build_config_docs(iter, root);
2644 if (!item || !item->
node) {
2653 syntax = _ast_xmldoc_build_syntax(item->
node, item->
type, name);
2654 seealso = _ast_xmldoc_build_seealso(item->
node);
2655 arguments = _ast_xmldoc_build_arguments(item->
node);
2656 synopsis = _ast_xmldoc_build_synopsis(item->
node);
2657 description = _ast_xmldoc_build_description(item->
node);
2677 ast_free(arguments);
2679 ast_free(description);
2687 struct ast_xml_node *node = NULL, *instance = NULL;
2692 ast_xml_doc_item_hash, NULL, ast_xml_doc_item_cmp);
2694 ast_log(AST_LOG_ERROR,
"Failed to create container for xml document item instances\n");
2718 switch (xmldoc_get_syntax_type(type)) {
2719 case MANAGER_EVENT_SYNTAX:
2729 temp = xmldoc_build_documentation_item(instance, name, type);
2738 case CONFIG_INFO_SYNTAX:
2746 item = xmldoc_build_documentation_item(node, name,
"configInfo");
2752 build_config_docs(node, &root);
2757 item = xmldoc_build_documentation_item(node, name, type);
2763 ao2_t_ref(item, -1,
"Dispose of creation ref");
2775 #if !defined(HAVE_GLOB_NOMAGIC) || !defined(HAVE_GLOB_BRACE) || defined(DEBUG_NONGNU)
2776 static int xml_pathmatch(
char *xmlpattern,
int xmlpattern_maxlen, glob_t *globbuf)
2780 snprintf(xmlpattern, xmlpattern_maxlen,
"%s/documentation/thirdparty/*-%s.xml",
2782 if((globret = glob(xmlpattern, GLOB_NOCHECK, NULL, globbuf))) {
2786 snprintf(xmlpattern, xmlpattern_maxlen,
"%s/documentation/thirdparty/*-%.2s_??.xml",
2788 if((globret = glob(xmlpattern, GLOB_APPEND | GLOB_NOCHECK, NULL, globbuf))) {
2792 snprintf(xmlpattern, xmlpattern_maxlen,
"%s/documentation/thirdparty/*-%s.xml",
2794 if((globret = glob(xmlpattern, GLOB_APPEND | GLOB_NOCHECK, NULL, globbuf))) {
2798 snprintf(xmlpattern, xmlpattern_maxlen,
"%s/documentation/*-%s.xml",
2800 if((globret = glob(xmlpattern, GLOB_APPEND | GLOB_NOCHECK, NULL, globbuf))) {
2804 snprintf(xmlpattern, xmlpattern_maxlen,
"%s/documentation/*-%.2s_??.xml",
2806 if((globret = glob(xmlpattern, GLOB_APPEND | GLOB_NOCHECK, NULL, globbuf))) {
2810 snprintf(xmlpattern, xmlpattern_maxlen,
"%s/documentation/*-%s.xml",
2812 globret = glob(xmlpattern, GLOB_APPEND | GLOB_NOCHECK, NULL, globbuf);
2821 struct ast_xml_doc *dumpdoc;
2822 struct ast_xml_node *dumproot;
2829 "Usage: xmldoc dump <filename>\n"
2830 " Dump XML documentation to a file\n";
2837 return CLI_SHOWUSAGE;
2842 ast_log(LOG_ERROR,
"Could not create new XML document\n");
2849 ast_log(LOG_ERROR,
"Could not create new XML root node\n");
2859 struct ast_xml_node *kids_copy;
2869 ast_log(LOG_ERROR,
"Could not create copy of XML node list\n");
2877 if (!(f = fopen(a->argv[2],
"w"))) {
2879 ast_log(LOG_ERROR,
"Could not open file '%s': %s\n", a->argv[2], strerror(errno));
2890 static struct ast_cli_entry cli_dump_xmldocs = AST_CLI_DEFINE(handle_dump_docs,
"Dump the XML docs to the specified file");
2893 static struct ast_cli_entry cli_reload_xmldocs = AST_CLI_DEFINE(handle_reload_docs,
"Reload the XML docs");
2920 static int xmldoc_load_documentation(
int first_time)
2922 struct ast_xml_node *root_node;
2923 struct ast_xml_doc *tmpdoc;
2929 int globret, i, dup, duplicate;
2931 #if !defined(HAVE_GLOB_NOMAGIC) || !defined(HAVE_GLOB_BRACE) || defined(DEBUG_NONGNU)
2932 int xmlpattern_maxlen;
2938 if ((cfg =
ast_config_load2(
"asterisk.conf",
"" , cnfflags)) && cfg != CONFIG_STATUS_FILEINVALID) {
2939 for (var = ast_variable_browse(cfg,
"options"); var; var = var->
next) {
2940 if (!strcasecmp(var->
name,
"documentation_language")) {
2941 if (!ast_strlen_zero(var->
value)) {
2958 globbuf.gl_offs = 0;
2960 #if !defined(HAVE_GLOB_NOMAGIC) || !defined(HAVE_GLOB_BRACE) || defined(DEBUG_NONGNU)
2961 xmlpattern_maxlen = strlen(ast_config_AST_DATA_DIR) + strlen(
"/documentation/thirdparty") + strlen(
"/*-??_??.xml") + 1;
2963 globret = xml_pathmatch(xmlpattern, xmlpattern_maxlen, &globbuf);
2966 if (
ast_asprintf(&xmlpattern,
"%s/documentation{/thirdparty/,/}*-{%s,%.2s_??,%s}.xml", ast_config_AST_DATA_DIR,
2970 globret = glob(xmlpattern, MY_GLOB_FLAGS, NULL, &globbuf);
2973 ast_debug(3,
"gl_pathc %zu\n", (
size_t)globbuf.gl_pathc);
2974 if (globret == GLOB_NOSPACE) {
2975 ast_log(LOG_WARNING,
"XML load failure, glob expansion of pattern '%s' failed: Not enough memory\n", xmlpattern);
2976 ast_free(xmlpattern);
2978 }
else if (globret == GLOB_ABORTED) {
2979 ast_log(LOG_WARNING,
"XML load failure, glob expansion of pattern '%s' failed: Read error\n", xmlpattern);
2980 ast_free(xmlpattern);
2983 ast_free(xmlpattern);
2997 for (i = 0; i < globbuf.gl_pathc; i++) {
3000 for (dup = 0; dup < i; dup++) {
3001 if (!strcmp(globbuf.gl_pathv[i], globbuf.gl_pathv[dup])) {
3006 if (duplicate || strchr(globbuf.gl_pathv[i],
'*')) {
3014 ast_log(LOG_ERROR,
"Could not open XML documentation at '%s'\n", globbuf.gl_pathv[i]);
3020 ast_log(LOG_ERROR,
"Error getting documentation root node\n");
3026 ast_log(LOG_ERROR,
"Documentation file is not well formed!\n");
3032 ast_log(LOG_ERROR,
"Unable to allocate documentation_tree structure!\n");
3036 doc_tree->
doc = tmpdoc;
3049 return xmldoc_load_documentation(1);
3052 static int xmldoc_reload_documentation(
void)
3054 return xmldoc_load_documentation(0);
3063 "Usage: xmldoc reload\n"
3064 " Reload XML documentation\n";
3070 xmldoc_reload_documentation();
struct ast_variable * next
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
#define ast_realloc(p, len)
A wrapper for realloc()
int ast_xml_init(void)
Initialize the XML library implementation. This function is used to setup everything needed to start ...
static void xmldoc_purge_documentation(void)
struct ast_xml_xpath_results * ast_xmldoc_query(const char *fmt,...)
Execute an XPath query on the loaded XML documentation.
struct ast_xml_doc_item * ast_xmldoc_build_list_responses(const char *type, const char *name, const char *module)
Generate the [list responses] tag based on type of node ('application', 'function' or 'agi') and name...
const ast_string_field ref
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
descriptor for a cli entry.
struct ast_xml_node * node
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
struct ast_xml_doc * ast_xml_open(char *filename)
Open an XML document.
struct ast_xml_doc * ast_xml_new(void)
Create a XML document.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Mapping between type of node and type of syntax to generate.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Structure for variables, used for configurations and for channel variables.
int ast_str_set_va(struct ast_str **buf, ssize_t max_len, const char *fmt, va_list ap)
Set a dynamic string from a va_list.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
int ast_term_color_code(struct ast_str **str, int fgcolor, int bgcolor)
Append a color sequence to an ast_str.
int ast_xmldoc_regenerate_doc_item(struct ast_xml_doc_item *item)
Regenerate the documentation for a particular item.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
int ast_xml_doc_dump_file(FILE *output, struct ast_xml_doc *doc)
Dump the specified document to a file.
#define ast_vasprintf(ret, fmt, ap)
A wrapper for vasprintf()
#define ast_strdup(str)
A wrapper for strdup()
struct ast_xml_node * ast_xml_get_root(struct ast_xml_doc *doc)
Get the document root node.
char * ast_xmldoc_build_seealso(const char *type, const char *name, const char *module)
Parse the node content.
char * ast_xmldoc_build_syntax(const char *type, const char *name, const char *module)
Get the syntax for a specified application or function.
int ast_xmldoc_load_documentation(void)
Load XML documentation. Provided by xmldoc.c.
The struct to be used as the head of an ast_xml_doc_item list when being manipulated.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
struct ast_xml_doc_item * ast_xmldoc_build_final_response(const char *type, const char *name, const char *module)
Generate the [final response] tag based on type of node ('application', 'function' or 'agi') and name...
char * ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
Generate synopsis documentation from XML.
#define ast_cli_register(e)
Registers a command or an array of commands.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
const char * ast_xml_get_attribute(struct ast_xml_node *node, const char *attrname)
Get a node attribute by name.
void ast_xml_free_attr(const char *attribute)
Free an attribute returned by ast_xml_get_attribute()
syntaxtype
Types of syntax that we are able to generate.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Configuration File Parser.
struct ast_xml_node * ast_xml_add_child_list(struct ast_xml_node *parent, struct ast_xml_node *child)
Add a list of child nodes, to a specified parent node.
const ast_string_field type
char * ast_xmldoc_build_arguments(const char *type, const char *name, const char *module)
Generate the [arguments] tag based on type of node ('application', 'function' or 'agi') and name...
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Asterisk file paths, configured in asterisk.conf.
static const char default_documentation_language[]
Default documentation language.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
struct ast_xml_node * ast_xml_find_element(struct ast_xml_node *root_node, const char *name, const char *attrname, const char *attrvalue)
Find a node element by name.
A set of macros to manage forward-linked lists.
#define ast_malloc(len)
A wrapper for malloc()
struct ast_xml_node * ast_xml_new_node(const char *name)
Create a XML node.
#define ast_debug(level,...)
Log a DEBUG message.
char * ast_xmldoc_printable(const char *bwinput, int withcolors)
Colorize and put delimiters (instead of tags) to the xmldoc output.
struct ast_str * description
static char documentation_language[6]
XML documentation language.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
struct ast_xml_xpath_results * ast_xml_query(struct ast_xml_doc *doc, const char *xpath_str)
Execute an XPath query on an XML document.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Support for dynamic strings.
static const int xmldoc_text_columns
Number of columns to print when showing the XML documentation with a 'core show application/function ...
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
void ast_xml_set_root(struct ast_xml_doc *doc, struct ast_xml_node *node)
Specify the root node of a XML document.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
const ast_string_field name
static void xmldoc_unload_documentation(void)
Close and unload XML documentation.
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define ast_calloc(num, len)
A wrapper for calloc()
const char * ast_term_reset(void)
Returns the terminal reset code.
struct ast_xml_node * ast_xml_copy_node_list(struct ast_xml_node *list)
Create a copy of a n ode list.
Asterisk XML Documentation API.
Prototypes for public functions only of internal interest,.
void ast_xml_close(struct ast_xml_doc *doc)
Close an already open document and free the used structure.
Structure used to handle boolean flags.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
const char * ast_xml_get_text(struct ast_xml_node *node)
Get an element content string.
Handy terminal functions for vt* terms.
Struct that contains the XML documentation for a particular item. Note that this is an ao2 ref counte...
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Container of documentation trees.
struct ast_str * arguments
void ast_str_trim_blanks(struct ast_str *buf)
Trims trailing whitespace characters from an ast_str string.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
struct ast_xml_node * ast_xml_node_get_next(struct ast_xml_node *node)
Get the next node in the same level.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
int ast_xml_finish(void)
Cleanup library allocated global data.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
char * ast_xmldoc_build_description(const char *type, const char *name, const char *module)
Generate description documentation from XML.
struct ast_xml_node * ast_xml_node_get_children(struct ast_xml_node *node)
Get the node's children.
const char * ast_xml_node_get_name(struct ast_xml_node *node)
Get the name of a node.
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
void ast_xml_free_text(const char *text)
Free a content element that was returned by ast_xml_get_text()
struct ao2_container * ast_xmldoc_build_documentation(const char *type)
Build the documentation for a particular source type.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
struct ast_str * synopsis
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ao2_link(container, obj)
Add an object to a container.