Index: apps/app_while.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_while.c,v retrieving revision 1.8 diff -u -r1.8 app_while.c --- apps/app_while.c 6 Jun 2005 22:39:32 -0000 1.8 +++ apps/app_while.c 8 Sep 2005 16:52:00 -0000 @@ -27,6 +27,7 @@ #include "asterisk/pbx.h" #include "asterisk/module.h" #include "asterisk/lock.h" +#include "asterisk/options.h" #define ALL_DONE(u,ret) {LOCAL_USER_REMOVE(u); return ret;} @@ -108,6 +109,81 @@ return pbx_builtin_getvar_helper(chan, varname); } +static struct ast_exten *find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid) +{ + struct ast_exten *e; + struct ast_include *i; + struct ast_context *c2; + + for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) { + if (ast_extension_match(ast_get_extension_name(e), exten)) { + int needmatch = ast_get_extension_matchcid(e); + if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) || + (!needmatch)) { + /* This is the matching extension we want */ + struct ast_exten *p; + for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) { + if (priority != ast_get_extension_priority(p)) + continue; + return p; + } + } + } + } + + /* No match; run through includes */ + for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) { + for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) { + if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) { + e = find_matching_priority(c2, exten, priority, callerid); + if (e) + return e; + } + } + } + return NULL; +} + +static int find_matching_endwhile(struct ast_channel *chan) +{ + struct ast_context *c; + int res=-1; + + if (ast_lock_contexts()) { + ast_log(LOG_ERROR, "Failed to lock contexts list\n"); + return -1; + } + + for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) { + struct ast_exten *e; + + if (!ast_lock_context(c)) { + if (!strcmp(ast_get_context_name(c), chan->context)) { + /* This is the matching context we want */ + int cur_priority = chan->priority + 1, level=1; + + for (e = find_matching_priority(c, chan->exten, cur_priority, chan->cid.cid_num); e; e = find_matching_priority(c, chan->exten, ++cur_priority, chan->cid.cid_num)) { + if (!strcasecmp(ast_get_extension_app(e), "WHILE")) { + level++; + } else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) { + level--; + } + + if (level == 0) { + res = cur_priority; + break; + } + } + } + ast_unlock_context(c); + if (res > 0) { + break; + } + } + } + ast_unlock_contexts(); + return res; +} static int _while_exec(struct ast_channel *chan, void *data, int end) { @@ -181,6 +257,15 @@ if ((goto_str=pbx_builtin_getvar_helper(chan, end_varname))) { pbx_builtin_setvar_helper(chan, end_varname, NULL); ast_parseable_goto(chan, goto_str); + } else { + int pri = find_matching_endwhile(chan); + if (pri > 0) { + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Jumping to priority %d\n", pri); + chan->priority = pri; + } else { + ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority); + } } ALL_DONE(u,res); }