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);