@ -63,8 +63,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
static char * config = " extensions.ael " ;
static char * config = " extensions.ael " ;
static char * registrar = " pbx_ael " ;
static char * registrar = " pbx_ael " ;
static int pbx_load_module ( void ) ;
static int pbx_load_module ( void ) ;
static int warns , errs ;
static struct pval * current_db ;
# ifndef AAL_ARGCHECK
# ifndef AAL_ARGCHECK
/* for the time being, short circuit all the AAL related structures
/* for the time being, short circuit all the AAL related structures
@ -103,799 +101,7 @@ int is_float(char *arg );
int is_int ( char * arg ) ;
int is_int ( char * arg ) ;
int is_empty ( char * arg ) ;
int is_empty ( char * arg ) ;
static const char * match_context ;
static const char * match_exten ;
static const char * match_label ;
static int count_labels ; /* true, put matcher in label counting mode */
static int return_on_context_match ;
struct pval * match_pval ( pval * item ) ;
static void check_goto ( pval * item ) ;
static void find_pval_goto_item ( pval * item , int lev ) ;
static void find_pval_gotos ( pval * item , int lev ) ;
static struct pval * find_label_in_current_context ( char * exten , char * label , pval * curr_cont ) ;
static struct pval * find_first_label_in_current_context ( char * label , pval * curr_cont ) ;
static void print_pval_list ( FILE * fin , pval * item , int depth ) ;
static struct pval * find_label_in_current_extension ( const char * label , pval * curr_ext ) ;
static struct pval * find_label_in_current_db ( const char * context , const char * exten , const char * label ) ;
static pval * get_extension_or_contxt ( pval * p ) ;
static pval * get_contxt ( pval * p ) ;
/* static void substitute_commas(char *str); */
/* static void substitute_commas(char *str); */
# ifdef NOMORE
/*! \brief I am adding this code to substitute commas with vertbars in the args to apps */
static void substitute_commas ( char * str )
{
char * p = str ;
while ( p & & * p )
{
if ( * p = = ' , ' & & ( ( p ! = str & & * ( p - 1 ) ! = ' \\ ' )
| | p = = str ) )
* p = ' | ' ;
if ( * p = = ' \\ ' & & * ( p + 1 ) = = ' , ' ) { /* learning experience: the '\,' is turned into just ',' by pbx_config; So we need to do the same */
char * q = p ;
while ( * q ) { /* move the ',' and everything after it up 1 char */
* q = * ( q + 1 ) ;
q + + ;
}
}
p + + ;
}
}
# endif
/* PRETTY PRINTER FOR AEL: ============================================================================= */
static void print_pval ( FILE * fin , pval * item , int depth )
{
int i ;
pval * lp ;
for ( i = 0 ; i < depth ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
switch ( item - > type ) {
case PV_WORD :
fprintf ( fin , " %s; \n " , item - > u1 . str ) ; /* usually, words are encapsulated in something else */
break ;
case PV_MACRO :
fprintf ( fin , " macro %s( " , item - > u1 . str ) ;
for ( lp = item - > u2 . arglist ; lp ; lp = lp - > next ) {
if ( lp ! = item - > u2 . arglist )
fprintf ( fin , " , " ) ;
fprintf ( fin , " %s " , lp - > u1 . str ) ;
}
fprintf ( fin , " ) { \n " ) ;
print_pval_list ( fin , item - > u3 . macro_statements , depth + 1 ) ;
for ( i = 0 ; i < depth ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
fprintf ( fin , " }; \n \n " ) ;
break ;
case PV_CONTEXT :
if ( item - > u3 . abstract )
fprintf ( fin , " abstract context %s { \n " , item - > u1 . str ) ;
else
fprintf ( fin , " context %s { \n " , item - > u1 . str ) ;
print_pval_list ( fin , item - > u2 . statements , depth + 1 ) ;
for ( i = 0 ; i < depth ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
fprintf ( fin , " }; \n \n " ) ;
break ;
case PV_MACRO_CALL :
fprintf ( fin , " &%s( " , item - > u1 . str ) ;
for ( lp = item - > u2 . arglist ; lp ; lp = lp - > next ) {
if ( lp ! = item - > u2 . arglist )
fprintf ( fin , " , " ) ;
fprintf ( fin , " %s " , lp - > u1 . str ) ;
}
fprintf ( fin , " ); \n " ) ;
break ;
case PV_APPLICATION_CALL :
fprintf ( fin , " %s( " , item - > u1 . str ) ;
for ( lp = item - > u2 . arglist ; lp ; lp = lp - > next ) {
if ( lp ! = item - > u2 . arglist )
fprintf ( fin , " , " ) ;
fprintf ( fin , " %s " , lp - > u1 . str ) ;
}
fprintf ( fin , " ); \n " ) ;
break ;
case PV_CASE :
fprintf ( fin , " case %s: \n " , item - > u1 . str ) ;
print_pval_list ( fin , item - > u2 . statements , depth + 1 ) ;
break ;
case PV_PATTERN :
fprintf ( fin , " pattern %s: \n " , item - > u1 . str ) ;
print_pval_list ( fin , item - > u2 . statements , depth + 1 ) ;
break ;
case PV_DEFAULT :
fprintf ( fin , " default: \n " ) ;
print_pval_list ( fin , item - > u2 . statements , depth + 1 ) ;
break ;
case PV_CATCH :
fprintf ( fin , " catch %s { \n " , item - > u1 . str ) ;
print_pval_list ( fin , item - > u2 . statements , depth + 1 ) ;
for ( i = 0 ; i < depth ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
fprintf ( fin , " }; \n " ) ;
break ;
case PV_SWITCHES :
fprintf ( fin , " switches { \n " ) ;
print_pval_list ( fin , item - > u1 . list , depth + 1 ) ;
for ( i = 0 ; i < depth ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
fprintf ( fin , " }; \n " ) ;
break ;
case PV_ESWITCHES :
fprintf ( fin , " eswitches { \n " ) ;
print_pval_list ( fin , item - > u1 . list , depth + 1 ) ;
for ( i = 0 ; i < depth ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
fprintf ( fin , " }; \n " ) ;
break ;
case PV_INCLUDES :
fprintf ( fin , " includes { \n " ) ;
for ( lp = item - > u1 . list ; lp ; lp = lp - > next ) {
for ( i = 0 ; i < depth + 1 ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
fprintf ( fin , " %s " , lp - > u1 . str ) ; /* usually, words are encapsulated in something else */
if ( lp - > u2 . arglist )
fprintf ( fin , " |%s|%s|%s|%s " ,
lp - > u2 . arglist - > u1 . str ,
lp - > u2 . arglist - > next - > u1 . str ,
lp - > u2 . arglist - > next - > next - > u1 . str ,
lp - > u2 . arglist - > next - > next - > next - > u1 . str
) ;
fprintf ( fin , " ; \n " ) ; /* usually, words are encapsulated in something else */
}
print_pval_list ( fin , item - > u1 . list , depth + 1 ) ;
for ( i = 0 ; i < depth ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
fprintf ( fin , " }; \n " ) ;
break ;
case PV_STATEMENTBLOCK :
fprintf ( fin , " { \n " ) ;
print_pval_list ( fin , item - > u1 . list , depth + 1 ) ;
for ( i = 0 ; i < depth ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
fprintf ( fin , " }; \n " ) ;
break ;
case PV_VARDEC :
fprintf ( fin , " %s=%s; \n " , item - > u1 . str , item - > u2 . val ) ;
break ;
case PV_LOCALVARDEC :
fprintf ( fin , " local %s=%s; \n " , item - > u1 . str , item - > u2 . val ) ;
break ;
case PV_GOTO :
fprintf ( fin , " goto %s " , item - > u1 . list - > u1 . str ) ;
if ( item - > u1 . list - > next )
fprintf ( fin , " ,%s " , item - > u1 . list - > next - > u1 . str ) ;
if ( item - > u1 . list - > next & & item - > u1 . list - > next - > next )
fprintf ( fin , " ,%s " , item - > u1 . list - > next - > next - > u1 . str ) ;
fprintf ( fin , " \n " ) ;
break ;
case PV_LABEL :
fprintf ( fin , " %s: \n " , item - > u1 . str ) ;
break ;
case PV_FOR :
fprintf ( fin , " for (%s; %s; %s) \n " , item - > u1 . for_init , item - > u2 . for_test , item - > u3 . for_inc ) ;
print_pval_list ( fin , item - > u4 . for_statements , depth + 1 ) ;
break ;
case PV_WHILE :
fprintf ( fin , " while (%s) \n " , item - > u1 . str ) ;
print_pval_list ( fin , item - > u2 . statements , depth + 1 ) ;
break ;
case PV_BREAK :
fprintf ( fin , " break; \n " ) ;
break ;
case PV_RETURN :
fprintf ( fin , " return; \n " ) ;
break ;
case PV_CONTINUE :
fprintf ( fin , " continue; \n " ) ;
break ;
case PV_RANDOM :
case PV_IFTIME :
case PV_IF :
if ( item - > type = = PV_IFTIME ) {
fprintf ( fin , " ifTime ( %s|%s|%s|%s ) \n " ,
item - > u1 . list - > u1 . str ,
item - > u1 . list - > next - > u1 . str ,
item - > u1 . list - > next - > next - > u1 . str ,
item - > u1 . list - > next - > next - > next - > u1 . str
) ;
} else if ( item - > type = = PV_RANDOM ) {
fprintf ( fin , " random ( %s ) \n " , item - > u1 . str ) ;
} else
fprintf ( fin , " if ( %s ) \n " , item - > u1 . str ) ;
if ( item - > u2 . statements & & item - > u2 . statements - > next ) {
for ( i = 0 ; i < depth ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
fprintf ( fin , " { \n " ) ;
print_pval_list ( fin , item - > u2 . statements , depth + 1 ) ;
for ( i = 0 ; i < depth ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
if ( item - > u3 . else_statements )
fprintf ( fin , " } \n " ) ;
else
fprintf ( fin , " }; \n " ) ;
} else if ( item - > u2 . statements ) {
print_pval_list ( fin , item - > u2 . statements , depth + 1 ) ;
} else {
if ( item - > u3 . else_statements )
fprintf ( fin , " {} " ) ;
else
fprintf ( fin , " {}; " ) ;
}
if ( item - > u3 . else_statements ) {
for ( i = 0 ; i < depth ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
fprintf ( fin , " else \n " ) ;
print_pval_list ( fin , item - > u3 . else_statements , depth ) ;
}
break ;
case PV_SWITCH :
fprintf ( fin , " switch( %s ) { \n " , item - > u1 . str ) ;
print_pval_list ( fin , item - > u2 . statements , depth + 1 ) ;
for ( i = 0 ; i < depth ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
fprintf ( fin , " } \n " ) ;
break ;
case PV_EXTENSION :
if ( item - > u4 . regexten )
fprintf ( fin , " regexten " ) ;
if ( item - > u3 . hints )
fprintf ( fin , " hints(%s) " , item - > u3 . hints ) ;
fprintf ( fin , " %s => \n " , item - > u1 . str ) ;
print_pval_list ( fin , item - > u2 . statements , depth + 1 ) ;
break ;
case PV_IGNOREPAT :
fprintf ( fin , " ignorepat => %s \n " , item - > u1 . str ) ;
break ;
case PV_GLOBALS :
fprintf ( fin , " globals { \n " ) ;
print_pval_list ( fin , item - > u1 . statements , depth + 1 ) ;
for ( i = 0 ; i < depth ; i + + ) {
fprintf ( fin , " \t " ) ; /* depth == indentation */
}
fprintf ( fin , " } \n " ) ;
break ;
}
}
static void print_pval_list ( FILE * fin , pval * item , int depth )
{
pval * i ;
for ( i = item ; i ; i = i - > next ) {
print_pval ( fin , i , depth ) ;
}
}
#if 0
static void ael2_print ( char * fname , pval * tree )
{
FILE * fin = fopen ( fname , " w " ) ;
if ( ! fin ) {
ast_log ( LOG_ERROR , " Couldn't open %s for writing. \n " , fname ) ;
return ;
}
print_pval_list ( fin , tree , 0 ) ;
fclose ( fin ) ;
}
# endif
/* SEMANTIC CHECKING FOR AEL: ============================================================================= */
/* (not all that is syntactically legal is good! */
static struct pval * in_macro ( pval * item )
{
struct pval * curr ;
curr = item ;
while ( curr ) {
if ( curr - > type = = PV_MACRO ) {
return curr ;
}
curr = curr - > dad ;
}
return 0 ;
}
static struct pval * in_context ( pval * item )
{
struct pval * curr ;
curr = item ;
while ( curr ) {
if ( curr - > type = = PV_MACRO | | curr - > type = = PV_CONTEXT ) {
return curr ;
}
curr = curr - > dad ;
}
return 0 ;
}
static void check_goto ( pval * item )
{
/* check for the target of the goto-- does it exist? */
if ( ! ( item - > u1 . list ) - > next & & ! ( item - > u1 . list ) - > u1 . str ) {
ast_log ( LOG_ERROR , " Error: file %s, line %d-%d: goto: empty label reference found! \n " ,
item - > filename , item - > startline , item - > endline ) ;
errs + + ;
}
/* just one item-- the label should be in the current extension */
if ( item - > u1 . list & & ! item - > u1 . list - > next & & ! strstr ( ( item - > u1 . list ) - > u1 . str , " ${ " ) ) {
struct pval * z = get_extension_or_contxt ( item ) ;
struct pval * x = 0 ;
if ( z )
x = find_label_in_current_extension ( ( char * ) ( ( item - > u1 . list ) - > u1 . str ) , z ) ; /* if in macro, use current context instead */
/* printf("Called find_label_in_current_extension with arg %s; current_extension is %x: %d\n",
( char * ) ( ( item - > u1 . list ) - > u1 . str ) , current_extension ? current_extension : current_context , current_extension ? current_extension - > type : current_context - > type ) ; */
if ( ! x ) {
ast_log ( LOG_ERROR , " Error: file %s, line %d-%d: goto: no label %s exists in the current extension! \n " ,
item - > filename , item - > startline , item - > endline , item - > u1 . list - > u1 . str ) ;
errs + + ;
}
else
return ;
}
/* TWO items */
if ( item - > u1 . list - > next & & ! item - > u1 . list - > next - > next ) {
/* two items */
/* printf("Calling find_label_in_current_context with args %s, %s\n",
( char * ) ( ( item - > u1 . list ) - > u1 . str ) , ( char * ) item - > u1 . list - > next - > u1 . str ) ; */
if ( ! strstr ( ( item - > u1 . list ) - > u1 . str , " ${ " )
& & ! strstr ( item - > u1 . list - > next - > u1 . str , " ${ " ) ) /* Don't try to match variables */ {
struct pval * z = get_contxt ( item ) ;
struct pval * x = 0 ;
if ( z )
x = find_label_in_current_context ( ( char * ) item - > u1 . list - > u1 . str , ( char * ) item - > u1 . list - > next - > u1 . str , z ) ;
if ( ! x ) {
ast_log ( LOG_ERROR , " Error: file %s, line %d-%d: goto: no label %s|%s exists in the current context, or any of its inclusions! \n " ,
item - > filename , item - > startline , item - > endline , item - > u1 . list - > u1 . str , item - > u1 . list - > next - > u1 . str ) ;
errs + + ;
}
else
return ;
}
}
/* All 3 items! */
if ( item - > u1 . list - > next & & item - > u1 . list - > next - > next ) {
/* all three */
pval * first = item - > u1 . list ;
pval * second = item - > u1 . list - > next ;
pval * third = item - > u1 . list - > next - > next ;
/* printf("Calling find_label_in_current_db with args %s, %s, %s\n",
( char * ) first - > u1 . str , ( char * ) second - > u1 . str , ( char * ) third - > u1 . str ) ; */
if ( ! strstr ( ( item - > u1 . list ) - > u1 . str , " ${ " )
& & ! strstr ( item - > u1 . list - > next - > u1 . str , " ${ " )
& & ! strstr ( item - > u1 . list - > next - > next - > u1 . str , " ${ " ) ) /* Don't try to match variables */ {
struct pval * x = find_label_in_current_db ( ( char * ) first - > u1 . str , ( char * ) second - > u1 . str , ( char * ) third - > u1 . str ) ;
if ( ! x ) {
struct pval * p3 ;
struct pval * found = 0 ;
struct pval * that_context = find_context ( item - > u1 . list - > u1 . str ) ;
/* the target of the goto could be in an included context!! Fancy that!! */
/* look for includes in the current context */
if ( that_context ) {
for ( p3 = that_context - > u2 . statements ; p3 ; p3 = p3 - > next ) {
if ( p3 - > type = = PV_INCLUDES ) {
struct pval * p4 ;
for ( p4 = p3 - > u1 . list ; p4 ; p4 = p4 - > next ) {
/* for each context pointed to, find it, then find a context/label that matches the
target here ! */
char * incl_context = p4 - > u1 . str ;
/* find a matching context name */
struct pval * that_other_context = find_context ( incl_context ) ;
if ( that_other_context ) {
struct pval * x3 ;
x3 = find_label_in_current_context ( ( char * ) item - > u1 . list - > next - > u1 . str , ( char * ) item - > u1 . list - > next - > next - > u1 . str , that_other_context ) ;
if ( x3 ) {
found = x3 ;
break ;
}
}
}
}
}
if ( ! found ) {
ast_log ( LOG_ERROR , " Error: file %s, line %d-%d: goto: no label %s|%s exists in the context %s or its inclusions! \n " ,
item - > filename , item - > startline , item - > endline , item - > u1 . list - > next - > u1 . str , item - > u1 . list - > next - > next - > u1 . str , item - > u1 . list - > u1 . str ) ;
errs + + ;
} else {
struct pval * mac = in_macro ( item ) ; /* is this goto inside a macro? */
if ( mac ) { /* yes! */
struct pval * targ = in_context ( found ) ;
if ( mac ! = targ )
{
ast_log ( LOG_WARNING , " Warning: file %s, line %d-%d: It's bad form to have a goto in a macro to a target outside the macro! \n " ,
item - > filename , item - > startline , item - > endline ) ;
warns + + ;
}
}
}
} else {
/* here is where code would go to check for target existence in extensions.conf files */
ast_log ( LOG_WARNING , " Warning: file %s, line %d-%d: goto: no context %s could be found that matches the goto target! \n " ,
item - > filename , item - > startline , item - > endline , item - > u1 . list - > u1 . str ) ;
warns + + ; /* this is just a warning, because this context could be in extensions.conf or somewhere */
}
} else {
struct pval * mac = in_macro ( item ) ; /* is this goto inside a macro? */
if ( mac ) { /* yes! */
struct pval * targ = in_context ( x ) ;
if ( mac ! = targ )
{
ast_log ( LOG_WARNING , " Warning: file %s, line %d-%d: It's bad form to have a goto in a macro to a target outside the macro! \n " ,
item - > filename , item - > startline , item - > endline ) ;
warns + + ;
}
}
}
}
}
}
static void find_pval_goto_item ( pval * item , int lev )
{
struct pval * p4 ;
if ( lev > 100 ) {
ast_log ( LOG_ERROR , " find_pval_goto in infinite loop! \n \n " ) ;
return ;
}
switch ( item - > type ) {
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 .
*/
/* printf("Descending into matching macro %s\n", match_context); */
find_pval_gotos ( item - > u3 . macro_statements , lev + 1 ) ; /* if we're just searching for a context, don't bother descending into them */
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
*/
break ;
case PV_CASE :
/* fields: item->u1.str == value of case
item - > u2 . statements = = pval list of statements under the case
*/
find_pval_gotos ( item - > u2 . statements , lev + 1 ) ;
break ;
case PV_PATTERN :
/* fields: item->u1.str == value of case
item - > u2 . statements = = pval list of statements under the case
*/
find_pval_gotos ( item - > u2 . statements , lev + 1 ) ;
break ;
case PV_DEFAULT :
/* fields:
item - > u2 . statements = = pval list of statements under the case
*/
find_pval_gotos ( item - > u2 . statements , lev + 1 ) ;
break ;
case PV_CATCH :
/* fields: item->u1.str == name of extension to catch
item - > u2 . statements = = pval list of statements in context body
*/
find_pval_gotos ( item - > u2 . statements , lev + 1 ) ;
break ;
case PV_STATEMENTBLOCK :
/* fields: item->u1.list == pval list of statements in block, one per entry in the list
*/
find_pval_gotos ( item - > u1 . list , lev + 1 ) ;
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 .
*/
check_goto ( item ) ; /* THE WHOLE FUNCTION OF THIS ENTIRE ROUTINE!!!! */
break ;
case PV_INCLUDES :
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
*/
for ( p4 = item - > u1 . list ; p4 ; p4 = p4 - > next ) {
/* for each context pointed to, find it, then find a context/label that matches the
target here ! */
char * incl_context = p4 - > u1 . str ;
/* find a matching context name */
struct pval * that_context = find_context ( incl_context ) ;
if ( that_context ) {
find_pval_gotos ( that_context , lev + 1 ) ; /* keep working up the includes */
}
}
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 ( )
*/
find_pval_gotos ( item - > u4 . for_statements , lev + 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 ( )
*/
find_pval_gotos ( item - > u2 . statements , lev + 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 )
fall thru to PV_IF */
case PV_IFTIME :
/* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list
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 )
fall thru to PV_IF */
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 )
*/
find_pval_gotos ( item - > u2 . statements , lev + 1 ) ;
if ( item - > u3 . else_statements ) {
find_pval_gotos ( item - > u3 . else_statements , lev + 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 ! )
*/
find_pval_gotos ( item - > u3 . else_statements , lev + 1 ) ;
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
*/
find_pval_gotos ( item - > u2 . statements , lev + 1 ) ;
break ;
default :
break ;
}
}
static void find_pval_gotos ( pval * item , int lev )
{
pval * i ;
for ( i = item ; i ; i = i - > next ) {
find_pval_goto_item ( i , lev ) ;
}
}
struct pval * find_first_label_in_current_context ( char * label , pval * curr_cont )
{
/* printf(" --- Got args %s, %s\n", exten, label); */
struct pval * ret ;
struct pval * p3 ;
struct pval * startpt = ( ( curr_cont - > type = = PV_MACRO ) ? curr_cont - > u3 . macro_statements : curr_cont - > u2 . statements ) ;
count_labels = 0 ;
return_on_context_match = 0 ;
match_context = " * " ;
match_exten = " * " ;
match_label = label ;
ret = match_pval ( curr_cont ) ;
if ( ret )
return ret ;
/* the target of the goto could be in an included context!! Fancy that!! */
/* look for includes in the current context */
for ( p3 = startpt ; p3 ; p3 = p3 - > next ) {
if ( p3 - > type = = PV_INCLUDES ) {
struct pval * p4 ;
for ( p4 = p3 - > u1 . list ; p4 ; p4 = p4 - > next ) {
/* for each context pointed to, find it, then find a context/label that matches the
target here ! */
char * incl_context = p4 - > u1 . str ;
/* find a matching context name */
struct pval * that_context = find_context ( incl_context ) ;
if ( that_context ) {
struct pval * x3 ;
x3 = find_first_label_in_current_context ( label , that_context ) ;
if ( x3 ) {
return x3 ;
}
}
}
}
}
return 0 ;
}
struct pval * find_label_in_current_context ( char * exten , char * label , pval * curr_cont )
{
/* printf(" --- Got args %s, %s\n", exten, label); */
struct pval * ret ;
struct pval * p3 ;
struct pval * startpt ;
count_labels = 0 ;
return_on_context_match = 0 ;
match_context = " * " ;
match_exten = exten ;
match_label = label ;
if ( curr_cont - > type = = PV_MACRO )
startpt = curr_cont - > u3 . macro_statements ;
else
startpt = curr_cont - > u2 . statements ;
ret = match_pval ( startpt ) ;
if ( ret )
return ret ;
/* the target of the goto could be in an included context!! Fancy that!! */
/* look for includes in the current context */
for ( p3 = startpt ; p3 ; p3 = p3 - > next ) {
if ( p3 - > type = = PV_INCLUDES ) {
struct pval * p4 ;
for ( p4 = p3 - > u1 . list ; p4 ; p4 = p4 - > next ) {
/* for each context pointed to, find it, then find a context/label that matches the
target here ! */
char * incl_context = p4 - > u1 . str ;
/* find a matching context name */
struct pval * that_context = find_context ( incl_context ) ;
if ( that_context ) {
struct pval * x3 ;
x3 = find_label_in_current_context ( exten , label , that_context ) ;
if ( x3 ) {
return x3 ;
}
}
}
}
}
return 0 ;
}
static struct pval * find_label_in_current_extension ( const char * label , pval * curr_ext )
{
/* printf(" --- Got args %s\n", label); */
count_labels = 0 ;
return_on_context_match = 0 ;
match_context = " * " ;
match_exten = " * " ;
match_label = label ;
return match_pval ( curr_ext ) ;
}
static struct pval * find_label_in_current_db ( const char * context , const char * exten , const char * label )
{
/* printf(" --- Got args %s, %s, %s\n", context, exten, label); */
count_labels = 0 ;
return_on_context_match = 0 ;
match_context = context ;
match_exten = exten ;
match_label = label ;
return match_pval ( current_db ) ;
}
/* =============================================================================================== */
/* "CODE" GENERATOR -- Convert the AEL representation to asterisk extension language */
/* =============================================================================================== */
static pval * get_extension_or_contxt ( pval * p )
{
while ( p & & p - > type ! = PV_EXTENSION & & p - > type ! = PV_CONTEXT & & p - > type ! = PV_MACRO ) {
p = p - > dad ;
}
return p ;
}
static pval * get_contxt ( pval * p )
{
while ( p & & p - > type ! = PV_CONTEXT & & p - > type ! = PV_MACRO ) {
p = p - > dad ;
}
return p ;
}
static int aeldebug = 0 ;
static int aeldebug = 0 ;