diff --git a/doc/appdocsxml.dtd b/doc/appdocsxml.dtd index 426d959466..ad5f16c0b6 100644 --- a/doc/appdocsxml.dtd +++ b/doc/appdocsxml.dtd @@ -72,10 +72,10 @@ - + - + diff --git a/include/asterisk/agi.h b/include/asterisk/agi.h index 568cd5d116..dfa6dceacd 100644 --- a/include/asterisk/agi.h +++ b/include/asterisk/agi.h @@ -60,6 +60,10 @@ typedef struct agi_command { struct ast_module *mod; /*! Linked list pointer */ AST_LIST_ENTRY(agi_command) list; + /*! Since content */ + const char * const since; + /*! Syntax arguments content */ + const char * const arguments; } agi_command; /*! diff --git a/include/asterisk/manager.h b/include/asterisk/manager.h index b9fe794850..802c9fddf3 100644 --- a/include/asterisk/manager.h +++ b/include/asterisk/manager.h @@ -181,6 +181,7 @@ struct manager_action { * function and unregistering the AMI action object. */ unsigned int registered:1; + AST_STRING_FIELD_EXTENDED(since); /*!< Documentation "since" element */ }; /*! \brief External routines may register/unregister manager callbacks this way diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h index ec752a96db..f66b54c1bc 100644 --- a/include/asterisk/pbx.h +++ b/include/asterisk/pbx.h @@ -150,6 +150,7 @@ struct ast_custom_function { * \since 12 */ AST_RWLIST_ENTRY(ast_custom_function) acflist; + AST_STRING_FIELD_EXTENDED(since); /*!< Since text for 'show functions' */ }; /*! \brief All switch functions have the same interface, so define a type for them */ diff --git a/include/asterisk/xmldoc.h b/include/asterisk/xmldoc.h index b14288f852..5f9164fd2c 100644 --- a/include/asterisk/xmldoc.h +++ b/include/asterisk/xmldoc.h @@ -78,6 +78,8 @@ struct ast_xml_doc_item { struct ast_xml_node *node; /*! The next XML documentation item that matches the same name/item type */ AST_LIST_ENTRY(ast_xml_doc_item) next; + /*! Since tagged information, if it exists */ + struct ast_str *since; }; /*! \brief Execute an XPath query on the loaded XML documentation @@ -110,6 +112,16 @@ char *ast_xmldoc_build_syntax(const char *type, const char *name, const char *mo */ char *ast_xmldoc_build_seealso(const char *type, const char *name, const char *module); +/*! + * \brief Parse the 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 since node. + */ +char *ast_xmldoc_build_since(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. diff --git a/main/config_options.c b/main/config_options.c index 9769fd3ae1..ae3fae549f 100644 --- a/main/config_options.c +++ b/main/config_options.c @@ -1244,10 +1244,14 @@ static void cli_show_module_types(struct ast_cli_args *a) } if (ast_str_strlen(item->synopsis)) { - ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(item->synopsis), 1)); + char *value = ast_xmldoc_printable(ast_str_buffer(item->synopsis), 1); + ast_cli(a->fd, "%s\n\n", value); + ast_free(value); } if (ast_str_strlen(item->description)) { - ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(item->description), 1)); + char *value = ast_xmldoc_printable(ast_str_buffer(item->description), 1); + ast_cli(a->fd, "%s\n\n",value); + ast_free(value); } tmp = item; @@ -1267,8 +1271,8 @@ static void cli_show_module_type(struct ast_cli_args *a) { RAII_VAR(struct ast_xml_doc_item *, item, NULL, ao2_cleanup); struct ast_xml_doc_item *tmp; - char option_type[64]; int match = 0; + char *synopsis, *since, *description, *syntax, *seealso; ast_assert(a->argc == 5); @@ -1281,19 +1285,48 @@ static void cli_show_module_type(struct ast_cli_args *a) while ((tmp = AST_LIST_NEXT(tmp, next))) { if (!strcasecmp(tmp->type, "configObject") && !strcasecmp(tmp->name, a->argv[4])) { match = 1; - term_color(option_type, tmp->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(option_type)); - ast_cli(a->fd, "%s", option_type); - if (ast_str_strlen(tmp->syntax)) { - ast_cli(a->fd, ": [%s]\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->syntax), 1)); - } else { - ast_cli(a->fd, "\n\n"); - } - if (ast_str_strlen(tmp->synopsis)) { - ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->synopsis), 1)); - } - if (ast_str_strlen(tmp->description)) { - ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->description), 1)); + + synopsis = ast_xmldoc_printable(AS_OR(tmp->synopsis, "Not available"), 1); + since = ast_xmldoc_printable(AS_OR(tmp->since, "Not available"), 1); + description = ast_xmldoc_printable(AS_OR(tmp->description, "Not available"), 1); + syntax = ast_xmldoc_printable(AS_OR(tmp->syntax, "Not available"), 1); + seealso = ast_xmldoc_printable(AS_OR(tmp->seealso, "Not available"), 1); + + if (!synopsis || !since || !description || !syntax || !seealso ) { + ast_free(synopsis); + ast_free(since); + ast_free(description); + ast_free(syntax); + ast_free(seealso); + ast_cli(a->fd, "Error: Memory allocation failed\n"); + break; } + + ast_cli(a->fd, "\n" + "%s -= Info about Config Object '%s:%s' =- %s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s [%s]\n\n" + COLORIZE_FMT "\n" + "%s\n\n", + ast_term_color(COLOR_MAGENTA, 0), a->argv[3], tmp->name, ast_term_reset(), + COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis, + COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since, + COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description, + COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), tmp->name, syntax, + COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso + ); + ast_free(synopsis); + ast_free(since); + ast_free(description); + ast_free(syntax); + ast_free(seealso); + } } @@ -1304,6 +1337,8 @@ static void cli_show_module_type(struct ast_cli_args *a) /* Now iterate over the options for the type */ tmp = item; + ast_cli(a->fd, COLORIZE_FMT "\n", COLORIZE(COLOR_MAGENTA, 0, "[Config Options]")); + while ((tmp = AST_LIST_NEXT(tmp, next))) { if (!strcasecmp(tmp->type, "configOption") && !strcasecmp(tmp->ref, a->argv[4])) { ast_cli(a->fd, "%-25s -- %-120.120s\n", tmp->name, @@ -1319,8 +1354,8 @@ static void cli_show_module_options(struct ast_cli_args *a) { RAII_VAR(struct ast_xml_doc_item *, item, NULL, ao2_cleanup); struct ast_xml_doc_item *tmp; - char option_name[64]; int match = 0; + char *synopsis, *since, *description, *syntax, *seealso; ast_assert(a->argc == 6); @@ -1334,21 +1369,48 @@ static void cli_show_module_options(struct ast_cli_args *a) if (match) { ast_cli(a->fd, "\n"); } - term_color(option_name, tmp->ref, COLOR_MAGENTA, COLOR_BLACK, sizeof(option_name)); - ast_cli(a->fd, "[%s%s]\n", option_name, ast_term_reset()); - if (ast_str_strlen(tmp->syntax)) { - ast_cli(a->fd, "%s\n", ast_xmldoc_printable(ast_str_buffer(tmp->syntax), 1)); - } - ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(AS_OR(tmp->synopsis, "No information available"), 1)); - if (ast_str_strlen(tmp->description)) { - ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->description), 1)); - } - if (ast_str_strlen(tmp->seealso)) { - ast_cli(a->fd, "See Also:\n"); - ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->seealso), 1)); + synopsis = ast_xmldoc_printable(AS_OR(tmp->synopsis, "Not available"), 1); + since = ast_xmldoc_printable(AS_OR(tmp->since, "Not available"), 1); + description = ast_xmldoc_printable(AS_OR(tmp->description, "Not available"), 1); + syntax = ast_xmldoc_printable(AS_OR(tmp->syntax, "Not available"), 1); + seealso = ast_xmldoc_printable(AS_OR(tmp->seealso, "Not available"), 1); + + if (!synopsis || !since || !description || !syntax || !seealso ) { + ast_free(synopsis); + ast_free(since); + ast_free(description); + ast_free(syntax); + ast_free(seealso); + ast_cli(a->fd, "Error: Memory allocation failed\n"); + break; } + ast_cli(a->fd, "\n" + "%s -= Info about Config Option '%s:%s:%s' =- %s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n", + ast_term_color(COLOR_MAGENTA, 0), a->argv[3], a->argv[4], tmp->name, ast_term_reset(), + COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis, + COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since, + COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description, + COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax, + COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso + ); + ast_free(synopsis); + ast_free(since); + ast_free(description); + ast_free(syntax); + ast_free(seealso); + match = 1; } } diff --git a/main/manager.c b/main/manager.c index 2a543151b2..7fe245335f 100644 --- a/main/manager.c +++ b/main/manager.c @@ -1084,10 +1084,6 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_ int num; int l; const char *auth_str; -#ifdef AST_XML_DOCS - char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64]; - char arguments_title[64], privilege_title[64], final_response_title[64], list_responses_title[64]; -#endif switch (cmd) { case CLI_INIT: @@ -1115,18 +1111,6 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_ authority = ast_str_alloca(MAX_AUTH_PERM_STRING); -#ifdef AST_XML_DOCS - /* setup the titles */ - term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); - term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40); - term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40); - term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40); - term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40); - term_color(privilege_title, "[Privilege]\n", COLOR_MAGENTA, 0, 40); - term_color(final_response_title, "[Final Response]\n", COLOR_MAGENTA, 0, 40); - term_color(list_responses_title, "[List Responses]\n", COLOR_MAGENTA, 0, 40); -#endif - AST_RWLIST_RDLOCK(&actions); AST_RWLIST_TRAVERSE(&actions, cur, list) { for (num = 3; num < a->argc; num++) { @@ -1135,22 +1119,24 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_ #ifdef AST_XML_DOCS if (cur->docsrc == AST_XML_DOC) { - char *syntax = ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1); char *synopsis = ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1); + char *since = ast_xmldoc_printable(S_OR(cur->since, "Not available"), 1); char *description = ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1); + char *syntax = ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1); char *arguments = ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1); - char *seealso = ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1); char *privilege = ast_xmldoc_printable(S_OR(auth_str, "Not available"), 1); + char *seealso = ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1); char *responses = ast_xmldoc_printable("None", 1); - if (!syntax || !synopsis || !description || !arguments - || !seealso || !privilege || !responses) { - ast_free(syntax); + if (!synopsis || !since || !description || !syntax || !arguments + || !privilege || !seealso || !responses) { ast_free(synopsis); + ast_free(since); ast_free(description); + ast_free(syntax); ast_free(arguments); - ast_free(seealso); ast_free(privilege); + ast_free(seealso); ast_free(responses); ast_cli(a->fd, "Allocation failure.\n"); AST_RWLIST_UNLOCK(&actions); @@ -1158,14 +1144,33 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_ return CLI_FAILURE; } - ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s", - syntax_title, syntax, - synopsis_title, synopsis, - description_title, description, - arguments_title, arguments, - seealso_title, seealso, - privilege_title, privilege, - list_responses_title); + ast_cli(a->fd, "\n" + "%s -= Info about Manager Command '%s' =- %s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n", + ast_term_color(COLOR_MAGENTA, 0), cur->action, ast_term_reset(), + COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis, + COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since, + COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description, + COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax, + COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments, + COLORIZE(COLOR_MAGENTA, 0, "[Privilege]"), privilege, + COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso, + COLORIZE(COLOR_MAGENTA, 0, "[List Responses]") + ); if (!cur->list_responses) { ast_cli(a->fd, "%s\n\n", responses); @@ -1176,22 +1181,33 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_ print_event_instance(a, temp); } } - - ast_cli(a->fd, "%s", final_response_title); - + ast_cli(a->fd, + COLORIZE_FMT "\n", + COLORIZE(COLOR_MAGENTA, 0, "[End List Responses]") + ); + + ast_cli(a->fd, "\n" + COLORIZE_FMT "\n", + COLORIZE(COLOR_MAGENTA, 0, "[Final Response]") + ); if (!cur->final_response) { ast_cli(a->fd, "%s\n\n", responses); } else { ast_cli(a->fd, "Event: %s\n", cur->final_response->name); print_event_instance(a, cur->final_response); } + ast_cli(a->fd, + COLORIZE_FMT "\n", + COLORIZE(COLOR_MAGENTA, 0, "[End Final Response]") + ); - ast_free(syntax); ast_free(synopsis); + ast_free(since); ast_free(description); + ast_free(syntax); ast_free(arguments); - ast_free(seealso); ast_free(privilege); + ast_free(seealso); ast_free(responses); } else #endif @@ -7754,6 +7770,11 @@ int ast_manager_register2(const char *action, int auth, int (*func)(struct manse return -1; } + if (ast_string_field_init_extended(cur, since)) { + ao2_t_ref(cur, -1, "action object creation failed"); + return -1; + } + cur->action = action; cur->authority = auth; cur->func = func; @@ -7762,6 +7783,10 @@ int ast_manager_register2(const char *action, int auth, int (*func)(struct manse if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { char *tmpxml; + tmpxml = ast_xmldoc_build_since("manager", action, NULL); + ast_string_field_set(cur, since, tmpxml); + ast_free(tmpxml); + tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL); ast_string_field_set(cur, synopsis, tmpxml); ast_free(tmpxml); @@ -9174,39 +9199,50 @@ static char *handle_manager_show_events(struct ast_cli_entry *e, int cmd, struct static void print_event_instance(struct ast_cli_args *a, struct ast_xml_doc_item *instance) { - char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64]; - - term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); - term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40); - term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40); - term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40); - term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40); - - if (!ast_strlen_zero(ast_str_buffer(instance->synopsis))) { - char *synopsis = ast_xmldoc_printable(ast_str_buffer(instance->synopsis), 1); - ast_cli(a->fd, "%s%s\n\n", synopsis_title, synopsis); - ast_free(synopsis); - } - if (!ast_strlen_zero(ast_str_buffer(instance->syntax))) { - char *syntax = ast_xmldoc_printable(ast_str_buffer(instance->syntax), 1); - ast_cli(a->fd, "%s%s\n\n", syntax_title, syntax); - ast_free(syntax); - } - if (!ast_strlen_zero(ast_str_buffer(instance->description))) { - char *description = ast_xmldoc_printable(ast_str_buffer(instance->description), 1); - ast_cli(a->fd, "%s%s\n\n", description_title, description); - ast_free(description); - } - if (!ast_strlen_zero(ast_str_buffer(instance->arguments))) { - char *arguments = ast_xmldoc_printable(ast_str_buffer(instance->arguments), 1); - ast_cli(a->fd, "%s%s\n\n", arguments_title, arguments); - ast_free(arguments); - } - if (!ast_strlen_zero(ast_str_buffer(instance->seealso))) { - char *seealso = ast_xmldoc_printable(ast_str_buffer(instance->seealso), 1); - ast_cli(a->fd, "%s%s\n\n", seealso_title, seealso); - ast_free(seealso); - } + char *since, *syntax, *description, *synopsis, *seealso, *arguments; + + synopsis = ast_xmldoc_printable(AS_OR(instance->synopsis, "Not available"), 1); + since = ast_xmldoc_printable(AS_OR(instance->since, "Not available"), 1); + description = ast_xmldoc_printable(AS_OR(instance->description, "Not available"), 1); + syntax = ast_xmldoc_printable(AS_OR(instance->syntax, "Not available"), 1); + arguments = ast_xmldoc_printable(AS_OR(instance->arguments, "Not available"), 1); + seealso = ast_xmldoc_printable(AS_OR(instance->seealso, "Not available"), 1); + + if (!synopsis || !since || !description || !syntax || !arguments || !seealso) { + ast_cli(a->fd, "Error: Memory allocation failed\n"); + goto free_docs; + } + + ast_cli(a->fd, "\n" + "%s -= Info about Manager Event '%s' =- %s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n", + ast_term_color(COLOR_MAGENTA, 0), instance->name, ast_term_reset(), + COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis, + COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since, + COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description, + COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax, + COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments, + COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso + ); + +free_docs: + ast_free(synopsis); + ast_free(since); + ast_free(description); + ast_free(syntax); + ast_free(arguments); + ast_free(seealso); } static char *handle_manager_show_event(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) diff --git a/main/pbx_app.c b/main/pbx_app.c index ecbca1d85f..9b2068d29f 100644 --- a/main/pbx_app.c +++ b/main/pbx_app.c @@ -46,6 +46,7 @@ struct ast_app { int (*execute)(struct ast_channel *chan, const char *data); AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(synopsis); /*!< Synopsis text for 'show applications' */ + AST_STRING_FIELD(since); /*!< Since text for 'show applications' */ AST_STRING_FIELD(description); /*!< Description (help text) for 'show application <name>' */ AST_STRING_FIELD(syntax); /*!< Syntax text for 'core show applications' */ AST_STRING_FIELD(arguments); /*!< Arguments description */ @@ -142,6 +143,11 @@ int ast_register_application2(const char *app, int (*execute)(struct ast_channel ast_string_field_set(tmp, synopsis, tmpxml); ast_free(tmpxml); + /* load since */ + tmpxml = ast_xmldoc_build_since("application", app, ast_module_name(tmp->module)); + ast_string_field_set(tmp, since, tmpxml); + ast_free(tmpxml); + /* load description */ tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module)); ast_string_field_set(tmp, description, tmpxml); @@ -191,67 +197,61 @@ int ast_register_application2(const char *app, int (*execute)(struct ast_channel static void print_app_docs(struct ast_app *aa, int fd) { + char *synopsis = NULL, *since = NULL, *description = NULL, *syntax = NULL, *arguments = NULL, *seealso = NULL; + #ifdef AST_XML_DOCS - char *synopsis = NULL, *description = NULL, *arguments = NULL, *seealso = NULL; if (aa->docsrc == AST_XML_DOC) { synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1); + since = ast_xmldoc_printable(S_OR(aa->since, "Not available"), 1); description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1); + syntax = ast_xmldoc_printable(S_OR(aa->syntax, "Not available"), 1); arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1); seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1); - if (!synopsis || !description || !arguments || !seealso) { - goto free_docs; - } - ast_cli(fd, "\n" - "%s -= Info about application '%s' =- %s\n\n" - COLORIZE_FMT "\n" - "%s\n\n" - COLORIZE_FMT "\n" - "%s\n\n" - COLORIZE_FMT "\n" - "%s%s%s\n\n" - COLORIZE_FMT "\n" - "%s\n\n" - COLORIZE_FMT "\n" - "%s\n", - ast_term_color(COLOR_MAGENTA, 0), aa->name, ast_term_reset(), - COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis, - COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description, - COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), - ast_term_color(COLOR_CYAN, 0), S_OR(aa->syntax, "Not available"), ast_term_reset(), - COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments, - COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso); -free_docs: - ast_free(synopsis); - ast_free(description); - ast_free(arguments); - ast_free(seealso); } else #endif { - ast_cli(fd, "\n" - "%s -= Info about application '%s' =- %s\n\n" - COLORIZE_FMT "\n" - COLORIZE_FMT "\n\n" - COLORIZE_FMT "\n" - COLORIZE_FMT "\n\n" - COLORIZE_FMT "\n" - COLORIZE_FMT "\n\n" - COLORIZE_FMT "\n" - COLORIZE_FMT "\n\n" - COLORIZE_FMT "\n" - COLORIZE_FMT "\n", - ast_term_color(COLOR_MAGENTA, 0), aa->name, ast_term_reset(), - COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), - COLORIZE(COLOR_CYAN, 0, S_OR(aa->synopsis, "Not available")), - COLORIZE(COLOR_MAGENTA, 0, "[Description]"), - COLORIZE(COLOR_CYAN, 0, S_OR(aa->description, "Not available")), - COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), - COLORIZE(COLOR_CYAN, 0, S_OR(aa->syntax, "Not available")), - COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), - COLORIZE(COLOR_CYAN, 0, S_OR(aa->arguments, "Not available")), - COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), - COLORIZE(COLOR_CYAN, 0, S_OR(aa->seealso, "Not available"))); + synopsis = ast_strdup(S_OR(aa->synopsis, "Not Available")); + since = ast_strdup(S_OR(aa->since, "Not Available")); + description = ast_strdup(S_OR(aa->description, "Not Available")); + syntax = ast_strdup(S_OR(aa->syntax, "Not Available")); + arguments = ast_strdup(S_OR(aa->arguments, "Not Available")); + seealso = ast_strdup(S_OR(aa->seealso, "Not Available")); } + /* check allocated memory. */ + if (!synopsis || !since || !description || !syntax || !arguments || !seealso) { + goto free_docs; + } + + ast_cli(fd, "\n" + "%s -= Info about Application '%s' =- %s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n", + ast_term_color(COLOR_MAGENTA, 0), aa->name, ast_term_reset(), + COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis, + COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since, + COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description, + COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax, + COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments, + COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso + ); + +free_docs: + ast_free(synopsis); + ast_free(since); + ast_free(description); + ast_free(syntax); + ast_free(arguments); + ast_free(seealso); } /*! diff --git a/main/pbx_functions.c b/main/pbx_functions.c index 1402696b6b..a244ddcc08 100644 --- a/main/pbx_functions.c +++ b/main/pbx_functions.c @@ -144,10 +144,8 @@ static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_c { struct ast_custom_function *acf; /* Maximum number of characters added by terminal coloring is 22 */ - char infotitle[64 + AST_MAX_APP + 22], syntitle[40], desctitle[40], argtitle[40], seealsotitle[40]; - char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL; - char stxtitle[40], *syntax = NULL, *arguments = NULL; - int syntax_size, description_size, synopsis_size, arguments_size, seealso_size; + char *synopsis = NULL, *since = NULL, *description = NULL, *syntax = NULL, *arguments = NULL, *seealso = NULL; + char *rtn = CLI_SUCCESS; switch (cmd) { case CLI_INIT: @@ -170,71 +168,62 @@ static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_c return CLI_FAILURE; } - syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; - syntax = ast_malloc(syntax_size); - if (!syntax) { - ast_cli(a->fd, "Memory allocation failure!\n"); - - return CLI_FAILURE; - } - - snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name); - term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); - term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); - term_color(desctitle, "[Description]\n", COLOR_MAGENTA, 0, 40); - term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); - term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); - term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); - term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); #ifdef AST_XML_DOCS if (acf->docsrc == AST_XML_DOC) { - arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1); synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1); + since = ast_xmldoc_printable(S_OR(acf->since, "Not available"), 1); description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1); + syntax = ast_xmldoc_printable(S_OR(acf->syntax, "Not available"), 1); + arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1); seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1); } else #endif { - synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; - synopsis = ast_malloc(synopsis_size); - - description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; - description = ast_malloc(description_size); - - arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; - arguments = ast_malloc(arguments_size); - - seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; - seealso = ast_malloc(seealso_size); - - /* check allocated memory. */ - if (!synopsis || !description || !arguments || !seealso) { - ast_free(synopsis); - ast_free(description); - ast_free(arguments); - ast_free(seealso); - ast_free(syntax); - - return CLI_FAILURE; - } - - term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); - term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); - term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size); - term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); + synopsis = ast_strdup(S_OR(acf->synopsis, "Not Available")); + since = ast_strdup(S_OR(acf->since, "Not Available")); + description = ast_strdup(S_OR(acf->desc, "Not Available")); + syntax = ast_strdup(S_OR(acf->syntax, "Not Available")); + arguments = ast_strdup(S_OR(acf->arguments, "Not Available")); + seealso = ast_strdup(S_OR(acf->seealso, "Not Available")); } - - ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", - infotitle, syntitle, synopsis, desctitle, description, - stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); - - ast_free(arguments); + /* check allocated memory. */ + if (!synopsis || !since || !description || !syntax || !arguments || !seealso) { + rtn = CLI_FAILURE; + goto free_docs; + } + + ast_cli(a->fd, "\n" + "%s -= Info about Function '%s' =- %s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n", + ast_term_color(COLOR_MAGENTA, 0), acf->name, ast_term_reset(), + COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis, + COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since, + COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description, + COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax, + COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments, + COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso + ); + +free_docs: ast_free(synopsis); + ast_free(since); ast_free(description); - ast_free(seealso); ast_free(syntax); + ast_free(arguments); + ast_free(seealso); - return CLI_SUCCESS; + return rtn; } static struct ast_custom_function *ast_custom_function_find_nolock(const char *name) @@ -339,11 +328,21 @@ static int acf_retrieve_docs(struct ast_custom_function *acf) return -1; } + if (ast_string_field_init_extended(acf, since)) { + ast_string_field_free_memory(acf); + return -1; + } + /* load synopsis */ tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod)); ast_string_field_set(acf, synopsis, tmpxml); ast_free(tmpxml); + /* load since */ + tmpxml = ast_xmldoc_build_since("function", acf->name, ast_module_name(acf->mod)); + ast_string_field_set(acf, since, tmpxml); + ast_free(tmpxml); + /* load description */ tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod)); ast_string_field_set(acf, desc, tmpxml); diff --git a/main/xmldoc.c b/main/xmldoc.c index 2b75523402..a960addb36 100644 --- a/main/xmldoc.c +++ b/main/xmldoc.c @@ -1722,6 +1722,91 @@ char *ast_xmldoc_build_seealso(const char *type, const char *name, const char *m return output; } +/*! + * \internal + * \brief Build since information for an item + * + * \param node The since node to parse + * + * \note This method exists for when you already have the node. This + * prevents having to lock the documentation tree twice + * + * \retval A malloc'd character pointer to the since information of the item + * \retval NULL on failure + * + * \since 22 + */ +static char *_ast_xmldoc_build_since(struct ast_xml_node *node) +{ + char *output; + struct ast_str *outputstr; + const char *content; + int first = 1; + + /* Find the node. */ + for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) { + if (!strcasecmp(ast_xml_node_get_name(node), "since")) { + break; + } + } + + if (!node || !ast_xml_node_get_children(node)) { + /* we couldnt find a node. */ + return NULL; + } + + /* prepare the output string. */ + outputstr = ast_str_create(128); + if (!outputstr) { + return NULL; + } + + /* get into the node. */ + for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) { + if (strcasecmp(ast_xml_node_get_name(node), "version")) { + continue; + } + + content = ast_xml_get_text(node); + if (!content) { + continue; + } + + ast_str_append(&outputstr, 0, "%s%s", (first ? "" : ", "), content); + + first = 0; + ast_xml_free_text(content); + } + + output = ast_strdup(ast_str_buffer(outputstr)); + ast_free(outputstr); + + return output; +} + +char *ast_xmldoc_build_since(const char *type, const char *name, const char *module) +{ + char *output; + struct ast_xml_node *node; + + if (ast_strlen_zero(type) || ast_strlen_zero(name)) { + return NULL; + } + + /* get the application/function root node. */ + AST_RWLIST_RDLOCK(&xmldoc_tree); + node = xmldoc_get_node(type, name, module, documentation_language); + if (!node || !ast_xml_node_get_children(node)) { + AST_RWLIST_UNLOCK(&xmldoc_tree); + return NULL; + } + + output = _ast_xmldoc_build_since(node); + AST_RWLIST_UNLOCK(&xmldoc_tree); + + return output; +} + /*! * \internal * \brief Parse a \ node. @@ -2286,11 +2371,12 @@ static void ast_xml_doc_item_destructor(void *obj) return; } - ast_free(doc->syntax); - ast_free(doc->seealso); - ast_free(doc->arguments); ast_free(doc->synopsis); + ast_free(doc->since); ast_free(doc->description); + ast_free(doc->syntax); + ast_free(doc->arguments); + ast_free(doc->seealso); ast_string_field_free_memory(doc); if (AST_LIST_NEXT(doc, next)) { @@ -2318,11 +2404,13 @@ static struct ast_xml_doc_item *ast_xml_doc_item_alloc(const char *name, const c return NULL; } - if ( !(item->syntax = ast_str_create(128)) - || !(item->seealso = ast_str_create(128)) + if ( !(item->synopsis = ast_str_create(128)) + || !(item->since = ast_str_create(128)) + || !(item->description = ast_str_create(128)) + || !(item->syntax = ast_str_create(128)) || !(item->arguments = ast_str_create(128)) - || !(item->synopsis = ast_str_create(128)) - || !(item->description = ast_str_create(128))) { + || !(item->seealso = ast_str_create(128)) + ) { ast_log(AST_LOG_ERROR, "Failed to allocate strings for ast_xml_doc_item instance\n"); goto ast_xml_doc_item_failure; } @@ -2381,44 +2469,50 @@ static int ast_xml_doc_item_cmp(void *obj, void *arg, int flags) static struct ast_xml_doc_item *xmldoc_build_documentation_item(struct ast_xml_node *node, const char *name, const char *type) { struct ast_xml_doc_item *item; - char *syntax; - char *seealso; - char *arguments; char *synopsis; + char *since; char *description; + char *syntax; + char *arguments; + char *seealso; if (!(item = ast_xml_doc_item_alloc(name, type))) { return NULL; } item->node = node; - syntax = _ast_xmldoc_build_syntax(node, type, name); - seealso = _ast_xmldoc_build_seealso(node); - arguments = _ast_xmldoc_build_arguments(node); synopsis = _ast_xmldoc_build_synopsis(node); + since = _ast_xmldoc_build_since(node); description = _ast_xmldoc_build_description(node); + syntax = _ast_xmldoc_build_syntax(node, type, name); + arguments = _ast_xmldoc_build_arguments(node); + seealso = _ast_xmldoc_build_seealso(node); + if (synopsis) { + ast_str_set(&item->synopsis, 0, "%s", synopsis); + } + if (since) { + ast_str_set(&item->since, 0, "%s", since); + } + if (description) { + ast_str_set(&item->description, 0, "%s", description); + } if (syntax) { ast_str_set(&item->syntax, 0, "%s", syntax); } - if (seealso) { - ast_str_set(&item->seealso, 0, "%s", seealso); - } if (arguments) { ast_str_set(&item->arguments, 0, "%s", arguments); } - if (synopsis) { - ast_str_set(&item->synopsis, 0, "%s", synopsis); - } - if (description) { - ast_str_set(&item->description, 0, "%s", description); + if (seealso) { + ast_str_set(&item->seealso, 0, "%s", seealso); } - ast_free(syntax); - ast_free(seealso); - ast_free(arguments); ast_free(synopsis); + ast_free(since); ast_free(description); + ast_free(syntax); + ast_free(arguments); + ast_free(seealso); return item; } diff --git a/res/res_agi.c b/res/res_agi.c index b3eb8034d6..f008139611 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -3834,8 +3834,10 @@ int AST_OPTIONAL_API_NAME(ast_agi_register)(struct ast_module *mod, agi_command if (ast_strlen_zero(cmd->summary) && ast_strlen_zero(cmd->usage)) { #ifdef AST_XML_DOCS *((char **) &cmd->summary) = ast_xmldoc_build_synopsis("agi", fullcmd, NULL); + *((char **) &cmd->since) = ast_xmldoc_build_since("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->arguments) = ast_xmldoc_build_arguments("agi", fullcmd, NULL); *((char **) &cmd->seealso) = ast_xmldoc_build_seealso("agi", fullcmd, NULL); *((enum ast_doc_src *) &cmd->docsrc) = AST_XML_DOC; #endif @@ -3882,12 +3884,16 @@ int AST_OPTIONAL_API_NAME(ast_agi_unregister)(agi_command *cmd) #ifdef AST_XML_DOCS if (e->docsrc == AST_XML_DOC) { ast_free((char *) e->summary); + ast_free((char *) e->since); ast_free((char *) e->usage); ast_free((char *) e->syntax); + ast_free((char *) e->arguments); ast_free((char *) e->seealso); *((char **) &e->summary) = NULL; + *((char **) &e->since) = NULL; *((char **) &e->usage) = NULL; *((char **) &e->syntax) = NULL; + *((char **) &e->arguments) = NULL; *((char **) &e->seealso) = NULL; } #endif @@ -4346,72 +4352,66 @@ static char *handle_cli_agi_show(struct ast_cli_entry *e, int cmd, struct ast_cl if (a->argc > e->args - 1) { command = find_command(a->argv + e->args, 1); if (command) { - char *synopsis = NULL, *description = NULL, *syntax = NULL, *seealso = NULL; - char info[30 + MAX_CMD_LEN]; /* '-= Info about...' */ - char infotitle[30 + MAX_CMD_LEN + AST_TERM_MAX_ESCAPE_CHARS]; /* '-= Info about...' with colors */ - char syntitle[11 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */ - char desctitle[15 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Description]\n with colors */ - char deadtitle[13 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Runs Dead]\n with colors */ - char deadcontent[3 + AST_TERM_MAX_ESCAPE_CHARS]; /* 'Yes' or 'No' with colors */ - char seealsotitle[12 + AST_TERM_MAX_ESCAPE_CHARS]; /* [See Also]\n with colors */ - char stxtitle[10 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */ - size_t synlen, desclen, seealsolen, stxlen; - - term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, sizeof(syntitle)); - term_color(desctitle, "[Description]\n", COLOR_MAGENTA, 0, sizeof(desctitle)); - term_color(deadtitle, "[Runs Dead]\n", COLOR_MAGENTA, 0, sizeof(deadtitle)); - term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, sizeof(seealsotitle)); - term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, sizeof(stxtitle)); - term_color(deadcontent, command->dead ? "Yes" : "No", COLOR_CYAN, 0, sizeof(deadcontent)); + char *synopsis = NULL, *since = NULL, *description = NULL, *syntax = NULL, *arguments = NULL, *seealso = NULL; ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args); - snprintf(info, sizeof(info), "\n -= Info about agi '%s' =- ", fullcmd); - term_color(infotitle, info, COLOR_CYAN, 0, sizeof(infotitle)); + #ifdef AST_XML_DOCS if (command->docsrc == AST_XML_DOC) { synopsis = ast_xmldoc_printable(S_OR(command->summary, "Not available"), 1); + since = ast_xmldoc_printable(S_OR(command->since, "Not available"), 1); description = ast_xmldoc_printable(S_OR(command->usage, "Not available"), 1); + syntax = ast_xmldoc_printable(S_OR(command->syntax, "Not available"), 1); + arguments = ast_xmldoc_printable(S_OR(command->arguments, "Not available"), 1); seealso = ast_xmldoc_printable(S_OR(command->seealso, "Not available"), 1); - if (!seealso || !description || !synopsis) { - error = 1; - goto return_cleanup; - } } else #endif { - synlen = strlen(S_OR(command->summary, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS; - synopsis = ast_malloc(synlen); - - desclen = strlen(S_OR(command->usage, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS; - description = ast_malloc(desclen); - - seealsolen = strlen(S_OR(command->seealso, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS; - seealso = ast_malloc(seealsolen); - - if (!synopsis || !description || !seealso) { - error = 1; - goto return_cleanup; - } - term_color(synopsis, S_OR(command->summary, "Not available"), COLOR_CYAN, 0, synlen); - term_color(description, S_OR(command->usage, "Not available"), COLOR_CYAN, 0, desclen); - term_color(seealso, S_OR(command->seealso, "Not available"), COLOR_CYAN, 0, seealsolen); + synopsis = ast_strdup(S_OR(command->summary, "Not Available")); + since = ast_strdup(S_OR(command->since, "Not Available")); + description = ast_strdup(S_OR(command->usage, "Not Available")); + syntax = ast_strdup(S_OR(command->syntax, "Not Available")); + arguments = ast_strdup(S_OR(command->arguments, "Not Available")); + seealso = ast_strdup(S_OR(command->seealso, "Not Available")); } - stxlen = strlen(S_OR(command->syntax, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS; - syntax = ast_malloc(stxlen); - if (!syntax) { + if (!synopsis || !since || !description || !syntax || !arguments || !seealso) { error = 1; goto return_cleanup; } - term_color(syntax, S_OR(command->syntax, "Not available"), COLOR_CYAN, 0, stxlen); - ast_cli(a->fd, "%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n", infotitle, stxtitle, syntax, - desctitle, description, syntitle, synopsis, deadtitle, deadcontent, - seealsotitle, seealso); + ast_cli(a->fd, "\n" + "%s -= Info about AGI '%s' =- %s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n" + COLORIZE_FMT "\n" + "%s\n\n", + ast_term_color(COLOR_MAGENTA, 0), fullcmd, ast_term_reset(), + COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis, + COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since, + COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description, + COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax, + COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments, + COLORIZE(COLOR_MAGENTA, 0, "[Runs Dead]"), command->dead ? "Yes" : "No", + COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso + ); + return_cleanup: ast_free(synopsis); + ast_free(since); ast_free(description); ast_free(syntax); + ast_free(arguments); ast_free(seealso); } else { if (find_command(a->argv + e->args, -1)) { diff --git a/rest-api-templates/api.wiki.mustache b/rest-api-templates/api.wiki.mustache index 2680645822..57da975901 100644 --- a/rest-api-templates/api.wiki.mustache +++ b/rest-api-templates/api.wiki.mustache @@ -1,11 +1,14 @@ {{#api_declaration}} # {{name_title}} +{{#since}} +## Since: {{since}} +{{/since}} -| Method | Path (Parameters are case-sensitive) | Return Model | Summary | -|:------ |:------------------------------------ |:------------ |:------- | +| Method | Path (Parameters are case-sensitive) | Return Model | Summary | Since | +|:------ |:------------------------------------ |:------------ |:------- |:----- | {{#apis}} {{#operations}} -| {{http_method}} | [{{wiki_path}}](#{{nickname_lc}}) | {{#response_class}}{{#is_primitive}}{{name}}{{/is_primitive}}{{^is_primitive}}[{{wiki_name}}]({{wiki_prefix}}Asterisk_REST_Data_Models#{{lc_singular_name}}){{/is_primitive}}{{/response_class}} | {{{summary}}} | +| {{http_method}} | [{{wiki_path}}](#{{nickname_lc}}) | {{#response_class}}{{#is_primitive}}{{name}}{{/is_primitive}}{{^is_primitive}}[{{wiki_name}}]({{wiki_prefix}}Asterisk_REST_Data_Models#{{lc_singular_name}}){{/is_primitive}}{{/response_class}} | {{{summary}}} | {{since}} | {{/operations}} {{/apis}} {{#apis}} @@ -14,6 +17,9 @@ --- [//]: # (anchor:{{nickname_lc}}) ## {{nickname}} +{{#since}} +### Since: {{since}} +{{/since}} ### {{http_method}} {{wiki_path}} {{{wiki_summary}}}{{#wiki_notes}} {{{wiki_notes}}}{{/wiki_notes}} {{#has_path_parameters}} diff --git a/rest-api-templates/swagger_model.py b/rest-api-templates/swagger_model.py index 23dcb8cbf1..cfc23a1851 100644 --- a/rest-api-templates/swagger_model.py +++ b/rest-api-templates/swagger_model.py @@ -373,6 +373,7 @@ class Operation(Stringify): self.summary = None self.notes = None self.error_responses = [] + self.since = [] def load(self, op_json, processor, context): context = context.next_stack(op_json, 'nickname') @@ -383,6 +384,8 @@ class Operation(Stringify): response_class = op_json.get('responseClass') self.response_class = response_class and SwaggerType().load( response_class, processor, context) + since = op_json.get('since') or [] + self.since = ", ".join(since) # Specifying WebSocket URL's is our own extension self.is_websocket = op_json.get('upgrade') == 'websocket' @@ -611,6 +614,7 @@ class ApiDeclaration(Stringify): self.api_version = None self.base_path = None self.resource_path = None + self.since = [] self.apis = [] self.models = [] @@ -658,6 +662,8 @@ class ApiDeclaration(Stringify): self.base_path = api_decl_json.get('basePath') self.resource_path = api_decl_json.get('resourcePath') self.requires_modules = api_decl_json.get('requiresModules') or [] + since = api_decl_json.get('since') or [] + self.since = ", ".join(since) api_json = api_decl_json.get('apis') or [] self.apis = [ Api().load(j, processor, context) for j in api_json]