mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-22 12:52:33 +00:00
Merged revisions 136726 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r136726 | murf | 2008-08-07 18:15:34 -0600 (Thu, 07 Aug 2008) | 32 lines (closes issue #13236) Reported by: korihor Wow, this one was a challenge! I regrouped and ran a new strategy for setting the ~~MACRO~~ value; I set it once per extension, up near the top. It is only set if there is a switch in the extension. So, I had to put in a chunk of code to detect a switch in the pval tree. I moved the code to insert the set of ~~exten~~ up to the beginning of the gen_prios routine, instead of down in the switch code. I learned that I have to push the detection of the switches down into the code, so everywhere I create a new exten in gen_prios, I make sure to pass onto it the values of the mother_exten first, and the exten next. I had to add a couple fields to the exten struct to accomplish this, in the ael_structs.h file. The checked field makes it so we don't repeat the switch search if it's been done. I also updated the regressions. ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@136746 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
355
res/ael/pval.c
355
res/ael/pval.c
@@ -3076,6 +3076,263 @@ static void gen_match_to_pattern(char *pattern, char *result)
|
||||
*t++ = 0; /* cap it off */
|
||||
}
|
||||
|
||||
/* ==== a set of routines to search for a switch statement contained in the pval description */
|
||||
|
||||
int find_switch_item(pval *item);
|
||||
int contains_switch(pval *item);
|
||||
|
||||
|
||||
int find_switch_item(pval *item)
|
||||
{
|
||||
switch ( item->type ) {
|
||||
case PV_LOCALVARDEC:
|
||||
/* fields: item->u1.str == string associated with this (word). */
|
||||
break;
|
||||
|
||||
case PV_WORD:
|
||||
/* fields: item->u1.str == string associated with this (word). */
|
||||
break;
|
||||
|
||||
case PV_MACRO:
|
||||
/* fields: item->u1.str == name of macro
|
||||
item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
|
||||
item->u2.arglist->u1.str == argument
|
||||
item->u2.arglist->next == next arg
|
||||
|
||||
item->u3.macro_statements == pval list of statements in macro body.
|
||||
*/
|
||||
/* had better not see this */
|
||||
if (contains_switch(item->u3.macro_statements))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case PV_CONTEXT:
|
||||
/* fields: item->u1.str == name of context
|
||||
item->u2.statements == pval list of statements in context body
|
||||
item->u3.abstract == int 1 if an abstract keyword were present
|
||||
*/
|
||||
/* had better not see this */
|
||||
if (contains_switch(item->u2.statements))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case PV_MACRO_CALL:
|
||||
/* fields: item->u1.str == name of macro to call
|
||||
item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
|
||||
item->u2.arglist->u1.str == argument
|
||||
item->u2.arglist->next == next arg
|
||||
*/
|
||||
break;
|
||||
|
||||
case PV_APPLICATION_CALL:
|
||||
/* fields: item->u1.str == name of application to call
|
||||
item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
|
||||
item->u2.arglist->u1.str == argument
|
||||
item->u2.arglist->next == next arg
|
||||
*/
|
||||
break;
|
||||
|
||||
case PV_CASE:
|
||||
/* fields: item->u1.str == value of case
|
||||
item->u2.statements == pval list of statements under the case
|
||||
*/
|
||||
/* had better not see this */
|
||||
if (contains_switch(item->u2.statements))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case PV_PATTERN:
|
||||
/* fields: item->u1.str == value of case
|
||||
item->u2.statements == pval list of statements under the case
|
||||
*/
|
||||
/* had better not see this */
|
||||
if (contains_switch(item->u2.statements))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case PV_DEFAULT:
|
||||
/* fields:
|
||||
item->u2.statements == pval list of statements under the case
|
||||
*/
|
||||
/* had better not see this */
|
||||
if (contains_switch(item->u2.statements))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case PV_CATCH:
|
||||
/* fields: item->u1.str == name of extension to catch
|
||||
item->u2.statements == pval list of statements in context body
|
||||
*/
|
||||
/* had better not see this */
|
||||
if (contains_switch(item->u2.statements))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case PV_SWITCHES:
|
||||
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
|
||||
*/
|
||||
break;
|
||||
|
||||
case PV_ESWITCHES:
|
||||
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
|
||||
*/
|
||||
break;
|
||||
|
||||
case PV_INCLUDES:
|
||||
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
|
||||
item->u2.arglist == pval list of 4 PV_WORD elements for time values
|
||||
*/
|
||||
break;
|
||||
|
||||
case PV_STATEMENTBLOCK:
|
||||
/* fields: item->u1.list == pval list of statements in block, one per entry in the list
|
||||
*/
|
||||
if (contains_switch(item->u1.list) )
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case PV_VARDEC:
|
||||
/* fields: item->u1.str == variable name
|
||||
item->u2.val == variable value to assign
|
||||
*/
|
||||
break;
|
||||
|
||||
case PV_GOTO:
|
||||
/* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user.
|
||||
item->u1.list->u1.str == where the data on a PV_WORD will always be.
|
||||
*/
|
||||
break;
|
||||
|
||||
case PV_LABEL:
|
||||
/* fields: item->u1.str == label name
|
||||
*/
|
||||
break;
|
||||
|
||||
case PV_FOR:
|
||||
/* fields: item->u1.for_init == a string containing the initalizer
|
||||
item->u2.for_test == a string containing the loop test
|
||||
item->u3.for_inc == a string containing the loop increment
|
||||
|
||||
item->u4.for_statements == a pval list of statements in the for ()
|
||||
*/
|
||||
if (contains_switch(item->u4.for_statements))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case PV_WHILE:
|
||||
/* fields: item->u1.str == the while conditional, as supplied by user
|
||||
|
||||
item->u2.statements == a pval list of statements in the while ()
|
||||
*/
|
||||
if (contains_switch(item->u2.statements))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case PV_BREAK:
|
||||
/* fields: none
|
||||
*/
|
||||
break;
|
||||
|
||||
case PV_RETURN:
|
||||
/* fields: none
|
||||
*/
|
||||
break;
|
||||
|
||||
case PV_CONTINUE:
|
||||
/* fields: none
|
||||
*/
|
||||
break;
|
||||
|
||||
case PV_IFTIME:
|
||||
/* fields: item->u1.list == there are 4 linked PV_WORDs here.
|
||||
|
||||
item->u2.statements == a pval list of statements in the if ()
|
||||
item->u3.else_statements == a pval list of statements in the else
|
||||
(could be zero)
|
||||
*/
|
||||
if (contains_switch(item->u2.statements))
|
||||
return 1;
|
||||
if ( item->u3.else_statements ) {
|
||||
if (contains_switch(item->u3.else_statements))
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PV_RANDOM:
|
||||
/* fields: item->u1.str == the random number expression, as supplied by user
|
||||
|
||||
item->u2.statements == a pval list of statements in the if ()
|
||||
item->u3.else_statements == a pval list of statements in the else
|
||||
(could be zero)
|
||||
*/
|
||||
if (contains_switch(item->u2.statements))
|
||||
return 1;
|
||||
if ( item->u3.else_statements ) {
|
||||
if (contains_switch(item->u3.else_statements))
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PV_IF:
|
||||
/* fields: item->u1.str == the if conditional, as supplied by user
|
||||
|
||||
item->u2.statements == a pval list of statements in the if ()
|
||||
item->u3.else_statements == a pval list of statements in the else
|
||||
(could be zero)
|
||||
*/
|
||||
if (contains_switch(item->u2.statements))
|
||||
return 1;
|
||||
if ( item->u3.else_statements ) {
|
||||
if (contains_switch(item->u3.else_statements))
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PV_SWITCH:
|
||||
/* fields: item->u1.str == the switch expression
|
||||
|
||||
item->u2.statements == a pval list of statements in the switch,
|
||||
(will be case statements, most likely!)
|
||||
*/
|
||||
return 1; /* JACKPOT */
|
||||
break;
|
||||
|
||||
case PV_EXTENSION:
|
||||
/* fields: item->u1.str == the extension name, label, whatever it's called
|
||||
|
||||
item->u2.statements == a pval list of statements in the extension
|
||||
item->u3.hints == a char * hint argument
|
||||
item->u4.regexten == an int boolean. non-zero says that regexten was specified
|
||||
*/
|
||||
if (contains_switch(item->u2.statements))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case PV_IGNOREPAT:
|
||||
/* fields: item->u1.str == the ignorepat data
|
||||
*/
|
||||
break;
|
||||
|
||||
case PV_GLOBALS:
|
||||
/* fields: item->u1.statements == pval list of statements, usually vardecs
|
||||
*/
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int contains_switch(pval *item)
|
||||
{
|
||||
pval *i;
|
||||
|
||||
for (i=item; i; i=i->next) {
|
||||
if (find_switch_item(i))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *this_context )
|
||||
{
|
||||
pval *p,*p2,*p3;
|
||||
@@ -3098,6 +3355,46 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
|
||||
struct ael_priority *loop_continue_save;
|
||||
struct ael_extension *switch_case,*switch_null;
|
||||
|
||||
if ((mother_exten && !mother_exten->checked_switch) || (exten && !exten->checked_switch)) {
|
||||
if (contains_switch(statement)) { /* only run contains_switch if you haven't checked before */
|
||||
if (mother_exten) {
|
||||
if (!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;
|
||||
mother_exten->checked_switch = 1;
|
||||
if (exten) {
|
||||
exten->has_switch = 1;
|
||||
exten->checked_switch = 1;
|
||||
}
|
||||
}
|
||||
} else if (exten) {
|
||||
if (!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);
|
||||
exten->has_switch = 1;
|
||||
exten->checked_switch = 1;
|
||||
if (mother_exten) {
|
||||
mother_exten->has_switch = 1;
|
||||
mother_exten->checked_switch = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mother_exten) {
|
||||
mother_exten->checked_switch = 1;
|
||||
}
|
||||
if (exten) {
|
||||
exten->checked_switch = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (p=statement; p; p=p->next) {
|
||||
switch (p->type) {
|
||||
case PV_VARDEC:
|
||||
@@ -3121,7 +3418,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
|
||||
pr->origin = p;
|
||||
linkprio(exten, pr, mother_exten);
|
||||
break;
|
||||
|
||||
|
||||
case PV_GOTO:
|
||||
pr = new_prio();
|
||||
pr->type = AEL_APPCALL;
|
||||
@@ -3344,21 +3641,6 @@ 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;
|
||||
@@ -3384,6 +3666,14 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
|
||||
if (p2->type == PV_CASE) {
|
||||
/* ok, generate a extension and link it in */
|
||||
switch_case = new_exten();
|
||||
if (mother_exten && mother_exten->checked_switch) {
|
||||
switch_case->has_switch = mother_exten->has_switch;
|
||||
switch_case->checked_switch = mother_exten->checked_switch;
|
||||
}
|
||||
if (exten && exten->checked_switch) {
|
||||
switch_case->has_switch = exten->has_switch;
|
||||
switch_case->checked_switch = exten->checked_switch;
|
||||
}
|
||||
switch_case->context = this_context;
|
||||
switch_case->is_switch = 1;
|
||||
/* the break/continue locations are inherited from parent */
|
||||
@@ -3448,6 +3738,14 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
|
||||
} else if (p2->type == PV_PATTERN) {
|
||||
/* ok, generate a extension and link it in */
|
||||
switch_case = new_exten();
|
||||
if (mother_exten && mother_exten->checked_switch) {
|
||||
switch_case->has_switch = mother_exten->has_switch;
|
||||
switch_case->checked_switch = mother_exten->checked_switch;
|
||||
}
|
||||
if (exten && exten->checked_switch) {
|
||||
switch_case->has_switch = exten->has_switch;
|
||||
switch_case->checked_switch = exten->checked_switch;
|
||||
}
|
||||
switch_case->context = this_context;
|
||||
switch_case->is_switch = 1;
|
||||
/* the break/continue locations are inherited from parent */
|
||||
@@ -3511,6 +3809,14 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
|
||||
} else if (p2->type == PV_DEFAULT) {
|
||||
/* ok, generate a extension and link it in */
|
||||
switch_case = new_exten();
|
||||
if (mother_exten && mother_exten->checked_switch) {
|
||||
switch_case->has_switch = mother_exten->has_switch;
|
||||
switch_case->checked_switch = mother_exten->checked_switch;
|
||||
}
|
||||
if (exten && exten->checked_switch) {
|
||||
switch_case->has_switch = exten->has_switch;
|
||||
switch_case->checked_switch = exten->checked_switch;
|
||||
}
|
||||
switch_case->context = this_context;
|
||||
switch_case->is_switch = 1;
|
||||
|
||||
@@ -3520,6 +3826,14 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
|
||||
|
||||
default_exists++;
|
||||
switch_null = new_exten();
|
||||
if (mother_exten && mother_exten->checked_switch) {
|
||||
switch_null->has_switch = mother_exten->has_switch;
|
||||
switch_null->checked_switch = mother_exten->checked_switch;
|
||||
}
|
||||
if (exten && exten->checked_switch) {
|
||||
switch_null->has_switch = exten->has_switch;
|
||||
switch_null->checked_switch = exten->checked_switch;
|
||||
}
|
||||
switch_null->context = this_context;
|
||||
switch_null->is_switch = 1;
|
||||
switch_empty = new_prio();
|
||||
@@ -3783,6 +4097,15 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
|
||||
/* generate an extension with name of catch, put all catch stats
|
||||
into this exten! */
|
||||
switch_case = new_exten();
|
||||
if (mother_exten && mother_exten->checked_switch) {
|
||||
switch_case->has_switch = mother_exten->has_switch;
|
||||
switch_case->checked_switch = mother_exten->checked_switch;
|
||||
}
|
||||
if (exten && exten->checked_switch) {
|
||||
switch_case->has_switch = exten->has_switch;
|
||||
switch_case->checked_switch = exten->checked_switch;
|
||||
}
|
||||
|
||||
switch_case->context = this_context;
|
||||
linkexten(exten,switch_case);
|
||||
switch_case->name = strdup(p->u1.str);
|
||||
|
Reference in New Issue
Block a user