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.
+
+
+ [Goto]s
+ [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);