mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	Gosub arguments (Issue 7780)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@43667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * Asterisk -- An open source telephony toolkit. | ||||
|  * | ||||
|  * Copyright (c) 2004-2006 Tilghman Lesher <app_stack_v002@the-tilghman.com>. | ||||
|  * Copyright (c) 2004-2006 Tilghman Lesher <app_stack_v003@the-tilghman.com>. | ||||
|  * | ||||
|  * This code is released by the author with no restrictions on usage. | ||||
|  * | ||||
| @@ -20,7 +20,7 @@ | ||||
|  * | ||||
|  * \brief Stack applications Gosub, Return, etc. | ||||
|  * | ||||
|  * \author Tilghman Lesher <app_stack_v002@the-tilghman.com> | ||||
|  * \author Tilghman Lesher <app_stack_v003@the-tilghman.com> | ||||
|  *  | ||||
|  * \ingroup applications | ||||
|  */ | ||||
| @@ -41,6 +41,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | ||||
| #include "asterisk/pbx.h" | ||||
| #include "asterisk/module.h" | ||||
| #include "asterisk/config.h" | ||||
| #include "asterisk/app.h" | ||||
|  | ||||
| #define STACKVAR	"~GOSUB~STACK~" | ||||
|  | ||||
| @@ -56,10 +57,10 @@ static const char *return_synopsis = "Return from gosub routine"; | ||||
| static const char *pop_synopsis = "Remove one address from gosub stack"; | ||||
|  | ||||
| static const char *gosub_descrip = | ||||
| "Gosub([[context|]exten|]priority)\n" | ||||
| "Gosub([[context|]exten|]priority[:arg1[|...][|argN]])\n" | ||||
| "  Jumps to the label specified, saving the return address.\n"; | ||||
| static const char *gosubif_descrip = | ||||
| "GosubIf(condition?labeliftrue[:labeliffalse])\n" | ||||
| "GosubIf(condition?labeliftrue[:labeliffalse[:arg1[|...][|argN]]])\n" | ||||
| "  If the condition is true, then jump to labeliftrue.  If false, jumps to\n" | ||||
| "labeliffalse, if specified.  In either case, a jump saves the return point\n" | ||||
| "in the dialplan, to be returned to with a Return.\n"; | ||||
| @@ -73,6 +74,20 @@ static const char *pop_descrip = | ||||
|  | ||||
| static int pop_exec(struct ast_channel *chan, void *data) | ||||
| { | ||||
| 	const char *frame = pbx_builtin_getvar_helper(chan, STACKVAR); | ||||
| 	int numargs = 0, i; | ||||
| 	char argname[15]; | ||||
|  | ||||
| 	/* Pop any arguments for this stack frame off the variable stack */ | ||||
| 	if (frame) { | ||||
| 		numargs = atoi(frame); | ||||
| 		for (i = 1; i <= numargs; i++) { | ||||
| 			snprintf(argname, sizeof(argname), "ARG%d", i); | ||||
| 			pbx_builtin_setvar_helper(chan, argname, NULL); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* Remove the last frame from the Gosub stack */ | ||||
| 	pbx_builtin_setvar_helper(chan, STACKVAR, NULL); | ||||
|  | ||||
| 	return 0; | ||||
| @@ -81,37 +96,74 @@ static int pop_exec(struct ast_channel *chan, void *data) | ||||
| static int return_exec(struct ast_channel *chan, void *data) | ||||
| { | ||||
| 	const char *label = pbx_builtin_getvar_helper(chan, STACKVAR); | ||||
| 	char argname[15], *retval = data; | ||||
| 	int numargs, i; | ||||
|  | ||||
| 	if (ast_strlen_zero(label)) { | ||||
| 		ast_log(LOG_ERROR, "Return without Gosub: stack is empty\n"); | ||||
| 		return -1; | ||||
| 	} else if (ast_parseable_goto(chan, label)) { | ||||
| 	} | ||||
|  | ||||
| 	/* Pop any arguments for this stack frame off the variable stack */ | ||||
| 	numargs = atoi(label); | ||||
| 	for (i = 1; i <= numargs; i++) { | ||||
| 		snprintf(argname, sizeof(argname), "ARG%d", i); | ||||
| 		pbx_builtin_setvar_helper(chan, argname, NULL); | ||||
| 	} | ||||
|  | ||||
| 	/* If the label exists, it will always have a ':' */ | ||||
| 	label = strchr(label, ':') + 1; | ||||
|  | ||||
| 	if (ast_parseable_goto(chan, label)) { | ||||
| 		ast_log(LOG_WARNING, "No next statement after Gosub?\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* Remove the current frame from the Gosub stack */ | ||||
| 	pbx_builtin_setvar_helper(chan, STACKVAR, NULL); | ||||
|  | ||||
| 	/* Set a return value, if any */ | ||||
| 	pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", S_OR(retval, "")); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int gosub_exec(struct ast_channel *chan, void *data) | ||||
| { | ||||
| 	char newlabel[AST_MAX_EXTENSION * 2 + 3 + 11]; | ||||
| 	char newlabel[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 11 + 11 + 4]; | ||||
| 	char argname[15], *tmp = ast_strdupa(data); | ||||
| 	int i; | ||||
| 	struct ast_module_user *u; | ||||
| 	AST_DECLARE_APP_ARGS(args, | ||||
| 		AST_APP_ARG(label); | ||||
| 		AST_APP_ARG(args); | ||||
| 	); | ||||
| 	AST_DECLARE_APP_ARGS(args2, | ||||
| 		AST_APP_ARG(argval)[100]; | ||||
| 	); | ||||
|  | ||||
| 	if (ast_strlen_zero(data)) { | ||||
| 		ast_log(LOG_ERROR, "%s requires an argument: %s([[context|]exten|]priority)\n", app_gosub, app_gosub); | ||||
| 		ast_log(LOG_ERROR, "%s requires an argument: %s([[context|]exten|]priority[:arg1[|...][|argN]])\n", app_gosub, app_gosub); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	u = ast_module_user_add(chan); | ||||
| 	snprintf(newlabel, sizeof(newlabel), "%s|%s|%d", chan->context, chan->exten, chan->priority + 1); | ||||
|  | ||||
| 	AST_NONSTANDARD_APP_ARGS(args, tmp, ':'); | ||||
| 	AST_STANDARD_APP_ARGS(args2, args.args); | ||||
|  | ||||
| 	snprintf(newlabel, sizeof(newlabel), "%d:%s|%s|%d", args2.argc, chan->context, chan->exten, chan->priority + 1); | ||||
|  | ||||
| 	if (ast_parseable_goto(chan, data)) { | ||||
| 		ast_module_user_remove(u); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* Now that we know for certain that we're going to a new location, set our arguments */ | ||||
| 	for (i = 0; i < args2.argc; i++) { | ||||
| 		snprintf(argname, sizeof(argname), "ARG%d", i + 1); | ||||
| 		pbx_builtin_pushvar_helper(chan, argname, args2.argval[i]); | ||||
| 	} | ||||
|  | ||||
| 	pbx_builtin_pushvar_helper(chan, STACKVAR, newlabel); | ||||
| 	ast_module_user_remove(u); | ||||
|  | ||||
| @@ -135,14 +187,22 @@ static int gosubif_exec(struct ast_channel *chan, void *data) | ||||
|  | ||||
| 	condition = strsep(&args, "?"); | ||||
| 	label1 = strsep(&args, ":"); | ||||
| 	label2 = args; | ||||
| 	label2 = strsep(&args, ":"); | ||||
|  | ||||
| 	if (pbx_checkcondition(condition)) { | ||||
| 		if (label1) { | ||||
| 			res = gosub_exec(chan, label1); | ||||
| 			int len = (args ? strlen(args) : 0) + strlen(label1) + 2; | ||||
| 			char *args2 = alloca(len); | ||||
|  | ||||
| 			snprintf(args2, len, "%s%c%s", label1, args ? ':' : '\0', args ? args : ""); | ||||
| 			res = gosub_exec(chan, args2); | ||||
| 		} | ||||
| 	} else if (label2) { | ||||
| 		res = gosub_exec(chan, label2); | ||||
| 		int len = (args ? strlen(args) : 0) + strlen(label2) + 2; | ||||
| 		char *args2 = alloca(len); | ||||
|  | ||||
| 		snprintf(args2, len, "%s%c%s", label2, args ? ':' : '\0', args ? args : ""); | ||||
| 		res = gosub_exec(chan, args2); | ||||
| 	} | ||||
|  | ||||
| 	ast_module_user_remove(u); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user