diff options
Diffstat (limited to 'pbx')
-rw-r--r-- | pbx/ael/ael-test/ref.ael-test16 | 19 | ||||
-rw-r--r-- | pbx/ael/ael-test/ref.ael-test19 | 4 | ||||
-rw-r--r-- | pbx/pbx_ael.c | 794 |
3 files changed, 11 insertions, 806 deletions
diff --git a/pbx/ael/ael-test/ref.ael-test16 b/pbx/ael/ael-test/ref.ael-test16 index ffa926009..9bbca8bee 100644 --- a/pbx/ael/ael-test/ref.ael-test16 +++ b/pbx/ael/ael-test/ref.ael-test16 @@ -2,13 +2,12 @@ (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) -LOG: lev:2 file:pbx_ael.c line:113 func: pbx_load_module Starting AEL load process. -LOG: lev:2 file:pbx_ael.c line:120 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. -LOG: lev:3 file:ael.y line:205 func: ael_yyparse ==== File: ./extensions.ael, Line 1, Cols: 19-19: Warning! The empty context real-small will be IGNORED! -LOG: lev:2 file:pbx_ael.c line:128 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. -LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. -LOG: lev:3 file:pval.c line:3633 func: add_extensions This file is Empty! -LOG: lev:2 file:pbx_ael.c line:133 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. -LOG: lev:2 file:pbx_ael.c line:136 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. -LOG: lev:2 file:pbx_ael.c line:139 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. -LOG: lev:4 file:ael2_parse line:499 func: main 0 contexts, 0 extensions, 0 priorities +LOG: lev:2 file:pbx_ael.c line:913 func: pbx_load_module Starting AEL load process. +LOG: lev:2 file:pbx_ael.c line:920 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:928 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:931 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. +LOG: lev:3 file:pval.c line:3784 func: add_extensions This file is Empty! +LOG: lev:2 file:pbx_ael.c line:933 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:936 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:939 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. +LOG: lev:4 file:ael2_parse line:543 func: main 1 contexts, 0 extensions, 0 priorities diff --git a/pbx/ael/ael-test/ref.ael-test19 b/pbx/ael/ael-test/ref.ael-test19 index 27a322b75..f0ab66717 100644 --- a/pbx/ael/ael-test/ref.ael-test19 +++ b/pbx/ael/ael-test/ref.ael-test19 @@ -5,7 +5,7 @@ LOG: lev:2 file:pbx_ael.c line:913 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:920 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:928 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. -LOG: lev:3 file:pval.c line:2298 func: check_context_names Warning: file ./extensions.ael, line 49-62: The context name (incoming) is also declared in file ./extensions.ael, line 62-69! +LOG: lev:3 file:pval.c line:2298 func: check_context_names Warning: file ./extensions.ael, line 49-62: The context name (incoming) is also declared in file ./extensions.ael, line 62-69! (and neither is marked 'extend') LOG: lev:3 file:pval.c line:670 func: check_macro_returns Warning: file ./extensions.ael, line 71-175: The macro std-priv-exten does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:2282 func: check_switch_expr Warning: file ./extensions.ael, line 245-246: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:2424 func: check_pval_item Warning: file ./extensions.ael, line 312-312: macro call to non-existent funcA! (Not even in the extensions.conf stuff!) @@ -16,4 +16,4 @@ LOG: lev:2 file:pbx_ael.c line:931 func: pbx_load_module AEL load process: che LOG: lev:2 file:pbx_ael.c line:933 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:936 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:939 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. -LOG: lev:4 file:ael2_parse line:527 func: main 13 contexts, 57 extensions, 188 priorities +LOG: lev:4 file:ael2_parse line:543 func: main 13 contexts, 57 extensions, 188 priorities diff --git a/pbx/pbx_ael.c b/pbx/pbx_ael.c index 506c75184..521d13ada 100644 --- a/pbx/pbx_ael.c +++ b/pbx/pbx_ael.c @@ -63,8 +63,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") static char *config = "extensions.ael"; static char *registrar = "pbx_ael"; static int pbx_load_module(void); -static int warns, errs; -static struct pval *current_db; #ifndef AAL_ARGCHECK /* 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_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); */ -#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; |