#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_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) |
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 in file pbx_ael.c.
#define DEBUG_CONTEXTS (1 << 3) |
#define DEBUG_MACROS (1 << 2) |
#define DEBUG_READ (1 << 0) |
#define DEBUG_TOKENS (1 << 1) |
void add_extensions | ( | struct ael_extension * | exten | ) |
Definition at line 3567 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(), AST_MAX_EXTENSION, 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, pbx_substitute_variables_helper(), PRIORITY_HINT, ael_priority::priority_num, PV_IFTIME, PV_SWITCH, strdup, pval::type, ael_priority::type, and pval::u3.
03568 { 03569 struct ael_priority *pr; 03570 char *label=0; 03571 char realext[AST_MAX_EXTENSION]; 03572 if (!exten) { 03573 ast_log(LOG_WARNING, "This file is Empty!\n" ); 03574 return; 03575 } 03576 do { 03577 struct ael_priority *last = 0; 03578 03579 memset(realext, '\0', sizeof(realext)); 03580 pbx_substitute_variables_helper(NULL, exten->name, realext, sizeof(realext) - 1); 03581 if (exten->hints) { 03582 if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, PRIORITY_HINT, NULL, exten->cidmatch, 03583 exten->hints, NULL, ast_free, registrar)) { 03584 ast_log(LOG_WARNING, "Unable to add step at priority 'hint' of extension '%s'\n", 03585 exten->name); 03586 } 03587 } 03588 03589 for (pr=exten->plist; pr; pr=pr->next) { 03590 char app[2000]; 03591 char appargs[2000]; 03592 03593 /* before we can add the extension, we need to prep the app/appargs; 03594 the CONTROL types need to be done after the priority numbers are calculated. 03595 */ 03596 if (pr->type == AEL_LABEL) /* don't try to put labels in the dialplan! */ { 03597 last = pr; 03598 continue; 03599 } 03600 03601 if (pr->app) 03602 strcpy(app, pr->app); 03603 else 03604 app[0] = 0; 03605 if (pr->appargs ) 03606 strcpy(appargs, pr->appargs); 03607 else 03608 appargs[0] = 0; 03609 switch( pr->type ) { 03610 case AEL_APPCALL: 03611 /* easy case. Everything is all set up */ 03612 break; 03613 03614 case AEL_CONTROL1: /* FOR loop, WHILE loop, BREAK, CONTINUE, IF, IFTIME */ 03615 /* simple, unconditional goto. */ 03616 strcpy(app,"Goto"); 03617 if (pr->goto_true->origin && pr->goto_true->origin->type == PV_SWITCH ) { 03618 snprintf(appargs,sizeof(appargs),"%s|%d", pr->goto_true->exten->name, pr->goto_true->priority_num); 03619 } else if (pr->goto_true->origin && pr->goto_true->origin->type == PV_IFTIME && pr->goto_true->origin->u3.else_statements ) { 03620 snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num+1); 03621 } else 03622 snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num); 03623 break; 03624 03625 case AEL_FOR_CONTROL: /* WHILE loop test, FOR loop test */ 03626 strcpy(app,"GotoIf"); 03627 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); 03628 break; 03629 03630 case AEL_IF_CONTROL: 03631 strcpy(app,"GotoIf"); 03632 if (pr->origin->u3.else_statements ) 03633 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num+1); 03634 else 03635 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); 03636 break; 03637 03638 case AEL_RAND_CONTROL: 03639 strcpy(app,"Random"); 03640 snprintf(appargs,sizeof(appargs),"%s:%d", pr->appargs, pr->goto_true->priority_num+1); 03641 break; 03642 03643 case AEL_IFTIME_CONTROL: 03644 strcpy(app,"GotoIfTime"); 03645 snprintf(appargs,sizeof(appargs),"%s?%d", pr->appargs, pr->priority_num+2); 03646 break; 03647 03648 case AEL_RETURN: 03649 strcpy(app,"Goto"); 03650 snprintf(appargs,sizeof(appargs), "%d", exten->return_target->priority_num); 03651 break; 03652 03653 default: 03654 break; 03655 } 03656 if (last && last->type == AEL_LABEL ) { 03657 label = last->origin->u1.str; 03658 } 03659 else 03660 label = 0; 03661 03662 if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, pr->priority_num, (label?label:NULL), exten->cidmatch, 03663 app, strdup(appargs), ast_free, registrar)) { 03664 ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num, 03665 exten->name); 03666 } 03667 last = pr; 03668 } 03669 exten = exten->next_exten; 03670 } while ( exten ); 03671 }
static int ael2_debug_contexts | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4034 of file pbx_ael.c.
References DEBUG_CONTEXTS.
04035 { 04036 aeldebug |= DEBUG_CONTEXTS; 04037 return 0; 04038 }
static int ael2_debug_macros | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4028 of file pbx_ael.c.
References DEBUG_MACROS.
04029 { 04030 aeldebug |= DEBUG_MACROS; 04031 return 0; 04032 }
static int ael2_debug_read | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4016 of file pbx_ael.c.
References DEBUG_READ.
04017 { 04018 aeldebug |= DEBUG_READ; 04019 return 0; 04020 }
static int ael2_debug_tokens | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4022 of file pbx_ael.c.
References DEBUG_TOKENS.
04023 { 04024 aeldebug |= DEBUG_TOKENS; 04025 return 0; 04026 }
static int ael2_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
static int ael2_reload | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4046 of file pbx_ael.c.
References pbx_load_module().
04047 { 04048 return (pbx_load_module()); 04049 }
static void ael2_semantic_check | ( | pval * | item, | |
int * | arg_errs, | |||
int * | arg_warns, | |||
int * | arg_notes | |||
) | [static] |
Definition at line 2727 of file pbx_ael.c.
References ast_config_AST_VAR_DIR, check_context_names(), check_pval(), and current_db.
Referenced by pbx_load_module().
02728 { 02729 02730 #ifdef AAL_ARGCHECK 02731 int argapp_errs =0; 02732 char *rfilename; 02733 #endif 02734 struct argapp *apps=0; 02735 02736 #ifdef AAL_ARGCHECK 02737 rfilename = alloca(10 + strlen(ast_config_AST_VAR_DIR)); 02738 sprintf(rfilename, "%s/applist", ast_config_AST_VAR_DIR); 02739 02740 apps = argdesc_parse(rfilename, &argapp_errs); /* giveth */ 02741 #endif 02742 current_db = item; 02743 errs = warns = notes = 0; 02744 02745 check_context_names(); 02746 check_pval(item, apps, 0); 02747 02748 #ifdef AAL_ARGCHECK 02749 argdesc_destroy(apps); /* taketh away */ 02750 #endif 02751 current_db = 0; 02752 02753 *arg_errs = errs; 02754 *arg_warns = warns; 02755 *arg_notes = notes; 02756 }
void ast_compile_ael2 | ( | struct ast_context ** | local_contexts, | |
struct pval * | root | |||
) |
Definition at line 3754 of file pbx_ael.c.
References context, exten, pval::list, pval::next, pbx_builtin_setvar(), PV_GLOBALS, pval::str, pval::type, pval::u1, pval::u2, and pval::val.
Referenced by pbx_load_module().
03755 { 03756 pval *p,*p2; 03757 struct ast_context *context; 03758 char buf[2000]; 03759 struct ael_extension *exten; 03760 struct ael_extension *exten_list = 0; 03761 03762 for (p=root; p; p=p->next ) { /* do the globals first, so they'll be there 03763 when we try to eval them */ 03764 switch (p->type) { 03765 case PV_GLOBALS: 03766 /* just VARDEC elements */ 03767 for (p2=p->u1.list; p2; p2=p2->next) { 03768 char buf2[2000]; 03769 snprintf(buf2,sizeof(buf2),"%s=%s", p2->u1.str, p2->u2.val); 03770 pbx_builtin_setvar(NULL, buf2); 03771 } 03772 break; 03773 default: 03774 break; 03775 } 03776 } 03777 03778 for (p=root; p; p=p->next ) { 03779 pval *lp; 03780 int argc; 03781 03782 switch (p->type) { 03783 case PV_MACRO: 03784 strcpy(buf,"macro-"); 03785 strcat(buf,p->u1.str); 03786 context = ast_context_create(local_contexts, buf, registrar); 03787 03788 exten = new_exten(); 03789 exten->context = context; 03790 exten->name = strdup("s"); 03791 argc = 1; 03792 for (lp=p->u2.arglist; lp; lp=lp->next) { 03793 /* for each arg, set up a "Set" command */ 03794 struct ael_priority *np2 = new_prio(); 03795 np2->type = AEL_APPCALL; 03796 np2->app = strdup("Set"); 03797 snprintf(buf,sizeof(buf),"%s=${ARG%d}", lp->u1.str, argc++); 03798 remove_spaces_before_equals(buf); 03799 np2->appargs = strdup(buf); 03800 linkprio(exten, np2); 03801 } 03802 /* add any includes */ 03803 for (p2=p->u3.macro_statements; p2; p2=p2->next) { 03804 pval *p3; 03805 03806 switch (p2->type) { 03807 case PV_INCLUDES: 03808 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 03809 if ( p3->u2.arglist ) { 03810 snprintf(buf,sizeof(buf), "%s|%s|%s|%s|%s", 03811 p3->u1.str, 03812 p3->u2.arglist->u1.str, 03813 p3->u2.arglist->next->u1.str, 03814 p3->u2.arglist->next->next->u1.str, 03815 p3->u2.arglist->next->next->next->u1.str); 03816 ast_context_add_include2(context, buf, registrar); 03817 } else 03818 ast_context_add_include2(context, p3->u1.str, registrar); 03819 } 03820 break; 03821 default: 03822 break; 03823 } 03824 } 03825 /* CONTAINS APPCALLS, CATCH, just like extensions... */ 03826 gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context ); 03827 if (exten->return_needed) { 03828 struct ael_priority *np2 = new_prio(); 03829 np2->type = AEL_APPCALL; 03830 np2->app = strdup("NoOp"); 03831 snprintf(buf,sizeof(buf),"End of Macro %s-%s",p->u1.str, exten->name); 03832 np2->appargs = strdup(buf); 03833 linkprio(exten, np2); 03834 exten-> return_target = np2; 03835 } 03836 03837 set_priorities(exten); 03838 attach_exten(&exten_list, exten); 03839 break; 03840 03841 case PV_GLOBALS: 03842 /* already done */ 03843 break; 03844 03845 case PV_CONTEXT: 03846 context = ast_context_create(local_contexts, p->u1.str, registrar); 03847 03848 /* contexts contain: ignorepat, includes, switches, eswitches, extensions, */ 03849 for (p2=p->u2.statements; p2; p2=p2->next) { 03850 pval *p3; 03851 char *s3; 03852 03853 switch (p2->type) { 03854 case PV_EXTENSION: 03855 exten = new_exten(); 03856 exten->name = strdup(p2->u1.str); 03857 exten->context = context; 03858 03859 if( (s3=strchr(exten->name, '/') ) != 0 ) 03860 { 03861 *s3 = 0; 03862 exten->cidmatch = s3+1; 03863 } 03864 03865 if ( p2->u3.hints ) 03866 exten->hints = strdup(p2->u3.hints); 03867 exten->regexten = p2->u4.regexten; 03868 gen_prios(exten, p->u1.str, p2->u2.statements, 0, context ); 03869 if (exten->return_needed) { 03870 struct ael_priority *np2 = new_prio(); 03871 np2->type = AEL_APPCALL; 03872 np2->app = strdup("NoOp"); 03873 snprintf(buf,sizeof(buf),"End of Extension %s", exten->name); 03874 np2->appargs = strdup(buf); 03875 linkprio(exten, np2); 03876 exten-> return_target = np2; 03877 } 03878 /* is the last priority in the extension a label? Then add a trailing no-op */ 03879 if( !exten->plist_last ) 03880 { 03881 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Empty Extension!\n", 03882 p2->filename, p2->startline, p2->endline); 03883 } 03884 03885 if ( exten->plist_last && exten->plist_last->type == AEL_LABEL ) { 03886 struct ael_priority *np2 = new_prio(); 03887 np2->type = AEL_APPCALL; 03888 np2->app = strdup("NoOp"); 03889 snprintf(buf,sizeof(buf),"A NoOp to follow a trailing label %s", exten->plist_last->origin->u1.str); 03890 np2->appargs = strdup(buf); 03891 linkprio(exten, np2); 03892 } 03893 03894 set_priorities(exten); 03895 attach_exten(&exten_list, exten); 03896 break; 03897 03898 case PV_IGNOREPAT: 03899 ast_context_add_ignorepat2(context, p2->u1.str, registrar); 03900 break; 03901 03902 case PV_INCLUDES: 03903 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 03904 if ( p3->u2.arglist ) { 03905 snprintf(buf,sizeof(buf), "%s|%s|%s|%s|%s", 03906 p3->u1.str, 03907 p3->u2.arglist->u1.str, 03908 p3->u2.arglist->next->u1.str, 03909 p3->u2.arglist->next->next->u1.str, 03910 p3->u2.arglist->next->next->next->u1.str); 03911 ast_context_add_include2(context, buf, registrar); 03912 } else 03913 ast_context_add_include2(context, p3->u1.str, registrar); 03914 } 03915 break; 03916 03917 case PV_SWITCHES: 03918 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 03919 char *c = strchr(p3->u1.str, '/'); 03920 if (c) { 03921 *c = '\0'; 03922 c++; 03923 } else 03924 c = ""; 03925 03926 ast_context_add_switch2(context, p3->u1.str, c, 0, registrar); 03927 } 03928 break; 03929 03930 case PV_ESWITCHES: 03931 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 03932 char *c = strchr(p3->u1.str, '/'); 03933 if (c) { 03934 *c = '\0'; 03935 c++; 03936 } else 03937 c = ""; 03938 03939 ast_context_add_switch2(context, p3->u1.str, c, 1, registrar); 03940 } 03941 break; 03942 default: 03943 break; 03944 } 03945 } 03946 03947 break; 03948 03949 default: 03950 /* huh? what? */ 03951 break; 03952 03953 } 03954 } 03955 /* moved these from being done after a macro or extension were processed, 03956 to after all processing is done, for the sake of fixing gotos to labels inside cases... */ 03957 /* I guess this would be considered 2nd pass of compiler now... */ 03958 fix_gotos_in_extensions(exten_list); /* find and fix extension ref in gotos to labels that are in case statements */ 03959 add_extensions(exten_list); /* actually makes calls to create priorities in ast_contexts -- feeds dialplan to asterisk */ 03960 destroy_extensions(exten_list); /* all that remains is an empty husk, discard of it as is proper */ 03961 03962 }
int ast_expr | ( | char * | expr, | |
char * | buf, | |||
int | length | |||
) |
Definition at line 3122 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 check_pval_item(), and pbx_substitute_variables_helper_full().
03123 { 03124 struct parse_io io; 03125 int return_value = 0; 03126 03127 memset(&io, 0, sizeof(io)); 03128 io.string = expr; /* to pass to the error routine */ 03129 03130 ast_yylex_init(&io.scanner); 03131 03132 ast_yy_scan_string(expr, io.scanner); 03133 03134 ast_yyparse ((void *) &io); 03135 03136 ast_yylex_destroy(io.scanner); 03137 03138 if (!io.val) { 03139 if (length > 1) { 03140 strcpy(buf, "0"); 03141 return_value = 1; 03142 } 03143 } else { 03144 if (io.val->type == AST_EXPR_integer) { 03145 int res_length; 03146 03147 res_length = snprintf(buf, length, "%ld", (long int) io.val->u.i); 03148 return_value = (res_length <= length) ? res_length : length; 03149 } else { 03150 #if defined(STANDALONE) || defined(LOW_MEMORY) || defined(STANDALONE_AEL) 03151 strncpy(buf, io.val->u.s, length - 1); 03152 #else /* !STANDALONE && !LOW_MEMORY */ 03153 ast_copy_string(buf, io.val->u.s, length); 03154 #endif /* STANDALONE || LOW_MEMORY */ 03155 return_value = strlen(buf); 03156 free(io.val->u.s); 03157 } 03158 free(io.val); 03159 } 03160 return return_value; 03161 }
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] |
Definition at line 3673 of file pbx_ael.c.
References ael_extension::next_exten.
03674 { 03675 /* travel to the end of the list... */ 03676 struct ael_extension *lptr; 03677 if( !*list ) { 03678 *list = newmem; 03679 return; 03680 } 03681 lptr = *list; 03682 03683 while( lptr->next_exten ) { 03684 lptr = lptr->next_exten; 03685 } 03686 /* lptr should now pointing to the last element in the list; it has a null next_exten pointer */ 03687 lptr->next_exten = newmem; 03688 }
static void check_abstract_reference | ( | pval * | abstract_context | ) | [static] |
Definition at line 2260 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().
02261 { 02262 pval *i,*j; 02263 /* find some context includes that reference this context */ 02264 02265 02266 /* otherwise, print out a warning */ 02267 for (i=current_db; i; i=i->next) { 02268 if (i->type == PV_CONTEXT) { 02269 for (j=i->u2. statements; j; j=j->next) { 02270 if ( j->type == PV_INCLUDES ) { 02271 struct pval *p4; 02272 for (p4=j->u1.list; p4; p4=p4->next) { 02273 /* for each context pointed to, find it, then find a context/label that matches the 02274 target here! */ 02275 if ( !strcmp(p4->u1.str, abstract_context->u1.str) ) 02276 return; /* found a match! */ 02277 } 02278 } 02279 } 02280 } 02281 } 02282 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", 02283 abstract_context->filename, abstract_context->startline, abstract_context->endline, abstract_context->u1.str); 02284 warns++; 02285 }
Definition at line 2061 of file pbx_ael.c.
References app, ast_log(), pval::endline, pval::filename, LOG_WARNING, pval::next, pval::startline, pval::str, and pval::u1.
Referenced by check_pval_item().
02062 { 02063 #ifdef AAL_ARGCHECK 02064 struct argdesc *ad = app->args; 02065 pval *pa; 02066 int z; 02067 02068 for (pa = arglist; pa; pa=pa->next) { 02069 if (!ad) { 02070 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Extra argument %s not in application call to %s !\n", 02071 arglist->filename, arglist->startline, arglist->endline, pa->u1.str, app->name); 02072 warns++; 02073 return 1; 02074 } else { 02075 /* find the first entry in the ad list that will match */ 02076 do { 02077 if ( ad->dtype == ARGD_VARARG ) /* once we hit the VARARG, all bets are off. Discontinue the comparisons */ 02078 break; 02079 02080 z= option_matches( ad, pa, app); 02081 if (!z) { 02082 if ( !arglist ) 02083 arglist=appcall; 02084 02085 if (ad->type == ARGD_REQUIRED) { 02086 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", 02087 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); 02088 warns++; 02089 return 1; 02090 } 02091 } else if (z && ad->dtype == ARGD_OPTIONSET) { 02092 option_matches_j( ad, pa, app); 02093 } 02094 ad = ad->next; 02095 } while (ad && !z); 02096 } 02097 } 02098 /* any app nodes left, that are not optional? */ 02099 for ( ; ad; ad=ad->next) { 02100 if (ad->type == ARGD_REQUIRED && ad->dtype != ARGD_VARARG) { 02101 if ( !arglist ) 02102 arglist=appcall; 02103 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", 02104 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); 02105 warns++; 02106 return 1; 02107 } 02108 } 02109 return 0; 02110 #else 02111 return 0; 02112 #endif 02113 }
static int check_break | ( | pval * | item | ) | [static] |
Definition at line 1054 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.
Referenced by check_pval_item().
01055 { 01056 pval *p = item; 01057 01058 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ { 01059 /* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make 01060 no sense */ 01061 if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN 01062 || p->type == PV_WHILE || p->type == PV_FOR ) { 01063 return 1; 01064 } 01065 p = p->dad; 01066 } 01067 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'break' not in switch, for, or while statement!\n", 01068 item->filename, item->startline, item->endline); 01069 errs++; 01070 01071 return 0; 01072 }
static void check_context_names | ( | void | ) | [static] |
Definition at line 2241 of file pbx_ael.c.
References ast_log(), current_db, pval::endline, pval::filename, LOG_ERROR, pval::next, PV_CONTEXT, PV_MACRO, pval::startline, pval::str, pval::type, and pval::u1.
Referenced by ael2_semantic_check().
02242 { 02243 pval *i,*j; 02244 for (i=current_db; i; i=i->next) { 02245 if (i->type == PV_CONTEXT || i->type == PV_MACRO) { 02246 for (j=i->next; j; j=j->next) { 02247 if ( j->type == PV_CONTEXT || j->type == PV_MACRO ) { 02248 if ( !strcmp(i->u1.str, j->u1.str) ) 02249 { 02250 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: The context name (%s) is also declared in file %s, line %d-%d!\n", 02251 i->filename, i->startline, i->endline, i->u1.str, j->filename, j->startline, j->endline); 02252 errs++; 02253 } 02254 } 02255 } 02256 } 02257 } 02258 }
static int check_continue | ( | pval * | item | ) | [static] |
Definition at line 1074 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.
Referenced by check_pval_item().
01075 { 01076 pval *p = item; 01077 01078 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ { 01079 /* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make 01080 no sense */ 01081 if( p->type == PV_WHILE || p->type == PV_FOR ) { 01082 return 1; 01083 } 01084 p = p->dad; 01085 } 01086 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'continue' not in 'for' or 'while' statement!\n", 01087 item->filename, item->startline, item->endline); 01088 errs++; 01089 01090 return 0; 01091 }
static void check_day | ( | pval * | DAY | ) | [static] |
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.
Referenced by check_pval_item().
00954 { 00955 char *day; 00956 char *c; 00957 /* The following line is coincidence, really! */ 00958 int s, e; 00959 00960 day = ast_strdupa(DAY->u1.str); 00961 00962 /* Check for all days */ 00963 if (ast_strlen_zero(day) || !strcmp(day, "*")) { 00964 return; 00965 } 00966 /* Get start and ending days */ 00967 c = strchr(day, '-'); 00968 if (c) { 00969 *c = '\0'; 00970 c++; 00971 } 00972 /* Find the start */ 00973 if (sscanf(day, "%d", &s) != 1) { 00974 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start day of month (%s) must be a number!\n", 00975 DAY->filename, DAY->startline, DAY->endline, day); 00976 warns++; 00977 } 00978 else if ((s < 1) || (s > 31)) { 00979 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", 00980 DAY->filename, DAY->startline, DAY->endline, day); 00981 warns++; 00982 } 00983 s--; 00984 if (c) { 00985 if (sscanf(c, "%d", &e) != 1) { 00986 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end day of month (%s) must be a number!\n", 00987 DAY->filename, DAY->startline, DAY->endline, c); 00988 warns++; 00989 } 00990 else if ((e < 1) || (e > 31)) { 00991 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", 00992 DAY->filename, DAY->startline, DAY->endline, day); 00993 warns++; 00994 } 00995 e--; 00996 } else 00997 e = s; 00998 }
static void check_dow | ( | pval * | DOW | ) | [static] |
get_dow: Get day of week
Definition at line 914 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.
Referenced by check_pval_item().
00915 { 00916 char *dow; 00917 char *c; 00918 /* The following line is coincidence, really! */ 00919 int s, e; 00920 00921 dow = ast_strdupa(DOW->u1.str); 00922 00923 /* Check for all days */ 00924 if (ast_strlen_zero(dow) || !strcmp(dow, "*")) 00925 return; 00926 /* Get start and ending days */ 00927 c = strchr(dow, '-'); 00928 if (c) { 00929 *c = '\0'; 00930 c++; 00931 } else 00932 c = NULL; 00933 /* Find the start */ 00934 s = 0; 00935 while ((s < 7) && strcasecmp(dow, days[s])) s++; 00936 if (s >= 7) { 00937 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", 00938 DOW->filename, DOW->startline, DOW->endline, dow); 00939 warns++; 00940 } 00941 if (c) { 00942 e = 0; 00943 while ((e < 7) && strcasecmp(c, days[e])) e++; 00944 if (e >= 7) { 00945 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", 00946 DOW->filename, DOW->startline, DOW->endline, c); 00947 warns++; 00948 } 00949 } else 00950 e = s; 00951 }
static void check_expr2_input | ( | pval * | expr, | |
char * | str | |||
) | [static] |
Definition at line 818 of file pbx_ael.c.
References ast_log(), pval::endline, pval::filename, LOG_WARNING, and pval::startline.
Referenced by check_pval_item().
00819 { 00820 int spaces = strspn(str,"\t \n"); 00821 if ( !strncmp(str+spaces,"$[",2) ) { 00822 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The expression '%s' is redundantly wrapped in '$[ ]'. \n", 00823 expr->filename, expr->startline, expr->endline, str); 00824 warns++; 00825 } 00826 }
static void check_goto | ( | pval * | item | ) | [static] |
Definition at line 1189 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(), 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 check_pval_item(), and find_pval_goto_item().
01190 { 01191 /* check for the target of the goto-- does it exist? */ 01192 if ( !(item->u1.list)->next && !(item->u1.list)->u1.str ) { 01193 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: empty label reference found!\n", 01194 item->filename, item->startline, item->endline); 01195 errs++; 01196 } 01197 01198 /* just one item-- the label should be in the current extension */ 01199 01200 if (item->u1.list && !item->u1.list->next && !strstr((item->u1.list)->u1.str,"${")) { 01201 struct pval *z = get_extension_or_contxt(item); 01202 struct pval *x = 0; 01203 if (z) 01204 x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), z); /* if in macro, use current context instead */ 01205 /* printf("Called find_label_in_current_extension with arg %s; current_extension is %x: %d\n", 01206 (char*)((item->u1.list)->u1.str), current_extension?current_extension:current_context, current_extension?current_extension->type:current_context->type); */ 01207 if (!x) { 01208 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s exists in the current extension!\n", 01209 item->filename, item->startline, item->endline, item->u1.list->u1.str); 01210 errs++; 01211 } 01212 else 01213 return; 01214 } 01215 01216 /* TWO items */ 01217 if (item->u1.list->next && !item->u1.list->next->next) { 01218 /* two items */ 01219 /* printf("Calling find_label_in_current_context with args %s, %s\n", 01220 (char*)((item->u1.list)->u1.str), (char *)item->u1.list->next->u1.str); */ 01221 if (!strstr((item->u1.list)->u1.str,"${") 01222 && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ { 01223 struct pval *z = get_contxt(item); 01224 struct pval *x = 0; 01225 01226 if (z) 01227 x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, z); 01228 01229 if (!x) { 01230 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", 01231 item->filename, item->startline, item->endline, item->u1.list->u1.str, item->u1.list->next->u1.str ); 01232 errs++; 01233 } 01234 else 01235 return; 01236 } 01237 } 01238 01239 /* All 3 items! */ 01240 if (item->u1.list->next && item->u1.list->next->next) { 01241 /* all three */ 01242 pval *first = item->u1.list; 01243 pval *second = item->u1.list->next; 01244 pval *third = item->u1.list->next->next; 01245 01246 /* printf("Calling find_label_in_current_db with args %s, %s, %s\n", 01247 (char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); */ 01248 if (!strstr((item->u1.list)->u1.str,"${") 01249 && !strstr(item->u1.list->next->u1.str,"${") 01250 && !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ { 01251 struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); 01252 if (!x) { 01253 struct pval *p3; 01254 struct pval *found = 0; 01255 struct pval *that_context = find_context(item->u1.list->u1.str); 01256 01257 /* the target of the goto could be in an included context!! Fancy that!! */ 01258 /* look for includes in the current context */ 01259 if (that_context) { 01260 for (p3=that_context->u2.statements; p3; p3=p3->next) { 01261 if (p3->type == PV_INCLUDES) { 01262 struct pval *p4; 01263 for (p4=p3->u1.list; p4; p4=p4->next) { 01264 /* for each context pointed to, find it, then find a context/label that matches the 01265 target here! */ 01266 char *incl_context = p4->u1.str; 01267 /* find a matching context name */ 01268 struct pval *that_other_context = find_context(incl_context); 01269 if (that_other_context) { 01270 struct pval *x3; 01271 x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context); 01272 if (x3) { 01273 found = x3; 01274 break; 01275 } 01276 } 01277 } 01278 } 01279 } 01280 if (!found) { 01281 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s|%s exists in the context %s or its inclusions!\n", 01282 item->filename, item->startline, item->endline, item->u1.list->next->u1.str, item->u1.list->next->next->u1.str, item->u1.list->u1.str ); 01283 errs++; 01284 } 01285 } else { 01286 /* here is where code would go to check for target existence in extensions.conf files */ 01287 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: goto: no context %s could be found that matches the goto target!\n", 01288 item->filename, item->startline, item->endline, item->u1.list->u1.str); 01289 warns++; /* this is just a warning, because this context could be in extensions.conf or somewhere */ 01290 } 01291 } 01292 } 01293 } 01294 }
static void check_includes | ( | pval * | includes | ) | [static] |
Definition at line 828 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.
Referenced by check_pval_item().
00829 { 00830 struct pval *p4; 00831 for (p4=includes->u1.list; p4; p4=p4->next) { 00832 /* for each context pointed to, find it, then find a context/label that matches the 00833 target here! */ 00834 char *incl_context = p4->u1.str; 00835 /* find a matching context name */ 00836 struct pval *that_other_context = find_context(incl_context); 00837 if (!that_other_context && strcmp(incl_context, "parkedcalls") != 0) { 00838 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The included context '%s' cannot be found.\n", 00839 includes->filename, includes->startline, includes->endline, incl_context); 00840 warns++; 00841 } 00842 } 00843 }
static void check_label | ( | pval * | item | ) | [static] |
Definition at line 1096 of file pbx_ael.c.
References ast_log(), current_context, current_extension, pval::endline, pval::filename, find_first_label_in_current_context(), LOG_ERROR, pval::startline, pval::str, and pval::u1.
Referenced by check_pval_item().
01097 { 01098 /* basically, ensure that a label is not repeated in a context. Period. 01099 The method: well, for each label, find the first label in the context 01100 with the same name. If it's not the current label, then throw an error. */ 01101 struct pval *curr; 01102 struct pval *x; 01103 01104 /* printf("==== check_label: ====\n"); */ 01105 if( !current_extension ) 01106 curr = current_context; 01107 else 01108 curr = current_extension; 01109 01110 x = find_first_label_in_current_context((char *)item->u1.str, curr); 01111 /* 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); */ 01112 if( x && x != item ) 01113 { 01114 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: Duplicate label %s! Previously defined at file %s, line %d.\n", 01115 item->filename, item->startline, item->endline, item->u1.str, x->filename, x->startline); 01116 errs++; 01117 } 01118 /* printf("<<<<< check_label: ====\n"); */ 01119 }
static void check_month | ( | pval * | MON | ) | [static] |
Definition at line 1016 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.
Referenced by check_pval_item().
01017 { 01018 char *mon; 01019 char *c; 01020 /* The following line is coincidence, really! */ 01021 int s, e; 01022 01023 mon = ast_strdupa(MON->u1.str); 01024 01025 /* Check for all days */ 01026 if (ast_strlen_zero(mon) || !strcmp(mon, "*")) 01027 return ; 01028 /* Get start and ending days */ 01029 c = strchr(mon, '-'); 01030 if (c) { 01031 *c = '\0'; 01032 c++; 01033 } 01034 /* Find the start */ 01035 s = 0; 01036 while ((s < 12) && strcasecmp(mon, months[s])) s++; 01037 if (s >= 12) { 01038 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n", 01039 MON->filename, MON->startline, MON->endline, mon); 01040 warns++; 01041 } 01042 if (c) { 01043 e = 0; 01044 while ((e < 12) && strcasecmp(mon, months[e])) e++; 01045 if (e >= 12) { 01046 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n", 01047 MON->filename, MON->startline, MON->endline, c); 01048 warns++; 01049 } 01050 } else 01051 e = s; 01052 }
Definition at line 2707 of file pbx_ael.c.
References check_pval_item(), and pval::next.
Referenced by ael2_semantic_check(), and check_pval_item().
02708 { 02709 pval *i; 02710 02711 /* checks to do: 02712 1. Do goto's point to actual labels? 02713 2. Do macro calls reference a macro? 02714 3. Does the number of macro args match the definition? 02715 4. Is a macro call missing its & at the front? 02716 5. Application calls-- we could check syntax for existing applications, 02717 but I need some some sort of universal description bnf for a general 02718 sort of method for checking arguments, in number, maybe even type, at least. 02719 Don't want to hand code checks for hundreds of applications. 02720 */ 02721 02722 for (i=item; i; i=i->next) { 02723 check_pval_item(i,apps,in_globals); 02724 } 02725 }
Definition at line 2288 of file pbx_ael.c.
References pval::abstract, app, pval::arglist, ast_expr(), ast_expr_clear_extra_error_info(), ast_expr_register_extra_error_info(), ast_log(), check_abstract_reference(), check_app_args(), check_break(), check_continue(), check_day(), check_dow(), check_expr2_input(), check_goto(), check_includes(), check_label(), check_month(), check_pval(), check_switch_expr(), check_timerange(), current_context, current_extension, pval::else_statements, pval::endcol, pval::endline, pval::filename, find_context(), find_macro(), find_pval_gotos(), pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, pval::list, LOG_ERROR, LOG_WARNING, pval::macro_statements, pval::next, 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::startcol, pval::startline, pval::statements, pval::str, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.
Referenced by check_pval().
02289 { 02290 pval *lp; 02291 #ifdef AAL_ARGCHECK 02292 struct argapp *app, *found; 02293 #endif 02294 struct pval *macro_def; 02295 struct pval *app_def; 02296 02297 char errmsg[4096]; 02298 char *strp; 02299 02300 switch (item->type) { 02301 case PV_WORD: 02302 /* fields: item->u1.str == string associated with this (word). 02303 item->u2.arglist == pval list of 4 PV_WORD elements for time values (only in PV_INCLUDES) */ 02304 break; 02305 02306 case PV_MACRO: 02307 /* fields: item->u1.str == name of macro 02308 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 02309 item->u2.arglist->u1.str == argument 02310 item->u2.arglist->next == next arg 02311 02312 item->u3.macro_statements == pval list of statements in macro body. 02313 */ 02314 in_abstract_context = 0; 02315 current_context = item; 02316 current_extension = 0; 02317 for (lp=item->u2.arglist; lp; lp=lp->next) { 02318 02319 } 02320 check_pval(item->u3.macro_statements, apps,in_globals); 02321 break; 02322 02323 case PV_CONTEXT: 02324 /* fields: item->u1.str == name of context 02325 item->u2.statements == pval list of statements in context body 02326 item->u3.abstract == int 1 if an abstract keyword were present 02327 */ 02328 current_context = item; 02329 current_extension = 0; 02330 if ( item->u3.abstract ) { 02331 in_abstract_context = 1; 02332 check_abstract_reference(item); 02333 } else 02334 in_abstract_context = 0; 02335 check_pval(item->u2.statements, apps,in_globals); 02336 break; 02337 02338 case PV_MACRO_CALL: 02339 /* fields: item->u1.str == name of macro to call 02340 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 02341 item->u2.arglist->u1.str == argument 02342 item->u2.arglist->next == next arg 02343 */ 02344 macro_def = find_macro(item->u1.str); 02345 if (!macro_def) { 02346 /* here is a good place to check to see if the definition is in extensions.conf! */ 02347 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to non-existent %s ! Hopefully it is present in extensions.conf! \n", 02348 item->filename, item->startline, item->endline, item->u1.str); 02349 warns++; 02350 } else if (macro_def->type != PV_MACRO) { 02351 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: macro call to %s references a context, not a macro!\n", 02352 item->filename, item->startline, item->endline, item->u1.str); 02353 errs++; 02354 } else { 02355 /* macro_def is a MACRO, so do the args match in number? */ 02356 int hereargs = 0; 02357 int thereargs = 0; 02358 02359 for (lp=item->u2.arglist; lp; lp=lp->next) { 02360 hereargs++; 02361 } 02362 for (lp=macro_def->u2.arglist; lp; lp=lp->next) { 02363 thereargs++; 02364 } 02365 if (hereargs != thereargs ) { 02366 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", 02367 item->filename, item->startline, item->endline, item->u1.str, hereargs, thereargs); 02368 errs++; 02369 } 02370 } 02371 break; 02372 02373 case PV_APPLICATION_CALL: 02374 /* fields: item->u1.str == name of application to call 02375 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 02376 item->u2.arglist->u1.str == argument 02377 item->u2.arglist->next == next arg 02378 */ 02379 /* Need to check to see if the application is available! */ 02380 app_def = find_context(item->u1.str); 02381 if (app_def && app_def->type == PV_MACRO) { 02382 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: application call to %s references an existing macro, but had no & preceding it!\n", 02383 item->filename, item->startline, item->endline, item->u1.str); 02384 errs++; 02385 } 02386 if (strcasecmp(item->u1.str,"GotoIf") == 0 02387 || strcasecmp(item->u1.str,"GotoIfTime") == 0 02388 || strcasecmp(item->u1.str,"while") == 0 02389 || strcasecmp(item->u1.str,"endwhile") == 0 02390 || strcasecmp(item->u1.str,"random") == 0 02391 || strcasecmp(item->u1.str,"execIf") == 0 ) { 02392 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: application call to %s needs to be re-written using AEL if, while, goto, etc. keywords instead!\n", 02393 item->filename, item->startline, item->endline, item->u1.str); 02394 warns++; 02395 } 02396 #ifdef AAL_ARGCHECK 02397 found = 0; 02398 for (app=apps; app; app=app->next) { 02399 if (strcasecmp(app->name, item->u1.str) == 0) { 02400 found =app; 02401 break; 02402 } 02403 } 02404 if (!found) { 02405 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: application call to %s not listed in applist database!\n", 02406 item->filename, item->startline, item->endline, item->u1.str); 02407 warns++; 02408 } else 02409 check_app_args(item, item->u2.arglist, app); 02410 #endif 02411 break; 02412 02413 case PV_CASE: 02414 /* fields: item->u1.str == value of case 02415 item->u2.statements == pval list of statements under the case 02416 */ 02417 /* Make sure sequence of statements under case is terminated with goto, return, or break */ 02418 /* find the last statement */ 02419 check_pval(item->u2.statements, apps,in_globals); 02420 break; 02421 02422 case PV_PATTERN: 02423 /* fields: item->u1.str == value of case 02424 item->u2.statements == pval list of statements under the case 02425 */ 02426 /* Make sure sequence of statements under case is terminated with goto, return, or break */ 02427 /* find the last statement */ 02428 02429 check_pval(item->u2.statements, apps,in_globals); 02430 break; 02431 02432 case PV_DEFAULT: 02433 /* fields: 02434 item->u2.statements == pval list of statements under the case 02435 */ 02436 02437 check_pval(item->u2.statements, apps,in_globals); 02438 break; 02439 02440 case PV_CATCH: 02441 /* fields: item->u1.str == name of extension to catch 02442 item->u2.statements == pval list of statements in context body 02443 */ 02444 check_pval(item->u2.statements, apps,in_globals); 02445 break; 02446 02447 case PV_SWITCHES: 02448 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02449 */ 02450 check_pval(item->u1.list, apps,in_globals); 02451 break; 02452 02453 case PV_ESWITCHES: 02454 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02455 */ 02456 check_pval(item->u1.list, apps,in_globals); 02457 break; 02458 02459 case PV_INCLUDES: 02460 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02461 */ 02462 check_pval(item->u1.list, apps,in_globals); 02463 check_includes(item); 02464 for (lp=item->u1.list; lp; lp=lp->next){ 02465 char *incl_context = lp->u1.str; 02466 struct pval *that_context = find_context(incl_context); 02467 02468 if ( lp->u2.arglist ) { 02469 check_timerange(lp->u2.arglist); 02470 check_dow(lp->u2.arglist->next); 02471 check_day(lp->u2.arglist->next->next); 02472 check_month(lp->u2.arglist->next->next->next); 02473 } 02474 02475 if (that_context) { 02476 find_pval_gotos(that_context->u2.statements,0); 02477 02478 } 02479 } 02480 break; 02481 02482 case PV_STATEMENTBLOCK: 02483 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 02484 */ 02485 check_pval(item->u1.list, apps,in_globals); 02486 break; 02487 02488 case PV_VARDEC: 02489 /* fields: item->u1.str == variable name 02490 item->u2.val == variable value to assign 02491 */ 02492 /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */ 02493 if( !in_globals ) { /* don't check stuff inside the globals context; no wrapping in $[ ] there... */ 02494 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); 02495 ast_expr_register_extra_error_info(errmsg); 02496 ast_expr(item->u2.val, expr_output, sizeof(expr_output)); 02497 ast_expr_clear_extra_error_info(); 02498 if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) { 02499 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02500 item->filename, item->startline, item->endline, item->u2.val); 02501 warns++; 02502 } 02503 check_expr2_input(item,item->u2.val); 02504 } 02505 break; 02506 02507 case PV_GOTO: 02508 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 02509 item->u1.list->u1.str == where the data on a PV_WORD will always be. 02510 */ 02511 /* don't check goto's in abstract contexts */ 02512 if ( in_abstract_context ) 02513 break; 02514 02515 check_goto(item); 02516 break; 02517 02518 case PV_LABEL: 02519 /* fields: item->u1.str == label name 02520 */ 02521 if ( strspn(item->u1.str, "0123456789") == strlen(item->u1.str) ) { 02522 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: label '%s' is numeric, this is bad practice!\n", 02523 item->filename, item->startline, item->endline, item->u1.str); 02524 warns++; 02525 } 02526 02527 check_label(item); 02528 break; 02529 02530 case PV_FOR: 02531 /* fields: item->u1.for_init == a string containing the initalizer 02532 item->u2.for_test == a string containing the loop test 02533 item->u3.for_inc == a string containing the loop increment 02534 02535 item->u4.for_statements == a pval list of statements in the for () 02536 */ 02537 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); 02538 ast_expr_register_extra_error_info(errmsg); 02539 02540 strp = strchr(item->u1.for_init, '='); 02541 if (strp) { 02542 ast_expr(strp+1, expr_output, sizeof(expr_output)); 02543 } 02544 ast_expr(item->u2.for_test, expr_output, sizeof(expr_output)); 02545 strp = strchr(item->u3.for_inc, '='); 02546 if (strp) { 02547 ast_expr(strp+1, expr_output, sizeof(expr_output)); 02548 } 02549 if ( strpbrk(item->u2.for_test,"~!-+<>=*/&^") && !strstr(item->u2.for_test,"${") ) { 02550 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02551 item->filename, item->startline, item->endline, item->u2.for_test); 02552 warns++; 02553 } 02554 if ( strpbrk(item->u3.for_inc,"~!-+<>=*/&^") && !strstr(item->u3.for_inc,"${") ) { 02555 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02556 item->filename, item->startline, item->endline, item->u3.for_inc); 02557 warns++; 02558 } 02559 check_expr2_input(item,item->u2.for_test); 02560 check_expr2_input(item,item->u3.for_inc); 02561 02562 ast_expr_clear_extra_error_info(); 02563 check_pval(item->u4.for_statements, apps,in_globals); 02564 break; 02565 02566 case PV_WHILE: 02567 /* fields: item->u1.str == the while conditional, as supplied by user 02568 02569 item->u2.statements == a pval list of statements in the while () 02570 */ 02571 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, while expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str); 02572 ast_expr_register_extra_error_info(errmsg); 02573 ast_expr(item->u1.str, expr_output, sizeof(expr_output)); 02574 ast_expr_clear_extra_error_info(); 02575 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02576 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02577 item->filename, item->startline, item->endline, item->u1.str); 02578 warns++; 02579 } 02580 check_expr2_input(item,item->u1.str); 02581 check_pval(item->u2.statements, apps,in_globals); 02582 break; 02583 02584 case PV_BREAK: 02585 /* fields: none 02586 */ 02587 check_break(item); 02588 break; 02589 02590 case PV_RETURN: 02591 /* fields: none 02592 */ 02593 break; 02594 02595 case PV_CONTINUE: 02596 /* fields: none 02597 */ 02598 check_continue(item); 02599 break; 02600 02601 case PV_RANDOM: 02602 /* fields: item->u1.str == the random number expression, as supplied by user 02603 02604 item->u2.statements == a pval list of statements in the if () 02605 item->u3.else_statements == a pval list of statements in the else 02606 (could be zero) 02607 */ 02608 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, random expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str); 02609 ast_expr_register_extra_error_info(errmsg); 02610 ast_expr(item->u1.str, expr_output, sizeof(expr_output)); 02611 ast_expr_clear_extra_error_info(); 02612 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02613 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: random expression '%s' has operators, but no variables. Interesting...\n", 02614 item->filename, item->startline, item->endline, item->u1.str); 02615 warns++; 02616 } 02617 check_expr2_input(item,item->u1.str); 02618 check_pval(item->u2.statements, apps,in_globals); 02619 if (item->u3.else_statements) { 02620 check_pval(item->u3.else_statements, apps,in_globals); 02621 } 02622 break; 02623 02624 case PV_IFTIME: 02625 /* fields: item->u1.list == the if time values, 4 of them, each in PV_WORD, linked list 02626 02627 item->u2.statements == a pval list of statements in the if () 02628 item->u3.else_statements == a pval list of statements in the else 02629 (could be zero) 02630 */ 02631 if ( item->u2.arglist ) { 02632 check_timerange(item->u1.list); 02633 check_dow(item->u1.list->next); 02634 check_day(item->u1.list->next->next); 02635 check_month(item->u1.list->next->next->next); 02636 } 02637 02638 check_pval(item->u2.statements, apps,in_globals); 02639 if (item->u3.else_statements) { 02640 check_pval(item->u3.else_statements, apps,in_globals); 02641 } 02642 break; 02643 02644 case PV_IF: 02645 /* fields: item->u1.str == the if conditional, as supplied by user 02646 02647 item->u2.statements == a pval list of statements in the if () 02648 item->u3.else_statements == a pval list of statements in the else 02649 (could be zero) 02650 */ 02651 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, if expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str); 02652 ast_expr_register_extra_error_info(errmsg); 02653 ast_expr(item->u1.str, expr_output, sizeof(expr_output)); 02654 ast_expr_clear_extra_error_info(); 02655 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02656 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression '%s' has operators, but no variables. Interesting...\n", 02657 item->filename, item->startline, item->endline, item->u1.str); 02658 warns++; 02659 } 02660 check_expr2_input(item,item->u1.str); 02661 check_pval(item->u2.statements, apps,in_globals); 02662 if (item->u3.else_statements) { 02663 check_pval(item->u3.else_statements, apps,in_globals); 02664 } 02665 break; 02666 02667 case PV_SWITCH: 02668 /* fields: item->u1.str == the switch expression 02669 02670 item->u2.statements == a pval list of statements in the switch, 02671 (will be case statements, most likely!) 02672 */ 02673 /* we can check the switch expression, see if it matches any of the app variables... 02674 if it does, then, are all the possible cases accounted for? */ 02675 check_switch_expr(item, apps); 02676 check_pval(item->u2.statements, apps,in_globals); 02677 break; 02678 02679 case PV_EXTENSION: 02680 /* fields: item->u1.str == the extension name, label, whatever it's called 02681 02682 item->u2.statements == a pval list of statements in the extension 02683 item->u3.hints == a char * hint argument 02684 item->u4.regexten == an int boolean. non-zero says that regexten was specified 02685 */ 02686 current_extension = item ; 02687 02688 check_pval(item->u2.statements, apps,in_globals); 02689 break; 02690 02691 case PV_IGNOREPAT: 02692 /* fields: item->u1.str == the ignorepat data 02693 */ 02694 break; 02695 02696 case PV_GLOBALS: 02697 /* fields: item->u1.statements == pval list of statements, usually vardecs 02698 */ 02699 in_abstract_context = 0; 02700 check_pval(item->u1.statements, apps, 1); 02701 break; 02702 default: 02703 break; 02704 } 02705 }
Definition at line 2115 of file pbx_ael.c.
References ast_strdupa, argapp::next, pval::str, t, and pval::u1.
Referenced by check_pval_item().
02116 { 02117 #ifdef AAL_ARGCHECK 02118 /* get and clean the variable name */ 02119 char *buff1, *p; 02120 struct argapp *a,*a2; 02121 struct appsetvar *v,*v2; 02122 struct argchoice *c; 02123 pval *t; 02124 02125 p = item->u1.str; 02126 while (p && *p && (*p == ' ' || *p == '\t' || *p == '$' || *p == '{' ) ) 02127 p++; 02128 02129 buff1 = ast_strdupa(p); 02130 02131 while (strlen(buff1) > 0 && ( buff1[strlen(buff1)-1] == '}' || buff1[strlen(buff1)-1] == ' ' || buff1[strlen(buff1)-1] == '\t')) 02132 buff1[strlen(buff1)-1] = 0; 02133 /* buff1 now contains the variable name */ 02134 v = 0; 02135 for (a=apps; a; a=a->next) { 02136 for (v=a->setvars;v;v=v->next) { 02137 if (strcmp(v->name,buff1) == 0) { 02138 break; 02139 } 02140 } 02141 if ( v ) 02142 break; 02143 } 02144 if (v && v->vals) { 02145 /* we have a match, to a variable that has a set of determined values */ 02146 int def= 0; 02147 int pat = 0; 02148 int f1 = 0; 02149 02150 /* first of all, does this switch have a default case ? */ 02151 for (t=item->u2.statements; t; t=t->next) { 02152 if (t->type == PV_DEFAULT) { 02153 def =1; 02154 break; 02155 } 02156 if (t->type == PV_PATTERN) { 02157 pat++; 02158 } 02159 } 02160 if (def || pat) /* nothing to check. All cases accounted for! */ 02161 return; 02162 for (c=v->vals; c; c=c->next) { 02163 f1 = 0; 02164 for (t=item->u2.statements; t; t=t->next) { 02165 if (t->type == PV_CASE || t->type == PV_PATTERN) { 02166 if (!strcmp(t->u1.str,c->name)) { 02167 f1 = 1; 02168 break; 02169 } 02170 } 02171 } 02172 if (!f1) { 02173 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: switch with expression(%s) does not handle the case of %s !\n", 02174 item->filename, item->startline, item->endline, item->u1.str, c->name); 02175 warns++; 02176 } 02177 } 02178 /* next, is there an app call in the current exten, that would set this var? */ 02179 f1 = 0; 02180 t = current_extension->u2.statements; 02181 if ( t && t->type == PV_STATEMENTBLOCK ) 02182 t = t->u1.statements; 02183 for (; t && t != item; t=t->next) { 02184 if (t->type == PV_APPLICATION_CALL) { 02185 /* find the application that matches the u1.str */ 02186 for (a2=apps; a2; a2=a2->next) { 02187 if (strcasecmp(a2->name, t->u1.str)==0) { 02188 for (v2=a2->setvars; v2; v2=v2->next) { 02189 if (strcmp(v2->name, buff1) == 0) { 02190 /* found an app that sets the var */ 02191 f1 = 1; 02192 break; 02193 } 02194 } 02195 } 02196 if (f1) 02197 break; 02198 } 02199 } 02200 if (f1) 02201 break; 02202 } 02203 02204 /* see if it sets the var */ 02205 if (!f1) { 02206 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", 02207 item->filename, item->startline, item->endline, item->u1.str); 02208 warns++; 02209 } 02210 } 02211 #else 02212 pval *t,*tl=0,*p2; 02213 int def= 0; 02214 02215 /* first of all, does this switch have a default case ? */ 02216 for (t=item->u2.statements; t; t=t->next) { 02217 if (t->type == PV_DEFAULT) { 02218 def =1; 02219 break; 02220 } 02221 tl = t; 02222 } 02223 if (def) /* nothing to check. All cases accounted for! */ 02224 return; 02225 /* if no default, warn and insert a default case at the end */ 02226 p2 = tl->next = calloc(1, sizeof(struct pval)); 02227 02228 p2->type = PV_DEFAULT; 02229 p2->startline = tl->startline; 02230 p2->endline = tl->endline; 02231 p2->startcol = tl->startcol; 02232 p2->endcol = tl->endcol; 02233 p2->filename = strdup(tl->filename); 02234 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: A default case was automatically added to the switch.\n", 02235 p2->filename, p2->startline, p2->endline); 02236 warns++; 02237 02238 #endif 02239 }
static void check_timerange | ( | pval * | p | ) | [static] |
Definition at line 846 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.
Referenced by check_pval_item().
00847 { 00848 char *times; 00849 char *e; 00850 int s1, s2; 00851 int e1, e2; 00852 00853 times = ast_strdupa(p->u1.str); 00854 00855 /* Star is all times */ 00856 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 00857 return; 00858 } 00859 /* Otherwise expect a range */ 00860 e = strchr(times, '-'); 00861 if (!e) { 00862 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", 00863 p->filename, p->startline, p->endline, times); 00864 warns++; 00865 return; 00866 } 00867 *e = '\0'; 00868 e++; 00869 while (*e && !isdigit(*e)) 00870 e++; 00871 if (!*e) { 00872 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The time range format (%s) is missing the end time!\n", 00873 p->filename, p->startline, p->endline, p->u1.str); 00874 warns++; 00875 } 00876 if (sscanf(times, "%d:%d", &s1, &s2) != 2) { 00877 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) isn't quite right!\n", 00878 p->filename, p->startline, p->endline, times); 00879 warns++; 00880 } 00881 if (sscanf(e, "%d:%d", &e1, &e2) != 2) { 00882 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) isn't quite right!\n", 00883 p->filename, p->startline, p->endline, times); 00884 warns++; 00885 } 00886 00887 s1 = s1 * 30 + s2/2; 00888 if ((s1 < 0) || (s1 >= 24*30)) { 00889 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) is out of range!\n", 00890 p->filename, p->startline, p->endline, times); 00891 warns++; 00892 } 00893 e1 = e1 * 30 + e2/2; 00894 if ((e1 < 0) || (e1 >= 24*30)) { 00895 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) is out of range!\n", 00896 p->filename, p->startline, p->endline, e); 00897 warns++; 00898 } 00899 return; 00900 }
void destroy_extensions | ( | struct ael_extension * | exten | ) |
Definition at line 2789 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::loop_break, ael_extension::loop_continue, ael_extension::name, ael_priority::next, ael_extension::next_exten, ael_priority::origin, ael_extension::plist, and ael_extension::plist_last.
02790 { 02791 struct ael_extension *ne, *nen; 02792 for (ne=exten; ne; ne=nen) { 02793 struct ael_priority *pe, *pen; 02794 02795 if (ne->name) 02796 free(ne->name); 02797 02798 /* cidmatch fields are allocated with name, and freed when 02799 the name field is freed. Don't do a free for this field, 02800 unless you LIKE to see a crash! */ 02801 02802 if (ne->hints) 02803 free(ne->hints); 02804 02805 for (pe=ne->plist; pe; pe=pen) { 02806 pen = pe->next; 02807 if (pe->app) 02808 free(pe->app); 02809 pe->app = 0; 02810 if (pe->appargs) 02811 free(pe->appargs); 02812 pe->appargs = 0; 02813 pe->origin = 0; 02814 pe->goto_true = 0; 02815 pe->goto_false = 0; 02816 free(pe); 02817 } 02818 nen = ne->next_exten; 02819 ne->next_exten = 0; 02820 ne->plist =0; 02821 ne->plist_last = 0; 02822 ne->next_exten = 0; 02823 ne->loop_break = 0; 02824 ne->loop_continue = 0; 02825 free(ne); 02826 } 02827 }
void destroy_pval | ( | pval * | item | ) |
void destroy_pval_item | ( | pval * | item | ) |
Definition at line 4116 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().
04117 { 04118 if (item == NULL) { 04119 ast_log(LOG_WARNING, "null item\n"); 04120 return; 04121 } 04122 04123 if (item->filename) 04124 free(item->filename); 04125 04126 switch (item->type) { 04127 case PV_WORD: 04128 /* fields: item->u1.str == string associated with this (word). */ 04129 if (item->u1.str ) 04130 free(item->u1.str); 04131 if ( item->u2.arglist ) 04132 destroy_pval(item->u2.arglist); 04133 break; 04134 04135 case PV_MACRO: 04136 /* fields: item->u1.str == name of macro 04137 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 04138 item->u2.arglist->u1.str == argument 04139 item->u2.arglist->next == next arg 04140 04141 item->u3.macro_statements == pval list of statements in macro body. 04142 */ 04143 destroy_pval(item->u2.arglist); 04144 if (item->u1.str ) 04145 free(item->u1.str); 04146 destroy_pval(item->u3.macro_statements); 04147 break; 04148 04149 case PV_CONTEXT: 04150 /* fields: item->u1.str == name of context 04151 item->u2.statements == pval list of statements in context body 04152 item->u3.abstract == int 1 if an abstract keyword were present 04153 */ 04154 if (item->u1.str) 04155 free(item->u1.str); 04156 destroy_pval(item->u2.statements); 04157 break; 04158 04159 case PV_MACRO_CALL: 04160 /* fields: item->u1.str == name of macro to call 04161 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 04162 item->u2.arglist->u1.str == argument 04163 item->u2.arglist->next == next arg 04164 */ 04165 if (item->u1.str) 04166 free(item->u1.str); 04167 destroy_pval(item->u2.arglist); 04168 break; 04169 04170 case PV_APPLICATION_CALL: 04171 /* fields: item->u1.str == name of application to call 04172 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 04173 item->u2.arglist->u1.str == argument 04174 item->u2.arglist->next == next arg 04175 */ 04176 if (item->u1.str) 04177 free(item->u1.str); 04178 destroy_pval(item->u2.arglist); 04179 break; 04180 04181 case PV_CASE: 04182 /* fields: item->u1.str == value of case 04183 item->u2.statements == pval list of statements under the case 04184 */ 04185 if (item->u1.str) 04186 free(item->u1.str); 04187 destroy_pval(item->u2.statements); 04188 break; 04189 04190 case PV_PATTERN: 04191 /* fields: item->u1.str == value of case 04192 item->u2.statements == pval list of statements under the case 04193 */ 04194 if (item->u1.str) 04195 free(item->u1.str); 04196 destroy_pval(item->u2.statements); 04197 break; 04198 04199 case PV_DEFAULT: 04200 /* fields: 04201 item->u2.statements == pval list of statements under the case 04202 */ 04203 destroy_pval(item->u2.statements); 04204 break; 04205 04206 case PV_CATCH: 04207 /* fields: item->u1.str == name of extension to catch 04208 item->u2.statements == pval list of statements in context body 04209 */ 04210 if (item->u1.str) 04211 free(item->u1.str); 04212 destroy_pval(item->u2.statements); 04213 break; 04214 04215 case PV_SWITCHES: 04216 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04217 */ 04218 destroy_pval(item->u1.list); 04219 break; 04220 04221 case PV_ESWITCHES: 04222 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04223 */ 04224 destroy_pval(item->u1.list); 04225 break; 04226 04227 case PV_INCLUDES: 04228 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04229 item->u2.arglist == pval list of 4 PV_WORD elements for time values 04230 */ 04231 destroy_pval(item->u1.list); 04232 break; 04233 04234 case PV_STATEMENTBLOCK: 04235 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 04236 */ 04237 destroy_pval(item->u1.list); 04238 break; 04239 04240 case PV_VARDEC: 04241 /* fields: item->u1.str == variable name 04242 item->u2.val == variable value to assign 04243 */ 04244 if (item->u1.str) 04245 free(item->u1.str); 04246 if (item->u2.val) 04247 free(item->u2.val); 04248 break; 04249 04250 case PV_GOTO: 04251 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 04252 item->u1.list->u1.str == where the data on a PV_WORD will always be. 04253 */ 04254 04255 destroy_pval(item->u1.list); 04256 break; 04257 04258 case PV_LABEL: 04259 /* fields: item->u1.str == label name 04260 */ 04261 if (item->u1.str) 04262 free(item->u1.str); 04263 break; 04264 04265 case PV_FOR: 04266 /* fields: item->u1.for_init == a string containing the initalizer 04267 item->u2.for_test == a string containing the loop test 04268 item->u3.for_inc == a string containing the loop increment 04269 04270 item->u4.for_statements == a pval list of statements in the for () 04271 */ 04272 if (item->u1.for_init) 04273 free(item->u1.for_init); 04274 if (item->u2.for_test) 04275 free(item->u2.for_test); 04276 if (item->u3.for_inc) 04277 free(item->u3.for_inc); 04278 destroy_pval(item->u4.for_statements); 04279 break; 04280 04281 case PV_WHILE: 04282 /* fields: item->u1.str == the while conditional, as supplied by user 04283 04284 item->u2.statements == a pval list of statements in the while () 04285 */ 04286 if (item->u1.str) 04287 free(item->u1.str); 04288 destroy_pval(item->u2.statements); 04289 break; 04290 04291 case PV_BREAK: 04292 /* fields: none 04293 */ 04294 break; 04295 04296 case PV_RETURN: 04297 /* fields: none 04298 */ 04299 break; 04300 04301 case PV_CONTINUE: 04302 /* fields: none 04303 */ 04304 break; 04305 04306 case PV_IFTIME: 04307 /* fields: item->u1.list == the 4 time values, in PV_WORD structs, linked list 04308 04309 item->u2.statements == a pval list of statements in the if () 04310 item->u3.else_statements == a pval list of statements in the else 04311 (could be zero) 04312 */ 04313 destroy_pval(item->u1.list); 04314 destroy_pval(item->u2.statements); 04315 if (item->u3.else_statements) { 04316 destroy_pval(item->u3.else_statements); 04317 } 04318 break; 04319 04320 case PV_RANDOM: 04321 /* fields: item->u1.str == the random percentage, as supplied by user 04322 04323 item->u2.statements == a pval list of statements in the true part () 04324 item->u3.else_statements == a pval list of statements in the else 04325 (could be zero) 04326 fall thru to If */ 04327 case PV_IF: 04328 /* fields: item->u1.str == the if conditional, as supplied by user 04329 04330 item->u2.statements == a pval list of statements in the if () 04331 item->u3.else_statements == a pval list of statements in the else 04332 (could be zero) 04333 */ 04334 if (item->u1.str) 04335 free(item->u1.str); 04336 destroy_pval(item->u2.statements); 04337 if (item->u3.else_statements) { 04338 destroy_pval(item->u3.else_statements); 04339 } 04340 break; 04341 04342 case PV_SWITCH: 04343 /* fields: item->u1.str == the switch expression 04344 04345 item->u2.statements == a pval list of statements in the switch, 04346 (will be case statements, most likely!) 04347 */ 04348 if (item->u1.str) 04349 free(item->u1.str); 04350 destroy_pval(item->u2.statements); 04351 break; 04352 04353 case PV_EXTENSION: 04354 /* fields: item->u1.str == the extension name, label, whatever it's called 04355 04356 item->u2.statements == a pval list of statements in the extension 04357 item->u3.hints == a char * hint argument 04358 item->u4.regexten == an int boolean. non-zero says that regexten was specified 04359 */ 04360 if (item->u1.str) 04361 free(item->u1.str); 04362 if (item->u3.hints) 04363 free(item->u3.hints); 04364 destroy_pval(item->u2.statements); 04365 break; 04366 04367 case PV_IGNOREPAT: 04368 /* fields: item->u1.str == the ignorepat data 04369 */ 04370 if (item->u1.str) 04371 free(item->u1.str); 04372 break; 04373 04374 case PV_GLOBALS: 04375 /* fields: item->u1.statements == pval list of statements, usually vardecs 04376 */ 04377 destroy_pval(item->u1.statements); 04378 break; 04379 } 04380 free(item); 04381 }
static int extension_matches | ( | pval * | here, | |
const char * | exten, | |||
const char * | pattern | |||
) | [static] |
Definition at line 707 of file pbx_ael.c.
References ast_log(), pval::endline, pval::filename, LOG_ERROR, LOG_WARNING, and pval::startline.
Referenced by match_pval_item().
00708 { 00709 int err1; 00710 regex_t preg; 00711 00712 /* simple case, they match exactly, the pattern and exten name */ 00713 if( !strcmp(pattern,exten) == 0 ) 00714 return 1; 00715 00716 if ( pattern[0] == '_' ) { 00717 char reg1[2000]; 00718 const char *p; 00719 char *r = reg1; 00720 00721 if ( strlen(pattern)*5 >= 2000 ) /* safety valve */ { 00722 ast_log(LOG_ERROR,"Error: The pattern %s is way too big. Pattern matching cancelled.\n", 00723 pattern); 00724 return 0; 00725 } 00726 /* form a regular expression from the pattern, and then match it against exten */ 00727 *r++ = '^'; /* what if the extension is a pattern ?? */ 00728 *r++ = '_'; /* what if the extension is a pattern ?? */ 00729 *r++ = '?'; 00730 for (p=pattern+1; *p; p++) { 00731 switch ( *p ) { 00732 case 'X': 00733 *r++ = '['; 00734 *r++ = '0'; 00735 *r++ = '-'; 00736 *r++ = '9'; 00737 *r++ = 'X'; 00738 *r++ = ']'; 00739 break; 00740 00741 case 'Z': 00742 *r++ = '['; 00743 *r++ = '1'; 00744 *r++ = '-'; 00745 *r++ = '9'; 00746 *r++ = 'Z'; 00747 *r++ = ']'; 00748 break; 00749 00750 case 'N': 00751 *r++ = '['; 00752 *r++ = '2'; 00753 *r++ = '-'; 00754 *r++ = '9'; 00755 *r++ = 'N'; 00756 *r++ = ']'; 00757 break; 00758 00759 case '[': 00760 while ( *p && *p != ']' ) { 00761 *r++ = *p++; 00762 } 00763 if ( *p != ']') { 00764 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The extension pattern '%s' is missing a closing bracket \n", 00765 here->filename, here->startline, here->endline, pattern); 00766 } 00767 break; 00768 00769 case '.': 00770 case '!': 00771 *r++ = '.'; 00772 *r++ = '*'; 00773 break; 00774 case '*': 00775 *r++ = '\\'; 00776 *r++ = '*'; 00777 break; 00778 default: 00779 *r++ = *p; 00780 break; 00781 00782 } 00783 } 00784 *r++ = '$'; /* what if the extension is a pattern ?? */ 00785 *r++ = *p++; /* put in the closing null */ 00786 err1 = regcomp(&preg, reg1, REG_NOSUB|REG_EXTENDED); 00787 if ( err1 ) { 00788 char errmess[500]; 00789 regerror(err1,&preg,errmess,sizeof(errmess)); 00790 regfree(&preg); 00791 ast_log(LOG_WARNING, "Regcomp of %s failed, error code %d\n", 00792 reg1, err1); 00793 return 0; 00794 } 00795 err1 = regexec(&preg, exten, 0, 0, 0); 00796 regfree(&preg); 00797 00798 if ( err1 ) { 00799 /* ast_log(LOG_NOTICE,"*****************************[%d]Extension %s did not match %s(%s)\n", 00800 err1,exten, pattern, reg1); */ 00801 return 0; /* no match */ 00802 } else { 00803 /* ast_log(LOG_NOTICE,"*****************************Extension %s matched %s\n", 00804 exten, pattern); */ 00805 return 1; 00806 } 00807 00808 00809 } else { 00810 if ( strcmp(exten,pattern) == 0 ) { 00811 return 1; 00812 } else 00813 return 0; 00814 } 00815 }
struct pval * find_context | ( | char * | name | ) |
Definition at line 1884 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().
01885 { 01886 return_on_context_match = 1; 01887 count_labels = 0; 01888 match_context = name; 01889 match_exten = "*"; /* don't really need to set these, shouldn't be reached */ 01890 match_label = "*"; 01891 return match_pval(current_db); 01892 }
Definition at line 1763 of file pbx_ael.c.
References find_context(), pval::list, pval::macro_statements, match_pval(), pval::next, PV_INCLUDES, PV_MACRO, pval::statements, pval::str, pval::type, pval::u1, pval::u2, and pval::u3.
Referenced by check_label().
01764 { 01765 /* printf(" --- Got args %s, %s\n", exten, label); */ 01766 struct pval *ret; 01767 struct pval *p3; 01768 struct pval *startpt = ((curr_cont->type==PV_MACRO)?curr_cont->u3.macro_statements: curr_cont->u2.statements); 01769 01770 count_labels = 0; 01771 return_on_context_match = 0; 01772 match_context = "*"; 01773 match_exten = "*"; 01774 match_label = label; 01775 01776 ret = match_pval(curr_cont); 01777 if (ret) 01778 return ret; 01779 01780 /* the target of the goto could be in an included context!! Fancy that!! */ 01781 /* look for includes in the current context */ 01782 for (p3=startpt; p3; p3=p3->next) { 01783 if (p3->type == PV_INCLUDES) { 01784 struct pval *p4; 01785 for (p4=p3->u1.list; p4; p4=p4->next) { 01786 /* for each context pointed to, find it, then find a context/label that matches the 01787 target here! */ 01788 char *incl_context = p4->u1.str; 01789 /* find a matching context name */ 01790 struct pval *that_context = find_context(incl_context); 01791 if (that_context) { 01792 struct pval *x3; 01793 x3 = find_first_label_in_current_context(label, that_context); 01794 if (x3) { 01795 return x3; 01796 } 01797 } 01798 } 01799 } 01800 } 01801 return 0; 01802 }
struct pval * find_label_in_current_context | ( | char * | exten, | |
char * | label, | |||
pval * | curr_cont | |||
) | [static] |
Definition at line 1804 of file pbx_ael.c.
References find_context(), pval::list, pval::macro_statements, match_pval(), pval::next, PV_INCLUDES, PV_MACRO, pval::statements, pval::str, pval::type, pval::u1, pval::u2, and pval::u3.
Referenced by check_goto(), and get_goto_target().
01805 { 01806 /* printf(" --- Got args %s, %s\n", exten, label); */ 01807 struct pval *ret; 01808 struct pval *p3; 01809 struct pval *startpt; 01810 01811 count_labels = 0; 01812 return_on_context_match = 0; 01813 match_context = "*"; 01814 match_exten = exten; 01815 match_label = label; 01816 if (curr_cont->type == PV_MACRO) 01817 startpt = curr_cont->u3.macro_statements; 01818 else 01819 startpt = curr_cont->u2.statements; 01820 01821 ret = match_pval(startpt); 01822 if (ret) 01823 return ret; 01824 01825 /* the target of the goto could be in an included context!! Fancy that!! */ 01826 /* look for includes in the current context */ 01827 for (p3=startpt; p3; p3=p3->next) { 01828 if (p3->type == PV_INCLUDES) { 01829 struct pval *p4; 01830 for (p4=p3->u1.list; p4; p4=p4->next) { 01831 /* for each context pointed to, find it, then find a context/label that matches the 01832 target here! */ 01833 char *incl_context = p4->u1.str; 01834 /* find a matching context name */ 01835 struct pval *that_context = find_context(incl_context); 01836 if (that_context) { 01837 struct pval *x3; 01838 x3 = find_label_in_current_context(exten, label, that_context); 01839 if (x3) { 01840 return x3; 01841 } 01842 } 01843 } 01844 } 01845 } 01846 return 0; 01847 }
static struct pval * find_label_in_current_db | ( | const char * | context, | |
const char * | exten, | |||
const char * | label | |||
) | [static] |
Definition at line 1860 of file pbx_ael.c.
References current_db, and match_pval().
Referenced by check_goto(), and get_goto_target().
01861 { 01862 /* printf(" --- Got args %s, %s, %s\n", context, exten, label); */ 01863 count_labels = 0; 01864 return_on_context_match = 0; 01865 01866 match_context = context; 01867 match_exten = exten; 01868 match_label = label; 01869 01870 return match_pval(current_db); 01871 }
static struct pval * find_label_in_current_extension | ( | const char * | label, | |
pval * | curr_ext | |||
) | [static] |
Definition at line 1849 of file pbx_ael.c.
References match_pval().
Referenced by check_goto(), and get_goto_target().
01850 { 01851 /* printf(" --- Got args %s\n", label); */ 01852 count_labels = 0; 01853 return_on_context_match = 0; 01854 match_context = "*"; 01855 match_exten = "*"; 01856 match_label = label; 01857 return match_pval(curr_ext); 01858 }
struct pval * find_macro | ( | char * | name | ) |
Definition at line 1874 of file pbx_ael.c.
References current_db, and match_pval().
Referenced by check_pval_item().
01875 { 01876 return_on_context_match = 1; 01877 count_labels = 0; 01878 match_context = name; 01879 match_exten = "*"; /* don't really need to set these, shouldn't be reached */ 01880 match_label = "*"; 01881 return match_pval(current_db); 01882 }
static void find_pval_goto_item | ( | pval * | item, | |
int | lev | |||
) | [static] |
Definition at line 1297 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().
01298 { 01299 struct pval *p4; 01300 if (lev>100) { 01301 ast_log(LOG_ERROR,"find_pval_goto in infinite loop!\n\n"); 01302 return; 01303 } 01304 01305 switch ( item->type ) { 01306 case PV_MACRO: 01307 /* fields: item->u1.str == name of macro 01308 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 01309 item->u2.arglist->u1.str == argument 01310 item->u2.arglist->next == next arg 01311 01312 item->u3.macro_statements == pval list of statements in macro body. 01313 */ 01314 01315 /* printf("Descending into matching macro %s\n", match_context); */ 01316 find_pval_gotos(item->u3.macro_statements,lev+1); /* if we're just searching for a context, don't bother descending into them */ 01317 01318 break; 01319 01320 case PV_CONTEXT: 01321 /* fields: item->u1.str == name of context 01322 item->u2.statements == pval list of statements in context body 01323 item->u3.abstract == int 1 if an abstract keyword were present 01324 */ 01325 break; 01326 01327 case PV_CASE: 01328 /* fields: item->u1.str == value of case 01329 item->u2.statements == pval list of statements under the case 01330 */ 01331 find_pval_gotos(item->u2.statements,lev+1); 01332 break; 01333 01334 case PV_PATTERN: 01335 /* fields: item->u1.str == value of case 01336 item->u2.statements == pval list of statements under the case 01337 */ 01338 find_pval_gotos(item->u2.statements,lev+1); 01339 break; 01340 01341 case PV_DEFAULT: 01342 /* fields: 01343 item->u2.statements == pval list of statements under the case 01344 */ 01345 find_pval_gotos(item->u2.statements,lev+1); 01346 break; 01347 01348 case PV_CATCH: 01349 /* fields: item->u1.str == name of extension to catch 01350 item->u2.statements == pval list of statements in context body 01351 */ 01352 find_pval_gotos(item->u2.statements,lev+1); 01353 break; 01354 01355 case PV_STATEMENTBLOCK: 01356 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 01357 */ 01358 find_pval_gotos(item->u1.list,lev+1); 01359 break; 01360 01361 case PV_GOTO: 01362 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 01363 item->u1.list->u1.str == where the data on a PV_WORD will always be. 01364 */ 01365 check_goto(item); /* THE WHOLE FUNCTION OF THIS ENTIRE ROUTINE!!!! */ 01366 break; 01367 01368 case PV_INCLUDES: 01369 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 01370 */ 01371 for (p4=item->u1.list; p4; p4=p4->next) { 01372 /* for each context pointed to, find it, then find a context/label that matches the 01373 target here! */ 01374 char *incl_context = p4->u1.str; 01375 /* find a matching context name */ 01376 struct pval *that_context = find_context(incl_context); 01377 if (that_context) { 01378 find_pval_gotos(that_context,lev+1); /* keep working up the includes */ 01379 } 01380 } 01381 break; 01382 01383 case PV_FOR: 01384 /* fields: item->u1.for_init == a string containing the initalizer 01385 item->u2.for_test == a string containing the loop test 01386 item->u3.for_inc == a string containing the loop increment 01387 01388 item->u4.for_statements == a pval list of statements in the for () 01389 */ 01390 find_pval_gotos(item->u4.for_statements,lev+1); 01391 break; 01392 01393 case PV_WHILE: 01394 /* fields: item->u1.str == the while conditional, as supplied by user 01395 01396 item->u2.statements == a pval list of statements in the while () 01397 */ 01398 find_pval_gotos(item->u2.statements,lev+1); 01399 break; 01400 01401 case PV_RANDOM: 01402 /* fields: item->u1.str == the random number expression, as supplied by user 01403 01404 item->u2.statements == a pval list of statements in the if () 01405 item->u3.else_statements == a pval list of statements in the else 01406 (could be zero) 01407 fall thru to PV_IF */ 01408 01409 case PV_IFTIME: 01410 /* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list 01411 01412 item->u2.statements == a pval list of statements in the if () 01413 item->u3.else_statements == a pval list of statements in the else 01414 (could be zero) 01415 fall thru to PV_IF*/ 01416 case PV_IF: 01417 /* fields: item->u1.str == the if conditional, as supplied by user 01418 01419 item->u2.statements == a pval list of statements in the if () 01420 item->u3.else_statements == a pval list of statements in the else 01421 (could be zero) 01422 */ 01423 find_pval_gotos(item->u2.statements,lev+1); 01424 01425 if (item->u3.else_statements) { 01426 find_pval_gotos(item->u3.else_statements,lev+1); 01427 } 01428 break; 01429 01430 case PV_SWITCH: 01431 /* fields: item->u1.str == the switch expression 01432 01433 item->u2.statements == a pval list of statements in the switch, 01434 (will be case statements, most likely!) 01435 */ 01436 find_pval_gotos(item->u3.else_statements,lev+1); 01437 break; 01438 01439 case PV_EXTENSION: 01440 /* fields: item->u1.str == the extension name, label, whatever it's called 01441 01442 item->u2.statements == a pval list of statements in the extension 01443 item->u3.hints == a char * hint argument 01444 item->u4.regexten == an int boolean. non-zero says that regexten was specified 01445 */ 01446 01447 find_pval_gotos(item->u2.statements,lev+1); 01448 break; 01449 01450 default: 01451 break; 01452 } 01453 }
static void find_pval_gotos | ( | pval * | item, | |
int | lev | |||
) | [static] |
Definition at line 1455 of file pbx_ael.c.
References find_pval_goto_item(), and pval::next.
Referenced by check_pval_item(), and find_pval_goto_item().
01456 { 01457 pval *i; 01458 01459 for (i=item; i; i=i->next) { 01460 01461 find_pval_goto_item(i, lev); 01462 } 01463 }
static void fix_gotos_in_extensions | ( | struct ael_extension * | exten | ) | [static] |
Definition at line 3710 of file pbx_ael.c.
References exten, ael_priority::next, ael_extension::next_exten, ael_extension::plist, PV_GOTO, and strdup.
03711 { 03712 struct ael_extension *e; 03713 for(e=exten;e;e=e->next_exten) { 03714 03715 struct ael_priority *p; 03716 for(p=e->plist;p;p=p->next) { 03717 03718 if( p->origin && p->origin->type == PV_GOTO && p->origin->u3.goto_target_in_case ) { 03719 03720 /* fix the extension of the goto target to the actual extension in the post-compiled dialplan */ 03721 03722 pval *target = p->origin->u2.goto_target; 03723 struct ael_extension *z = target->u3.compiled_label; 03724 pval *pv2 = p->origin; 03725 char buf1[500]; 03726 char *apparg_save = p->appargs; 03727 03728 p->appargs = 0; 03729 if (!pv2->u1.list->next) /* just one -- it won't hurt to repeat the extension */ { 03730 snprintf(buf1,sizeof(buf1),"%s|%s", z->name, pv2->u1.list->u1.str); 03731 p->appargs = strdup(buf1); 03732 03733 } else if (pv2->u1.list->next && !pv2->u1.list->next->next) /* two */ { 03734 snprintf(buf1,sizeof(buf1),"%s|%s", z->name, pv2->u1.list->next->u1.str); 03735 p->appargs = strdup(buf1); 03736 } else if (pv2->u1.list->next && pv2->u1.list->next->next) { 03737 snprintf(buf1,sizeof(buf1),"%s|%s|%s", pv2->u1.list->u1.str, 03738 z->name, 03739 pv2->u1.list->next->next->u1.str); 03740 p->appargs = strdup(buf1); 03741 } 03742 else 03743 printf("WHAT? The goto doesn't fall into one of three cases for GOTO????\n"); 03744 03745 if( apparg_save ) { 03746 free(apparg_save); 03747 } 03748 } 03749 } 03750 } 03751 }
static void gen_match_to_pattern | ( | char * | pattern, | |
char * | result | |||
) | [static] |
Definition at line 2868 of file pbx_ael.c.
References t.
Referenced by gen_prios().
02869 { 02870 /* the result will be a string that will be matched by pattern */ 02871 char *p=pattern, *t=result; 02872 while (*p) { 02873 if (*p == 'x' || *p == 'n' || *p == 'z' || *p == 'X' || *p == 'N' || *p == 'Z') 02874 *t++ = '9'; 02875 else if (*p == '[') { 02876 char *z = p+1; 02877 while (*z != ']') 02878 z++; 02879 if (*(z+1)== ']') 02880 z++; 02881 *t++=*(p+1); /* use the first char in the set */ 02882 p = z; 02883 } else { 02884 *t++ = *p; 02885 } 02886 p++; 02887 } 02888 *t++ = 0; /* cap it off */ 02889 }
static void gen_prios | ( | struct ael_extension * | exten, | |
char * | label, | |||
pval * | statement, | |||
struct ael_extension * | mother_exten, | |||
struct ast_context * | context | |||
) | [static] |
Definition at line 2891 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, 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, ael_extension::is_switch, 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.
02892 { 02893 pval *p,*p2,*p3; 02894 struct ael_priority *pr; 02895 struct ael_priority *for_init, *for_test, *for_inc, *for_loop, *for_end; 02896 struct ael_priority *while_test, *while_loop, *while_end; 02897 struct ael_priority *switch_test, *switch_end, *fall_thru; 02898 struct ael_priority *if_test, *if_end, *if_skip, *if_false; 02899 #ifdef OLD_RAND_ACTION 02900 struct ael_priority *rand_test, *rand_end, *rand_skip; 02901 #endif 02902 char buf1[2000]; 02903 char buf2[2000]; 02904 char *strp, *strp2; 02905 char new_label[2000]; 02906 int default_exists; 02907 int local_control_statement_count; 02908 struct ael_priority *loop_break_save; 02909 struct ael_priority *loop_continue_save; 02910 struct ael_extension *switch_case; 02911 02912 for (p=statement; p; p=p->next) { 02913 switch (p->type) { 02914 case PV_VARDEC: 02915 pr = new_prio(); 02916 pr->type = AEL_APPCALL; 02917 snprintf(buf1,sizeof(buf1),"%s=$[%s]", p->u1.str, p->u2.val); 02918 pr->app = strdup("Set"); 02919 remove_spaces_before_equals(buf1); 02920 pr->appargs = strdup(buf1); 02921 pr->origin = p; 02922 linkprio(exten, pr); 02923 break; 02924 02925 case PV_GOTO: 02926 pr = new_prio(); 02927 pr->type = AEL_APPCALL; 02928 p->u2.goto_target = get_goto_target(p); 02929 if( p->u2.goto_target ) { 02930 p->u3.goto_target_in_case = p->u2.goto_target->u2.label_in_case = label_inside_case(p->u2.goto_target); 02931 } 02932 02933 if (!p->u1.list->next) /* just one */ { 02934 pr->app = strdup("Goto"); 02935 if (!mother_exten) 02936 pr->appargs = strdup(p->u1.list->u1.str); 02937 else { /* for the case of simple within-extension gotos in case/pattern/default statement blocks: */ 02938 snprintf(buf1,sizeof(buf1),"%s|%s", mother_exten->name, p->u1.list->u1.str); 02939 pr->appargs = strdup(buf1); 02940 } 02941 02942 } else if (p->u1.list->next && !p->u1.list->next->next) /* two */ { 02943 snprintf(buf1,sizeof(buf1),"%s|%s", p->u1.list->u1.str, p->u1.list->next->u1.str); 02944 pr->app = strdup("Goto"); 02945 pr->appargs = strdup(buf1); 02946 } else if (p->u1.list->next && p->u1.list->next->next) { 02947 snprintf(buf1,sizeof(buf1),"%s|%s|%s", p->u1.list->u1.str, 02948 p->u1.list->next->u1.str, 02949 p->u1.list->next->next->u1.str); 02950 pr->app = strdup("Goto"); 02951 pr->appargs = strdup(buf1); 02952 } 02953 pr->origin = p; 02954 linkprio(exten, pr); 02955 break; 02956 02957 case PV_LABEL: 02958 pr = new_prio(); 02959 pr->type = AEL_LABEL; 02960 pr->origin = p; 02961 p->u3.compiled_label = exten; 02962 linkprio(exten, pr); 02963 break; 02964 02965 case PV_FOR: 02966 control_statement_count++; 02967 loop_break_save = exten->loop_break; /* save them, then restore before leaving */ 02968 loop_continue_save = exten->loop_continue; 02969 snprintf(new_label,sizeof(new_label),"for-%s-%d", label, control_statement_count); 02970 for_init = new_prio(); 02971 for_inc = new_prio(); 02972 for_test = new_prio(); 02973 for_loop = new_prio(); 02974 for_end = new_prio(); 02975 for_init->type = AEL_APPCALL; 02976 for_inc->type = AEL_APPCALL; 02977 for_test->type = AEL_FOR_CONTROL; 02978 for_test->goto_false = for_end; 02979 for_loop->type = AEL_CONTROL1; /* simple goto */ 02980 for_end->type = AEL_APPCALL; 02981 for_init->app = strdup("Set"); 02982 02983 strcpy(buf2,p->u1.for_init); 02984 remove_spaces_before_equals(buf2); 02985 strp = strchr(buf2, '='); 02986 strp2 = strchr(p->u1.for_init, '='); 02987 if (strp) { 02988 *(strp+1) = 0; 02989 strcat(buf2,"$["); 02990 strncat(buf2,strp2+1, sizeof(buf2)-strlen(strp2+1)-2); 02991 strcat(buf2,"]"); 02992 for_init->appargs = strdup(buf2); 02993 } else 02994 for_init->appargs = strdup(p->u1.for_init); 02995 02996 for_inc->app = strdup("Set"); 02997 02998 strcpy(buf2,p->u3.for_inc); 02999 remove_spaces_before_equals(buf2); 03000 strp = strchr(buf2, '='); 03001 strp2 = strchr(p->u3.for_inc, '='); 03002 if (strp) { 03003 *(strp+1) = 0; 03004 strcat(buf2,"$["); 03005 strncat(buf2,strp2+1, sizeof(buf2)-strlen(strp2+1)-2); 03006 strcat(buf2,"]"); 03007 for_inc->appargs = strdup(buf2); 03008 } else 03009 for_inc->appargs = strdup(p->u3.for_inc); 03010 snprintf(buf1,sizeof(buf1),"$[%s]",p->u2.for_test); 03011 for_test->app = 0; 03012 for_test->appargs = strdup(buf1); 03013 for_loop->goto_true = for_test; 03014 snprintf(buf1,sizeof(buf1),"Finish for-%s-%d", label, control_statement_count); 03015 for_end->app = strdup("NoOp"); 03016 for_end->appargs = strdup(buf1); 03017 /* link & load! */ 03018 linkprio(exten, for_init); 03019 linkprio(exten, for_test); 03020 03021 /* now, put the body of the for loop here */ 03022 exten->loop_break = for_end; 03023 exten->loop_continue = for_inc; 03024 03025 gen_prios(exten, new_label, p->u4.for_statements, mother_exten, this_context); /* this will link in all the statements here */ 03026 03027 linkprio(exten, for_inc); 03028 linkprio(exten, for_loop); 03029 linkprio(exten, for_end); 03030 03031 03032 exten->loop_break = loop_break_save; 03033 exten->loop_continue = loop_continue_save; 03034 for_loop->origin = p; 03035 break; 03036 03037 case PV_WHILE: 03038 control_statement_count++; 03039 loop_break_save = exten->loop_break; /* save them, then restore before leaving */ 03040 loop_continue_save = exten->loop_continue; 03041 snprintf(new_label,sizeof(new_label),"while-%s-%d", label, control_statement_count); 03042 while_test = new_prio(); 03043 while_loop = new_prio(); 03044 while_end = new_prio(); 03045 while_test->type = AEL_FOR_CONTROL; 03046 while_test->goto_false = while_end; 03047 while_loop->type = AEL_CONTROL1; /* simple goto */ 03048 while_end->type = AEL_APPCALL; 03049 snprintf(buf1,sizeof(buf1),"$[%s]",p->u1.str); 03050 while_test->app = 0; 03051 while_test->appargs = strdup(buf1); 03052 while_loop->goto_true = while_test; 03053 snprintf(buf1,sizeof(buf1),"Finish while-%s-%d", label, control_statement_count); 03054 while_end->app = strdup("NoOp"); 03055 while_end->appargs = strdup(buf1); 03056 03057 linkprio(exten, while_test); 03058 03059 /* now, put the body of the for loop here */ 03060 exten->loop_break = while_end; 03061 exten->loop_continue = while_test; 03062 03063 gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the while body statements here */ 03064 03065 linkprio(exten, while_loop); 03066 linkprio(exten, while_end); 03067 03068 03069 exten->loop_break = loop_break_save; 03070 exten->loop_continue = loop_continue_save; 03071 while_loop->origin = p; 03072 break; 03073 03074 case PV_SWITCH: 03075 control_statement_count++; 03076 local_control_statement_count = control_statement_count; 03077 loop_break_save = exten->loop_break; /* save them, then restore before leaving */ 03078 loop_continue_save = exten->loop_continue; 03079 snprintf(new_label,sizeof(new_label),"sw-%s-%d", label, control_statement_count); 03080 03081 switch_test = new_prio(); 03082 switch_end = new_prio(); 03083 switch_test->type = AEL_APPCALL; 03084 switch_end->type = AEL_APPCALL; 03085 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",control_statement_count, p->u1.str); 03086 switch_test->app = strdup("Goto"); 03087 switch_test->appargs = strdup(buf1); 03088 snprintf(buf1,sizeof(buf1),"Finish switch-%s-%d", label, control_statement_count); 03089 switch_end->app = strdup("NoOp"); 03090 switch_end->appargs = strdup(buf1); 03091 switch_end->origin = p; 03092 switch_end->exten = exten; 03093 03094 linkprio(exten, switch_test); 03095 linkprio(exten, switch_end); 03096 03097 exten->loop_break = switch_end; 03098 exten->loop_continue = 0; 03099 default_exists = 0; 03100 03101 for (p2=p->u2.statements; p2; p2=p2->next) { 03102 /* now, for each case/default put the body of the for loop here */ 03103 if (p2->type == PV_CASE) { 03104 /* ok, generate a extension and link it in */ 03105 switch_case = new_exten(); 03106 switch_case->context = this_context; 03107 switch_case->is_switch = 1; 03108 /* the break/continue locations are inherited from parent */ 03109 switch_case->loop_break = exten->loop_break; 03110 switch_case->loop_continue = exten->loop_continue; 03111 03112 linkexten(exten,switch_case); 03113 snprintf(buf1,sizeof(buf1),"sw-%d-%s", local_control_statement_count, p2->u1.str); 03114 switch_case->name = strdup(buf1); 03115 snprintf(new_label,sizeof(new_label),"sw-%s-%s-%d", label, p2->u1.str, local_control_statement_count); 03116 03117 gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context); /* this will link in all the case body statements here */ 03118 03119 /* here is where we write code to "fall thru" to the next case... if there is one... */ 03120 for (p3=p2->u2.statements; p3; p3=p3->next) { 03121 if (!p3->next) 03122 break; 03123 } 03124 /* p3 now points the last statement... */ 03125 if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN) ) { 03126 /* is there a following CASE/PATTERN/DEFAULT? */ 03127 if (p2->next && p2->next->type == PV_CASE) { 03128 fall_thru = new_prio(); 03129 fall_thru->type = AEL_APPCALL; 03130 fall_thru->app = strdup("Goto"); 03131 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, p2->next->u1.str); 03132 fall_thru->appargs = strdup(buf1); 03133 linkprio(switch_case, fall_thru); 03134 } else if (p2->next && p2->next->type == PV_PATTERN) { 03135 fall_thru = new_prio(); 03136 fall_thru->type = AEL_APPCALL; 03137 fall_thru->app = strdup("Goto"); 03138 gen_match_to_pattern(p2->next->u1.str, buf2); 03139 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10", local_control_statement_count, buf2); 03140 fall_thru->appargs = strdup(buf1); 03141 linkprio(switch_case, fall_thru); 03142 } else if (p2->next && p2->next->type == PV_DEFAULT) { 03143 fall_thru = new_prio(); 03144 fall_thru->type = AEL_APPCALL; 03145 fall_thru->app = strdup("Goto"); 03146 snprintf(buf1,sizeof(buf1),"sw-%d-.|10",local_control_statement_count); 03147 fall_thru->appargs = strdup(buf1); 03148 linkprio(switch_case, fall_thru); 03149 } else if (!p2->next) { 03150 fall_thru = new_prio(); 03151 fall_thru->type = AEL_CONTROL1; 03152 fall_thru->goto_true = switch_end; 03153 fall_thru->app = strdup("Goto"); 03154 linkprio(switch_case, fall_thru); 03155 } 03156 } 03157 if (switch_case->return_needed) { 03158 char buf[2000]; 03159 struct ael_priority *np2 = new_prio(); 03160 np2->type = AEL_APPCALL; 03161 np2->app = strdup("NoOp"); 03162 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); 03163 np2->appargs = strdup(buf); 03164 linkprio(switch_case, np2); 03165 switch_case-> return_target = np2; 03166 } 03167 } else if (p2->type == PV_PATTERN) { 03168 /* ok, generate a extension and link it in */ 03169 switch_case = new_exten(); 03170 switch_case->context = this_context; 03171 switch_case->is_switch = 1; 03172 /* the break/continue locations are inherited from parent */ 03173 switch_case->loop_break = exten->loop_break; 03174 switch_case->loop_continue = exten->loop_continue; 03175 03176 linkexten(exten,switch_case); 03177 snprintf(buf1,sizeof(buf1),"_sw-%d-%s", local_control_statement_count, p2->u1.str); 03178 switch_case->name = strdup(buf1); 03179 snprintf(new_label,sizeof(new_label),"sw-%s-%s-%d", label, p2->u1.str, local_control_statement_count); 03180 03181 gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context); /* this will link in all the while body statements here */ 03182 /* here is where we write code to "fall thru" to the next case... if there is one... */ 03183 for (p3=p2->u2.statements; p3; p3=p3->next) { 03184 if (!p3->next) 03185 break; 03186 } 03187 /* p3 now points the last statement... */ 03188 if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) { 03189 /* is there a following CASE/PATTERN/DEFAULT? */ 03190 if (p2->next && p2->next->type == PV_CASE) { 03191 fall_thru = new_prio(); 03192 fall_thru->type = AEL_APPCALL; 03193 fall_thru->app = strdup("Goto"); 03194 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, p2->next->u1.str); 03195 fall_thru->appargs = strdup(buf1); 03196 linkprio(switch_case, fall_thru); 03197 } else if (p2->next && p2->next->type == PV_PATTERN) { 03198 fall_thru = new_prio(); 03199 fall_thru->type = AEL_APPCALL; 03200 fall_thru->app = strdup("Goto"); 03201 gen_match_to_pattern(p2->next->u1.str, buf2); 03202 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, buf2); 03203 fall_thru->appargs = strdup(buf1); 03204 linkprio(switch_case, fall_thru); 03205 } else if (p2->next && p2->next->type == PV_DEFAULT) { 03206 fall_thru = new_prio(); 03207 fall_thru->type = AEL_APPCALL; 03208 fall_thru->app = strdup("Goto"); 03209 snprintf(buf1,sizeof(buf1),"sw-%d-.|10",local_control_statement_count); 03210 fall_thru->appargs = strdup(buf1); 03211 linkprio(switch_case, fall_thru); 03212 } else if (!p2->next) { 03213 fall_thru = new_prio(); 03214 fall_thru->type = AEL_CONTROL1; 03215 fall_thru->goto_true = switch_end; 03216 fall_thru->app = strdup("Goto"); 03217 linkprio(switch_case, fall_thru); 03218 } 03219 } 03220 if (switch_case->return_needed) { 03221 char buf[2000]; 03222 struct ael_priority *np2 = new_prio(); 03223 np2->type = AEL_APPCALL; 03224 np2->app = strdup("NoOp"); 03225 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); 03226 np2->appargs = strdup(buf); 03227 linkprio(switch_case, np2); 03228 switch_case-> return_target = np2; 03229 } 03230 } else if (p2->type == PV_DEFAULT) { 03231 default_exists++; 03232 /* ok, generate a extension and link it in */ 03233 switch_case = new_exten(); 03234 switch_case->context = this_context; 03235 switch_case->is_switch = 1; 03236 /* the break/continue locations are inherited from parent */ 03237 switch_case->loop_break = exten->loop_break; 03238 switch_case->loop_continue = exten->loop_continue; 03239 linkexten(exten,switch_case); 03240 snprintf(buf1,sizeof(buf1),"_sw-%d-.", local_control_statement_count); 03241 switch_case->name = strdup(buf1); 03242 03243 snprintf(new_label,sizeof(new_label),"sw-%s-default-%d", label, local_control_statement_count); 03244 03245 gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context); /* this will link in all the while body statements here */ 03246 03247 /* here is where we write code to "fall thru" to the next case... if there is one... */ 03248 for (p3=p2->u2.statements; p3; p3=p3->next) { 03249 if (!p3->next) 03250 break; 03251 } 03252 /* p3 now points the last statement... */ 03253 if (!p3 || (p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) { 03254 /* is there a following CASE/PATTERN/DEFAULT? */ 03255 if (p2->next && p2->next->type == PV_CASE) { 03256 fall_thru = new_prio(); 03257 fall_thru->type = AEL_APPCALL; 03258 fall_thru->app = strdup("Goto"); 03259 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, p2->next->u1.str); 03260 fall_thru->appargs = strdup(buf1); 03261 linkprio(switch_case, fall_thru); 03262 } else if (p2->next && p2->next->type == PV_PATTERN) { 03263 fall_thru = new_prio(); 03264 fall_thru->type = AEL_APPCALL; 03265 fall_thru->app = strdup("Goto"); 03266 gen_match_to_pattern(p2->next->u1.str, buf2); 03267 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, buf2); 03268 fall_thru->appargs = strdup(buf1); 03269 linkprio(switch_case, fall_thru); 03270 } else if (p2->next && p2->next->type == PV_DEFAULT) { 03271 fall_thru = new_prio(); 03272 fall_thru->type = AEL_APPCALL; 03273 fall_thru->app = strdup("Goto"); 03274 snprintf(buf1,sizeof(buf1),"sw-%d-.|10",local_control_statement_count); 03275 fall_thru->appargs = strdup(buf1); 03276 linkprio(switch_case, fall_thru); 03277 } else if (!p2->next) { 03278 fall_thru = new_prio(); 03279 fall_thru->type = AEL_CONTROL1; 03280 fall_thru->goto_true = switch_end; 03281 fall_thru->app = strdup("Goto"); 03282 linkprio(switch_case, fall_thru); 03283 } 03284 } 03285 if (switch_case->return_needed) { 03286 char buf[2000]; 03287 struct ael_priority *np2 = new_prio(); 03288 np2->type = AEL_APPCALL; 03289 np2->app = strdup("NoOp"); 03290 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); 03291 np2->appargs = strdup(buf); 03292 linkprio(switch_case, np2); 03293 switch_case-> return_target = np2; 03294 } 03295 } else { 03296 /* what could it be??? */ 03297 } 03298 } 03299 03300 exten->loop_break = loop_break_save; 03301 exten->loop_continue = loop_continue_save; 03302 switch_test->origin = p; 03303 switch_end->origin = p; 03304 break; 03305 03306 case PV_MACRO_CALL: 03307 pr = new_prio(); 03308 pr->type = AEL_APPCALL; 03309 snprintf(buf1,sizeof(buf1),"%s", p->u1.str); 03310 for (p2 = p->u2.arglist; p2; p2 = p2->next) { 03311 strcat(buf1,"|"); 03312 strcat(buf1,p2->u1.str); 03313 } 03314 pr->app = strdup("Macro"); 03315 pr->appargs = strdup(buf1); 03316 pr->origin = p; 03317 linkprio(exten, pr); 03318 break; 03319 03320 case PV_APPLICATION_CALL: 03321 pr = new_prio(); 03322 pr->type = AEL_APPCALL; 03323 buf1[0] = 0; 03324 for (p2 = p->u2.arglist; p2; p2 = p2->next) { 03325 if (p2 != p->u2.arglist ) 03326 strcat(buf1,"|"); 03327 substitute_commas(p2->u1.str); 03328 strcat(buf1,p2->u1.str); 03329 } 03330 pr->app = strdup(p->u1.str); 03331 pr->appargs = strdup(buf1); 03332 pr->origin = p; 03333 linkprio(exten, pr); 03334 break; 03335 03336 case PV_BREAK: 03337 pr = new_prio(); 03338 pr->type = AEL_CONTROL1; /* simple goto */ 03339 pr->goto_true = exten->loop_break; 03340 pr->origin = p; 03341 linkprio(exten, pr); 03342 break; 03343 03344 case PV_RETURN: /* hmmmm */ 03345 pr = new_prio(); 03346 pr->type = AEL_RETURN; /* simple goto */ 03347 exten->return_needed++; 03348 pr->app = strdup("Goto"); 03349 pr->appargs = strdup(""); 03350 pr->origin = p; 03351 linkprio(exten, pr); 03352 break; 03353 03354 case PV_CONTINUE: 03355 pr = new_prio(); 03356 pr->type = AEL_CONTROL1; /* simple goto */ 03357 pr->goto_true = exten->loop_continue; 03358 pr->origin = p; 03359 linkprio(exten, pr); 03360 break; 03361 03362 #ifdef OLD_RAND_ACTION 03363 case PV_RANDOM: 03364 control_statement_count++; 03365 snprintf(new_label,sizeof(new_label),"rand-%s-%d", label, control_statement_count); 03366 rand_test = new_prio(); 03367 rand_test->type = AEL_RAND_CONTROL; 03368 snprintf(buf1,sizeof(buf1),"$[%s]", 03369 p->u1.str ); 03370 rand_test->app = 0; 03371 rand_test->appargs = strdup(buf1); 03372 rand_test->origin = p; 03373 03374 rand_end = new_prio(); 03375 rand_end->type = AEL_APPCALL; 03376 snprintf(buf1,sizeof(buf1),"Finish rand-%s-%d", label, control_statement_count); 03377 rand_end->app = strdup("NoOp"); 03378 rand_end->appargs = strdup(buf1); 03379 03380 rand_skip = new_prio(); 03381 rand_skip->type = AEL_CONTROL1; /* simple goto */ 03382 rand_skip->goto_true = rand_end; 03383 rand_skip->origin = p; 03384 03385 rand_test->goto_true = rand_skip; /* +1, really */ 03386 03387 linkprio(exten, rand_test); 03388 03389 if (p->u3.else_statements) { 03390 gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the else statements here */ 03391 } 03392 03393 linkprio(exten, rand_skip); 03394 03395 gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the "true" statements here */ 03396 03397 linkprio(exten, rand_end); 03398 03399 break; 03400 #endif 03401 03402 case PV_IFTIME: 03403 control_statement_count++; 03404 snprintf(new_label,sizeof(new_label),"iftime-%s-%d", label, control_statement_count); 03405 03406 if_test = new_prio(); 03407 if_test->type = AEL_IFTIME_CONTROL; 03408 snprintf(buf1,sizeof(buf1),"%s|%s|%s|%s", 03409 p->u1.list->u1.str, 03410 p->u1.list->next->u1.str, 03411 p->u1.list->next->next->u1.str, 03412 p->u1.list->next->next->next->u1.str); 03413 if_test->app = 0; 03414 if_test->appargs = strdup(buf1); 03415 if_test->origin = p; 03416 03417 if_end = new_prio(); 03418 if_end->type = AEL_APPCALL; 03419 snprintf(buf1,sizeof(buf1),"Finish iftime-%s-%d", label, control_statement_count); 03420 if_end->app = strdup("NoOp"); 03421 if_end->appargs = strdup(buf1); 03422 03423 if (p->u3.else_statements) { 03424 if_skip = new_prio(); 03425 if_skip->type = AEL_CONTROL1; /* simple goto */ 03426 if_skip->goto_true = if_end; 03427 if_skip->origin = p; 03428 03429 } else { 03430 if_skip = 0; 03431 03432 if_test->goto_false = if_end; 03433 } 03434 03435 if_false = new_prio(); 03436 if_false->type = AEL_CONTROL1; 03437 if (p->u3.else_statements) { 03438 if_false->goto_true = if_skip; /* +1 */ 03439 } else { 03440 if_false->goto_true = if_end; 03441 } 03442 03443 /* link & load! */ 03444 linkprio(exten, if_test); 03445 linkprio(exten, if_false); 03446 03447 /* now, put the body of the if here */ 03448 03449 gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the statements here */ 03450 03451 if (p->u3.else_statements) { 03452 linkprio(exten, if_skip); 03453 gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the statements here */ 03454 03455 } 03456 03457 linkprio(exten, if_end); 03458 03459 break; 03460 03461 case PV_RANDOM: 03462 case PV_IF: 03463 control_statement_count++; 03464 snprintf(new_label,sizeof(new_label),"if-%s-%d", label, control_statement_count); 03465 03466 if_test = new_prio(); 03467 if_end = new_prio(); 03468 if_test->type = AEL_IF_CONTROL; 03469 if_end->type = AEL_APPCALL; 03470 if ( p->type == PV_RANDOM ) 03471 snprintf(buf1,sizeof(buf1),"$[${RAND(0,99)} < (%s)]",p->u1.str); 03472 else 03473 snprintf(buf1,sizeof(buf1),"$[%s]",p->u1.str); 03474 if_test->app = 0; 03475 if_test->appargs = strdup(buf1); 03476 snprintf(buf1,sizeof(buf1),"Finish if-%s-%d", label, control_statement_count); 03477 if_end->app = strdup("NoOp"); 03478 if_end->appargs = strdup(buf1); 03479 if_test->origin = p; 03480 03481 if (p->u3.else_statements) { 03482 if_skip = new_prio(); 03483 if_skip->type = AEL_CONTROL1; /* simple goto */ 03484 if_skip->goto_true = if_end; 03485 if_test->goto_false = if_skip;; 03486 } else { 03487 if_skip = 0; 03488 if_test->goto_false = if_end;; 03489 } 03490 03491 /* link & load! */ 03492 linkprio(exten, if_test); 03493 03494 /* now, put the body of the if here */ 03495 03496 gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the statements here */ 03497 03498 if (p->u3.else_statements) { 03499 linkprio(exten, if_skip); 03500 gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the statements here */ 03501 03502 } 03503 03504 linkprio(exten, if_end); 03505 03506 break; 03507 03508 case PV_STATEMENTBLOCK: 03509 gen_prios(exten, label, p->u1.list, mother_exten, this_context ); /* recurse into the block */ 03510 break; 03511 03512 case PV_CATCH: 03513 control_statement_count++; 03514 /* generate an extension with name of catch, put all catch stats 03515 into this exten! */ 03516 switch_case = new_exten(); 03517 switch_case->context = this_context; 03518 linkexten(exten,switch_case); 03519 switch_case->name = strdup(p->u1.str); 03520 snprintf(new_label,sizeof(new_label),"catch-%s-%d",p->u1.str, control_statement_count); 03521 03522 gen_prios(switch_case, new_label, p->u2.statements,mother_exten,this_context); /* this will link in all the catch body statements here */ 03523 if (switch_case->return_needed) { 03524 char buf[2000]; 03525 struct ael_priority *np2 = new_prio(); 03526 np2->type = AEL_APPCALL; 03527 np2->app = strdup("NoOp"); 03528 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); 03529 np2->appargs = strdup(buf); 03530 linkprio(switch_case, np2); 03531 switch_case-> return_target = np2; 03532 } 03533 03534 break; 03535 default: 03536 break; 03537 } 03538 } 03539 }
Definition at line 3700 of file pbx_ael.c.
References pval::dad, PV_CONTEXT, PV_MACRO, and pval::type.
Referenced by check_goto(), and get_goto_target().
03701 { 03702 while( p && p->type != PV_CONTEXT && p->type != PV_MACRO ) { 03703 03704 p = p->dad; 03705 } 03706 03707 return p; 03708 }
Definition at line 3690 of file pbx_ael.c.
References pval::dad, PV_CONTEXT, PV_EXTENSION, PV_MACRO, and pval::type.
Referenced by check_goto(), and get_goto_target().
03691 { 03692 while( p && p->type != PV_EXTENSION && p->type != PV_CONTEXT && p->type != PV_MACRO ) { 03693 03694 p = p->dad; 03695 } 03696 03697 return p; 03698 }
Definition at line 1121 of file pbx_ael.c.
References find_context(), find_label_in_current_context(), find_label_in_current_db(), find_label_in_current_extension(), get_contxt(), get_extension_or_contxt(), pval::list, pval::next, PV_INCLUDES, pval::statements, pval::str, pval::type, pval::u1, and pval::u2.
Referenced by gen_prios().
01122 { 01123 /* just one item-- the label should be in the current extension */ 01124 pval *curr_ext = get_extension_or_contxt(item); /* containing exten, or macro */ 01125 pval *curr_cont; 01126 01127 if (item->u1.list && !item->u1.list->next && !strstr((item->u1.list)->u1.str,"${")) { 01128 struct pval *x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), curr_ext); 01129 return x; 01130 } 01131 01132 curr_cont = get_contxt(item); 01133 01134 /* TWO items */ 01135 if (item->u1.list->next && !item->u1.list->next->next) { 01136 if (!strstr((item->u1.list)->u1.str,"${") 01137 && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ { 01138 struct pval *x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, curr_cont); 01139 return x; 01140 } 01141 } 01142 01143 /* All 3 items! */ 01144 if (item->u1.list->next && item->u1.list->next->next) { 01145 /* all three */ 01146 pval *first = item->u1.list; 01147 pval *second = item->u1.list->next; 01148 pval *third = item->u1.list->next->next; 01149 01150 if (!strstr((item->u1.list)->u1.str,"${") 01151 && !strstr(item->u1.list->next->u1.str,"${") 01152 && !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ { 01153 struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); 01154 if (!x) { 01155 01156 struct pval *p3; 01157 struct pval *that_context = find_context(item->u1.list->u1.str); 01158 01159 /* the target of the goto could be in an included context!! Fancy that!! */ 01160 /* look for includes in the current context */ 01161 if (that_context) { 01162 for (p3=that_context->u2.statements; p3; p3=p3->next) { 01163 if (p3->type == PV_INCLUDES) { 01164 struct pval *p4; 01165 for (p4=p3->u1.list; p4; p4=p4->next) { 01166 /* for each context pointed to, find it, then find a context/label that matches the 01167 target here! */ 01168 char *incl_context = p4->u1.str; 01169 /* find a matching context name */ 01170 struct pval *that_other_context = find_context(incl_context); 01171 if (that_other_context) { 01172 struct pval *x3; 01173 x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context); 01174 if (x3) { 01175 return x3; 01176 } 01177 } 01178 } 01179 } 01180 } 01181 } 01182 } 01183 return x; 01184 } 01185 } 01186 return 0; 01187 }
int is_empty | ( | char * | arg | ) |
int is_float | ( | char * | arg | ) |
int is_int | ( | char * | arg | ) |
static int label_inside_case | ( | pval * | label | ) | [static] |
Definition at line 2829 of file pbx_ael.c.
References pval::dad, PV_CASE, PV_CONTEXT, PV_DEFAULT, PV_MACRO, PV_PATTERN, and pval::type.
Referenced by gen_prios().
02830 { 02831 pval *p = label; 02832 02833 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ { 02834 if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN ) { 02835 return 1; 02836 } 02837 02838 p = p->dad; 02839 } 02840 return 0; 02841 }
static void linkexten | ( | struct ael_extension * | exten, | |
struct ael_extension * | add | |||
) | [static] |
Definition at line 2843 of file pbx_ael.c.
References exten, and ael_extension::next_exten.
Referenced by gen_prios().
02844 { 02845 add->next_exten = exten->next_exten; /* this will reverse the order. Big deal. */ 02846 exten->next_exten = add; 02847 }
void linkprio | ( | struct ael_extension * | exten, | |
struct ael_priority * | prio | |||
) |
Definition at line 2776 of file pbx_ael.c.
References ael_priority::exten, and exten.
Referenced by gen_prios().
02777 { 02778 if (!exten->plist) { 02779 exten->plist = prio; 02780 exten->plist_last = prio; 02781 } else { 02782 exten->plist_last->next = prio; 02783 exten->plist_last = prio; 02784 } 02785 if( !prio->exten ) 02786 prio->exten = exten; /* don't override the switch value */ 02787 }
static int load_module | ( | void | ) | [static] |
Definition at line 4084 of file pbx_ael.c.
References ast_cli_register_multiple(), cli_ael, and pbx_load_module().
04085 { 04086 ast_cli_register_multiple(cli_ael, sizeof(cli_ael) / sizeof(struct ast_cli_entry)); 04087 return (pbx_load_module()); 04088 }
Definition at line 1735 of file pbx_ael.c.
References match_pval_item(), and pval::next.
Referenced by find_context(), find_first_label_in_current_context(), find_label_in_current_context(), find_label_in_current_db(), find_label_in_current_extension(), find_macro(), and match_pval_item().
01736 { 01737 pval *i; 01738 01739 for (i=item; i; i=i->next) { 01740 pval *x; 01741 /* printf(" -- match pval: item %d\n", i->type); */ 01742 01743 if ((x = match_pval_item(i))) { 01744 /* printf("match_pval: returning x=%x\n", (int)x); */ 01745 return x; /* cut the search short */ 01746 } 01747 } 01748 return 0; 01749 }
Definition at line 1468 of file pbx_ael.c.
References pval::else_statements, extension_matches(), pval::for_statements, last_matched_label, pval::list, pval::macro_statements, match_pval(), pval::next, PV_CASE, PV_CATCH, PV_CONTEXT, PV_DEFAULT, PV_EXTENSION, PV_FOR, PV_IF, PV_IFTIME, PV_LABEL, 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 match_pval().
01469 { 01470 pval *x; 01471 01472 switch ( item->type ) { 01473 case PV_MACRO: 01474 /* fields: item->u1.str == name of macro 01475 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 01476 item->u2.arglist->u1.str == argument 01477 item->u2.arglist->next == next arg 01478 01479 item->u3.macro_statements == pval list of statements in macro body. 01480 */ 01481 /* printf(" matching in MACRO %s, match_context=%s; retoncontmtch=%d; \n", item->u1.str, match_context, return_on_context_match); */ 01482 if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) { 01483 01484 /* printf("MACRO: match context is: %s\n", match_context); */ 01485 01486 if (return_on_context_match && !strcmp(item->u1.str, match_context)) /* if we're just searching for a context, don't bother descending into them */ { 01487 /* printf("Returning on matching macro %s\n", match_context); */ 01488 return item; 01489 } 01490 01491 01492 if (!return_on_context_match) { 01493 /* printf("Descending into matching macro %s/%s\n", match_context, item->u1.str); */ 01494 if ((x=match_pval(item->u3.macro_statements))) { 01495 /* printf("Responded with pval match %x\n", x); */ 01496 return x; 01497 } 01498 } 01499 } else { 01500 /* printf("Skipping context/macro %s\n", item->u1.str); */ 01501 } 01502 01503 break; 01504 01505 case PV_CONTEXT: 01506 /* fields: item->u1.str == name of context 01507 item->u2.statements == pval list of statements in context body 01508 item->u3.abstract == int 1 if an abstract keyword were present 01509 */ 01510 /* printf(" matching in CONTEXT\n"); */ 01511 if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) { 01512 if (return_on_context_match && !strcmp(item->u1.str, match_context)) { 01513 /* printf("Returning on matching context %s\n", match_context); */ 01514 /* printf("non-CONTEXT: Responded with pval match %x\n", x); */ 01515 return item; 01516 } 01517 01518 if (!return_on_context_match ) { 01519 /* printf("Descending into matching context %s\n", match_context); */ 01520 if ((x=match_pval(item->u2.statements))) /* if we're just searching for a context, don't bother descending into them */ { 01521 /* printf("CONTEXT: Responded with pval match %x\n", x); */ 01522 return x; 01523 } 01524 } 01525 } else { 01526 /* printf("Skipping context/macro %s\n", item->u1.str); */ 01527 } 01528 break; 01529 01530 case PV_CASE: 01531 /* fields: item->u1.str == value of case 01532 item->u2.statements == pval list of statements under the case 01533 */ 01534 /* printf(" matching in CASE\n"); */ 01535 if ((x=match_pval(item->u2.statements))) { 01536 /* printf("CASE: Responded with pval match %x\n", x); */ 01537 return x; 01538 } 01539 break; 01540 01541 case PV_PATTERN: 01542 /* fields: item->u1.str == value of case 01543 item->u2.statements == pval list of statements under the case 01544 */ 01545 /* printf(" matching in PATTERN\n"); */ 01546 if ((x=match_pval(item->u2.statements))) { 01547 /* printf("PATTERN: Responded with pval match %x\n", x); */ 01548 return x; 01549 } 01550 break; 01551 01552 case PV_DEFAULT: 01553 /* fields: 01554 item->u2.statements == pval list of statements under the case 01555 */ 01556 /* printf(" matching in DEFAULT\n"); */ 01557 if ((x=match_pval(item->u2.statements))) { 01558 /* printf("DEFAULT: Responded with pval match %x\n", x); */ 01559 return x; 01560 } 01561 break; 01562 01563 case PV_CATCH: 01564 /* fields: item->u1.str == name of extension to catch 01565 item->u2.statements == pval list of statements in context body 01566 */ 01567 /* printf(" matching in CATCH\n"); */ 01568 if (!strcmp(match_exten,"*") || extension_matches(item, match_exten, item->u1.str) ) { 01569 /* printf("Descending into matching catch %s => %s\n", match_exten, item->u1.str); */ 01570 if (strcmp(match_label,"1") == 0) { 01571 if (item->u2.statements) { 01572 struct pval *p5 = item->u2.statements; 01573 while (p5 && p5->type == PV_LABEL) /* find the first non-label statement in this context. If it exists, there's a "1" */ 01574 p5 = p5->next; 01575 if (p5) 01576 return p5; 01577 else 01578 return 0; 01579 } 01580 else 01581 return 0; 01582 } 01583 01584 if ((x=match_pval(item->u2.statements))) { 01585 /* printf("CATCH: Responded with pval match %x\n", (unsigned int)x); */ 01586 return x; 01587 } 01588 } else { 01589 /* printf("Skipping catch %s\n", item->u1.str); */ 01590 } 01591 break; 01592 01593 case PV_STATEMENTBLOCK: 01594 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 01595 */ 01596 /* printf(" matching in STATEMENTBLOCK\n"); */ 01597 if ((x=match_pval(item->u1.list))) { 01598 /* printf("STATEMENTBLOCK: Responded with pval match %x\n", x); */ 01599 return x; 01600 } 01601 break; 01602 01603 case PV_LABEL: 01604 /* fields: item->u1.str == label name 01605 */ 01606 /* printf("PV_LABEL %s (cont=%s, exten=%s\n", 01607 item->u1.str, current_context->u1.str, (current_extension?current_extension->u1.str:"<macro>"));*/ 01608 01609 if (count_labels) { 01610 if (!strcmp(match_label, item->u1.str)) { 01611 label_count++; 01612 last_matched_label = item; 01613 } 01614 01615 } else { 01616 if (!strcmp(match_label, item->u1.str)) { 01617 /* printf("LABEL: Responded with pval match %x\n", x); */ 01618 return item; 01619 } 01620 } 01621 break; 01622 01623 case PV_FOR: 01624 /* fields: item->u1.for_init == a string containing the initalizer 01625 item->u2.for_test == a string containing the loop test 01626 item->u3.for_inc == a string containing the loop increment 01627 01628 item->u4.for_statements == a pval list of statements in the for () 01629 */ 01630 /* printf(" matching in FOR\n"); */ 01631 if ((x=match_pval(item->u4.for_statements))) { 01632 /* printf("FOR: Responded with pval match %x\n", x);*/ 01633 return x; 01634 } 01635 break; 01636 01637 case PV_WHILE: 01638 /* fields: item->u1.str == the while conditional, as supplied by user 01639 01640 item->u2.statements == a pval list of statements in the while () 01641 */ 01642 /* printf(" matching in WHILE\n"); */ 01643 if ((x=match_pval(item->u2.statements))) { 01644 /* printf("WHILE: Responded with pval match %x\n", x); */ 01645 return x; 01646 } 01647 break; 01648 01649 case PV_RANDOM: 01650 /* fields: item->u1.str == the random number expression, as supplied by user 01651 01652 item->u2.statements == a pval list of statements in the if () 01653 item->u3.else_statements == a pval list of statements in the else 01654 (could be zero) 01655 fall thru to PV_IF */ 01656 01657 case PV_IFTIME: 01658 /* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list 01659 01660 item->u2.statements == a pval list of statements in the if () 01661 item->u3.else_statements == a pval list of statements in the else 01662 (could be zero) 01663 fall thru to PV_IF*/ 01664 case PV_IF: 01665 /* fields: item->u1.str == the if conditional, as supplied by user 01666 01667 item->u2.statements == a pval list of statements in the if () 01668 item->u3.else_statements == a pval list of statements in the else 01669 (could be zero) 01670 */ 01671 /* printf(" matching in IF/IFTIME/RANDOM\n"); */ 01672 if ((x=match_pval(item->u2.statements))) { 01673 return x; 01674 } 01675 if (item->u3.else_statements) { 01676 if ((x=match_pval(item->u3.else_statements))) { 01677 /* printf("IF/IFTIME/RANDOM: Responded with pval match %x\n", x); */ 01678 return x; 01679 } 01680 } 01681 break; 01682 01683 case PV_SWITCH: 01684 /* fields: item->u1.str == the switch expression 01685 01686 item->u2.statements == a pval list of statements in the switch, 01687 (will be case statements, most likely!) 01688 */ 01689 /* printf(" matching in SWITCH\n"); */ 01690 if ((x=match_pval(item->u2.statements))) { 01691 /* printf("SWITCH: Responded with pval match %x\n", x); */ 01692 return x; 01693 } 01694 break; 01695 01696 case PV_EXTENSION: 01697 /* fields: item->u1.str == the extension name, label, whatever it's called 01698 01699 item->u2.statements == a pval list of statements in the extension 01700 item->u3.hints == a char * hint argument 01701 item->u4.regexten == an int boolean. non-zero says that regexten was specified 01702 */ 01703 /* printf(" matching in EXTENSION\n"); */ 01704 if (!strcmp(match_exten,"*") || extension_matches(item, match_exten, item->u1.str) ) { 01705 /* printf("Descending into matching exten %s => %s\n", match_exten, item->u1.str); */ 01706 if (strcmp(match_label,"1") == 0) { 01707 if (item->u2.statements) { 01708 struct pval *p5 = item->u2.statements; 01709 while (p5 && p5->type == PV_LABEL) /* find the first non-label statement in this context. If it exists, there's a "1" */ 01710 p5 = p5->next; 01711 if (p5) 01712 return p5; 01713 else 01714 return 0; 01715 } 01716 else 01717 return 0; 01718 } 01719 01720 if ((x=match_pval(item->u2.statements))) { 01721 /* printf("EXTENSION: Responded with pval match %x\n", x); */ 01722 return x; 01723 } 01724 } else { 01725 /* printf("Skipping exten %s\n", item->u1.str); */ 01726 } 01727 break; 01728 default: 01729 /* printf(" matching in default = %d\n", item->type); */ 01730 break; 01731 } 01732 return 0; 01733 }
struct ael_extension * new_exten | ( | void | ) |
Definition at line 2770 of file pbx_ael.c.
References calloc.
Referenced by gen_prios().
02771 { 02772 struct ael_extension *x = (struct ael_extension *)calloc(sizeof(struct ael_extension),1); 02773 return x; 02774 }
struct ael_priority * new_prio | ( | void | ) |
Definition at line 2764 of file pbx_ael.c.
References calloc.
Referenced by gen_prios().
02765 { 02766 struct ael_priority *x = (struct ael_priority *)calloc(sizeof(struct ael_priority),1); 02767 return x; 02768 }
static int pbx_load_module | ( | void | ) | [static] |
Definition at line 3971 of file pbx_ael.c.
References ael2_parse(), ael2_semantic_check(), ast_compile_ael2(), ast_config_AST_CONFIG_DIR, ast_context_verify_includes(), ast_log(), ast_merge_contexts_and_delete(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_walk_contexts(), destroy_pval(), local_contexts, LOG_ERROR, and LOG_NOTICE.
Referenced by ael2_reload(), handle_reload_extensions(), load_module(), and reload().
03972 { 03973 int errs, sem_err, sem_warn, sem_note; 03974 char *rfilename; 03975 struct ast_context *local_contexts=NULL, *con; 03976 struct pval *parse_tree; 03977 03978 ast_log(LOG_NOTICE, "Starting AEL load process.\n"); 03979 if (config[0] == '/') 03980 rfilename = (char *)config; 03981 else { 03982 rfilename = alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2); 03983 sprintf(rfilename, "%s/%s", ast_config_AST_CONFIG_DIR, config); 03984 } 03985 ast_log(LOG_NOTICE, "AEL load process: calculated config file name '%s'.\n", rfilename); 03986 03987 if (access(rfilename,R_OK) != 0) { 03988 ast_log(LOG_NOTICE, "File %s not found; AEL declining load\n", rfilename); 03989 return AST_MODULE_LOAD_DECLINE; 03990 } 03991 03992 parse_tree = ael2_parse(rfilename, &errs); 03993 ast_log(LOG_NOTICE, "AEL load process: parsed config file name '%s'.\n", rfilename); 03994 ael2_semantic_check(parse_tree, &sem_err, &sem_warn, &sem_note); 03995 if (errs == 0 && sem_err == 0) { 03996 ast_log(LOG_NOTICE, "AEL load process: checked config file name '%s'.\n", rfilename); 03997 ast_compile_ael2(&local_contexts, parse_tree); 03998 ast_log(LOG_NOTICE, "AEL load process: compiled config file name '%s'.\n", rfilename); 03999 04000 ast_merge_contexts_and_delete(&local_contexts, registrar); 04001 ast_log(LOG_NOTICE, "AEL load process: merged config file name '%s'.\n", rfilename); 04002 for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con)) 04003 ast_context_verify_includes(con); 04004 ast_log(LOG_NOTICE, "AEL load process: verified config file name '%s'.\n", rfilename); 04005 } else { 04006 ast_log(LOG_ERROR, "Sorry, but %d syntax errors and %d semantic errors were detected. It doesn't make sense to compile.\n", errs, sem_err); 04007 destroy_pval(parse_tree); /* free up the memory */ 04008 return AST_MODULE_LOAD_DECLINE; 04009 } 04010 destroy_pval(parse_tree); /* free up the memory */ 04011 04012 return AST_MODULE_LOAD_SUCCESS; 04013 }
static void print_pval | ( | FILE * | fin, | |
pval * | item, | |||
int | depth | |||
) | [static] |
Definition at line 174 of file pbx_ael.c.
References pval::arglist, pval::next, PV_MACRO, PV_WORD, pval::str, pval::type, pval::u1, and pval::u2.
Referenced by print_pval_list().
00175 { 00176 int i; 00177 pval *lp; 00178 00179 for (i=0; i<depth; i++) { 00180 fprintf(fin, "\t"); /* depth == indentation */ 00181 } 00182 00183 switch ( item->type ) { 00184 case PV_WORD: 00185 fprintf(fin,"%s;\n", item->u1.str); /* usually, words are encapsulated in something else */ 00186 break; 00187 00188 case PV_MACRO: 00189 fprintf(fin,"macro %s(", item->u1.str); 00190 for (lp=item->u2.arglist; lp; lp=lp->next) { 00191 if (lp != item->u2.arglist ) 00192 fprintf(fin,", "); 00193 fprintf(fin,"%s", lp->u1.str); 00194 } 00195 fprintf(fin,") {\n"); 00196 print_pval_list(fin,item->u3.macro_statements,depth+1); 00197 for (i=0; i<depth; i++) { 00198 fprintf(fin,"\t"); /* depth == indentation */ 00199 } 00200 fprintf(fin,"};\n\n"); 00201 break; 00202 00203 case PV_CONTEXT: 00204 if ( item->u3.abstract ) 00205 fprintf(fin,"abstract context %s {\n", item->u1.str); 00206 else 00207 fprintf(fin,"context %s {\n", item->u1.str); 00208 print_pval_list(fin,item->u2.statements,depth+1); 00209 for (i=0; i<depth; i++) { 00210 fprintf(fin,"\t"); /* depth == indentation */ 00211 } 00212 fprintf(fin,"};\n\n"); 00213 break; 00214 00215 case PV_MACRO_CALL: 00216 fprintf(fin,"&%s(", item->u1.str); 00217 for (lp=item->u2.arglist; lp; lp=lp->next) { 00218 if ( lp != item->u2.arglist ) 00219 fprintf(fin,", "); 00220 fprintf(fin,"%s", lp->u1.str); 00221 } 00222 fprintf(fin,");\n"); 00223 break; 00224 00225 case PV_APPLICATION_CALL: 00226 fprintf(fin,"%s(", item->u1.str); 00227 for (lp=item->u2.arglist; lp; lp=lp->next) { 00228 if ( lp != item->u2.arglist ) 00229 fprintf(fin,","); 00230 fprintf(fin,"%s", lp->u1.str); 00231 } 00232 fprintf(fin,");\n"); 00233 break; 00234 00235 case PV_CASE: 00236 fprintf(fin,"case %s:\n", item->u1.str); 00237 print_pval_list(fin,item->u2.statements, depth+1); 00238 break; 00239 00240 case PV_PATTERN: 00241 fprintf(fin,"pattern %s:\n", item->u1.str); 00242 print_pval_list(fin,item->u2.statements, depth+1); 00243 break; 00244 00245 case PV_DEFAULT: 00246 fprintf(fin,"default:\n"); 00247 print_pval_list(fin,item->u2.statements, depth+1); 00248 break; 00249 00250 case PV_CATCH: 00251 fprintf(fin,"catch %s {\n", item->u1.str); 00252 print_pval_list(fin,item->u2.statements, depth+1); 00253 for (i=0; i<depth; i++) { 00254 fprintf(fin,"\t"); /* depth == indentation */ 00255 } 00256 fprintf(fin,"};\n"); 00257 break; 00258 00259 case PV_SWITCHES: 00260 fprintf(fin,"switches {\n"); 00261 print_pval_list(fin,item->u1.list,depth+1); 00262 for (i=0; i<depth; i++) { 00263 fprintf(fin,"\t"); /* depth == indentation */ 00264 } 00265 fprintf(fin,"};\n"); 00266 break; 00267 00268 case PV_ESWITCHES: 00269 fprintf(fin,"eswitches {\n"); 00270 print_pval_list(fin,item->u1.list,depth+1); 00271 for (i=0; i<depth; i++) { 00272 fprintf(fin,"\t"); /* depth == indentation */ 00273 } 00274 fprintf(fin,"};\n"); 00275 break; 00276 00277 case PV_INCLUDES: 00278 fprintf(fin,"includes {\n"); 00279 for (lp=item->u1.list; lp; lp=lp->next) { 00280 for (i=0; i<depth+1; i++) { 00281 fprintf(fin,"\t"); /* depth == indentation */ 00282 } 00283 fprintf(fin,"%s", lp->u1.str); /* usually, words are encapsulated in something else */ 00284 if ( lp->u2.arglist ) 00285 fprintf(fin,"|%s|%s|%s|%s", 00286 lp->u2.arglist->u1.str, 00287 lp->u2.arglist->next->u1.str, 00288 lp->u2.arglist->next->next->u1.str, 00289 lp->u2.arglist->next->next->next->u1.str 00290 ); 00291 fprintf(fin,";\n"); /* usually, words are encapsulated in something else */ 00292 } 00293 00294 print_pval_list(fin,item->u1.list,depth+1); 00295 for (i=0; i<depth; i++) { 00296 fprintf(fin,"\t"); /* depth == indentation */ 00297 } 00298 fprintf(fin,"};\n"); 00299 break; 00300 00301 case PV_STATEMENTBLOCK: 00302 fprintf(fin,"{\n"); 00303 print_pval_list(fin,item->u1.list, depth+1); 00304 for (i=0; i<depth; i++) { 00305 fprintf(fin,"\t"); /* depth == indentation */ 00306 } 00307 fprintf(fin,"};\n"); 00308 break; 00309 00310 case PV_VARDEC: 00311 fprintf(fin,"%s=%s;\n", item->u1.str, item->u2.val); 00312 break; 00313 00314 case PV_GOTO: 00315 fprintf(fin,"goto %s", item->u1.list->u1.str); 00316 if ( item->u1.list->next ) 00317 fprintf(fin,"|%s", item->u1.list->next->u1.str); 00318 if ( item->u1.list->next && item->u1.list->next->next ) 00319 fprintf(fin,"|%s", item->u1.list->next->next->u1.str); 00320 fprintf(fin,"\n"); 00321 break; 00322 00323 case PV_LABEL: 00324 fprintf(fin,"%s:\n", item->u1.str); 00325 break; 00326 00327 case PV_FOR: 00328 fprintf(fin,"for (%s; %s; %s)\n", item->u1.for_init, item->u2.for_test, item->u3.for_inc); 00329 print_pval_list(fin,item->u4.for_statements,depth+1); 00330 break; 00331 00332 case PV_WHILE: 00333 fprintf(fin,"while (%s)\n", item->u1.str); 00334 print_pval_list(fin,item->u2.statements,depth+1); 00335 break; 00336 00337 case PV_BREAK: 00338 fprintf(fin,"break;\n"); 00339 break; 00340 00341 case PV_RETURN: 00342 fprintf(fin,"return;\n"); 00343 break; 00344 00345 case PV_CONTINUE: 00346 fprintf(fin,"continue;\n"); 00347 break; 00348 00349 case PV_RANDOM: 00350 case PV_IFTIME: 00351 case PV_IF: 00352 if ( item->type == PV_IFTIME ) { 00353 00354 fprintf(fin,"ifTime ( %s|%s|%s|%s )\n", 00355 item->u1.list->u1.str, 00356 item->u1.list->next->u1.str, 00357 item->u1.list->next->next->u1.str, 00358 item->u1.list->next->next->next->u1.str 00359 ); 00360 } else if ( item->type == PV_RANDOM ) { 00361 fprintf(fin,"random ( %s )\n", item->u1.str ); 00362 } else 00363 fprintf(fin,"if ( %s )\n", item->u1.str); 00364 if ( item->u2.statements && item->u2.statements->next ) { 00365 for (i=0; i<depth; i++) { 00366 fprintf(fin,"\t"); /* depth == indentation */ 00367 } 00368 fprintf(fin,"{\n"); 00369 print_pval_list(fin,item->u2.statements,depth+1); 00370 for (i=0; i<depth; i++) { 00371 fprintf(fin,"\t"); /* depth == indentation */ 00372 } 00373 if ( item->u3.else_statements ) 00374 fprintf(fin,"}\n"); 00375 else 00376 fprintf(fin,"};\n"); 00377 } else if (item->u2.statements ) { 00378 print_pval_list(fin,item->u2.statements,depth+1); 00379 } else { 00380 if (item->u3.else_statements ) 00381 fprintf(fin, " {} "); 00382 else 00383 fprintf(fin, " {}; "); 00384 } 00385 if ( item->u3.else_statements ) { 00386 for (i=0; i<depth; i++) { 00387 fprintf(fin,"\t"); /* depth == indentation */ 00388 } 00389 fprintf(fin,"else\n"); 00390 print_pval_list(fin,item->u3.else_statements, depth); 00391 } 00392 break; 00393 00394 case PV_SWITCH: 00395 fprintf(fin,"switch( %s ) {\n", item->u1.str); 00396 print_pval_list(fin,item->u2.statements,depth+1); 00397 for (i=0; i<depth; i++) { 00398 fprintf(fin,"\t"); /* depth == indentation */ 00399 } 00400 fprintf(fin,"}\n"); 00401 break; 00402 00403 case PV_EXTENSION: 00404 if ( item->u4.regexten ) 00405 fprintf(fin, "regexten "); 00406 if ( item->u3.hints ) 00407 fprintf(fin,"hints(%s) ", item->u3.hints); 00408 00409 fprintf(fin,"%s => \n", item->u1.str); 00410 print_pval_list(fin,item->u2.statements,depth+1); 00411 break; 00412 00413 case PV_IGNOREPAT: 00414 fprintf(fin,"ignorepat => %s\n", item->u1.str); 00415 break; 00416 00417 case PV_GLOBALS: 00418 fprintf(fin,"globals {\n"); 00419 print_pval_list(fin,item->u1.statements,depth+1); 00420 for (i=0; i<depth; i++) { 00421 fprintf(fin,"\t"); /* depth == indentation */ 00422 } 00423 fprintf(fin,"}\n"); 00424 break; 00425 } 00426 }
static void print_pval_list | ( | FILE * | fin, | |
pval * | item, | |||
int | depth | |||
) | [static] |
Definition at line 428 of file pbx_ael.c.
References pval::next, and print_pval().
00429 { 00430 pval *i; 00431 00432 for (i=item; i; i=i->next) { 00433 print_pval(fin, i, depth); 00434 } 00435 }
static int reload | ( | void | ) | [static] |
Definition at line 4090 of file pbx_ael.c.
References pbx_load_module().
04091 { 04092 return pbx_load_module(); 04093 }
static void remove_spaces_before_equals | ( | char * | str | ) | [static] |
Definition at line 2849 of file pbx_ael.c.
Referenced by gen_prios().
02850 { 02851 char *p; 02852 while( str && *str && *str != '=' ) 02853 { 02854 if( *str == ' ' || *str == '\n' || *str == '\r' || *str == '\t' ) 02855 { 02856 p = str; 02857 while( *p ) 02858 { 02859 *p = *(p+1); 02860 p++; 02861 } 02862 } 02863 else 02864 str++; 02865 } 02866 }
void set_priorities | ( | struct ael_extension * | exten | ) |
Definition at line 3541 of file pbx_ael.c.
References exten, ael_priority::next, ael_priority::origin, ael_priority::priority_num, PV_LABEL, and pval::type.
03542 { 03543 int i; 03544 struct ael_priority *pr; 03545 do { 03546 if (exten->is_switch) 03547 i = 10; 03548 else if (exten->regexten) 03549 i=2; 03550 else 03551 i=1; 03552 03553 for (pr=exten->plist; pr; pr=pr->next) { 03554 pr->priority_num = i; 03555 03556 if (!pr->origin || (pr->origin && pr->origin->type != PV_LABEL) ) /* Labels don't show up in the dialplan, 03557 but we want them to point to the right 03558 priority, which would be the next line 03559 after the label; */ 03560 i++; 03561 } 03562 03563 exten = exten->next_exten; 03564 } while ( exten ); 03565 }
static void substitute_commas | ( | char * | str | ) | [static] |
Definition at line 151 of file pbx_ael.c.
Referenced by gen_prios().
00152 { 00153 char *p = str; 00154 00155 while (p && *p) 00156 { 00157 if (*p == ',' && ((p != str && *(p-1) != '\\') 00158 || p == str)) 00159 *p = '|'; 00160 if (*p == '\\' && *(p+1) == ',') { /* learning experience: the '\,' is turned into just ',' by pbx_config; So we need to do the same */ 00161 char *q = p; 00162 while (*q) { /* move the ',' and everything after it up 1 char */ 00163 *q = *(q+1); 00164 q++; 00165 } 00166 } 00167 p++; 00168 } 00169 }
void traverse_pval_item_template | ( | pval * | item, | |
int | depth | |||
) |
Definition at line 457 of file pbx_ael.c.
References pval::arglist, pval::else_statements, pval::for_statements, pval::list, pval::macro_statements, pval::next, 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::type, pval::u1, pval::u2, pval::u3, and pval::u4.
Referenced by traverse_pval_template().
00459 { 00460 pval *lp; 00461 00462 switch ( item->type ) { 00463 case PV_WORD: 00464 /* fields: item->u1.str == string associated with this (word). */ 00465 break; 00466 00467 case PV_MACRO: 00468 /* fields: item->u1.str == name of macro 00469 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 00470 item->u2.arglist->u1.str == argument 00471 item->u2.arglist->next == next arg 00472 00473 item->u3.macro_statements == pval list of statements in macro body. 00474 */ 00475 for (lp=item->u2.arglist; lp; lp=lp->next) { 00476 00477 } 00478 traverse_pval_item_template(item->u3.macro_statements,depth+1); 00479 break; 00480 00481 case PV_CONTEXT: 00482 /* fields: item->u1.str == name of context 00483 item->u2.statements == pval list of statements in context body 00484 item->u3.abstract == int 1 if an abstract keyword were present 00485 */ 00486 traverse_pval_item_template(item->u2.statements,depth+1); 00487 break; 00488 00489 case PV_MACRO_CALL: 00490 /* fields: item->u1.str == name of macro to call 00491 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 00492 item->u2.arglist->u1.str == argument 00493 item->u2.arglist->next == next arg 00494 */ 00495 for (lp=item->u2.arglist; lp; lp=lp->next) { 00496 } 00497 break; 00498 00499 case PV_APPLICATION_CALL: 00500 /* fields: item->u1.str == name of application to call 00501 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 00502 item->u2.arglist->u1.str == argument 00503 item->u2.arglist->next == next arg 00504 */ 00505 for (lp=item->u2.arglist; lp; lp=lp->next) { 00506 } 00507 break; 00508 00509 case PV_CASE: 00510 /* fields: item->u1.str == value of case 00511 item->u2.statements == pval list of statements under the case 00512 */ 00513 traverse_pval_item_template(item->u2.statements,depth+1); 00514 break; 00515 00516 case PV_PATTERN: 00517 /* fields: item->u1.str == value of case 00518 item->u2.statements == pval list of statements under the case 00519 */ 00520 traverse_pval_item_template(item->u2.statements,depth+1); 00521 break; 00522 00523 case PV_DEFAULT: 00524 /* fields: 00525 item->u2.statements == pval list of statements under the case 00526 */ 00527 traverse_pval_item_template(item->u2.statements,depth+1); 00528 break; 00529 00530 case PV_CATCH: 00531 /* fields: item->u1.str == name of extension to catch 00532 item->u2.statements == pval list of statements in context body 00533 */ 00534 traverse_pval_item_template(item->u2.statements,depth+1); 00535 break; 00536 00537 case PV_SWITCHES: 00538 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 00539 */ 00540 traverse_pval_item_template(item->u1.list,depth+1); 00541 break; 00542 00543 case PV_ESWITCHES: 00544 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 00545 */ 00546 traverse_pval_item_template(item->u1.list,depth+1); 00547 break; 00548 00549 case PV_INCLUDES: 00550 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 00551 item->u2.arglist == pval list of 4 PV_WORD elements for time values 00552 */ 00553 traverse_pval_item_template(item->u1.list,depth+1); 00554 traverse_pval_item_template(item->u2.arglist,depth+1); 00555 break; 00556 00557 case PV_STATEMENTBLOCK: 00558 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 00559 */ 00560 traverse_pval_item_template(item->u1.list,depth+1); 00561 break; 00562 00563 case PV_VARDEC: 00564 /* fields: item->u1.str == variable name 00565 item->u2.val == variable value to assign 00566 */ 00567 break; 00568 00569 case PV_GOTO: 00570 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 00571 item->u1.list->u1.str == where the data on a PV_WORD will always be. 00572 */ 00573 00574 if ( item->u1.list->next ) 00575 ; 00576 if ( item->u1.list->next && item->u1.list->next->next ) 00577 ; 00578 00579 break; 00580 00581 case PV_LABEL: 00582 /* fields: item->u1.str == label name 00583 */ 00584 break; 00585 00586 case PV_FOR: 00587 /* fields: item->u1.for_init == a string containing the initalizer 00588 item->u2.for_test == a string containing the loop test 00589 item->u3.for_inc == a string containing the loop increment 00590 00591 item->u4.for_statements == a pval list of statements in the for () 00592 */ 00593 traverse_pval_item_template(item->u4.for_statements,depth+1); 00594 break; 00595 00596 case PV_WHILE: 00597 /* fields: item->u1.str == the while conditional, as supplied by user 00598 00599 item->u2.statements == a pval list of statements in the while () 00600 */ 00601 traverse_pval_item_template(item->u2.statements,depth+1); 00602 break; 00603 00604 case PV_BREAK: 00605 /* fields: none 00606 */ 00607 break; 00608 00609 case PV_RETURN: 00610 /* fields: none 00611 */ 00612 break; 00613 00614 case PV_CONTINUE: 00615 /* fields: none 00616 */ 00617 break; 00618 00619 case PV_IFTIME: 00620 /* fields: item->u1.list == there are 4 linked PV_WORDs here. 00621 00622 item->u2.statements == a pval list of statements in the if () 00623 item->u3.else_statements == a pval list of statements in the else 00624 (could be zero) 00625 */ 00626 traverse_pval_item_template(item->u2.statements,depth+1); 00627 if ( item->u3.else_statements ) { 00628 traverse_pval_item_template(item->u3.else_statements,depth+1); 00629 } 00630 break; 00631 00632 case PV_RANDOM: 00633 /* fields: item->u1.str == the random number expression, as supplied by user 00634 00635 item->u2.statements == a pval list of statements in the if () 00636 item->u3.else_statements == a pval list of statements in the else 00637 (could be zero) 00638 */ 00639 traverse_pval_item_template(item->u2.statements,depth+1); 00640 if ( item->u3.else_statements ) { 00641 traverse_pval_item_template(item->u3.else_statements,depth+1); 00642 } 00643 break; 00644 00645 case PV_IF: 00646 /* fields: item->u1.str == the if conditional, as supplied by user 00647 00648 item->u2.statements == a pval list of statements in the if () 00649 item->u3.else_statements == a pval list of statements in the else 00650 (could be zero) 00651 */ 00652 traverse_pval_item_template(item->u2.statements,depth+1); 00653 if ( item->u3.else_statements ) { 00654 traverse_pval_item_template(item->u3.else_statements,depth+1); 00655 } 00656 break; 00657 00658 case PV_SWITCH: 00659 /* fields: item->u1.str == the switch expression 00660 00661 item->u2.statements == a pval list of statements in the switch, 00662 (will be case statements, most likely!) 00663 */ 00664 traverse_pval_item_template(item->u2.statements,depth+1); 00665 break; 00666 00667 case PV_EXTENSION: 00668 /* fields: item->u1.str == the extension name, label, whatever it's called 00669 00670 item->u2.statements == a pval list of statements in the extension 00671 item->u3.hints == a char * hint argument 00672 item->u4.regexten == an int boolean. non-zero says that regexten was specified 00673 */ 00674 traverse_pval_item_template(item->u2.statements,depth+1); 00675 break; 00676 00677 case PV_IGNOREPAT: 00678 /* fields: item->u1.str == the ignorepat data 00679 */ 00680 break; 00681 00682 case PV_GLOBALS: 00683 /* fields: item->u1.statements == pval list of statements, usually vardecs 00684 */ 00685 traverse_pval_item_template(item->u1.statements,depth+1); 00686 break; 00687 } 00688 }
void traverse_pval_template | ( | pval * | item, | |
int | depth | |||
) |
Definition at line 690 of file pbx_ael.c.
References pval::next, and traverse_pval_item_template().
00692 { 00693 pval *i; 00694 00695 for (i=item; i; i=i->next) { 00696 traverse_pval_item_template(i, depth); 00697 } 00698 }
static int unload_module | ( | void | ) | [static] |
Definition at line 4077 of file pbx_ael.c.
References ast_cli_unregister_multiple(), ast_context_destroy(), and cli_ael.
04078 { 04079 ast_context_destroy(NULL, registrar); 04080 ast_cli_unregister_multiple(cli_ael, sizeof(cli_ael) / sizeof(struct ast_cli_entry)); 04081 return 0; 04082 }
struct ast_cli_entry cli_ael[] [static] |
struct ast_cli_entry cli_ael_no_debug [static] |
Initial value:
{ { "ael", "no", "debug", NULL }, ael2_no_debug, NULL, NULL }
int control_statement_count = 0 [static] |
int count_labels [static] |
pval* current_context [static] |
pval* current_db [static] |
Definition at line 112 of file pbx_ael.c.
Referenced by ael2_semantic_check(), check_abstract_reference(), check_context_names(), find_context(), find_label_in_current_db(), and find_macro().
pval* current_extension [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* registrar = "pbx_ael" [static] |
Definition at line 61 of file pbx_ael.c.
Referenced by park_add_hints(), pbx_load_module(), and pbx_load_users().
int return_on_context_match [static] |