Index: apps/app_stack.c =================================================================== --- apps/app_stack.c (revision 385038) +++ apps/app_stack.c (working copy) @@ -65,6 +65,25 @@ StackPop + + + Sets local variables to Gosub parameter values + + + + + + Loads arguments passed to current Gosub into LOCAL variables. + + + Gosub + GosubIf + Return + StackPop + Set + LOCAL + + Conditionally jump to label, saving return address. @@ -131,6 +150,24 @@ Gosub + + + Remove one address from gosub stack and performs a Goto + + + + + + + + Executes a StackPop followed by Goto. This allows the Goto destination + to be loaded from a LOCAL variable that is being discarded. + + + Gotos + StackPop + + Manage variables local to the gosub stack frame. @@ -207,10 +244,13 @@ static const char app_gosub[] = "Gosub"; static const char app_gosubif[] = "GosubIf"; +static const char app_gosubentry[] = "GosubEntry"; static const char app_return[] = "Return"; static const char app_pop[] = "StackPop"; +static const char app_popgoto[] = "StackPopGoto"; static void gosub_free(void *data); +static int local_write(struct ast_channel *chan, const char *cmd, char *var, const char *value); static const struct ast_datastore_info stack_info = { .type = "GOSUB", @@ -353,6 +393,15 @@ return res; } +static int popgoto_exec(struct ast_channel *chan, const char *data) +{ + pop_exec(chan, ""); + int res = ast_parseable_goto(chan, data); + if (!res) + ast_verb(3, "Goto (%s,%s,%d)\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan) + 1); + return res; +} + static int return_exec(struct ast_channel *chan, const char *data) { struct ast_datastore *stack_store; @@ -679,6 +728,38 @@ return res; } +static int gosubentry_exec(struct ast_channel *chan, const char *data) +{ + char *dcopy = strdupa(data); + char *iter; + int i = 0; + char argname[10]; + ast_channel_lock(chan); + if (!ast_channel_datastore_find(chan, &stack_info, NULL)) { + ast_log(LOG_ERROR, "Tried to run GosubEntry, but we aren't within a Gosub routine\n"); + ast_channel_unlock(chan); + return -1; + } + ast_channel_unlock(chan); + + if (ast_strlen_zero(data)) { + return 0; + } + + while((iter = strsep(&dcopy, ","))) { + const char *argval; + i++; + snprintf(&argname[0], 9, "ARG%d", i); + argval = pbx_builtin_getvar_helper(chan, &argname[0]); + ast_verb(6, "GosubEntry: %s=%s\n", iter, argval); + if(local_write(chan, NULL, iter, argval)) { + ast_log(LOG_ERROR, "Failed to write LOCAL variable\n"); + return -1; + } + } + return 0; +} + static int local_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) { struct ast_datastore *stack_store; @@ -1224,7 +1305,9 @@ ast_unregister_application(app_return); ast_unregister_application(app_pop); + ast_unregister_application(app_popgoto); ast_unregister_application(app_gosubif); + ast_unregister_application(app_gosubentry); ast_unregister_application(app_gosub); ast_custom_function_unregister(&local_function); ast_custom_function_unregister(&peek_function); @@ -1244,8 +1327,10 @@ ast_agi_register(ast_module_info->self, &gosub_agi_command); ast_register_application_xml(app_pop, pop_exec); + ast_register_application_xml(app_popgoto, popgoto_exec); ast_register_application_xml(app_return, return_exec); ast_register_application_xml(app_gosubif, gosubif_exec); + ast_register_application_xml(app_gosubentry, gosubentry_exec); ast_register_application_xml(app_gosub, gosub_exec); ast_custom_function_register(&local_function); ast_custom_function_register(&peek_function);