diff options
-rw-r--r-- | include/asterisk/ael_structs.h | 1 | ||||
-rw-r--r-- | pbx/pbx_ael.c | 149 |
2 files changed, 97 insertions, 53 deletions
diff --git a/include/asterisk/ael_structs.h b/include/asterisk/ael_structs.h index 8b428d33f..01a4244e1 100644 --- a/include/asterisk/ael_structs.h +++ b/include/asterisk/ael_structs.h @@ -178,6 +178,7 @@ struct ael_extension char *hints; int regexten; int is_switch; + int has_switch; struct ast_context *context; diff --git a/pbx/pbx_ael.c b/pbx/pbx_ael.c index 2af624c4f..bc0eeca2f 100644 --- a/pbx/pbx_ael.c +++ b/pbx/pbx_ael.c @@ -97,7 +97,7 @@ struct pval *find_context(char *name); struct pval *find_macro(char *name); struct ael_priority *new_prio(void); struct ael_extension *new_exten(void); -void linkprio(struct ael_extension *exten, struct ael_priority *prio); +void linkprio(struct ael_extension *exten, struct ael_priority *prio, struct ael_extension *mother_exten); void destroy_extensions(struct ael_extension *exten); static void linkexten(struct ael_extension *exten, struct ael_extension *add); static void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *context ); @@ -2776,8 +2776,10 @@ struct ael_extension *new_exten(void) return x; } -void linkprio(struct ael_extension *exten, struct ael_priority *prio) +void linkprio(struct ael_extension *exten, struct ael_priority *prio, struct ael_extension *mother_exten) { + char *p1, *p2; + if (!exten->plist) { exten->plist = prio; exten->plist_last = prio; @@ -2787,6 +2789,33 @@ void linkprio(struct ael_extension *exten, struct ael_priority *prio) } if( !prio->exten ) prio->exten = exten; /* don't override the switch value */ + /* The following code will cause all priorities within an extension + to have ${EXTEN} or ${EXTEN: replaced with ~~EXTEN~~, which is + set just before the first switch in an exten. The switches + will muck up the original ${EXTEN} value, so we save it away + and the user accesses this copy instead. */ + if (prio->appargs && ((mother_exten && mother_exten->has_switch) || exten->has_switch) ) { + while ((p1 = strstr(prio->appargs, "${EXTEN}"))) { + p2 = malloc(strlen(prio->appargs)+5); + *p1 = 0; + strcpy(p2, prio->appargs); + strcat(p2, "${~~EXTEN~~}"); + if (*(p1+8)) + strcat(p2, p1+8); + free(prio->appargs); + prio->appargs = p2; + } + while ((p1 = strstr(prio->appargs, "${EXTEN:"))) { + p2 = malloc(strlen(prio->appargs)+5); + *p1 = 0; + strcpy(p2, prio->appargs); + strcat(p2, "${~~EXTEN~~:"); + if (*(p1+8)) + strcat(p2, p1+8); + free(prio->appargs); + prio->appargs = p2; + } + } } void destroy_extensions(struct ael_extension *exten) @@ -2897,7 +2926,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_priority *pr; struct ael_priority *for_init, *for_test, *for_inc, *for_loop, *for_end; struct ael_priority *while_test, *while_loop, *while_end; - struct ael_priority *switch_test, *switch_end, *fall_thru, *switch_empty; + struct ael_priority *switch_set, *switch_test, *switch_end, *fall_thru, *switch_empty; struct ael_priority *if_test, *if_end, *if_skip, *if_false; #ifdef OLD_RAND_ACTION struct ael_priority *rand_test, *rand_end, *rand_skip; @@ -2922,7 +2951,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, remove_spaces_before_equals(buf1); pr->appargs = strdup(buf1); pr->origin = p; - linkprio(exten, pr); + linkprio(exten, pr, mother_exten); break; case PV_GOTO: @@ -2954,7 +2983,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, pr->appargs = strdup(buf1); } pr->origin = p; - linkprio(exten, pr); + linkprio(exten, pr, mother_exten); break; case PV_LABEL: @@ -2962,7 +2991,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, pr->type = AEL_LABEL; pr->origin = p; p->u3.compiled_label = exten; - linkprio(exten, pr); + linkprio(exten, pr, mother_exten); break; case PV_FOR: @@ -3091,8 +3120,8 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, for_end->app = strdup("NoOp"); for_end->appargs = strdup(buf1); /* link & load! */ - linkprio(exten, for_init); - linkprio(exten, for_test); + linkprio(exten, for_init, mother_exten); + linkprio(exten, for_test, mother_exten); /* now, put the body of the for loop here */ exten->loop_break = for_end; @@ -3100,9 +3129,9 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, gen_prios(exten, new_label, p->u4.for_statements, mother_exten, this_context); /* this will link in all the statements here */ - linkprio(exten, for_inc); - linkprio(exten, for_loop); - linkprio(exten, for_end); + linkprio(exten, for_inc, mother_exten); + linkprio(exten, for_loop, mother_exten); + linkprio(exten, for_end, mother_exten); exten->loop_break = loop_break_save; @@ -3130,7 +3159,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, while_end->app = strdup("NoOp"); while_end->appargs = strdup(buf1); - linkprio(exten, while_test); + linkprio(exten, while_test, mother_exten); /* now, put the body of the for loop here */ exten->loop_break = while_end; @@ -3138,8 +3167,8 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the while body statements here */ - linkprio(exten, while_loop); - linkprio(exten, while_end); + linkprio(exten, while_loop, mother_exten); + linkprio(exten, while_end, mother_exten); exten->loop_break = loop_break_save; @@ -3153,7 +3182,21 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, loop_break_save = exten->loop_break; /* save them, then restore before leaving */ loop_continue_save = exten->loop_continue; snprintf(new_label,sizeof(new_label),"sw-%s-%d", label, control_statement_count); - + if ((mother_exten && !mother_exten->has_switch)) { + switch_set = new_prio(); + switch_set->type = AEL_APPCALL; + switch_set->app = strdup("Set"); + switch_set->appargs = strdup("~~EXTEN~~=${EXTEN}"); + linkprio(exten, switch_set, mother_exten); + mother_exten->has_switch = 1; + } else if ((exten && !exten->has_switch)) { + switch_set = new_prio(); + switch_set->type = AEL_APPCALL; + switch_set->app = strdup("Set"); + switch_set->appargs = strdup("~~EXTEN~~=${EXTEN}"); + linkprio(exten, switch_set, exten); + exten->has_switch = 1; + } switch_test = new_prio(); switch_end = new_prio(); switch_test->type = AEL_APPCALL; @@ -3170,8 +3213,8 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, switch_end->origin = p; switch_end->exten = exten; - linkprio(exten, switch_test); - linkprio(exten, switch_end); + linkprio(exten, switch_test, mother_exten); + linkprio(exten, switch_end, mother_exten); exten->loop_break = switch_end; exten->loop_continue = 0; @@ -3215,7 +3258,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, substitute_commas(buf2); snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, buf2); fall_thru->appargs = strdup(buf1); - linkprio(switch_case, fall_thru); + linkprio(switch_case, fall_thru, mother_exten); } else if (p2->next && p2->next->type == PV_PATTERN) { fall_thru = new_prio(); fall_thru->type = AEL_APPCALL; @@ -3224,20 +3267,20 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, substitute_commas(buf2); snprintf(buf1,sizeof(buf1),"sw-%d-%s|10", local_control_statement_count, buf2); fall_thru->appargs = strdup(buf1); - linkprio(switch_case, fall_thru); + linkprio(switch_case, fall_thru, mother_exten); } else if (p2->next && p2->next->type == PV_DEFAULT) { fall_thru = new_prio(); fall_thru->type = AEL_APPCALL; fall_thru->app = strdup("Goto"); snprintf(buf1,sizeof(buf1),"sw-%d-.|10",local_control_statement_count); fall_thru->appargs = strdup(buf1); - linkprio(switch_case, fall_thru); + linkprio(switch_case, fall_thru, mother_exten); } else if (!p2->next) { fall_thru = new_prio(); fall_thru->type = AEL_CONTROL1; fall_thru->goto_true = switch_end; fall_thru->app = strdup("Goto"); - linkprio(switch_case, fall_thru); + linkprio(switch_case, fall_thru, mother_exten); } } if (switch_case->return_needed) { @@ -3247,7 +3290,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, np2->app = strdup("NoOp"); snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); np2->appargs = strdup(buf); - linkprio(switch_case, np2); + linkprio(switch_case, np2, mother_exten); switch_case-> return_target = np2; } } else if (p2->type == PV_PATTERN) { @@ -3285,7 +3328,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, substitute_commas(buf2); snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, buf2); fall_thru->appargs = strdup(buf1); - linkprio(switch_case, fall_thru); + linkprio(switch_case, fall_thru, mother_exten); } else if (p2->next && p2->next->type == PV_PATTERN) { fall_thru = new_prio(); fall_thru->type = AEL_APPCALL; @@ -3294,20 +3337,20 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, substitute_commas(buf2); snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, buf2); fall_thru->appargs = strdup(buf1); - linkprio(switch_case, fall_thru); + linkprio(switch_case, fall_thru, mother_exten); } else if (p2->next && p2->next->type == PV_DEFAULT) { fall_thru = new_prio(); fall_thru->type = AEL_APPCALL; fall_thru->app = strdup("Goto"); snprintf(buf1,sizeof(buf1),"sw-%d-.|10",local_control_statement_count); fall_thru->appargs = strdup(buf1); - linkprio(switch_case, fall_thru); + linkprio(switch_case, fall_thru, mother_exten); } else if (!p2->next) { fall_thru = new_prio(); fall_thru->type = AEL_CONTROL1; fall_thru->goto_true = switch_end; fall_thru->app = strdup("Goto"); - linkprio(switch_case, fall_thru); + linkprio(switch_case, fall_thru, mother_exten); } } if (switch_case->return_needed) { @@ -3317,7 +3360,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, np2->app = strdup("NoOp"); snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); np2->appargs = strdup(buf); - linkprio(switch_case, np2); + linkprio(switch_case, np2, mother_exten); switch_case-> return_target = np2; } } else if (p2->type == PV_DEFAULT) { @@ -3338,7 +3381,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, snprintf(buf1,sizeof(buf1),"sw-%d-.|10",local_control_statement_count); switch_empty->app = strdup("Goto"); switch_empty->appargs = strdup(buf1); - linkprio(switch_null, switch_empty); + linkprio(switch_null, switch_empty, mother_exten); snprintf(buf1,sizeof(buf1),"sw-%d-", local_control_statement_count); switch_null->name = strdup(buf1); switch_null->loop_break = exten->loop_break; @@ -3373,7 +3416,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, substitute_commas(buf2); snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, buf2); fall_thru->appargs = strdup(buf1); - linkprio(switch_case, fall_thru); + linkprio(switch_case, fall_thru, mother_exten); } else if (p2->next && p2->next->type == PV_PATTERN) { fall_thru = new_prio(); fall_thru->type = AEL_APPCALL; @@ -3382,20 +3425,20 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, substitute_commas(buf2); snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, buf2); fall_thru->appargs = strdup(buf1); - linkprio(switch_case, fall_thru); + linkprio(switch_case, fall_thru, mother_exten); } else if (p2->next && p2->next->type == PV_DEFAULT) { fall_thru = new_prio(); fall_thru->type = AEL_APPCALL; fall_thru->app = strdup("Goto"); snprintf(buf1,sizeof(buf1),"sw-%d-.|10",local_control_statement_count); fall_thru->appargs = strdup(buf1); - linkprio(switch_case, fall_thru); + linkprio(switch_case, fall_thru, mother_exten); } else if (!p2->next) { fall_thru = new_prio(); fall_thru->type = AEL_CONTROL1; fall_thru->goto_true = switch_end; fall_thru->app = strdup("Goto"); - linkprio(switch_case, fall_thru); + linkprio(switch_case, fall_thru, mother_exten); } } if (switch_case->return_needed) { @@ -3405,7 +3448,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, np2->app = strdup("NoOp"); snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); np2->appargs = strdup(buf); - linkprio(switch_case, np2); + linkprio(switch_case, np2, mother_exten); switch_case-> return_target = np2; } } else { @@ -3430,7 +3473,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, pr->app = strdup("Macro"); pr->appargs = strdup(buf1); pr->origin = p; - linkprio(exten, pr); + linkprio(exten, pr, mother_exten); break; case PV_APPLICATION_CALL: @@ -3446,7 +3489,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, pr->app = strdup(p->u1.str); pr->appargs = strdup(buf1); pr->origin = p; - linkprio(exten, pr); + linkprio(exten, pr, mother_exten); break; case PV_BREAK: @@ -3454,7 +3497,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, pr->type = AEL_CONTROL1; /* simple goto */ pr->goto_true = exten->loop_break; pr->origin = p; - linkprio(exten, pr); + linkprio(exten, pr, mother_exten); break; case PV_RETURN: /* hmmmm */ @@ -3464,7 +3507,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, pr->app = strdup("Goto"); pr->appargs = strdup(""); pr->origin = p; - linkprio(exten, pr); + linkprio(exten, pr, mother_exten); break; case PV_CONTINUE: @@ -3472,7 +3515,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, pr->type = AEL_CONTROL1; /* simple goto */ pr->goto_true = exten->loop_continue; pr->origin = p; - linkprio(exten, pr); + linkprio(exten, pr, mother_exten); break; #ifdef OLD_RAND_ACTION @@ -3500,17 +3543,17 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, rand_test->goto_true = rand_skip; /* +1, really */ - linkprio(exten, rand_test); + linkprio(exten, rand_test, mother_exten); if (p->u3.else_statements) { gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the else statements here */ } - linkprio(exten, rand_skip); + linkprio(exten, rand_skip, mother_exten); gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the "true" statements here */ - linkprio(exten, rand_end); + linkprio(exten, rand_end, mother_exten); break; #endif @@ -3557,20 +3600,20 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, } /* link & load! */ - linkprio(exten, if_test); - linkprio(exten, if_false); + linkprio(exten, if_test, mother_exten); + linkprio(exten, if_false, mother_exten); /* now, put the body of the if here */ gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the statements here */ if (p->u3.else_statements) { - linkprio(exten, if_skip); + linkprio(exten, if_skip, mother_exten); gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the statements here */ } - linkprio(exten, if_end); + linkprio(exten, if_end, mother_exten); break; @@ -3605,19 +3648,19 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, } /* link & load! */ - linkprio(exten, if_test); + linkprio(exten, if_test, mother_exten); /* now, put the body of the if here */ gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the statements here */ if (p->u3.else_statements) { - linkprio(exten, if_skip); + linkprio(exten, if_skip, mother_exten); gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the statements here */ } - linkprio(exten, if_end); + linkprio(exten, if_end, mother_exten); break; @@ -3643,7 +3686,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, np2->app = strdup("NoOp"); snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); np2->appargs = strdup(buf); - linkprio(switch_case, np2); + linkprio(switch_case, np2, mother_exten); switch_case-> return_target = np2; } @@ -3913,7 +3956,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) snprintf(buf,sizeof(buf),"%s=${ARG%d}", lp->u1.str, argc++); remove_spaces_before_equals(buf); np2->appargs = strdup(buf); - linkprio(exten, np2); + linkprio(exten, np2, NULL); } /* add any includes */ for (p2=p->u3.macro_statements; p2; p2=p2->next) { @@ -3946,7 +3989,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) np2->app = strdup("NoOp"); snprintf(buf,sizeof(buf),"End of Macro %s-%s",p->u1.str, exten->name); np2->appargs = strdup(buf); - linkprio(exten, np2); + linkprio(exten, np2, NULL); exten-> return_target = np2; } @@ -3988,7 +4031,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) np2->app = strdup("NoOp"); snprintf(buf,sizeof(buf),"End of Extension %s", exten->name); np2->appargs = strdup(buf); - linkprio(exten, np2); + linkprio(exten, np2, NULL); exten-> return_target = np2; } /* is the last priority in the extension a label? Then add a trailing no-op */ @@ -4004,7 +4047,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) np2->app = strdup("NoOp"); snprintf(buf,sizeof(buf),"A NoOp to follow a trailing label %s", exten->plist_last->origin->u1.str); np2->appargs = strdup(buf); - linkprio(exten, np2); + linkprio(exten, np2, NULL); } set_priorities(exten); |