#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk/options.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/chanvars.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/app.h"
Include dependency graph for app_stack.c:
Go to the source code of this file.
Defines | |
#define | STACKVAR "~GOSUB~STACK~" |
Functions | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Stack Routines") | |
static int | gosub_exec (struct ast_channel *chan, void *data) |
static int | gosubif_exec (struct ast_channel *chan, void *data) |
static int | load_module (void) |
static int | pop_exec (struct ast_channel *chan, void *data) |
static int | return_exec (struct ast_channel *chan, void *data) |
static int | unload_module (void) |
Variables | |
static const char * | app_gosub = "Gosub" |
static const char * | app_gosubif = "GosubIf" |
static const char * | app_pop = "StackPop" |
static const char * | app_return = "Return" |
static const char * | gosub_descrip |
static const char * | gosub_synopsis = "Jump to label, saving return address" |
static const char * | gosubif_descrip |
static const char * | gosubif_synopsis = "Conditionally jump to label, saving return address" |
static const char * | pop_descrip |
static const char * | pop_synopsis = "Remove one address from gosub stack" |
static const char * | return_descrip |
static const char * | return_synopsis = "Return from gosub routine" |
Definition in file app_stack.c.
#define STACKVAR "~GOSUB~STACK~" |
Definition at line 46 of file app_stack.c.
Referenced by gosub_exec(), pop_exec(), and return_exec().
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Stack Routines" | ||||
) |
static int gosub_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 131 of file app_stack.c.
References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_module_user_add, ast_module_user_remove, ast_parseable_goto(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_module_user::chan, ast_channel::context, ast_channel::exten, LOG_DEBUG, LOG_ERROR, LOG_WARNING, pbx_builtin_pushvar_helper(), ast_channel::priority, STACKVAR, and strsep().
Referenced by gosubif_exec(), and load_module().
00132 { 00133 char newlabel[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 11 + 11 + 4]; 00134 char argname[15], *tmp = ast_strdupa(data), *label, *endparen; 00135 int i; 00136 struct ast_module_user *u; 00137 AST_DECLARE_APP_ARGS(args2, 00138 AST_APP_ARG(argval)[100]; 00139 ); 00140 00141 if (ast_strlen_zero(data)) { 00142 ast_log(LOG_ERROR, "%s requires an argument: %s([[context|]exten|]priority[(arg1[|...][|argN])])\n", app_gosub, app_gosub); 00143 return -1; 00144 } 00145 00146 u = ast_module_user_add(chan); 00147 00148 /* Separate the arguments from the label */ 00149 /* NOTE: you cannot use ast_app_separate_args for this, because '(' cannot be used as a delimiter. */ 00150 label = strsep(&tmp, "("); 00151 if (tmp) { 00152 endparen = strrchr(tmp, ')'); 00153 if (endparen) 00154 *endparen = '\0'; 00155 else 00156 ast_log(LOG_WARNING, "Ouch. No closing paren: '%s'?\n", (char *)data); 00157 AST_STANDARD_APP_ARGS(args2, tmp); 00158 } else 00159 args2.argc = 0; 00160 00161 /* Create the return address, but don't save it until we know that the Gosub destination exists */ 00162 snprintf(newlabel, sizeof(newlabel), "%d:%s|%s|%d", args2.argc, chan->context, chan->exten, chan->priority + 1); 00163 00164 if (ast_parseable_goto(chan, label)) { 00165 ast_log(LOG_ERROR, "Gosub address is invalid: '%s'\n", (char *)data); 00166 ast_module_user_remove(u); 00167 return -1; 00168 } 00169 00170 /* Now that we know for certain that we're going to a new location, set our arguments */ 00171 for (i = 0; i < args2.argc; i++) { 00172 snprintf(argname, sizeof(argname), "ARG%d", i + 1); 00173 pbx_builtin_pushvar_helper(chan, argname, args2.argval[i]); 00174 ast_log(LOG_DEBUG, "Setting '%s' to '%s'\n", argname, args2.argval[i]); 00175 } 00176 00177 /* And finally, save our return address */ 00178 pbx_builtin_pushvar_helper(chan, STACKVAR, newlabel); 00179 ast_log(LOG_DEBUG, "Setting gosub return address to '%s'\n", newlabel); 00180 ast_module_user_remove(u); 00181 00182 return 0; 00183 }
static int gosubif_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 185 of file app_stack.c.
References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_module_user_add, ast_module_user_remove, AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_module_user::chan, cond, gosub_exec(), LOG_WARNING, and pbx_checkcondition().
Referenced by load_module().
00186 { 00187 struct ast_module_user *u; 00188 char *args; 00189 int res=0; 00190 AST_DECLARE_APP_ARGS(cond, 00191 AST_APP_ARG(ition); 00192 AST_APP_ARG(labels); 00193 ); 00194 AST_DECLARE_APP_ARGS(label, 00195 AST_APP_ARG(iftrue); 00196 AST_APP_ARG(iffalse); 00197 ); 00198 00199 if (ast_strlen_zero(data)) { 00200 ast_log(LOG_WARNING, "GosubIf requires an argument: GosubIf(cond?label1(args):label2(args)\n"); 00201 return 0; 00202 } 00203 00204 u = ast_module_user_add(chan); 00205 00206 args = ast_strdupa(data); 00207 AST_NONSTANDARD_APP_ARGS(cond, args, '?'); 00208 if (cond.argc != 2) { 00209 ast_log(LOG_WARNING, "GosubIf requires an argument: GosubIf(cond?label1(args):label2(args)\n"); 00210 ast_module_user_remove(u); 00211 return 0; 00212 } 00213 00214 AST_NONSTANDARD_APP_ARGS(label, cond.labels, ':'); 00215 00216 if (pbx_checkcondition(cond.ition)) { 00217 if (!ast_strlen_zero(label.iftrue)) 00218 res = gosub_exec(chan, label.iftrue); 00219 } else if (!ast_strlen_zero(label.iffalse)) { 00220 res = gosub_exec(chan, label.iffalse); 00221 } 00222 00223 ast_module_user_remove(u); 00224 return res; 00225 }
static int load_module | ( | void | ) | [static] |
Definition at line 239 of file app_stack.c.
References ast_register_application(), gosub_exec(), gosubif_exec(), pop_exec(), and return_exec().
00240 { 00241 ast_register_application(app_pop, pop_exec, pop_synopsis, pop_descrip); 00242 ast_register_application(app_return, return_exec, return_synopsis, return_descrip); 00243 ast_register_application(app_gosubif, gosubif_exec, gosubif_synopsis, gosubif_descrip); 00244 ast_register_application(app_gosub, gosub_exec, gosub_synopsis, gosub_descrip); 00245 00246 return 0; 00247 }
static int pop_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 76 of file app_stack.c.
References pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), and STACKVAR.
Referenced by load_module().
00077 { 00078 const char *frame = pbx_builtin_getvar_helper(chan, STACKVAR); 00079 int numargs = 0, i; 00080 char argname[15]; 00081 00082 /* Pop any arguments for this stack frame off the variable stack */ 00083 if (frame) { 00084 numargs = atoi(frame); 00085 for (i = 1; i <= numargs; i++) { 00086 snprintf(argname, sizeof(argname), "ARG%d", i); 00087 pbx_builtin_setvar_helper(chan, argname, NULL); 00088 } 00089 } 00090 00091 /* Remove the last frame from the Gosub stack */ 00092 pbx_builtin_setvar_helper(chan, STACKVAR, NULL); 00093 00094 return 0; 00095 }
static int return_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 97 of file app_stack.c.
References ast_log(), ast_parseable_goto(), ast_strlen_zero(), LOG_ERROR, LOG_WARNING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), S_OR, and STACKVAR.
Referenced by load_module().
00098 { 00099 const char *label = pbx_builtin_getvar_helper(chan, STACKVAR); 00100 char argname[15], *retval = data; 00101 int numargs, i; 00102 00103 if (ast_strlen_zero(label)) { 00104 ast_log(LOG_ERROR, "Return without Gosub: stack is empty\n"); 00105 return -1; 00106 } 00107 00108 /* Pop any arguments for this stack frame off the variable stack */ 00109 numargs = atoi(label); 00110 for (i = 1; i <= numargs; i++) { 00111 snprintf(argname, sizeof(argname), "ARG%d", i); 00112 pbx_builtin_setvar_helper(chan, argname, NULL); 00113 } 00114 00115 /* If the label exists, it will always have a ':' */ 00116 label = strchr(label, ':') + 1; 00117 00118 if (ast_parseable_goto(chan, label)) { 00119 ast_log(LOG_WARNING, "No next statement after Gosub?\n"); 00120 return -1; 00121 } 00122 00123 /* Remove the current frame from the Gosub stack */ 00124 pbx_builtin_setvar_helper(chan, STACKVAR, NULL); 00125 00126 /* Set a return value, if any */ 00127 pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", S_OR(retval, "")); 00128 return 0; 00129 }
static int unload_module | ( | void | ) | [static] |
Definition at line 227 of file app_stack.c.
References ast_module_user_hangup_all, and ast_unregister_application().
00228 { 00229 ast_unregister_application(app_return); 00230 ast_unregister_application(app_pop); 00231 ast_unregister_application(app_gosubif); 00232 ast_unregister_application(app_gosub); 00233 00234 ast_module_user_hangup_all(); 00235 00236 return 0; 00237 }
const char* app_gosub = "Gosub" [static] |
Definition at line 49 of file app_stack.c.
const char* app_gosubif = "GosubIf" [static] |
Definition at line 50 of file app_stack.c.
const char* app_pop = "StackPop" [static] |
Definition at line 52 of file app_stack.c.
const char* app_return = "Return" [static] |
Definition at line 51 of file app_stack.c.
const char* gosub_descrip [static] |
Initial value:
"Gosub([[context|]exten|]priority[(arg1[|...][|argN])])\n" " Jumps to the label specified, saving the return address.\n"
Definition at line 59 of file app_stack.c.
const char* gosub_synopsis = "Jump to label, saving return address" [static] |
Definition at line 54 of file app_stack.c.
const char* gosubif_descrip [static] |
Initial value:
"GosubIf(condition?labeliftrue[(arg1[|...])][:labeliffalse[(arg1[|...])]])\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"
Definition at line 62 of file app_stack.c.
const char* gosubif_synopsis = "Conditionally jump to label, saving return address" [static] |
Definition at line 55 of file app_stack.c.
const char* pop_descrip [static] |
Initial value:
"StackPop()\n" " Removes last label on the stack, discarding it.\n"
Definition at line 71 of file app_stack.c.
const char* pop_synopsis = "Remove one address from gosub stack" [static] |
Definition at line 57 of file app_stack.c.
const char* return_descrip [static] |
Initial value:
"Return([return-value])\n" " Jumps to the last label on the stack, removing it. The return value, if\n" "any, is saved in the channel variable GOSUB_RETVAL.\n"
Definition at line 67 of file app_stack.c.
const char* return_synopsis = "Return from gosub routine" [static] |
Definition at line 56 of file app_stack.c.