Index: apps/app_macro.c =================================================================== --- apps/app_macro.c (revision 47430) +++ apps/app_macro.c (working copy) @@ -99,6 +99,41 @@ static char *exit_synopsis = "Exit From Macro"; +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 _macro_exec(struct ast_channel *chan, void *data, int exclusive) { const char *s; @@ -112,7 +147,7 @@ int argc, x; int res=0; char oldexten[256]=""; - int oldpriority; + int oldpriority, gosub_level = 0; char pc[80], depthc[12]; char oldcontext[AST_MAX_CONTEXT] = ""; int offset, depth = 0, maxdepth = 7; @@ -125,6 +160,9 @@ char *save_macro_offset; struct ast_module_user *u; + struct ast_context *c; + struct ast_exten *e; + if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "Macro() requires arguments. See \"show application macro\" for help.\n"); return -1; @@ -257,7 +295,25 @@ goto out; } } - if (strcasecmp(chan->context, fullmacro)) { + + /* What application just executed? */ + for (c = ast_walk_contexts(NULL); c; c = ast_walk_contexts(c)) { + e = NULL; + if (!strcmp(ast_get_context_name(c), chan->context)) { + e = find_matching_priority(c, chan->exten, chan->priority, chan->cid.cid_num); + break; + } + } + + if (e && !strcasecmp(ast_get_extension_app(e), "GOSUB")) { + gosub_level++; + } else if (e && !strcasecmp(ast_get_extension_app(e), "RETURN")) { + gosub_level--; + } else if (e && !strcasecmp(ast_get_extension_app(e), "STACKPOP")) { + gosub_level--; + } + + if (gosub_level == 0 && strcasecmp(chan->context, fullmacro)) { if (option_verbose > 1) ast_verbose(VERBOSE_PREFIX_2 "Channel '%s' jumping out of macro '%s'\n", chan->name, macro); break;