100 static char *start_app =
"While";
101 static char *stop_app =
"EndWhile";
102 static char *exit_app =
"ExitWhile";
103 static char *continue_app =
"ContinueWhile";
108 static const char *get_index(
struct ast_channel *chan,
const char *prefix,
int idx) {
109 char varname[VAR_SIZE];
111 snprintf(varname, VAR_SIZE,
"%s_%d", prefix, idx);
121 for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
123 int needmatch = ast_get_extension_matchcid(e);
128 for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
129 if (priority != ast_get_extension_priority(p))
138 for (idx = 0; idx < ast_context_includes_count(c); idx++) {
139 const struct ast_include *i = ast_context_includes_get(c, idx);
141 for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
142 if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
143 e = find_matching_priority(c2, exten, priority, callerid);
152 static int find_matching_endwhile(
struct ast_channel *chan)
158 ast_log(LOG_ERROR,
"Failed to lock contexts list\n");
162 for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) {
166 if (!strcmp(ast_get_context_name(c), ast_channel_context(chan))) {
168 int cur_priority = ast_channel_priority(chan) + 1, level=1;
170 for (e = find_matching_priority(c, ast_channel_exten(chan), cur_priority,
171 S_COR(ast_channel_caller(chan)->
id.
number.valid, ast_channel_caller(chan)->
id.
number.str, NULL));
173 e = find_matching_priority(c, ast_channel_exten(chan), ++cur_priority,
174 S_COR(ast_channel_caller(chan)->
id.
number.valid, ast_channel_caller(chan)->
id.
number.str, NULL))) {
175 if (!strcasecmp(ast_get_extension_app(e),
"WHILE")) {
177 }
else if (!strcasecmp(ast_get_extension_app(e),
"ENDWHILE")) {
197 static int _while_exec(
struct ast_channel *chan,
const char *
data,
int end)
200 const char *while_pri = NULL;
201 char *my_name = NULL;
202 const char *condition = NULL, *
label = NULL;
203 char varname[VAR_SIZE], end_varname[VAR_SIZE];
204 const char *prefix =
"WHILE";
206 int used_index_i = -1, x=0;
207 char used_index[VAR_SIZE] =
"0", new_index[VAR_SIZE] =
"0";
226 if (get_index(chan, prefix, x)) {
232 snprintf(used_index, VAR_SIZE,
"%d", used_index_i);
233 snprintf(new_index, VAR_SIZE,
"%d", used_index_i + 1);
238 size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
240 memset(my_name, 0, size);
241 snprintf(my_name, size,
"%s_%s_%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
243 ast_channel_lock(chan);
250 snprintf(varname, VAR_SIZE,
"%s_%s", prefix, label);
253 snprintf(end_varname,VAR_SIZE,
"END_%s",varname);
255 ast_channel_unlock(chan);
260 const char *goto_str;
263 snprintf(end_varname,VAR_SIZE,
"END_%s",varname);
264 ast_channel_lock(chan);
269 int pri = find_matching_endwhile(chan);
271 ast_verb(3,
"Jumping to priority %d\n", pri);
272 ast_channel_priority_set(chan, pri);
274 ast_log(LOG_WARNING,
"Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
277 ast_channel_unlock(chan);
281 if (!end && !while_pri) {
283 size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
285 memset(goto_str, 0, size);
286 snprintf(goto_str, size,
"%s,%s,%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
290 else if (end && while_pri) {
292 snprintf(end_varname, VAR_SIZE,
"END_%s", varname);
295 size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
297 memset(goto_str, 0, size);
298 snprintf(goto_str, size,
"%s,%s,%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan)+1);
307 static int while_start_exec(
struct ast_channel *chan,
const char *data) {
308 return _while_exec(chan, data, 0);
311 static int while_end_exec(
struct ast_channel *chan,
const char *data) {
312 return _while_exec(chan, data, 1);
315 static int while_exit_exec(
struct ast_channel *chan,
const char *data) {
316 return _while_exec(chan, data, 2);
319 static int while_continue_exec(
struct ast_channel *chan,
const char *data)
322 const char *prefix =
"WHILE", *while_pri=NULL;
325 const char *tmp = get_index(chan, prefix, x);
338 static int unload_module(
void)
350 static int load_module(
void)
362 AST_MODULE_INFO_STANDARD(
ASTERISK_GPL_KEY,
"While Loops and Conditional Execution");
ast_include: include= support in extensions.conf
int ast_unlock_context(struct ast_context *con)
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
int pbx_checkcondition(const char *condition)
Evaluate a condition.
int ast_rdlock_contexts(void)
Read locks the context list.
int ast_unregister_application(const char *app)
Unregister an application.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
General Asterisk PBX channel definitions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Core PBX routines and definitions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
int ast_unlock_contexts(void)
Unlocks contexts.
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
ast_context: An extension context
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.