![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
pbx_ael.c File Reference
Definition in file pbx_ael.c.
#include "asterisk.h"
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <regex.h>
#include <sys/stat.h>
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/callerid.h"
#include "asterisk/ael_structs.h"
Include dependency graph for pbx_ael.c:

Go to the source code of this file.
Data Structures | |
| struct | argapp |
Defines | |
| #define | DEBUG_CONTEXTS (1 << 3) |
| #define | DEBUG_MACROS (1 << 2) |
| #define | DEBUG_READ (1 << 0) |
| #define | DEBUG_TOKENS (1 << 1) |
Functions | |
| void | add_extensions (struct ael_extension *exten) |
| static int | ael2_debug_contexts (int fd, int argc, char *argv[]) |
| static int | ael2_debug_macros (int fd, int argc, char *argv[]) |
| static int | ael2_debug_read (int fd, int argc, char *argv[]) |
| static int | ael2_debug_tokens (int fd, int argc, char *argv[]) |
| static int | ael2_no_debug (int fd, int argc, char *argv[]) |
| static int | ael2_reload (int fd, int argc, char *argv[]) |
| static void | ael2_semantic_check (pval *item, int *arg_errs, int *arg_warns, int *arg_notes) |
| void | ast_compile_ael2 (struct ast_context **local_contexts, struct pval *root) |
| int | ast_expr (char *expr, char *buf, int length) |
| void | ast_expr_clear_extra_error_info (void) |
| void | ast_expr_register_extra_error_info (char *errmsg) |
| AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Asterisk Extension Language Compiler",.load=load_module,.unload=unload_module,.reload=reload,) | |
| static void | attach_exten (struct ael_extension **list, struct ael_extension *newmem) |
| static void | check_abstract_reference (pval *abstract_context) |
| int | check_app_args (pval *appcall, pval *arglist, struct argapp *app) |
| static int | check_break (pval *item) |
| static void | check_context_names (void) |
| static int | check_continue (pval *item) |
| static void | check_day (pval *DAY) |
| static void | check_dow (pval *DOW) |
| get_dow: Get day of week | |
| static void | check_expr2_input (pval *expr, char *str) |
| static void | check_goto (pval *item) |
| static void | check_includes (pval *includes) |
| static void | check_label (pval *item) |
| static void | check_macro_returns (pval *macro) |
| static void | check_month (pval *MON) |
| void | check_pval (pval *item, struct argapp *apps, int in_globals) |
| void | check_pval_item (pval *item, struct argapp *apps, int in_globals) |
| void | check_switch_expr (pval *item, struct argapp *apps) |
| static void | check_timerange (pval *p) |
| void | destroy_extensions (struct ael_extension *exten) |
| void | destroy_pval (pval *item) |
| void | destroy_pval_item (pval *item) |
| static int | extension_matches (pval *here, const char *exten, const char *pattern) |
| pval * | find_context (char *name) |
| static struct pval * | find_first_label_in_current_context (char *label, pval *curr_cont) |
| static struct pval * | find_label_in_current_context (char *exten, char *label, pval *curr_cont) |
| static struct pval * | find_label_in_current_db (const char *context, const char *exten, const char *label) |
| static struct pval * | find_label_in_current_extension (const char *label, pval *curr_ext) |
| pval * | find_macro (char *name) |
| static void | find_pval_goto_item (pval *item, int lev) |
| static void | find_pval_gotos (pval *item, int lev) |
| static void | fix_gotos_in_extensions (struct ael_extension *exten) |
| static void | gen_match_to_pattern (char *pattern, char *result) |
| static void | gen_prios (struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *context) |
| static pval * | get_contxt (pval *p) |
| static pval * | get_extension_or_contxt (pval *p) |
| static pval * | get_goto_target (pval *item) |
| static struct pval * | in_context (pval *item) |
| static struct pval * | in_macro (pval *item) |
| int | is_empty (char *arg) |
| int | is_float (char *arg) |
| int | is_int (char *arg) |
| static int | label_inside_case (pval *label) |
| static void | linkexten (struct ael_extension *exten, struct ael_extension *add) |
| void | linkprio (struct ael_extension *exten, struct ael_priority *prio) |
| static int | load_module (void) |
| pval * | match_pval (pval *item) |
| static struct pval * | match_pval_item (pval *item) |
| ael_extension * | new_exten (void) |
| ael_priority * | new_prio (void) |
| static int | pbx_load_module (void) |
| static void | print_pval (FILE *fin, pval *item, int depth) |
| static void | print_pval_list (FILE *fin, pval *item, int depth) |
| static int | reload (void) |
| static void | remove_spaces_before_equals (char *str) |
| void | set_priorities (struct ael_extension *exten) |
| static void | substitute_commas (char *str) |
| void | traverse_pval_item_template (pval *item, int depth) |
| void | traverse_pval_template (pval *item, int depth) |
| static int | unload_module (void) |
Variables | |
| static int | aeldebug = 0 |
| static struct ast_cli_entry | cli_ael [] |
| static struct ast_cli_entry | cli_ael_no_debug |
| static char * | config = "extensions.ael" |
| static int | control_statement_count = 0 |
| static int | count_labels |
| static pval * | current_context |
| static pval * | current_db |
| static pval * | current_extension |
| static char * | days [] |
| static int | errs |
| static char | expr_output [2096] |
| static int | in_abstract_context |
| static int | label_count |
| static pval * | last_matched_label |
| static const char * | match_context |
| static const char * | match_exten |
| static const char * | match_label |
| static char * | months [] |
| static int | notes |
| static char * | registrar = "pbx_ael" |
| static int | return_on_context_match |
| static int | warns |
|
|
Definition at line 58 of file pbx_ael.c. Referenced by ael2_debug_contexts(). |
|
|
Definition at line 57 of file pbx_ael.c. Referenced by ael2_debug_macros(). |
|
|
Definition at line 55 of file pbx_ael.c. Referenced by ael2_debug_read(). |
|
|
Definition at line 56 of file pbx_ael.c. Referenced by ael2_debug_tokens(). |
|
|
Definition at line 3611 of file pbx_ael.c. References AEL_APPCALL, AEL_CONTROL1, AEL_FOR_CONTROL, AEL_IF_CONTROL, AEL_IFTIME_CONTROL, AEL_LABEL, AEL_RAND_CONTROL, AEL_RETURN, ael_priority::app, app, ael_priority::appargs, ast_add_extension2(), ast_free, ast_log(), pval::else_statements, ael_priority::exten, exten, ael_priority::goto_false, ael_priority::goto_true, last, LOG_WARNING, ael_extension::name, ael_priority::next, ael_priority::origin, PRIORITY_HINT, ael_priority::priority_num, PV_IFTIME, PV_SWITCH, strdup, pval::type, ael_priority::type, and pval::u3. 03612 { 03613 struct ael_priority *pr; 03614 char *label=0; 03615 if (!exten) { 03616 ast_log(LOG_WARNING, "This file is Empty!\n" ); 03617 return; 03618 } 03619 do { 03620 struct ael_priority *last = 0; 03621 03622 if (exten->hints) { 03623 if (ast_add_extension2(exten->context, 0 /*no replace*/, exten->name, PRIORITY_HINT, NULL, exten->cidmatch, 03624 exten->hints, NULL, ast_free, registrar)) { 03625 ast_log(LOG_WARNING, "Unable to add step at priority 'hint' of extension '%s'\n", 03626 exten->name); 03627 } 03628 } 03629 03630 for (pr=exten->plist; pr; pr=pr->next) { 03631 char app[2000]; 03632 char appargs[2000]; 03633 03634 /* before we can add the extension, we need to prep the app/appargs; 03635 the CONTROL types need to be done after the priority numbers are calculated. 03636 */ 03637 if (pr->type == AEL_LABEL) /* don't try to put labels in the dialplan! */ { 03638 last = pr; 03639 continue; 03640 } 03641 03642 if (pr->app) 03643 strcpy(app, pr->app); 03644 else 03645 app[0] = 0; 03646 if (pr->appargs ) 03647 strcpy(appargs, pr->appargs); 03648 else 03649 appargs[0] = 0; 03650 switch( pr->type ) { 03651 case AEL_APPCALL: 03652 /* easy case. Everything is all set up */ 03653 break; 03654 03655 case AEL_CONTROL1: /* FOR loop, WHILE loop, BREAK, CONTINUE, IF, IFTIME */ 03656 /* simple, unconditional goto. */ 03657 strcpy(app,"Goto"); 03658 if (pr->goto_true->origin && pr->goto_true->origin->type == PV_SWITCH ) { 03659 snprintf(appargs,sizeof(appargs),"%s|%d", pr->goto_true->exten->name, pr->goto_true->priority_num); 03660 } else if (pr->goto_true->origin && pr->goto_true->origin->type == PV_IFTIME && pr->goto_true->origin->u3.else_statements ) { 03661 snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num+1); 03662 } else 03663 snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num); 03664 break; 03665 03666 case AEL_FOR_CONTROL: /* WHILE loop test, FOR loop test */ 03667 strcpy(app,"GotoIf"); 03668 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); 03669 break; 03670 03671 case AEL_IF_CONTROL: 03672 strcpy(app,"GotoIf"); 03673 if (pr->origin->u3.else_statements ) 03674 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num+1); 03675 else 03676 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); 03677 break; 03678 03679 case AEL_RAND_CONTROL: 03680 strcpy(app,"Random"); 03681 snprintf(appargs,sizeof(appargs),"%s:%d", pr->appargs, pr->goto_true->priority_num+1); 03682 break; 03683 03684 case AEL_IFTIME_CONTROL: 03685 strcpy(app,"GotoIfTime"); 03686 snprintf(appargs,sizeof(appargs),"%s?%d", pr->appargs, pr->priority_num+2); 03687 break; 03688 03689 case AEL_RETURN: 03690 strcpy(app,"Return"); 03691 appargs[0] = 0; 03692 break; 03693 03694 default: 03695 break; 03696 } 03697 if (last && last->type == AEL_LABEL ) { 03698 label = last->origin->u1.str; 03699 } 03700 else 03701 label = 0; 03702 03703 if (ast_add_extension2(exten->context, 0 /*no replace*/, exten->name, pr->priority_num, (label?label:NULL), exten->cidmatch, 03704 app, strdup(appargs), ast_free, registrar)) { 03705 ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num, 03706 exten->name); 03707 } 03708 last = pr; 03709 } 03710 exten = exten->next_exten; 03711 } while ( exten ); 03712 }
|
|
||||||||||||||||
|
Definition at line 4041 of file pbx_ael.c. References DEBUG_CONTEXTS. 04042 { 04043 aeldebug |= DEBUG_CONTEXTS; 04044 return 0; 04045 }
|
|
||||||||||||||||
|
Definition at line 4035 of file pbx_ael.c. References DEBUG_MACROS. 04036 { 04037 aeldebug |= DEBUG_MACROS; 04038 return 0; 04039 }
|
|
||||||||||||||||
|
Definition at line 4023 of file pbx_ael.c. References DEBUG_READ. 04024 { 04025 aeldebug |= DEBUG_READ; 04026 return 0; 04027 }
|
|
||||||||||||||||
|
Definition at line 4029 of file pbx_ael.c. References DEBUG_TOKENS. 04030 { 04031 aeldebug |= DEBUG_TOKENS; 04032 return 0; 04033 }
|
|
||||||||||||||||
|
Definition at line 4047 of file pbx_ael.c. 04048 { 04049 aeldebug = 0; 04050 return 0; 04051 }
|
|
||||||||||||||||
|
Definition at line 4053 of file pbx_ael.c. References pbx_load_module(). 04054 { 04055 return (pbx_load_module()); 04056 }
|
|
||||||||||||||||||||
|
Definition at line 2805 of file pbx_ael.c. References ast_config_AST_VAR_DIR, check_context_names(), check_pval(), and current_db. Referenced by pbx_load_module(). 02806 { 02807 02808 #ifdef AAL_ARGCHECK 02809 int argapp_errs =0; 02810 char *rfilename; 02811 #endif 02812 struct argapp *apps=0; 02813 02814 #ifdef AAL_ARGCHECK 02815 rfilename = alloca(10 + strlen(ast_config_AST_VAR_DIR)); 02816 sprintf(rfilename, "%s/applist", ast_config_AST_VAR_DIR); 02817 02818 apps = argdesc_parse(rfilename, &argapp_errs); /* giveth */ 02819 #endif 02820 current_db = item; 02821 errs = warns = notes = 0; 02822 02823 check_context_names(); 02824 check_pval(item, apps, 0); 02825 02826 #ifdef AAL_ARGCHECK 02827 argdesc_destroy(apps); /* taketh away */ 02828 #endif 02829 current_db = 0; 02830 02831 *arg_errs = errs; 02832 *arg_warns = warns; 02833 *arg_notes = notes; 02834 }
|
|
||||||||||||
|
Definition at line 3795 of file pbx_ael.c. References AEL_APPCALL, AEL_LABEL, ael_priority::app, ael_priority::appargs, pval::arglist, ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_create(), ast_log(), attach_exten(), context, pval::endline, exten, pval::filename, gen_prios(), pval::hints, linkprio(), pval::list, local_contexts, LOG_WARNING, pval::macro_statements, new_exten(), new_prio(), pval::next, pbx_builtin_setvar(), PV_CONTEXT, PV_ESWITCHES, PV_EXTENSION, PV_GLOBALS, PV_IGNOREPAT, PV_INCLUDES, PV_MACRO, PV_SWITCHES, pval::regexten, remove_spaces_before_equals(), set_priorities(), pval::startline, pval::statements, pval::str, strdup, ael_priority::type, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val. Referenced by pbx_load_module(). 03796 { 03797 pval *p,*p2; 03798 struct ast_context *context; 03799 char buf[2000]; 03800 struct ael_extension *exten; 03801 struct ael_extension *exten_list = 0; 03802 03803 for (p=root; p; p=p->next ) { 03804 pval *lp; 03805 int argc; 03806 03807 switch (p->type) { 03808 case PV_MACRO: 03809 03810 context = ast_context_create(local_contexts, p->u1.str, registrar); 03811 03812 exten = new_exten(); 03813 exten->context = context; 03814 exten->name = strdup("s"); 03815 argc = 1; 03816 for (lp=p->u2.arglist; lp; lp=lp->next) { 03817 /* for each arg, set up a "Set" command */ 03818 struct ael_priority *np2 = new_prio(); 03819 np2->type = AEL_APPCALL; 03820 np2->app = strdup("Set"); 03821 snprintf(buf,sizeof(buf),"%s=${ARG%d}", lp->u1.str, argc++); 03822 remove_spaces_before_equals(buf); 03823 np2->appargs = strdup(buf); 03824 linkprio(exten, np2); 03825 } 03826 03827 /* CONTAINS APPCALLS, CATCH, just like extensions... */ 03828 gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context ); 03829 if (exten->return_needed) { /* most likely, this will go away */ 03830 struct ael_priority *np2 = new_prio(); 03831 np2->type = AEL_APPCALL; 03832 np2->app = strdup("NoOp"); 03833 snprintf(buf,sizeof(buf),"End of Macro %s-%s",p->u1.str, exten->name); 03834 np2->appargs = strdup(buf); 03835 linkprio(exten, np2); 03836 exten-> return_target = np2; 03837 } 03838 03839 set_priorities(exten); 03840 attach_exten(&exten_list, exten); 03841 break; 03842 03843 case PV_GLOBALS: 03844 /* just VARDEC elements */ 03845 for (p2=p->u1.list; p2; p2=p2->next) { 03846 char buf2[2000]; 03847 snprintf(buf2,sizeof(buf2),"%s=%s", p2->u1.str, p2->u2.val); 03848 pbx_builtin_setvar(NULL, buf2); 03849 } 03850 break; 03851 03852 case PV_CONTEXT: 03853 context = ast_context_create(local_contexts, p->u1.str, registrar); 03854 03855 /* contexts contain: ignorepat, includes, switches, eswitches, extensions, */ 03856 for (p2=p->u2.statements; p2; p2=p2->next) { 03857 pval *p3; 03858 char *s3; 03859 03860 switch (p2->type) { 03861 case PV_EXTENSION: 03862 exten = new_exten(); 03863 exten->name = strdup(p2->u1.str); 03864 exten->context = context; 03865 03866 if( (s3=strchr(exten->name, '/') ) != 0 ) 03867 { 03868 *s3 = 0; 03869 exten->cidmatch = s3+1; 03870 } 03871 03872 if ( p2->u3.hints ) 03873 exten->hints = strdup(p2->u3.hints); 03874 exten->regexten = p2->u4.regexten; 03875 gen_prios(exten, p->u1.str, p2->u2.statements, 0, context ); 03876 if (exten->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */ 03877 struct ael_priority *np2 = new_prio(); 03878 np2->type = AEL_APPCALL; 03879 np2->app = strdup("NoOp"); 03880 snprintf(buf,sizeof(buf),"End of Extension %s", exten->name); 03881 np2->appargs = strdup(buf); 03882 linkprio(exten, np2); 03883 exten-> return_target = np2; 03884 } 03885 /* is the last priority in the extension a label? Then add a trailing no-op */ 03886 if( !exten->plist_last ) 03887 { 03888 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Empty Extension!\n", 03889 p2->filename, p2->startline, p2->endline); 03890 } 03891 03892 if ( exten->plist_last && exten->plist_last->type == AEL_LABEL ) { 03893 struct ael_priority *np2 = new_prio(); 03894 np2->type = AEL_APPCALL; 03895 np2->app = strdup("NoOp"); 03896 snprintf(buf,sizeof(buf),"A NoOp to follow a trailing label %s", exten->plist_last->origin->u1.str); 03897 np2->appargs = strdup(buf); 03898 linkprio(exten, np2); 03899 } 03900 03901 set_priorities(exten); 03902 attach_exten(&exten_list, exten); 03903 break; 03904 03905 case PV_IGNOREPAT: 03906 ast_context_add_ignorepat2(context, p2->u1.str, registrar); 03907 break; 03908 03909 case PV_INCLUDES: 03910 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 03911 if ( p3->u2.arglist ) { 03912 snprintf(buf,sizeof(buf), "%s|%s|%s|%s|%s", 03913 p3->u1.str, 03914 p3->u2.arglist->u1.str, 03915 p3->u2.arglist->next->u1.str, 03916 p3->u2.arglist->next->next->u1.str, 03917 p3->u2.arglist->next->next->next->u1.str); 03918 ast_context_add_include2(context, buf, registrar); 03919 } else 03920 ast_context_add_include2(context, p3->u1.str, registrar); 03921 } 03922 break; 03923 03924 case PV_SWITCHES: 03925 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 03926 char *c = strchr(p3->u1.str, '/'); 03927 if (c) { 03928 *c = '\0'; 03929 c++; 03930 } else 03931 c = ""; 03932 03933 ast_context_add_switch2(context, p3->u1.str, c, 0, registrar); 03934 } 03935 break; 03936 03937 case PV_ESWITCHES: 03938 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 03939 char *c = strchr(p3->u1.str, '/'); 03940 if (c) { 03941 *c = '\0'; 03942 c++; 03943 } else 03944 c = ""; 03945 03946 ast_context_add_switch2(context, p3->u1.str, c, 1, registrar); 03947 } 03948 break; 03949 default: 03950 break; 03951 } 03952 } 03953 03954 break; 03955 03956 default: 03957 /* huh? what? */ 03958 break; 03959 03960 } 03961 } 03962 /* moved these from being done after a macro or extension were processed, 03963 to after all processing is done, for the sake of fixing gotos to labels inside cases... */ 03964 /* I guess this would be considered 2nd pass of compiler now... */ 03965 fix_gotos_in_extensions(exten_list); /* find and fix extension ref in gotos to labels that are in case statements */ 03966 add_extensions(exten_list); /* actually makes calls to create priorities in ast_contexts -- feeds dialplan to asterisk */ 03967 destroy_extensions(exten_list); /* all that remains is an empty husk, discard of it as is proper */ 03968 03969 }
|
|
||||||||||||||||
|
Definition at line 3097 of file ast_expr2f.c. References AST_EXPR_integer, ast_yy_scan_string(), ast_yylex_destroy(), ast_yylex_init(), ast_yyparse(), free, and io. Referenced by pbx_substitute_variables_helper_full(). 03098 { 03099 struct parse_io io; 03100 int return_value = 0; 03101 03102 memset(&io, 0, sizeof(io)); 03103 io.string = expr; /* to pass to the error routine */ 03104 03105 ast_yylex_init(&io.scanner); 03106 03107 ast_yy_scan_string(expr, io.scanner); 03108 03109 ast_yyparse ((void *) &io); 03110 03111 ast_yylex_destroy(io.scanner); 03112 03113 if (!io.val) { 03114 if (length > 1) { 03115 strcpy(buf, "0"); 03116 return_value = 1; 03117 } 03118 } else { 03119 if (io.val->type == AST_EXPR_integer) { 03120 int res_length; 03121 03122 res_length = snprintf(buf, length, "%ld", (long int) io.val->u.i); 03123 return_value = (res_length <= length) ? res_length : length; 03124 } else { 03125 #if defined(STANDALONE) || defined(LOW_MEMORY) 03126 strncpy(buf, io.val->u.s, length - 1); 03127 #else /* !STANDALONE && !LOW_MEMORY */ 03128 ast_copy_string(buf, io.val->u.s, length); 03129 #endif /* STANDALONE || LOW_MEMORY */ 03130 return_value = strlen(buf); 03131 free(io.val->u.s); 03132 } 03133 free(io.val); 03134 } 03135 return return_value; 03136 }
|
|
|
|
|
|
|
|
||||||||||||||||||||||||||||
|
|
|
||||||||||||
|
Definition at line 3714 of file pbx_ael.c. References ael_extension::next_exten. Referenced by ast_compile_ael2(). 03715 { 03716 /* travel to the end of the list... */ 03717 struct ael_extension *lptr; 03718 if( !*list ) { 03719 *list = newmem; 03720 return; 03721 } 03722 lptr = *list; 03723 03724 while( lptr->next_exten ) { 03725 lptr = lptr->next_exten; 03726 } 03727 /* lptr should now pointing to the last element in the list; it has a null next_exten pointer */ 03728 lptr->next_exten = newmem; 03729 }
|
|
|
Definition at line 2315 of file pbx_ael.c. References current_db, pval::list, pval::next, PV_CONTEXT, PV_INCLUDES, pval::str, pval::type, pval::u1, and pval::u2. Referenced by check_pval_item(). 02316 { 02317 pval *i,*j; 02318 /* find some context includes that reference this context */ 02319 02320 02321 /* otherwise, print out a warning */ 02322 for (i=current_db; i; i=i->next) { 02323 if (i->type == PV_CONTEXT) { 02324 for (j=i->u2. statements; j; j=j->next) { 02325 if ( j->type == PV_INCLUDES ) { 02326 struct pval *p4; 02327 for (p4=j->u1.list; p4; p4=p4->next) { 02328 /* for each context pointed to, find it, then find a context/label that matches the 02329 target here! */ 02330 if ( !strcmp(p4->u1.str, abstract_context->u1.str) ) 02331 return; /* found a match! */ 02332 } 02333 } 02334 } 02335 } 02336 } 02337 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: Couldn't find a reference to this abstract context (%s) in any other context!\n", 02338 abstract_context->filename, abstract_context->startline, abstract_context->endline, abstract_context->u1.str); 02339 warns++; 02340 }
|
|
||||||||||||||||
|
Definition at line 2143 of file pbx_ael.c. References app, ast_log(), pval::endline, pval::filename, LOG_WARNING, pval::next, pval::startline, pval::str, and pval::u1. 02144 { 02145 #ifdef AAL_ARGCHECK 02146 struct argdesc *ad = app->args; 02147 pval *pa; 02148 int z; 02149 02150 for (pa = arglist; pa; pa=pa->next) { 02151 if (!ad) { 02152 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Extra argument %s not in application call to %s !\n", 02153 arglist->filename, arglist->startline, arglist->endline, pa->u1.str, app->name); 02154 warns++; 02155 return 1; 02156 } else { 02157 /* find the first entry in the ad list that will match */ 02158 do { 02159 if ( ad->dtype == ARGD_VARARG ) /* once we hit the VARARG, all bets are off. Discontinue the comparisons */ 02160 break; 02161 02162 z= option_matches( ad, pa, app); 02163 if (!z) { 02164 if ( !arglist ) 02165 arglist=appcall; 02166 02167 if (ad->type == ARGD_REQUIRED) { 02168 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", 02169 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); 02170 warns++; 02171 return 1; 02172 } 02173 } else if (z && ad->dtype == ARGD_OPTIONSET) { 02174 option_matches_j( ad, pa, app); 02175 } 02176 ad = ad->next; 02177 } while (ad && !z); 02178 } 02179 } 02180 /* any app nodes left, that are not optional? */ 02181 for ( ; ad; ad=ad->next) { 02182 if (ad->type == ARGD_REQUIRED && ad->dtype != ARGD_VARARG) { 02183 if ( !arglist ) 02184 arglist=appcall; 02185 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", 02186 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); 02187 warns++; 02188 return 1; 02189 } 02190 } 02191 return 0; 02192 #else 02193 return 0; 02194 #endif 02195 }
|
|
|
Definition at line 1093 of file pbx_ael.c. References ast_log(), pval::dad, pval::endline, pval::filename, LOG_ERROR, PV_CASE, PV_CONTEXT, PV_DEFAULT, PV_FOR, PV_MACRO, PV_PATTERN, PV_WHILE, pval::startline, and pval::type. 01094 { 01095 pval *p = item; 01096 01097 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ { 01098 /* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make 01099 no sense */ 01100 if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN 01101 || p->type == PV_WHILE || p->type == PV_FOR ) { 01102 return 1; 01103 } 01104 p = p->dad; 01105 } 01106 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'break' not in switch, for, or while statement!\n", 01107 item->filename, item->startline, item->endline); 01108 errs++; 01109 01110 return 0; 01111 }
|
|
|
Definition at line 2296 of file pbx_ael.c. References ast_log(), current_db, pval::endline, pval::filename, LOG_WARNING, pval::next, PV_CONTEXT, PV_MACRO, pval::startline, pval::str, pval::type, and pval::u1. Referenced by ael2_semantic_check(). 02297 { 02298 pval *i,*j; 02299 for (i=current_db; i; i=i->next) { 02300 if (i->type == PV_CONTEXT || i->type == PV_MACRO) { 02301 for (j=i->next; j; j=j->next) { 02302 if ( j->type == PV_CONTEXT || j->type == PV_MACRO ) { 02303 if ( !strcmp(i->u1.str, j->u1.str) ) 02304 { 02305 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: The context name (%s) is also declared in file %s, line %d-%d!\n", 02306 i->filename, i->startline, i->endline, i->u1.str, j->filename, j->startline, j->endline); 02307 warns++; 02308 } 02309 } 02310 } 02311 } 02312 } 02313 }
|
|
|
Definition at line 1113 of file pbx_ael.c. References ast_log(), pval::dad, pval::endline, pval::filename, LOG_ERROR, PV_CONTEXT, PV_FOR, PV_MACRO, PV_WHILE, pval::startline, and pval::type. 01114 { 01115 pval *p = item; 01116 01117 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ { 01118 /* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make 01119 no sense */ 01120 if( p->type == PV_WHILE || p->type == PV_FOR ) { 01121 return 1; 01122 } 01123 p = p->dad; 01124 } 01125 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'continue' not in 'for' or 'while' statement!\n", 01126 item->filename, item->startline, item->endline); 01127 errs++; 01128 01129 return 0; 01130 }
|
|
|
Definition at line 992 of file pbx_ael.c. References ast_log(), ast_strdupa, ast_strlen_zero(), pval::endline, pval::filename, LOG_WARNING, s, pval::startline, pval::str, and pval::u1. 00993 { 00994 char *day; 00995 char *c; 00996 /* The following line is coincidence, really! */ 00997 int s, e; 00998 00999 day = ast_strdupa(DAY->u1.str); 01000 01001 /* Check for all days */ 01002 if (ast_strlen_zero(day) || !strcmp(day, "*")) { 01003 return; 01004 } 01005 /* Get start and ending days */ 01006 c = strchr(day, '-'); 01007 if (c) { 01008 *c = '\0'; 01009 c++; 01010 } 01011 /* Find the start */ 01012 if (sscanf(day, "%d", &s) != 1) { 01013 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start day of month (%s) must be a number!\n", 01014 DAY->filename, DAY->startline, DAY->endline, day); 01015 warns++; 01016 } 01017 else if ((s < 1) || (s > 31)) { 01018 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start day of month (%s) must be a number in the range [1-31]!\n", 01019 DAY->filename, DAY->startline, DAY->endline, day); 01020 warns++; 01021 } 01022 s--; 01023 if (c) { 01024 if (sscanf(c, "%d", &e) != 1) { 01025 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end day of month (%s) must be a number!\n", 01026 DAY->filename, DAY->startline, DAY->endline, c); 01027 warns++; 01028 } 01029 else if ((e < 1) || (e > 31)) { 01030 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end day of month (%s) must be a number in the range [1-31]!\n", 01031 DAY->filename, DAY->startline, DAY->endline, day); 01032 warns++; 01033 } 01034 e--; 01035 } else 01036 e = s; 01037 }
|
|
|
get_dow: Get day of week
Definition at line 953 of file pbx_ael.c. References ast_log(), ast_strdupa, ast_strlen_zero(), pval::endline, pval::filename, LOG_WARNING, s, pval::startline, pval::str, and pval::u1. 00954 { 00955 char *dow; 00956 char *c; 00957 /* The following line is coincidence, really! */ 00958 int s, e; 00959 00960 dow = ast_strdupa(DOW->u1.str); 00961 00962 /* Check for all days */ 00963 if (ast_strlen_zero(dow) || !strcmp(dow, "*")) 00964 return; 00965 /* Get start and ending days */ 00966 c = strchr(dow, '-'); 00967 if (c) { 00968 *c = '\0'; 00969 c++; 00970 } else 00971 c = NULL; 00972 /* Find the start */ 00973 s = 0; 00974 while ((s < 7) && strcasecmp(dow, days[s])) s++; 00975 if (s >= 7) { 00976 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The day (%s) must be one of 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', or 'sat'!\n", 00977 DOW->filename, DOW->startline, DOW->endline, dow); 00978 warns++; 00979 } 00980 if (c) { 00981 e = 0; 00982 while ((e < 7) && strcasecmp(c, days[e])) e++; 00983 if (e >= 7) { 00984 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end day (%s) must be one of 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', or 'sat'!\n", 00985 DOW->filename, DOW->startline, DOW->endline, c); 00986 warns++; 00987 } 00988 } else 00989 e = s; 00990 }
|
|
||||||||||||
|
Definition at line 857 of file pbx_ael.c. References ast_log(), pval::endline, pval::filename, LOG_WARNING, and pval::startline. 00858 { 00859 int spaces = strspn(str,"\t \n"); 00860 if ( !strncmp(str+spaces,"$[",2) ) { 00861 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The expression '%s' is redundantly wrapped in '$[ ]'. \n", 00862 expr->filename, expr->startline, expr->endline, str); 00863 warns++; 00864 } 00865 }
|
|
|
Definition at line 1276 of file pbx_ael.c. References ast_log(), pval::endline, pval::filename, find_context(), find_label_in_current_context(), find_label_in_current_db(), find_label_in_current_extension(), get_contxt(), get_extension_or_contxt(), in_context(), in_macro(), pval::list, LOG_ERROR, LOG_WARNING, pval::next, PV_INCLUDES, pval::startline, pval::statements, pval::str, pval::type, pval::u1, and pval::u2. Referenced by find_pval_goto_item(). 01277 { 01278 /* check for the target of the goto-- does it exist? */ 01279 if ( !(item->u1.list)->next && !(item->u1.list)->u1.str ) { 01280 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: empty label reference found!\n", 01281 item->filename, item->startline, item->endline); 01282 errs++; 01283 } 01284 01285 /* just one item-- the label should be in the current extension */ 01286 01287 if (item->u1.list && !item->u1.list->next && !strstr((item->u1.list)->u1.str,"${")) { 01288 struct pval *z = get_extension_or_contxt(item); 01289 struct pval *x = 0; 01290 if (z) 01291 x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), z); /* if in macro, use current context instead */ 01292 /* printf("Called find_label_in_current_extension with arg %s; current_extension is %x: %d\n", 01293 (char*)((item->u1.list)->u1.str), current_extension?current_extension:current_context, current_extension?current_extension->type:current_context->type); */ 01294 if (!x) { 01295 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s exists in the current extension!\n", 01296 item->filename, item->startline, item->endline, item->u1.list->u1.str); 01297 errs++; 01298 } 01299 else 01300 return; 01301 } 01302 01303 /* TWO items */ 01304 if (item->u1.list->next && !item->u1.list->next->next) { 01305 /* two items */ 01306 /* printf("Calling find_label_in_current_context with args %s, %s\n", 01307 (char*)((item->u1.list)->u1.str), (char *)item->u1.list->next->u1.str); */ 01308 if (!strstr((item->u1.list)->u1.str,"${") 01309 && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ { 01310 struct pval *z = get_contxt(item); 01311 struct pval *x = 0; 01312 01313 if (z) 01314 x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, z); 01315 01316 if (!x) { 01317 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", 01318 item->filename, item->startline, item->endline, item->u1.list->u1.str, item->u1.list->next->u1.str ); 01319 errs++; 01320 } 01321 else 01322 return; 01323 } 01324 } 01325 01326 /* All 3 items! */ 01327 if (item->u1.list->next && item->u1.list->next->next) { 01328 /* all three */ 01329 pval *first = item->u1.list; 01330 pval *second = item->u1.list->next; 01331 pval *third = item->u1.list->next->next; 01332 01333 /* printf("Calling find_label_in_current_db with args %s, %s, %s\n", 01334 (char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); */ 01335 if (!strstr((item->u1.list)->u1.str,"${") 01336 && !strstr(item->u1.list->next->u1.str,"${") 01337 && !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ { 01338 struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); 01339 if (!x) { 01340 struct pval *p3; 01341 struct pval *found = 0; 01342 struct pval *that_context = find_context(item->u1.list->u1.str); 01343 01344 /* the target of the goto could be in an included context!! Fancy that!! */ 01345 /* look for includes in the current context */ 01346 if (that_context) { 01347 for (p3=that_context->u2.statements; p3; p3=p3->next) { 01348 if (p3->type == PV_INCLUDES) { 01349 struct pval *p4; 01350 for (p4=p3->u1.list; p4; p4=p4->next) { 01351 /* for each context pointed to, find it, then find a context/label that matches the 01352 target here! */ 01353 char *incl_context = p4->u1.str; 01354 /* find a matching context name */ 01355 struct pval *that_other_context = find_context(incl_context); 01356 if (that_other_context) { 01357 struct pval *x3; 01358 x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context); 01359 if (x3) { 01360 found = x3; 01361 break; 01362 } 01363 } 01364 } 01365 } 01366 } 01367 if (!found) { 01368 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s|%s exists in the context %s or its inclusions!\n", 01369 item->filename, item->startline, item->endline, item->u1.list->next->u1.str, item->u1.list->next->next->u1.str, item->u1.list->u1.str ); 01370 errs++; 01371 } else { 01372 struct pval *mac = in_macro(item); /* is this goto inside a macro? */ 01373 if( mac ) { /* yes! */ 01374 struct pval *targ = in_context(found); 01375 if( mac != targ ) 01376 { 01377 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", 01378 item->filename, item->startline, item->endline); 01379 warns++; 01380 } 01381 } 01382 } 01383 } else { 01384 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no context %s could be found that matches the goto target!\n", 01385 item->filename, item->startline, item->endline, item->u1.list->u1.str); 01386 errs++; 01387 } 01388 } else { 01389 struct pval *mac = in_macro(item); /* is this goto inside a macro? */ 01390 if( mac ) { /* yes! */ 01391 struct pval *targ = in_context(x); 01392 if( mac != targ ) 01393 { 01394 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", 01395 item->filename, item->startline, item->endline); 01396 warns++; 01397 } 01398 } 01399 } 01400 } 01401 } 01402 }
|
|
|
Definition at line 867 of file pbx_ael.c. References ast_log(), pval::endline, pval::filename, find_context(), pval::list, LOG_WARNING, pval::next, pval::startline, pval::str, and pval::u1. 00868 { 00869 struct pval *p4; 00870 for (p4=includes->u1.list; p4; p4=p4->next) { 00871 /* for each context pointed to, find it, then find a context/label that matches the 00872 target here! */ 00873 char *incl_context = p4->u1.str; 00874 /* find a matching context name */ 00875 struct pval *that_other_context = find_context(incl_context); 00876 if (!that_other_context && strcmp(incl_context, "parkedcalls") != 0) { 00877 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The included context '%s' cannot be found.\n", 00878 includes->filename, includes->startline, includes->endline, incl_context); 00879 warns++; 00880 } 00881 } 00882 }
|
|
|
Definition at line 1161 of file pbx_ael.c. References ast_log(), current_context, current_extension, pval::dad, pval::endline, pval::filename, find_first_label_in_current_context(), LOG_ERROR, PV_EXTENSION, PV_MACRO, pval::startline, pval::str, pval::type, and pval::u1. 01162 { 01163 struct pval *curr; 01164 struct pval *x; 01165 int alright = 0; 01166 01167 /* A label outside an extension just plain does not make sense! */ 01168 01169 curr = item; 01170 01171 while( curr ) { 01172 if( curr->type == PV_MACRO || curr->type == PV_EXTENSION ) { 01173 alright = 1; 01174 break; 01175 } 01176 curr = curr->dad; 01177 } 01178 if( !alright ) 01179 { 01180 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: Label %s is not within an extension or macro!\n", 01181 item->filename, item->startline, item->endline, item->u1.str); 01182 errs++; 01183 } 01184 01185 01186 /* basically, ensure that a label is not repeated in a context. Period. 01187 The method: well, for each label, find the first label in the context 01188 with the same name. If it's not the current label, then throw an error. */ 01189 01190 01191 /* printf("==== check_label: ====\n"); */ 01192 if( !current_extension ) 01193 curr = current_context; 01194 else 01195 curr = current_extension; 01196 01197 x = find_first_label_in_current_context((char *)item->u1.str, curr); 01198 /* printf("Hey, check_label found with item = %x, and x is %x, and currcont is %x, label name is %s\n", item,x, current_context, (char *)item->u1.str); */ 01199 if( x && x != item ) 01200 { 01201 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: Duplicate label %s! Previously defined at file %s, line %d.\n", 01202 item->filename, item->startline, item->endline, item->u1.str, x->filename, x->startline); 01203 errs++; 01204 } 01205 /* printf("<<<<< check_label: ====\n"); */ 01206 }
|
|
|
Definition at line 702 of file pbx_ael.c. References ast_log(), calloc, pval::endcol, pval::endline, pval::filename, LOG_WARNING, pval::macro_statements, pval::next, PV_RETURN, pval::startcol, pval::startline, pval::str, strdup, pval::type, pval::u1, and pval::u3. Referenced by check_pval_item(). 00703 { 00704 pval *i; 00705 if (!macro->u3.macro_statements) 00706 { 00707 pval *z = calloc(1, sizeof(struct pval)); 00708 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The macro %s is empty! I will insert a return.\n", 00709 macro->filename, macro->startline, macro->endline, macro->u1.str); 00710 00711 z->type = PV_RETURN; 00712 z->startline = macro->startline; 00713 z->endline = macro->endline; 00714 z->startcol = macro->startcol; 00715 z->endcol = macro->endcol; 00716 z->filename = strdup(macro->filename); 00717 00718 macro->u3.macro_statements = z; 00719 return; 00720 } 00721 for (i=macro->u3.macro_statements; i; i=i->next) { 00722 /* if the last statement in the list is not return, then insert a return there */ 00723 if (i->next == NULL) { 00724 if (i->type != PV_RETURN) { 00725 pval *z = calloc(1, sizeof(struct pval)); 00726 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The macro %s does not end with a return; I will insert one.\n", 00727 macro->filename, macro->startline, macro->endline, macro->u1.str); 00728 00729 z->type = PV_RETURN; 00730 z->startline = macro->startline; 00731 z->endline = macro->endline; 00732 z->startcol = macro->startcol; 00733 z->endcol = macro->endcol; 00734 z->filename = strdup(macro->filename); 00735 00736 i->next = z; 00737 return; 00738 } 00739 } 00740 } 00741 return; 00742 }
|
|
|
Definition at line 1055 of file pbx_ael.c. References ast_log(), ast_strdupa, ast_strlen_zero(), pval::endline, pval::filename, LOG_WARNING, s, pval::startline, pval::str, and pval::u1. 01056 { 01057 char *mon; 01058 char *c; 01059 /* The following line is coincidence, really! */ 01060 int s, e; 01061 01062 mon = ast_strdupa(MON->u1.str); 01063 01064 /* Check for all days */ 01065 if (ast_strlen_zero(mon) || !strcmp(mon, "*")) 01066 return ; 01067 /* Get start and ending days */ 01068 c = strchr(mon, '-'); 01069 if (c) { 01070 *c = '\0'; 01071 c++; 01072 } 01073 /* Find the start */ 01074 s = 0; 01075 while ((s < 12) && strcasecmp(mon, months[s])) s++; 01076 if (s >= 12) { 01077 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n", 01078 MON->filename, MON->startline, MON->endline, mon); 01079 warns++; 01080 } 01081 if (c) { 01082 e = 0; 01083 while ((e < 12) && strcasecmp(mon, months[e])) e++; 01084 if (e >= 12) { 01085 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n", 01086 MON->filename, MON->startline, MON->endline, c); 01087 warns++; 01088 } 01089 } else 01090 e = s; 01091 }
|
|
||||||||||||||||
|
Definition at line 2785 of file pbx_ael.c. References check_pval_item(), and pval::next. Referenced by ael2_semantic_check(), and check_pval_item(). 02786 { 02787 pval *i; 02788 02789 /* checks to do: 02790 1. Do goto's point to actual labels? 02791 2. Do macro calls reference a macro? 02792 3. Does the number of macro args match the definition? 02793 4. Is a macro call missing its & at the front? 02794 5. Application calls-- we could check syntax for existing applications, 02795 but I need some some sort of universal description bnf for a general 02796 sort of method for checking arguments, in number, maybe even type, at least. 02797 Don't want to hand code checks for hundreds of applications. 02798 */ 02799 02800 for (i=item; i; i=i->next) { 02801 check_pval_item(i,apps,in_globals); 02802 } 02803 }
|
|
||||||||||||||||
|
Definition at line 2343 of file pbx_ael.c. References pval::abstract, app, pval::arglist, ast_log(), check_abstract_reference(), check_macro_returns(), check_pval(), current_context, current_extension, pval::endline, pval::filename, find_context(), find_macro(), free, LOG_ERROR, LOG_WARNING, pval::macro_statements, pval::next, PV_APPLICATION_CALL, PV_CONTEXT, PV_MACRO, PV_MACRO_CALL, PV_RETURN, PV_WORD, pval::startline, pval::statements, pval::str, pval::type, pval::u1, pval::u2, and pval::u3. Referenced by check_pval(). 02344 { 02345 pval *lp; 02346 #ifdef AAL_ARGCHECK 02347 struct argapp *app, *found; 02348 #endif 02349 struct pval *macro_def; 02350 struct pval *app_def; 02351 02352 char errmsg[4096]; 02353 char *strp; 02354 02355 switch (item->type) { 02356 case PV_WORD: 02357 /* fields: item->u1.str == string associated with this (word). 02358 item->u2.arglist == pval list of 4 PV_WORD elements for time values (only in PV_INCLUDES) */ 02359 break; 02360 02361 case PV_MACRO: 02362 /* fields: item->u1.str == name of macro 02363 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 02364 item->u2.arglist->u1.str == argument 02365 item->u2.arglist->next == next arg 02366 02367 item->u3.macro_statements == pval list of statements in macro body. 02368 */ 02369 in_abstract_context = 0; 02370 current_context = item; 02371 current_extension = 0; 02372 02373 check_macro_returns(item); 02374 02375 for (lp=item->u2.arglist; lp; lp=lp->next) { 02376 02377 } 02378 check_pval(item->u3.macro_statements, apps,in_globals); 02379 break; 02380 02381 case PV_CONTEXT: 02382 /* fields: item->u1.str == name of context 02383 item->u2.statements == pval list of statements in context body 02384 item->u3.abstract == int 1 if an abstract keyword were present 02385 */ 02386 current_context = item; 02387 current_extension = 0; 02388 if ( item->u3.abstract ) { 02389 in_abstract_context = 1; 02390 check_abstract_reference(item); 02391 } else 02392 in_abstract_context = 0; 02393 check_pval(item->u2.statements, apps,in_globals); 02394 break; 02395 02396 case PV_MACRO_CALL: 02397 /* fields: item->u1.str == name of macro to call 02398 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 02399 item->u2.arglist->u1.str == argument 02400 item->u2.arglist->next == next arg 02401 */ 02402 macro_def = find_macro(item->u1.str); 02403 if (!macro_def) { 02404 ast_log(LOG_ERROR, "Error: file %s, line %d-%d: macro call to non-existent %s !\n", 02405 item->filename, item->startline, item->endline, item->u1.str); 02406 errs++; 02407 } else if (macro_def->type != PV_MACRO) { 02408 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: macro call to %s references a context, not a macro!\n", 02409 item->filename, item->startline, item->endline, item->u1.str); 02410 errs++; 02411 } else { 02412 /* macro_def is a MACRO, so do the args match in number? */ 02413 int hereargs = 0; 02414 int thereargs = 0; 02415 02416 for (lp=item->u2.arglist; lp; lp=lp->next) { 02417 hereargs++; 02418 } 02419 for (lp=macro_def->u2.arglist; lp; lp=lp->next) { 02420 thereargs++; 02421 } 02422 if (hereargs != thereargs ) { 02423 ast_log(LOG_ERROR, "Error: file %s, line %d-%d: The macro call to %s has %d arguments, but the macro definition has %d arguments\n", 02424 item->filename, item->startline, item->endline, item->u1.str, hereargs, thereargs); 02425 errs++; 02426 } 02427 } 02428 break; 02429 02430 case PV_APPLICATION_CALL: 02431 /* fields: item->u1.str == name of application to call 02432 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 02433 item->u2.arglist->u1.str == argument 02434 item->u2.arglist->next == next arg 02435 */ 02436 /* Need to check to see if the application is available! */ 02437 app_def = find_context(item->u1.str); 02438 if (app_def && app_def->type == PV_MACRO) { 02439 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: application call to %s references an existing macro, but had no & preceding it!\n", 02440 item->filename, item->startline, item->endline, item->u1.str); 02441 errs++; 02442 } 02443 if (strcasecmp(item->u1.str,"GotoIf") == 0 02444 || strcasecmp(item->u1.str,"GotoIfTime") == 0 02445 || strcasecmp(item->u1.str,"while") == 0 02446 || strcasecmp(item->u1.str,"endwhile") == 0 02447 || strcasecmp(item->u1.str,"random") == 0 02448 || strcasecmp(item->u1.str,"gosub") == 0 02449 || strcasecmp(item->u1.str,"return") == 0 02450 || strcasecmp(item->u1.str,"gosubif") == 0 02451 || strcasecmp(item->u1.str,"continuewhile") == 0 02452 || strcasecmp(item->u1.str,"endwhile") == 0 02453 || strcasecmp(item->u1.str,"execif") == 0 02454 || strcasecmp(item->u1.str,"execiftime") == 0 02455 || strcasecmp(item->u1.str,"exitwhile") == 0 02456 || strcasecmp(item->u1.str,"goto") == 0 02457 || strcasecmp(item->u1.str,"macro") == 0 02458 || strcasecmp(item->u1.str,"macroexclusive") == 0 02459 || strcasecmp(item->u1.str,"macroif") == 0 02460 || strcasecmp(item->u1.str,"stackpop") == 0 02461 || strcasecmp(item->u1.str,"execIf") == 0 ) { 02462 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: application call to %s affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead!\n", 02463 item->filename, item->startline, item->endline, item->u1.str); 02464 warns++; 02465 } 02466 if (strcasecmp(item->u1.str,"macroexit") == 0) { 02467 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: I am converting the MacroExit call here to a return statement.\n", 02468 item->filename, item->startline, item->endline); 02469 item->type = PV_RETURN; 02470 free(item->u1.str); 02471 item->u1.str = 0; 02472 } 02473 02474 #ifdef AAL_ARGCHECK 02475 found = 0; 02476 for (app=apps; app; app=app->next) { 02477 if (strcasecmp(app->name, item->u1.str) == 0) { 02478 found =app; 02479 break; 02480 } 02481 } 02482 if (!found) { 02483 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: application call to %s not listed in applist database!\n", 02484 item->filename, item->startline, item->endline, item->u1.str); 02485 warns++; 02486 } else 02487 check_app_args(item, item->u2.arglist, app); 02488 #endif 02489 break; 02490 02491 case PV_CASE: 02492 /* fields: item->u1.str == value of case 02493 item->u2.statements == pval list of statements under the case 02494 */ 02495 /* Make sure sequence of statements under case is terminated with goto, return, or break */ 02496 /* find the last statement */ 02497 check_pval(item->u2.statements, apps,in_globals); 02498 break; 02499 02500 case PV_PATTERN: 02501 /* fields: item->u1.str == value of case 02502 item->u2.statements == pval list of statements under the case 02503 */ 02504 /* Make sure sequence of statements under case is terminated with goto, return, or break */ 02505 /* find the last statement */ 02506 02507 check_pval(item->u2.statements, apps,in_globals); 02508 break; 02509 02510 case PV_DEFAULT: 02511 /* fields: 02512 item->u2.statements == pval list of statements under the case 02513 */ 02514 02515 check_pval(item->u2.statements, apps,in_globals); 02516 break; 02517 02518 case PV_CATCH: 02519 /* fields: item->u1.str == name of extension to catch 02520 item->u2.statements == pval list of statements in context body 02521 */ 02522 check_pval(item->u2.statements, apps,in_globals); 02523 break; 02524 02525 case PV_SWITCHES: 02526 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02527 */ 02528 check_pval(item->u1.list, apps,in_globals); 02529 break; 02530 02531 case PV_ESWITCHES: 02532 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02533 */ 02534 check_pval(item->u1.list, apps,in_globals); 02535 break; 02536 02537 case PV_INCLUDES: 02538 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02539 */ 02540 check_pval(item->u1.list, apps,in_globals); 02541 check_includes(item); 02542 for (lp=item->u1.list; lp; lp=lp->next){ 02543 char *incl_context = lp->u1.str; 02544 struct pval *that_context = find_context(incl_context); 02545 02546 if ( lp->u2.arglist ) { 02547 check_timerange(lp->u2.arglist); 02548 check_dow(lp->u2.arglist->next); 02549 check_day(lp->u2.arglist->next->next); 02550 check_month(lp->u2.arglist->next->next->next); 02551 } 02552 02553 if (that_context) { 02554 find_pval_gotos(that_context->u2.statements,0); 02555 02556 } 02557 } 02558 break; 02559 02560 case PV_STATEMENTBLOCK: 02561 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 02562 */ 02563 check_pval(item->u1.list, apps,in_globals); 02564 break; 02565 02566 case PV_VARDEC: 02567 /* fields: item->u1.str == variable name 02568 item->u2.val == variable value to assign 02569 */ 02570 /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */ 02571 if( !in_globals ) { /* don't check stuff inside the globals context; no wrapping in $[ ] there... */ 02572 snprintf(errmsg,sizeof(errmsg), "file %s, line %d, columns %d-%d, variable declaration expr '%s':", config, item->startline, item->startcol, item->endcol, item->u2.val); 02573 ast_expr_register_extra_error_info(errmsg); 02574 ast_expr(item->u2.val, expr_output, sizeof(expr_output)); 02575 ast_expr_clear_extra_error_info(); 02576 if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) { 02577 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02578 item->filename, item->startline, item->endline, item->u2.val); 02579 warns++; 02580 } 02581 check_expr2_input(item,item->u2.val); 02582 } 02583 break; 02584 02585 case PV_GOTO: 02586 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 02587 item->u1.list->u1.str == where the data on a PV_WORD will always be. 02588 */ 02589 /* don't check goto's in abstract contexts */ 02590 if ( in_abstract_context ) 02591 break; 02592 02593 check_goto(item); 02594 break; 02595 02596 case PV_LABEL: 02597 /* fields: item->u1.str == label name 02598 */ 02599 if ( strspn(item->u1.str, "0123456789") == strlen(item->u1.str) ) { 02600 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: label '%s' is numeric, this is bad practice!\n", 02601 item->filename, item->startline, item->endline, item->u1.str); 02602 warns++; 02603 } 02604 02605 check_label(item); 02606 break; 02607 02608 case PV_FOR: 02609 /* fields: item->u1.for_init == a string containing the initalizer 02610 item->u2.for_test == a string containing the loop test 02611 item->u3.for_inc == a string containing the loop increment 02612 02613 item->u4.for_statements == a pval list of statements in the for () 02614 */ 02615 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, for test expr '%s':", config, item->startline, item->startcol, item->endcol, item->u2.for_test); 02616 ast_expr_register_extra_error_info(errmsg); 02617 02618 strp = strchr(item->u1.for_init, '='); 02619 if (strp) { 02620 ast_expr(strp+1, expr_output, sizeof(expr_output)); 02621 } 02622 ast_expr(item->u2.for_test, expr_output, sizeof(expr_output)); 02623 strp = strchr(item->u3.for_inc, '='); 02624 if (strp) { 02625 ast_expr(strp+1, expr_output, sizeof(expr_output)); 02626 } 02627 if ( strpbrk(item->u2.for_test,"~!-+<>=*/&^") && !strstr(item->u2.for_test,"${") ) { 02628 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02629 item->filename, item->startline, item->endline, item->u2.for_test); 02630 warns++; 02631 } 02632 if ( strpbrk(item->u3.for_inc,"~!-+<>=*/&^") && !strstr(item->u3.for_inc,"${") ) { 02633 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02634 item->filename, item->startline, item->endline, item->u3.for_inc); 02635 warns++; 02636 } 02637 check_expr2_input(item,item->u2.for_test); 02638 check_expr2_input(item,item->u3.for_inc); 02639 02640 ast_expr_clear_extra_error_info(); 02641 check_pval(item->u4.for_statements, apps,in_globals); 02642 break; 02643 02644 case PV_WHILE: 02645 /* fields: item->u1.str == the while conditional, as supplied by user 02646 02647 item->u2.statements == a pval list of statements in the while () 02648 */ 02649 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, while expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str); 02650 ast_expr_register_extra_error_info(errmsg); 02651 ast_expr(item->u1.str, expr_output, sizeof(expr_output)); 02652 ast_expr_clear_extra_error_info(); 02653 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02654 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02655 item->filename, item->startline, item->endline, item->u1.str); 02656 warns++; 02657 } 02658 check_expr2_input(item,item->u1.str); 02659 check_pval(item->u2.statements, apps,in_globals); 02660 break; 02661 02662 case PV_BREAK: 02663 /* fields: none 02664 */ 02665 check_break(item); 02666 break; 02667 02668 case PV_RETURN: 02669 /* fields: none 02670 */ 02671 break; 02672 02673 case PV_CONTINUE: 02674 /* fields: none 02675 */ 02676 check_continue(item); 02677 break; 02678 02679 case PV_RANDOM: 02680 /* fields: item->u1.str == the random number expression, as supplied by user 02681 02682 item->u2.statements == a pval list of statements in the if () 02683 item->u3.else_statements == a pval list of statements in the else 02684 (could be zero) 02685 */ 02686 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, random expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str); 02687 ast_expr_register_extra_error_info(errmsg); 02688 ast_expr(item->u1.str, expr_output, sizeof(expr_output)); 02689 ast_expr_clear_extra_error_info(); 02690 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02691 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: random expression '%s' has operators, but no variables. Interesting...\n", 02692 item->filename, item->startline, item->endline, item->u1.str); 02693 warns++; 02694 } 02695 check_expr2_input(item,item->u1.str); 02696 check_pval(item->u2.statements, apps,in_globals); 02697 if (item->u3.else_statements) { 02698 check_pval(item->u3.else_statements, apps,in_globals); 02699 } 02700 break; 02701 02702 case PV_IFTIME: 02703 /* fields: item->u1.list == the if time values, 4 of them, each in PV_WORD, linked list 02704 02705 item->u2.statements == a pval list of statements in the if () 02706 item->u3.else_statements == a pval list of statements in the else 02707 (could be zero) 02708 */ 02709 if ( item->u2.arglist ) { 02710 check_timerange(item->u1.list); 02711 check_dow(item->u1.list->next); 02712 check_day(item->u1.list->next->next); 02713 check_month(item->u1.list->next->next->next); 02714 } 02715 02716 check_pval(item->u2.statements, apps,in_globals); 02717 if (item->u3.else_statements) { 02718 check_pval(item->u3.else_statements, apps,in_globals); 02719 } 02720 break; 02721 02722 case PV_IF: 02723 /* fields: item->u1.str == the if conditional, as supplied by user 02724 02725 item->u2.statements == a pval list of statements in the if () 02726 item->u3.else_statements == a pval list of statements in the else 02727 (could be zero) 02728 */ 02729 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, if expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str); 02730 ast_expr_register_extra_error_info(errmsg); 02731 ast_expr(item->u1.str, expr_output, sizeof(expr_output)); 02732 ast_expr_clear_extra_error_info(); 02733 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02734 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression '%s' has operators, but no variables. Interesting...\n", 02735 item->filename, item->startline, item->endline, item->u1.str); 02736 warns++; 02737 } 02738 check_expr2_input(item,item->u1.str); 02739 check_pval(item->u2.statements, apps,in_globals); 02740 if (item->u3.else_statements) { 02741 check_pval(item->u3.else_statements, apps,in_globals); 02742 } 02743 break; 02744 02745 case PV_SWITCH: 02746 /* fields: item->u1.str == the switch expression 02747 02748 item->u2.statements == a pval list of statements in the switch, 02749 (will be case statements, most likely!) 02750 */ 02751 /* we can check the switch expression, see if it matches any of the app variables... 02752 if it does, then, are all the possible cases accounted for? */ 02753 check_switch_expr(item, apps); 02754 check_pval(item->u2.statements, apps,in_globals); 02755 break; 02756 02757 case PV_EXTENSION: 02758 /* fields: item->u1.str == the extension name, label, whatever it's called 02759 02760 item->u2.statements == a pval list of statements in the extension 02761 item->u3.hints == a char * hint argument 02762 item->u4.regexten == an int boolean. non-zero says that regexten was specified 02763 */ 02764 current_extension = item ; 02765 02766 check_pval(item->u2.statements, apps,in_globals); 02767 break; 02768 02769 case PV_IGNOREPAT: 02770 /* fields: item->u1.str == the ignorepat data 02771 */ 02772 break; 02773 02774 case PV_GLOBALS: 02775 /* fields: item->u1.statements == pval list of statements, usually vardecs 02776 */ 02777 in_abstract_context = 0; 02778 check_pval(item->u1.statements, apps, 1); 02779 break; 02780 default: 02781 break; 02782 } 02783 }
|
|
||||||||||||
|
Definition at line 2197 of file pbx_ael.c. References ast_strdupa, argapp::next, pval::str, and pval::u1. 02198 { 02199 #ifdef AAL_ARGCHECK 02200 /* get and clean the variable name */ 02201 char *buff1, *p; 02202 struct argapp *a,*a2; 02203 struct appsetvar *v,*v2; 02204 struct argchoice *c; 02205 pval *t; 02206 02207 p = item->u1.str; 02208 while (p && *p && (*p == ' ' || *p == '\t' || *p == '$' || *p == '{' ) ) 02209 p++; 02210 02211 buff1 = ast_strdupa(p); 02212 02213 while (strlen(buff1) > 0 && ( buff1[strlen(buff1)-1] == '}' || buff1[strlen(buff1)-1] == ' ' || buff1[strlen(buff1)-1] == '\t')) 02214 buff1[strlen(buff1)-1] = 0; 02215 /* buff1 now contains the variable name */ 02216 v = 0; 02217 for (a=apps; a; a=a->next) { 02218 for (v=a->setvars;v;v=v->next) { 02219 if (strcmp(v->name,buff1) == 0) { 02220 break; 02221 } 02222 } 02223 if ( v ) 02224 break; 02225 } 02226 if (v && v->vals) { 02227 /* we have a match, to a variable that has a set of determined values */ 02228 int def= 0; 02229 int pat = 0; 02230 int f1 = 0; 02231 02232 /* first of all, does this switch have a default case ? */ 02233 for (t=item->u2.statements; t; t=t->next) { 02234 if (t->type == PV_DEFAULT) { 02235 def =1; 02236 break; 02237 } 02238 if (t->type == PV_PATTERN) { 02239 pat++; 02240 } 02241 } 02242 if (def || pat) /* nothing to check. All cases accounted for! */ 02243 return; 02244 for (c=v->vals; c; c=c->next) { 02245 f1 = 0; 02246 for (t=item->u2.statements; t; t=t->next) { 02247 if (t->type == PV_CASE || t->type == PV_PATTERN) { 02248 if (!strcmp(t->u1.str,c->name)) { 02249 f1 = 1; 02250 break; 02251 } 02252 } 02253 } 02254 if (!f1) { 02255 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: switch with expression(%s) does not handle the case of %s !\n", 02256 item->filename, item->startline, item->endline, item->u1.str, c->name); 02257 warns++; 02258 } 02259 } 02260 /* next, is there an app call in the current exten, that would set this var? */ 02261 f1 = 0; 02262 t = current_extension->u2.statements; 02263 if ( t && t->type == PV_STATEMENTBLOCK ) 02264 t = t->u1.statements; 02265 for (; t && t != item; t=t->next) { 02266 if (t->type == PV_APPLICATION_CALL) { 02267 /* find the application that matches the u1.str */ 02268 for (a2=apps; a2; a2=a2->next) { 02269 if (strcasecmp(a2->name, t->u1.str)==0) { 02270 for (v2=a2->setvars; v2; v2=v2->next) { 02271 if (strcmp(v2->name, buff1) == 0) { 02272 /* found an app that sets the var */ 02273 f1 = 1; 02274 break; 02275 } 02276 } 02277 } 02278 if (f1) 02279 break; 02280 } 02281 } 02282 if (f1) 02283 break; 02284 } 02285 02286 /* see if it sets the var */ 02287 if (!f1) { 02288 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: Couldn't find an application call in this extension that sets the expression (%s) value!\n", 02289 item->filename, item->startline, item->endline, item->u1.str); 02290 warns++; 02291 } 02292 } 02293 #endif 02294 }
|
|
|
Definition at line 885 of file pbx_ael.c. References ast_log(), ast_strdupa, ast_strlen_zero(), pval::endline, pval::filename, LOG_WARNING, pval::startline, pval::str, and pval::u1. 00886 { 00887 char *times; 00888 char *e; 00889 int s1, s2; 00890 int e1, e2; 00891 00892 times = ast_strdupa(p->u1.str); 00893 00894 /* Star is all times */ 00895 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 00896 return; 00897 } 00898 /* Otherwise expect a range */ 00899 e = strchr(times, '-'); 00900 if (!e) { 00901 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The time range format (%s) requires a '-' surrounded by two 24-hour times of day!\n", 00902 p->filename, p->startline, p->endline, times); 00903 warns++; 00904 return; 00905 } 00906 *e = '\0'; 00907 e++; 00908 while (*e && !isdigit(*e)) 00909 e++; 00910 if (!*e) { 00911 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The time range format (%s) is missing the end time!\n", 00912 p->filename, p->startline, p->endline, p->u1.str); 00913 warns++; 00914 } 00915 if (sscanf(times, "%d:%d", &s1, &s2) != 2) { 00916 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) isn't quite right!\n", 00917 p->filename, p->startline, p->endline, times); 00918 warns++; 00919 } 00920 if (sscanf(e, "%d:%d", &e1, &e2) != 2) { 00921 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) isn't quite right!\n", 00922 p->filename, p->startline, p->endline, times); 00923 warns++; 00924 } 00925 00926 s1 = s1 * 30 + s2/2; 00927 if ((s1 < 0) || (s1 >= 24*30)) { 00928 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) is out of range!\n", 00929 p->filename, p->startline, p->endline, times); 00930 warns++; 00931 } 00932 e1 = e1 * 30 + e2/2; 00933 if ((e1 < 0) || (e1 >= 24*30)) { 00934 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) is out of range!\n", 00935 p->filename, p->startline, p->endline, e); 00936 warns++; 00937 } 00938 return; 00939 }
|
|
|
Definition at line 2867 of file pbx_ael.c. References ael_priority::app, ael_priority::appargs, exten, free, ael_priority::goto_false, ael_priority::goto_true, ael_extension::hints, ael_extension::name, ael_priority::next, ael_priority::origin, and ael_extension::plist. 02868 { 02869 struct ael_extension *ne, *nen; 02870 for (ne=exten; ne; ne=nen) { 02871 struct ael_priority *pe, *pen; 02872 02873 if (ne->name) 02874 free(ne->name); 02875 02876 /* cidmatch fields are allocated with name, and freed when 02877 the name field is freed. Don't do a free for this field, 02878 unless you LIKE to see a crash! */ 02879 02880 if (ne->hints) 02881 free(ne->hints); 02882 02883 for (pe=ne->plist; pe; pe=pen) { 02884 pen = pe->next; 02885 if (pe->app) 02886 free(pe->app); 02887 pe->app = 0; 02888 if (pe->appargs) 02889 free(pe->appargs); 02890 pe->appargs = 0; 02891 pe->origin = 0; 02892 pe->goto_true = 0; 02893 pe->goto_false = 0; 02894 free(pe); 02895 } 02896 nen = ne->next_exten; 02897 ne->next_exten = 0; 02898 ne->plist =0; 02899 ne->plist_last = 0; 02900 ne->next_exten = 0; 02901 ne->loop_break = 0; 02902 ne->loop_continue = 0; 02903 free(ne); 02904 } 02905 }
|
|
|
|
|
|
Definition at line 4123 of file pbx_ael.c. References pval::arglist, ast_log(), destroy_pval(), pval::else_statements, pval::filename, pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, free, pval::hints, pval::list, LOG_WARNING, pval::macro_statements, PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTEXT, PV_CONTINUE, PV_DEFAULT, PV_ESWITCHES, PV_EXTENSION, PV_FOR, PV_GLOBALS, PV_GOTO, PV_IF, PV_IFTIME, PV_IGNOREPAT, PV_INCLUDES, PV_LABEL, PV_MACRO, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_SWITCHES, PV_VARDEC, PV_WHILE, PV_WORD, pval::statements, pval::str, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val. Referenced by destroy_pval(). 04124 { 04125 if (item == NULL) { 04126 ast_log(LOG_WARNING, "null item\n"); 04127 return; 04128 } 04129 04130 if (item->filename) 04131 free(item->filename); 04132 04133 switch (item->type) { 04134 case PV_WORD: 04135 /* fields: item->u1.str == string associated with this (word). */ 04136 if (item->u1.str ) 04137 free(item->u1.str); 04138 if ( item->u2.arglist ) 04139 destroy_pval(item->u2.arglist); 04140 break; 04141 04142 case PV_MACRO: 04143 /* fields: item->u1.str == name of macro 04144 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 04145 item->u2.arglist->u1.str == argument 04146 item->u2.arglist->next == next arg 04147 04148 item->u3.macro_statements == pval list of statements in macro body. 04149 */ 04150 destroy_pval(item->u2.arglist); 04151 if (item->u1.str ) 04152 free(item->u1.str); 04153 destroy_pval(item->u3.macro_statements); 04154 break; 04155 04156 case PV_CONTEXT: 04157 /* fields: item->u1.str == name of context 04158 item->u2.statements == pval list of statements in context body 04159 item->u3.abstract == int 1 if an abstract keyword were present 04160 */ 04161 if (item->u1.str) 04162 free(item->u1.str); 04163 destroy_pval(item->u2.statements); 04164 break; 04165 04166 case PV_MACRO_CALL: 04167 /* fields: item->u1.str == name of macro to call 04168 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 04169 item->u2.arglist->u1.str == argument 04170 item->u2.arglist->next == next arg 04171 */ 04172 if (item->u1.str) 04173 free(item->u1.str); 04174 destroy_pval(item->u2.arglist); 04175 break; 04176 04177 case PV_APPLICATION_CALL: 04178 /* fields: item->u1.str == name of application to call 04179 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 04180 item->u2.arglist->u1.str == argument 04181 item->u2.arglist->next == next arg 04182 */ 04183 if (item->u1.str) 04184 free(item->u1.str); 04185 destroy_pval(item->u2.arglist); 04186 break; 04187 04188 case PV_CASE: 04189 /* fields: item->u1.str == value of case 04190 item->u2.statements == pval list of statements under the case 04191 */ 04192 if (item->u1.str) 04193 free(item->u1.str); 04194 destroy_pval(item->u2.statements); 04195 break; 04196 04197 case PV_PATTERN: 04198 /* fields: item->u1.str == value of case 04199 item->u2.statements == pval list of statements under the case 04200 */ 04201 if (item->u1.str) 04202 free(item->u1.str); 04203 destroy_pval(item->u2.statements); 04204 break; 04205 04206 case PV_DEFAULT: 04207 /* fields: 04208 item->u2.statements == pval list of statements under the case 04209 */ 04210 destroy_pval(item->u2.statements); 04211 break; 04212 04213 case PV_CATCH: 04214 /* fields: item->u1.str == name of extension to catch 04215 item->u2.statements == pval list of statements in context body 04216 */ 04217 if (item->u1.str) 04218 free(item->u1.str); 04219 destroy_pval(item->u2.statements); 04220 break; 04221 04222 case PV_SWITCHES: 04223 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04224 */ 04225 destroy_pval(item->u1.list); 04226 break; 04227 04228 case PV_ESWITCHES: 04229 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04230 */ 04231 destroy_pval(item->u1.list); 04232 break; 04233 04234 case PV_INCLUDES: 04235 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04236 item->u2.arglist == pval list of 4 PV_WORD elements for time values 04237 */ 04238 destroy_pval(item->u1.list); 04239 break; 04240 04241 case PV_STATEMENTBLOCK: 04242 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 04243 */ 04244 destroy_pval(item->u1.list); 04245 break; 04246 04247 case PV_VARDEC: 04248 /* fields: item->u1.str == variable name 04249 item->u2.val == variable value to assign 04250 */ 04251 if (item->u1.str) 04252 free(item->u1.str); 04253 if (item->u2.val) 04254 free(item->u2.val); 04255 break; 04256 04257 case PV_GOTO: 04258 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 04259 item->u1.list->u1.str == where the data on a PV_WORD will always be. 04260 */ 04261 04262 destroy_pval(item->u1.list); 04263 break; 04264 04265 case PV_LABEL: 04266 /* fields: item->u1.str == label name 04267 */ 04268 if (item->u1.str) 04269 free(item->u1.str); 04270 break; 04271 04272 case PV_FOR: 04273 /* fields: item->u1.for_init == a string containing the initalizer 04274 item->u2.for_test == a string containing the loop test 04275 item->u3.for_inc == a string containing the loop increment 04276 04277 item->u4.for_statements == a pval list of statements in the for () 04278 */ 04279 if (item->u1.for_init) 04280 free(item->u1.for_init); 04281 if (item->u2.for_test) 04282 free(item->u2.for_test); 04283 if (item->u3.for_inc) 04284 free(item->u3.for_inc); 04285 destroy_pval(item->u4.for_statements); 04286 break; 04287 04288 case PV_WHILE: 04289 /* fields: item->u1.str == the while conditional, as supplied by user 04290 04291 item->u2.statements == a pval list of statements in the while () 04292 */ 04293 if (item->u1.str) 04294 free(item->u1.str); 04295 destroy_pval(item->u2.statements); 04296 break; 04297 04298 case PV_BREAK: 04299 /* fields: none 04300 */ 04301 break; 04302 04303 case PV_RETURN: 04304 /* fields: none 04305 */ 04306 break; 04307 04308 case PV_CONTINUE: 04309 /* fields: none 04310 */ 04311 break; 04312 04313 case PV_IFTIME: 04314 /* fields: item->u1.list == the 4 time values, in PV_WORD structs, linked list 04315 04316 item->u2.statements == a pval list of statements in the if () 04317 item->u3.else_statements == a pval list of statements in the else 04318 (could be zero) 04319 */ 04320 destroy_pval(item->u1.list); 04321 destroy_pval(item->u2.statements); 04322 if (item->u3.else_statements) { 04323 destroy_pval(item->u3.else_statements); 04324 } 04325 break; 04326 04327 case PV_RANDOM: 04328 /* fields: item->u1.str == the random percentage, as supplied by user 04329 04330 item->u2.statements == a pval list of statements in the true part () 04331 item->u3.else_statements == a pval list of statements in the else 04332 (could be zero) 04333 fall thru to If */ 04334 case PV_IF: 04335 /* fields: item->u1.str == the if conditional, as supplied by user 04336 04337 item->u2.statements == a pval list of statements in the if () 04338 item->u3.else_statements == a pval list of statements in the else 04339 (could be zero) 04340 */ 04341 if (item->u1.str) 04342 free(item->u1.str); 04343 destroy_pval(item->u2.statements); 04344 if (item->u3.else_statements) { 04345 destroy_pval(item->u3.else_statements); 04346 } 04347 break; 04348 04349 case PV_SWITCH: 04350 /* fields: item->u1.str == the switch expression 04351 04352 item->u2.statements == a pval list of statements in the switch, 04353 (will be case statements, most likely!) 04354 */ 04355 if (item->u1.str) 04356 free(item->u1.str); 04357 destroy_pval(item->u2.statements); 04358 break; 04359 04360 case PV_EXTENSION: 04361 /* fields: item->u1.str == the extension name, label, whatever it's called 04362 04363 item->u2.statements == a pval list of statements in the extension 04364 item->u3.hints == a char * hint argument 04365 item->u4.regexten == an int boolean. non-zero says that regexten was specified 04366 */ 04367 if (item->u1.str) 04368 free(item->u1.str); 04369 if (item->u3.hints) 04370 free(item->u3.hints); 04371 destroy_pval(item->u2.statements); 04372 break; 04373 04374 case PV_IGNOREPAT: 04375 /* fields: item->u1.str == the ignorepat data 04376 */ 04377 if (item->u1.str) 04378 free(item->u1.str); 04379 break; 04380 04381 case PV_GLOBALS: 04382 /* fields: item->u1.statements == pval list of statements, usually vardecs 04383 */ 04384 destroy_pval(item->u1.statements); 04385 break; 04386 } 04387 free(item); 04388 }
|
|
||||||||||||||||
|
Definition at line 746 of file pbx_ael.c. References ast_log(), pval::endline, pval::filename, LOG_ERROR, LOG_WARNING, and pval::startline. Referenced by match_pval_item(). 00747 { 00748 int err1; 00749 regex_t preg; 00750 00751 /* simple case, they match exactly, the pattern and exten name */ 00752 if (!strcmp(pattern,exten) == 0) 00753 return 1; 00754 00755 if (pattern[0] == '_') { 00756 char reg1[2000]; 00757 const char *p; 00758 char *r = reg1; 00759 00760 if ( strlen(pattern)*5 >= 2000 ) /* safety valve */ { 00761 ast_log(LOG_ERROR,"Error: The pattern %s is way too big. Pattern matching cancelled.\n", 00762 pattern); 00763 return 0; 00764 } 00765 /* form a regular expression from the pattern, and then match it against exten */ 00766 *r++ = '^'; /* what if the extension is a pattern ?? */ 00767 *r++ = '_'; /* what if the extension is a pattern ?? */ 00768 *r++ = '?'; 00769 for (p=pattern+1; *p; p++) { 00770 switch ( *p ) { 00771 case 'X': 00772 *r++ = '['; 00773 *r++ = '0'; 00774 *r++ = '-'; 00775 *r++ = '9'; 00776 *r++ = 'X'; 00777 *r++ = ']'; 00778 break; 00779 00780 case 'Z': 00781 *r++ = '['; 00782 *r++ = '1'; 00783 *r++ = '-'; 00784 *r++ = '9'; 00785 *r++ = 'Z'; 00786 *r++ = ']'; 00787 break; 00788 00789 case 'N': 00790 *r++ = '['; 00791 *r++ = '2'; 00792 *r++ = '-'; 00793 *r++ = '9'; 00794 *r++ = 'N'; 00795 *r++ = ']'; 00796 break; 00797 00798 case '[': 00799 while ( *p && *p != ']' ) { 00800 *r++ = *p++; 00801 } 00802 if ( *p != ']') { 00803 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The extension pattern '%s' is missing a closing bracket \n", 00804 here->filename, here->startline, here->endline, pattern); 00805 } 00806 break; 00807 00808 case '.': 00809 case '!': 00810 *r++ = '.'; 00811 *r++ = '*'; 00812 break; 00813 case '*': 00814 *r++ = '\\'; 00815 *r++ = '*'; 00816 break; 00817 default: 00818 *r++ = *p; 00819 break; 00820 00821 } 00822 } 00823 *r++ = '$'; /* what if the extension is a pattern ?? */ 00824 *r++ = *p++; /* put in the closing null */ 00825 err1 = regcomp(&preg, reg1, REG_NOSUB|REG_EXTENDED); 00826 if ( err1 ) { 00827 char errmess[500]; 00828 regerror(err1,&preg,errmess,sizeof(errmess)); 00829 regfree(&preg); 00830 ast_log(LOG_WARNING, "Regcomp of %s failed, error code %d\n", 00831 reg1, err1); 00832 return 0; 00833 } 00834 err1 = regexec(&preg, exten, 0, 0, 0); 00835 regfree(&preg); 00836 00837 if ( err1 ) { 00838 /* ast_log(LOG_NOTICE,"*****************************[%d]Extension %s did not match %s(%s)\n", 00839 err1,exten, pattern, reg1); */ 00840 return 0; /* no match */ 00841 } else { 00842 /* ast_log(LOG_NOTICE,"*****************************Extension %s matched %s\n", 00843 exten, pattern); */ 00844 return 1; 00845 } 00846 00847 00848 } else { 00849 if ( strcmp(exten,pattern) == 0 ) { 00850 return 1; 00851 } else 00852 return 0; 00853 } 00854 }
|
|
|
Definition at line 1966 of file pbx_ael.c. References current_db, and match_pval(). Referenced by check_goto(), check_includes(), check_pval_item(), find_first_label_in_current_context(), find_label_in_current_context(), find_pval_goto_item(), and get_goto_target(). 01967 { 01968 return_on_context_match = 1; 01969 count_labels = 0; 01970 match_context = name; 01971 match_exten = "*"; /* don't really need to set these, shouldn't be reached */ 01972 match_label = "*"; 01973 return match_pval(current_db); 01974 }
|
|
||||||||||||
|
Definition at line 1852 of file pbx_ael.c. References find_context(), pval::list, match_pval(), pval::next, PV_INCLUDES, pval::statements, pval::str, pval::type, pval::u1, and pval::u2. Referenced by check_label(). 01853 { 01854 /* printf(" --- Got args %s, %s\n", exten, label); */ 01855 struct pval *ret; 01856 struct pval *p3; 01857 01858 count_labels = 0; 01859 return_on_context_match = 0; 01860 match_context = "*"; 01861 match_exten = "*"; 01862 match_label = label; 01863 01864 ret = match_pval(curr_cont); 01865 if (ret) 01866 return ret; 01867 01868 /* the target of the goto could be in an included context!! Fancy that!! */ 01869 /* look for includes in the current context */ 01870 for (p3=curr_cont->u2.statements; p3; p3=p3->next) { 01871 if (p3->type == PV_INCLUDES) { 01872 struct pval *p4; 01873 for (p4=p3->u1.list; p4; p4=p4->next) { 01874 /* for each context pointed to, find it, then find a context/label that matches the 01875 target here! */ 01876 char *incl_context = p4->u1.str; 01877 /* find a matching context name */ 01878 struct pval *that_context = find_context(incl_context); 01879 if (that_context) { 01880 struct pval *x3; 01881 x3 = find_first_label_in_current_context(label, that_context); 01882 if (x3) { 01883 return x3; 01884 } 01885 } 01886 } 01887 } 01888 } 01889 return 0; 01890 }
|
|
||||||||||||||||
|
Definition at line 1892 of file pbx_ael.c. References find_context(), pval::list, match_pval(), pval::next, PV_INCLUDES, pval::statements, pval::str, pval::type, pval::u1, and pval::u2. Referenced by check_goto(), and get_goto_target(). 01893 { 01894 /* printf(" --- Got args %s, %s\n", exten, label); */ 01895 struct pval *ret; 01896 struct pval *p3; 01897 01898 count_labels = 0; 01899 return_on_context_match = 0; 01900 match_context = "*"; 01901 match_exten = exten; 01902 match_label = label; 01903 ret = match_pval(curr_cont->u2.statements); 01904 if (ret) 01905 return ret; 01906 01907 /* the target of the goto could be in an included context!! Fancy that!! */ 01908 /* look for includes in the current context */ 01909 for (p3=curr_cont->u2.statements; p3; p3=p3->next) { 01910 if (p3->type == PV_INCLUDES) { 01911 struct pval *p4; 01912 for (p4=p3->u1.list; p4; p4=p4->next) { 01913 /* for each context pointed to, find it, then find a context/label that matches the 01914 target here! */ 01915 char *incl_context = p4->u1.str; 01916 /* find a matching context name */ 01917 struct pval *that_context = find_context(incl_context); 01918 if (that_context) { 01919 struct pval *x3; 01920 x3 = find_label_in_current_context(exten, label, that_context); 01921 if (x3) { 01922 return x3; 01923 } 01924 } 01925 } 01926 } 01927 } 01928 return 0; 01929 }
|
|
||||||||||||||||
|
Definition at line 1942 of file pbx_ael.c. References current_db, and match_pval(). Referenced by check_goto(), and get_goto_target(). 01943 { 01944 /* printf(" --- Got args %s, %s, %s\n", context, exten, label); */ 01945 count_labels = 0; 01946 return_on_context_match = 0; 01947 01948 match_context = context; 01949 match_exten = exten; 01950 match_label = label; 01951 01952 return match_pval(current_db); 01953 }
|
|
||||||||||||
|
Definition at line 1931 of file pbx_ael.c. References match_pval(). Referenced by check_goto(), and get_goto_target(). 01932 { 01933 /* printf(" --- Got args %s\n", label); */ 01934 count_labels = 0; 01935 return_on_context_match = 0; 01936 match_context = "*"; 01937 match_exten = "*"; 01938 match_label = label; 01939 return match_pval(curr_ext); 01940 }
|
|
|
Definition at line 1956 of file pbx_ael.c. References current_db, and match_pval(). Referenced by check_pval_item(). 01957 { 01958 return_on_context_match = 1; 01959 count_labels = 0; 01960 match_context = name; 01961 match_exten = "*"; /* don't really need to set these, shouldn't be reached */ 01962 match_label = "*"; 01963 return match_pval(current_db); 01964 }
|
|
||||||||||||
|
Definition at line 1405 of file pbx_ael.c. References ast_log(), check_goto(), pval::else_statements, find_context(), find_pval_gotos(), pval::for_statements, pval::list, LOG_ERROR, pval::macro_statements, pval::next, PV_CASE, PV_CATCH, PV_CONTEXT, PV_DEFAULT, PV_EXTENSION, PV_FOR, PV_GOTO, PV_IF, PV_IFTIME, PV_INCLUDES, PV_MACRO, PV_PATTERN, PV_RANDOM, PV_STATEMENTBLOCK, PV_SWITCH, PV_WHILE, pval::statements, pval::str, pval::type, pval::u1, pval::u2, pval::u3, and pval::u4. Referenced by find_pval_gotos(). 01406 { 01407 struct pval *p4; 01408 if (lev>100) { 01409 ast_log(LOG_ERROR,"find_pval_goto in infinite loop!\n\n"); 01410 return; 01411 } 01412 01413 switch ( item->type ) { 01414 case PV_MACRO: 01415 /* fields: item->u1.str == name of macro 01416 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 01417 item->u2.arglist->u1.str == argument 01418 item->u2.arglist->next == next arg 01419 01420 item->u3.macro_statements == pval list of statements in macro body. 01421 */ 01422 01423 /* printf("Descending into matching macro %s\n", match_context); */ 01424 find_pval_gotos(item->u3.macro_statements,lev+1); /* if we're just searching for a context, don't bother descending into them */ 01425 01426 break; 01427 01428 case PV_CONTEXT: 01429 /* fields: item->u1.str == name of context 01430 item->u2.statements == pval list of statements in context body 01431 item->u3.abstract == int 1 if an abstract keyword were present 01432 */ 01433 break; 01434 01435 case PV_CASE: 01436 /* fields: item->u1.str == value of case 01437 item->u2.statements == pval list of statements under the case 01438 */ 01439 find_pval_gotos(item->u2.statements,lev+1); 01440 break; 01441 01442 case PV_PATTERN: 01443 /* fields: item->u1.str == value of case 01444 item->u2.statements == pval list of statements under the case 01445 */ 01446 find_pval_gotos(item->u2.statements,lev+1); 01447 break; 01448 01449 case PV_DEFAULT: 01450 /* fields: 01451 item->u2.statements == pval list of statements under the case 01452 */ 01453 find_pval_gotos(item->u2.statements,lev+1); 01454 break; 01455 01456 case PV_CATCH: 01457 /* fields: item->u1.str == name of extension to catch 01458 item->u2.statements == pval list of statements in context body 01459 */ 01460 find_pval_gotos(item->u2.statements,lev+1); 01461 break; 01462 01463 case PV_STATEMENTBLOCK: 01464 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 01465 */ 01466 find_pval_gotos(item->u1.list,lev+1); 01467 break; 01468 01469 case PV_GOTO: 01470 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 01471 item->u1.list->u1.str == where the data on a PV_WORD will always be. 01472 */ 01473 check_goto(item); /* THE WHOLE FUNCTION OF THIS ENTIRE ROUTINE!!!! */ 01474 break; 01475 01476 case PV_INCLUDES: 01477 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 01478 */ 01479 for (p4=item->u1.list; p4; p4=p4->next) { 01480 /* for each context pointed to, find it, then find a context/label that matches the 01481 target here! */ 01482 char *incl_context = p4->u1.str; 01483 /* find a matching context name */ 01484 struct pval *that_context = find_context(incl_context); 01485 if (that_context) { 01486 find_pval_gotos(that_context,lev+1); /* keep working up the includes */ 01487 } 01488 } 01489 break; 01490 01491 case PV_FOR: 01492 /* fields: item->u1.for_init == a string containing the initalizer 01493 item->u2.for_test == a string containing the loop test 01494 item->u3.for_inc == a string containing the loop increment 01495 01496 item->u4.for_statements == a pval list of statements in the for () 01497 */ 01498 find_pval_gotos(item->u4.for_statements,lev+1); 01499 break; 01500 01501 case PV_WHILE: 01502 /* fields: item->u1.str == the while conditional, as supplied by user 01503 01504 item->u2.statements == a pval list of statements in the while () 01505 */ 01506 find_pval_gotos(item->u2.statements,lev+1); 01507 break; 01508 01509 case PV_RANDOM: 01510 /* fields: item->u1.str == the random number expression, as supplied by user 01511 01512 item->u2.statements == a pval list of statements in the if () 01513 item->u3.else_statements == a pval list of statements in the else 01514 (could be zero) 01515 fall thru to PV_IF */ 01516 01517 case PV_IFTIME: 01518 /* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list 01519 01520 item->u2.statements == a pval list of statements in the if () 01521 item->u3.else_statements == a pval list of statements in the else 01522 (could be zero) 01523 fall thru to PV_IF*/ 01524 case PV_IF: 01525 /* fields: item->u1.str == the if conditional, as supplied by user 01526 01527 item->u2.statements == a pval list of statements in the if () 01528 item->u3.else_statements == a pval list of statements in the else 01529 (could be zero) 01530 */ 01531 find_pval_gotos(item->u2.statements,lev+1); 01532 01533 if (item->u3.else_statements) { 01534 find_pval_gotos(item->u3.else_statements,lev+1); 01535 } 01536 break; 01537 01538 case PV_SWITCH: 01539 /* fields: item->u1.str == the switch expression 01540 01541 item->u2.statements == a pval list of statements in the switch, 01542 (will be case statements, most likely!) 01543 */ 01544 find_pval_gotos(item->u3.else_statements,lev+1); 01545 break; 01546 01547 case PV_EXTENSION: 01548 /* fields: item->u1.str == the extension name, label, whatever it's called 01549 01550 item->u2.statements == a pval list of statements in the extension 01551 item->u3.hints == a char * hint argument 01552 item->u4.regexten == an int boolean. non-zero says that regexten was specified 01553 */ 01554 01555 find_pval_gotos(item->u2.statements,lev+1); 01556 break; 01557 01558 default: 01559 break; 01560 } 01561 }
|
|
||||||||||||
|
Definition at line 1563 of file pbx_ael.c. References find_pval_goto_item(), and pval::next. Referenced by find_pval_goto_item(). 01564 { 01565 pval *i; 01566 01567 for (i=item; i; i=i->next) { 01568 01569 find_pval_goto_item(i, lev); 01570 } 01571 }
|
|
|
Definition at line 3751 of file pbx_ael.c. References exten, ael_priority::next, ael_extension::next_exten, ael_extension::plist, PV_GOTO, and strdup. 03752 { 03753 struct ael_extension *e; 03754 for(e=exten;e;e=e->next_exten) { 03755 03756 struct ael_priority *p; 03757 for(p=e->plist;p;p=p->next) { 03758 03759 if( p->origin && p->origin->type == PV_GOTO && p->origin->u3.goto_target_in_case ) { 03760 03761 /* fix the extension of the goto target to the actual extension in the post-compiled dialplan */ 03762 03763 pval *target = p->origin->u2.goto_target; 03764 struct ael_extension *z = target->u3.compiled_label; 03765 pval *pv2 = p->origin; 03766 char buf1[500]; 03767 char *apparg_save = p->appargs; 03768 03769 p->appargs = 0; 03770 if (!pv2->u1.list->next) /* just one -- it won't hurt to repeat the extension */ { 03771 snprintf(buf1,sizeof(buf1),"%s|%s", z->name, pv2->u1.list->u1.str); 03772 p->appargs = strdup(buf1); 03773 03774 } else if (pv2->u1.list->next && !pv2->u1.list->next->next) /* two */ { 03775 snprintf(buf1,sizeof(buf1),"%s|%s", z->name, pv2->u1.list->next->u1.str); 03776 p->appargs = strdup(buf1); 03777 } else if (pv2->u1.list->next && pv2->u1.list->next->next) { 03778 snprintf(buf1,sizeof(buf1),"%s|%s|%s", pv2->u1.list->u1.str, 03779 z->name, 03780 pv2->u1.list->next->next->u1.str); 03781 p->appargs = strdup(buf1); 03782 } 03783 else 03784 printf("WHAT? The goto doesn't fall into one of three cases for GOTO????\n"); 03785 03786 if( apparg_save ) { 03787 free(apparg_save); 03788 } 03789 } 03790 } 03791 } 03792 }
|
|
||||||||||||
|
Definition at line 2946 of file pbx_ael.c. Referenced by gen_prios(). 02947 { 02948 /* the result will be a string that will be matched by pattern */ 02949 char *p=pattern, *t=result; 02950 while (*p) { 02951 if (*p == 'x' || *p == 'n' || *p == 'z' || *p == 'X' || *p == 'N' || *p == 'Z') 02952 *t++ = '9'; 02953 else if (*p == '[') { 02954 char *z = p+1; 02955 while (*z != ']') 02956 z++; 02957 if (*(z+1)== ']') 02958 z++; 02959 *t++=*(p+1); /* use the first char in the set */ 02960 p = z; 02961 } else { 02962 *t++ = *p; 02963 } 02964 p++; 02965 } 02966 *t++ = 0; /* cap it off */ 02967 }
|
|
||||||||||||||||||||||||
|
Definition at line 2969 of file pbx_ael.c. References AEL_APPCALL, AEL_CONTROL1, AEL_FOR_CONTROL, AEL_IF_CONTROL, AEL_IFTIME_CONTROL, AEL_LABEL, AEL_RETURN, ael_priority::app, ael_priority::appargs, pval::arglist, pval::compiled_label, ael_extension::context, control_statement_count, pval::else_statements, ael_priority::exten, exten, pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, gen_match_to_pattern(), get_goto_target(), ael_priority::goto_false, pval::goto_target, pval::goto_target_in_case, ael_priority::goto_true, pval::label_in_case, label_inside_case(), linkexten(), linkprio(), pval::list, ael_extension::loop_break, ael_extension::loop_continue, ael_extension::name, new_exten(), new_prio(), pval::next, ael_priority::origin, PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTINUE, PV_DEFAULT, PV_FOR, PV_GOTO, PV_IF, PV_IFTIME, PV_LABEL, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_VARDEC, PV_WHILE, remove_spaces_before_equals(), ael_extension::return_needed, pval::statements, pval::str, strdup, substitute_commas(), ael_priority::type, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val. Referenced by ast_compile_ael2(). 02970 { 02971 pval *p,*p2,*p3; 02972 struct ael_priority *pr; 02973 struct ael_priority *for_init, *for_test, *for_inc, *for_loop, *for_end; 02974 struct ael_priority *while_test, *while_loop, *while_end; 02975 struct ael_priority *switch_test, *switch_end, *fall_thru; 02976 struct ael_priority *if_test, *if_end, *if_skip, *if_false; 02977 #ifdef OLD_RAND_ACTION 02978 struct ael_priority *rand_test, *rand_end, *rand_skip; 02979 #endif 02980 char buf1[2000]; 02981 char buf2[2000]; 02982 char *strp, *strp2; 02983 char new_label[2000]; 02984 int default_exists; 02985 int local_control_statement_count; 02986 int first; 02987 struct ael_priority *loop_break_save; 02988 struct ael_priority *loop_continue_save; 02989 struct ael_extension *switch_case; 02990 02991 for (p=statement; p; p=p->next) { 02992 switch (p->type) { 02993 case PV_VARDEC: 02994 pr = new_prio(); 02995 pr->type = AEL_APPCALL; 02996 snprintf(buf1,sizeof(buf1),"%s=$[%s]", p->u1.str, p->u2.val); 02997 pr->app = strdup("Set"); 02998 remove_spaces_before_equals(buf1); 02999 pr->appargs = strdup(buf1); 03000 pr->origin = p; 03001 linkprio(exten, pr); 03002 break; 03003 03004 case PV_GOTO: 03005 pr = new_prio(); 03006 pr->type = AEL_APPCALL; 03007 p->u2.goto_target = get_goto_target(p); 03008 if( p->u2.goto_target ) { 03009 p->u3.goto_target_in_case = p->u2.goto_target->u2.label_in_case = label_inside_case(p->u2.goto_target); 03010 } 03011 03012 if (!p->u1.list->next) /* just one */ { 03013 pr->app = strdup("Goto"); 03014 if (!mother_exten) 03015 pr->appargs = strdup(p->u1.list->u1.str); 03016 else { /* for the case of simple within-extension gotos in case/pattern/default statement blocks: */ 03017 snprintf(buf1,sizeof(buf1),"%s|%s", mother_exten->name, p->u1.list->u1.str); 03018 pr->appargs = strdup(buf1); 03019 } 03020 03021 } else if (p->u1.list->next && !p->u1.list->next->next) /* two */ { 03022 snprintf(buf1,sizeof(buf1),"%s|%s", p->u1.list->u1.str, p->u1.list->next->u1.str); 03023 pr->app = strdup("Goto"); 03024 pr->appargs = strdup(buf1); 03025 } else if (p->u1.list->next && p->u1.list->next->next) { 03026 snprintf(buf1,sizeof(buf1),"%s|%s|%s", p->u1.list->u1.str, 03027 p->u1.list->next->u1.str, 03028 p->u1.list->next->next->u1.str); 03029 pr->app = strdup("Goto"); 03030 pr->appargs = strdup(buf1); 03031 } 03032 pr->origin = p; 03033 linkprio(exten, pr); 03034 break; 03035 03036 case PV_LABEL: 03037 pr = new_prio(); 03038 pr->type = AEL_LABEL; 03039 pr->origin = p; 03040 p->u3.compiled_label = exten; 03041 linkprio(exten, pr); 03042 break; 03043 03044 case PV_FOR: 03045 control_statement_count++; 03046 loop_break_save = exten->loop_break; /* save them, then restore before leaving */ 03047 loop_continue_save = exten->loop_continue; 03048 snprintf(new_label,sizeof(new_label),"for-%s-%d", label, control_statement_count); 03049 for_init = new_prio(); 03050 for_inc = new_prio(); 03051 for_test = new_prio(); 03052 for_loop = new_prio(); 03053 for_end = new_prio(); 03054 for_init->type = AEL_APPCALL; 03055 for_inc->type = AEL_APPCALL; 03056 for_test->type = AEL_FOR_CONTROL; 03057 for_test->goto_false = for_end; 03058 for_loop->type = AEL_CONTROL1; /* simple goto */ 03059 for_end->type = AEL_APPCALL; 03060 for_init->app = strdup("Set"); 03061 03062 strcpy(buf2,p->u1.for_init); 03063 remove_spaces_before_equals(buf2); 03064 strp = strchr(buf2, '='); 03065 strp2 = strchr(p->u1.for_init, '='); 03066 if (strp) { 03067 *(strp+1) = 0; 03068 strcat(buf2,"$["); 03069 strncat(buf2,strp2+1, sizeof(buf2)-strlen(strp2+1)-2); 03070 strcat(buf2,"]"); 03071 for_init->appargs = strdup(buf2); 03072 } else 03073 for_init->appargs = strdup(p->u1.for_init); 03074 03075 for_inc->app = strdup("Set"); 03076 03077 strcpy(buf2,p->u3.for_inc); 03078 remove_spaces_before_equals(buf2); 03079 strp = strchr(buf2, '='); 03080 strp2 = strchr(p->u3.for_inc, '='); 03081 if (strp) { 03082 *(strp+1) = 0; 03083 strcat(buf2,"$["); 03084 strncat(buf2,strp2+1, sizeof(buf2)-strlen(strp2+1)-2); 03085 strcat(buf2,"]"); 03086 for_inc->appargs = strdup(buf2); 03087 } else 03088 for_inc->appargs = strdup(p->u3.for_inc); 03089 snprintf(buf1,sizeof(buf1),"$[%s]",p->u2.for_test); 03090 for_test->app = 0; 03091 for_test->appargs = strdup(buf1); 03092 for_loop->goto_true = for_test; 03093 snprintf(buf1,sizeof(buf1),"Finish for-%s-%d", label, control_statement_count); 03094 for_end->app = strdup("NoOp"); 03095 for_end->appargs = strdup(buf1); 03096 /* link & load! */ 03097 linkprio(exten, for_init); 03098 linkprio(exten, for_test); 03099 03100 /* now, put the body of the for loop here */ 03101 exten->loop_break = for_end; 03102 exten->loop_continue = for_test; 03103 03104 gen_prios(exten, new_label, p->u4.for_statements, mother_exten, this_context); /* this will link in all the statements here */ 03105 03106 linkprio(exten, for_inc); 03107 linkprio(exten, for_loop); 03108 linkprio(exten, for_end); 03109 03110 03111 exten->loop_break = loop_break_save; 03112 exten->loop_continue = loop_continue_save; 03113 for_loop->origin = p; 03114 break; 03115 03116 case PV_WHILE: 03117 control_statement_count++; 03118 loop_break_save = exten->loop_break; /* save them, then restore before leaving */ 03119 loop_continue_save = exten->loop_continue; 03120 snprintf(new_label,sizeof(new_label),"while-%s-%d", label, control_statement_count); 03121 while_test = new_prio(); 03122 while_loop = new_prio(); 03123 while_end = new_prio(); 03124 while_test->type = AEL_FOR_CONTROL; 03125 while_test->goto_false = while_end; 03126 while_loop->type = AEL_CONTROL1; /* simple goto */ 03127 while_end->type = AEL_APPCALL; 03128 snprintf(buf1,sizeof(buf1),"$[%s]",p->u1.str); 03129 while_test->app = 0; 03130 while_test->appargs = strdup(buf1); 03131 while_loop->goto_true = while_test; 03132 snprintf(buf1,sizeof(buf1),"Finish while-%s-%d", label, control_statement_count); 03133 while_end->app = strdup("NoOp"); 03134 while_end->appargs = strdup(buf1); 03135 03136 linkprio(exten, while_test); 03137 03138 /* now, put the body of the for loop here */ 03139 exten->loop_break = while_end; 03140 exten->loop_continue = while_test; 03141 03142 gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the while body statements here */ 03143 03144 linkprio(exten, while_loop); 03145 linkprio(exten, while_end); 03146 03147 03148 exten->loop_break = loop_break_save; 03149 exten->loop_continue = loop_continue_save; 03150 while_loop->origin = p; 03151 break; 03152 03153 case PV_SWITCH: 03154 control_statement_count++; 03155 local_control_statement_count = control_statement_count; 03156 loop_break_save = exten->loop_break; /* save them, then restore before leaving */ 03157 loop_continue_save = exten->loop_continue; 03158 snprintf(new_label,sizeof(new_label),"sw-%s-%d", label, control_statement_count); 03159 03160 switch_test = new_prio(); 03161 switch_end = new_prio(); 03162 switch_test->type = AEL_APPCALL; 03163 switch_end->type = AEL_APPCALL; 03164 snprintf(buf1,sizeof(buf1),"sw-%d-%s|1",control_statement_count, p->u1.str); 03165 switch_test->app = strdup("Goto"); 03166 switch_test->appargs = strdup(buf1); 03167 snprintf(buf1,sizeof(buf1),"Finish switch-%s-%d", label, control_statement_count); 03168 switch_end->app = strdup("NoOp"); 03169 switch_end->appargs = strdup(buf1); 03170 switch_end->origin = p; 03171 switch_end->exten = exten; 03172 03173 linkprio(exten, switch_test); 03174 linkprio(exten, switch_end); 03175 03176 exten->loop_break = switch_end; 03177 exten->loop_continue = 0; 03178 default_exists = 0; 03179 03180 for (p2=p->u2.statements; p2; p2=p2->next) { 03181 /* now, for each case/default put the body of the for loop here */ 03182 if (p2->type == PV_CASE) { 03183 /* ok, generate a extension and link it in */ 03184 switch_case = new_exten(); 03185 switch_case->context = this_context; 03186 /* the break/continue locations are inherited from parent */ 03187 switch_case->loop_break = exten->loop_break; 03188 switch_case->loop_continue = exten->loop_continue; 03189 03190 linkexten(exten,switch_case); 03191 snprintf(buf1,sizeof(buf1),"sw-%d-%s", local_control_statement_count, p2->u1.str); 03192 switch_case->name = strdup(buf1); 03193 snprintf(new_label,sizeof(new_label),"sw-%s-%s-%d", label, p2->u1.str, local_control_statement_count); 03194 03195 gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context); /* this will link in all the case body statements here */ 03196 03197 /* here is where we write code to "fall thru" to the next case... if there is one... */ 03198 for (p3=p2->u2.statements; p3; p3=p3->next) { 03199 if (!p3->next) 03200 break; 03201 } 03202 /* p3 now points the last statement... */ 03203 if ( |