#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, struct ael_extension *mother_exten) |
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 = 0 |
static pval * | current_db = 0 |
static pval * | current_extension = 0 |
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 3726 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.
03727 { 03728 struct ael_priority *pr; 03729 char *label=0; 03730 char realext[AST_MAX_EXTENSION]; 03731 if (!exten) { 03732 ast_log(LOG_WARNING, "This file is Empty!\n" ); 03733 return; 03734 } 03735 do { 03736 struct ael_priority *last = 0; 03737 03738 memset(realext, '\0', sizeof(realext)); 03739 pbx_substitute_variables_helper(NULL, exten->name, realext, sizeof(realext) - 1); 03740 if (exten->hints) { 03741 if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, PRIORITY_HINT, NULL, exten->cidmatch, 03742 exten->hints, NULL, ast_free, registrar)) { 03743 ast_log(LOG_WARNING, "Unable to add step at priority 'hint' of extension '%s'\n", 03744 exten->name); 03745 } 03746 } 03747 03748 for (pr=exten->plist; pr; pr=pr->next) { 03749 char app[2000]; 03750 char appargs[2000]; 03751 03752 /* before we can add the extension, we need to prep the app/appargs; 03753 the CONTROL types need to be done after the priority numbers are calculated. 03754 */ 03755 if (pr->type == AEL_LABEL) /* don't try to put labels in the dialplan! */ { 03756 last = pr; 03757 continue; 03758 } 03759 03760 if (pr->app) 03761 strcpy(app, pr->app); 03762 else 03763 app[0] = 0; 03764 if (pr->appargs ) 03765 strcpy(appargs, pr->appargs); 03766 else 03767 appargs[0] = 0; 03768 switch( pr->type ) { 03769 case AEL_APPCALL: 03770 /* easy case. Everything is all set up */ 03771 break; 03772 03773 case AEL_CONTROL1: /* FOR loop, WHILE loop, BREAK, CONTINUE, IF, IFTIME */ 03774 /* simple, unconditional goto. */ 03775 strcpy(app,"Goto"); 03776 if (pr->goto_true->origin && pr->goto_true->origin->type == PV_SWITCH ) { 03777 snprintf(appargs,sizeof(appargs),"%s|%d", pr->goto_true->exten->name, pr->goto_true->priority_num); 03778 } else if (pr->goto_true->origin && pr->goto_true->origin->type == PV_IFTIME && pr->goto_true->origin->u3.else_statements ) { 03779 snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num+1); 03780 } else 03781 snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num); 03782 break; 03783 03784 case AEL_FOR_CONTROL: /* WHILE loop test, FOR loop test */ 03785 strcpy(app,"GotoIf"); 03786 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); 03787 break; 03788 03789 case AEL_IF_CONTROL: 03790 strcpy(app,"GotoIf"); 03791 if (pr->origin->u3.else_statements ) 03792 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num+1); 03793 else 03794 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); 03795 break; 03796 03797 case AEL_RAND_CONTROL: 03798 strcpy(app,"Random"); 03799 snprintf(appargs,sizeof(appargs),"%s:%d", pr->appargs, pr->goto_true->priority_num+1); 03800 break; 03801 03802 case AEL_IFTIME_CONTROL: 03803 strcpy(app,"GotoIfTime"); 03804 snprintf(appargs,sizeof(appargs),"%s?%d", pr->appargs, pr->priority_num+2); 03805 break; 03806 03807 case AEL_RETURN: 03808 strcpy(app,"Goto"); 03809 snprintf(appargs,sizeof(appargs), "%d", exten->return_target->priority_num); 03810 break; 03811 03812 default: 03813 break; 03814 } 03815 if (last && last->type == AEL_LABEL ) { 03816 label = last->origin->u1.str; 03817 } 03818 else 03819 label = 0; 03820 03821 if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, pr->priority_num, (label?label:NULL), exten->cidmatch, 03822 app, strdup(appargs), ast_free, registrar)) { 03823 ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num, 03824 exten->name); 03825 } 03826 last = pr; 03827 } 03828 exten = exten->next_exten; 03829 } while ( exten ); 03830 }
static int ael2_debug_contexts | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4193 of file pbx_ael.c.
References DEBUG_CONTEXTS.
04194 { 04195 aeldebug |= DEBUG_CONTEXTS; 04196 return 0; 04197 }
static int ael2_debug_macros | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4187 of file pbx_ael.c.
References DEBUG_MACROS.
04188 { 04189 aeldebug |= DEBUG_MACROS; 04190 return 0; 04191 }
static int ael2_debug_read | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4175 of file pbx_ael.c.
References DEBUG_READ.
04176 { 04177 aeldebug |= DEBUG_READ; 04178 return 0; 04179 }
static int ael2_debug_tokens | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4181 of file pbx_ael.c.
References DEBUG_TOKENS.
04182 { 04183 aeldebug |= DEBUG_TOKENS; 04184 return 0; 04185 }
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 4205 of file pbx_ael.c.
References pbx_load_module().
04206 { 04207 return (pbx_load_module()); 04208 }
static void ael2_semantic_check | ( | pval * | item, | |
int * | arg_errs, | |||
int * | arg_warns, | |||
int * | arg_notes | |||
) | [static] |
Definition at line 2728 of file pbx_ael.c.
References ast_config_AST_VAR_DIR, check_context_names(), check_pval(), and current_db.
Referenced by pbx_load_module().
02729 { 02730 02731 #ifdef AAL_ARGCHECK 02732 int argapp_errs =0; 02733 char *rfilename; 02734 #endif 02735 struct argapp *apps=0; 02736 02737 if (!item) 02738 return; /* don't check an empty tree */ 02739 #ifdef AAL_ARGCHECK 02740 rfilename = alloca(10 + strlen(ast_config_AST_VAR_DIR)); 02741 sprintf(rfilename, "%s/applist", ast_config_AST_VAR_DIR); 02742 02743 apps = argdesc_parse(rfilename, &argapp_errs); /* giveth */ 02744 #endif 02745 current_db = item; 02746 errs = warns = notes = 0; 02747 02748 check_context_names(); 02749 check_pval(item, apps, 0); 02750 02751 #ifdef AAL_ARGCHECK 02752 argdesc_destroy(apps); /* taketh away */ 02753 #endif 02754 current_db = 0; 02755 02756 *arg_errs = errs; 02757 *arg_warns = warns; 02758 *arg_notes = notes; 02759 }
void ast_compile_ael2 | ( | struct ast_context ** | local_contexts, | |
struct pval * | root | |||
) |
Definition at line 3913 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().
03914 { 03915 pval *p,*p2; 03916 struct ast_context *context; 03917 char buf[2000]; 03918 struct ael_extension *exten; 03919 struct ael_extension *exten_list = 0; 03920 03921 for (p=root; p; p=p->next ) { /* do the globals first, so they'll be there 03922 when we try to eval them */ 03923 switch (p->type) { 03924 case PV_GLOBALS: 03925 /* just VARDEC elements */ 03926 for (p2=p->u1.list; p2; p2=p2->next) { 03927 char buf2[2000]; 03928 snprintf(buf2,sizeof(buf2),"%s=%s", p2->u1.str, p2->u2.val); 03929 pbx_builtin_setvar(NULL, buf2); 03930 } 03931 break; 03932 default: 03933 break; 03934 } 03935 } 03936 03937 for (p=root; p; p=p->next ) { 03938 pval *lp; 03939 int argc; 03940 03941 switch (p->type) { 03942 case PV_MACRO: 03943 strcpy(buf,"macro-"); 03944 strcat(buf,p->u1.str); 03945 context = ast_context_create(local_contexts, buf, registrar); 03946 03947 exten = new_exten(); 03948 exten->context = context; 03949 exten->name = strdup("s"); 03950 argc = 1; 03951 for (lp=p->u2.arglist; lp; lp=lp->next) { 03952 /* for each arg, set up a "Set" command */ 03953 struct ael_priority *np2 = new_prio(); 03954 np2->type = AEL_APPCALL; 03955 np2->app = strdup("Set"); 03956 snprintf(buf,sizeof(buf),"%s=${ARG%d}", lp->u1.str, argc++); 03957 remove_spaces_before_equals(buf); 03958 np2->appargs = strdup(buf); 03959 linkprio(exten, np2, NULL); 03960 } 03961 /* add any includes */ 03962 for (p2=p->u3.macro_statements; p2; p2=p2->next) { 03963 pval *p3; 03964 03965 switch (p2->type) { 03966 case PV_INCLUDES: 03967 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 03968 if ( p3->u2.arglist ) { 03969 snprintf(buf,sizeof(buf), "%s|%s|%s|%s|%s", 03970 p3->u1.str, 03971 p3->u2.arglist->u1.str, 03972 p3->u2.arglist->next->u1.str, 03973 p3->u2.arglist->next->next->u1.str, 03974 p3->u2.arglist->next->next->next->u1.str); 03975 ast_context_add_include2(context, buf, registrar); 03976 } else 03977 ast_context_add_include2(context, p3->u1.str, registrar); 03978 } 03979 break; 03980 default: 03981 break; 03982 } 03983 } 03984 /* CONTAINS APPCALLS, CATCH, just like extensions... */ 03985 gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context ); 03986 if (exten->return_needed) { 03987 struct ael_priority *np2 = new_prio(); 03988 np2->type = AEL_APPCALL; 03989 np2->app = strdup("NoOp"); 03990 snprintf(buf,sizeof(buf),"End of Macro %s-%s",p->u1.str, exten->name); 03991 np2->appargs = strdup(buf); 03992 linkprio(exten, np2, NULL); 03993 exten-> return_target = np2; 03994 } 03995 03996 set_priorities(exten); 03997 attach_exten(&exten_list, exten); 03998 break; 03999 04000 case PV_GLOBALS: 04001 /* already done */ 04002 break; 04003 04004 case PV_CONTEXT: 04005 context = ast_context_find_or_create(local_contexts, p->u1.str, registrar); 04006 04007 /* contexts contain: ignorepat, includes, switches, eswitches, extensions, */ 04008 for (p2=p->u2.statements; p2; p2=p2->next) { 04009 pval *p3; 04010 char *s3; 04011 04012 switch (p2->type) { 04013 case PV_EXTENSION: 04014 exten = new_exten(); 04015 exten->name = strdup(p2->u1.str); 04016 exten->context = context; 04017 04018 if( (s3=strchr(exten->name, '/') ) != 0 ) 04019 { 04020 *s3 = 0; 04021 exten->cidmatch = s3+1; 04022 } 04023 04024 if ( p2->u3.hints ) 04025 exten->hints = strdup(p2->u3.hints); 04026 exten->regexten = p2->u4.regexten; 04027 gen_prios(exten, p->u1.str, p2->u2.statements, 0, context ); 04028 if (exten->return_needed) { 04029 struct ael_priority *np2 = new_prio(); 04030 np2->type = AEL_APPCALL; 04031 np2->app = strdup("NoOp"); 04032 snprintf(buf,sizeof(buf),"End of Extension %s", exten->name); 04033 np2->appargs = strdup(buf); 04034 linkprio(exten, np2, NULL); 04035 exten-> return_target = np2; 04036 } 04037 /* is the last priority in the extension a label? Then add a trailing no-op */ 04038 if( !exten->plist_last ) 04039 { 04040 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Empty Extension!\n", 04041 p2->filename, p2->startline, p2->endline); 04042 } 04043 04044 if ( exten->plist_last && exten->plist_last->type == AEL_LABEL ) { 04045 struct ael_priority *np2 = new_prio(); 04046 np2->type = AEL_APPCALL; 04047 np2->app = strdup("NoOp"); 04048 snprintf(buf,sizeof(buf),"A NoOp to follow a trailing label %s", exten->plist_last->origin->u1.str); 04049 np2->appargs = strdup(buf); 04050 linkprio(exten, np2, NULL); 04051 } 04052 04053 set_priorities(exten); 04054 attach_exten(&exten_list, exten); 04055 break; 04056 04057 case PV_IGNOREPAT: 04058 ast_context_add_ignorepat2(context, p2->u1.str, registrar); 04059 break; 04060 04061 case PV_INCLUDES: 04062 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 04063 if ( p3->u2.arglist ) { 04064 snprintf(buf,sizeof(buf), "%s|%s|%s|%s|%s", 04065 p3->u1.str, 04066 p3->u2.arglist->u1.str, 04067 p3->u2.arglist->next->u1.str, 04068 p3->u2.arglist->next->next->u1.str, 04069 p3->u2.arglist->next->next->next->u1.str); 04070 ast_context_add_include2(context, buf, registrar); 04071 } else 04072 ast_context_add_include2(context, p3->u1.str, registrar); 04073 } 04074 break; 04075 04076 case PV_SWITCHES: 04077 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 04078 char *c = strchr(p3->u1.str, '/'); 04079 if (c) { 04080 *c = '\0'; 04081 c++; 04082 } else 04083 c = ""; 04084 04085 ast_context_add_switch2(context, p3->u1.str, c, 0, registrar); 04086 } 04087 break; 04088 04089 case PV_ESWITCHES: 04090 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 04091 char *c = strchr(p3->u1.str, '/'); 04092 if (c) { 04093 *c = '\0'; 04094 c++; 04095 } else 04096 c = ""; 04097 04098 ast_context_add_switch2(context, p3->u1.str, c, 1, registrar); 04099 } 04100 break; 04101 default: 04102 break; 04103 } 04104 } 04105 04106 break; 04107 04108 default: 04109 /* huh? what? */ 04110 break; 04111 04112 } 04113 } 04114 /* moved these from being done after a macro or extension were processed, 04115 to after all processing is done, for the sake of fixing gotos to labels inside cases... */ 04116 /* I guess this would be considered 2nd pass of compiler now... */ 04117 fix_gotos_in_extensions(exten_list); /* find and fix extension ref in gotos to labels that are in case statements */ 04118 add_extensions(exten_list); /* actually makes calls to create priorities in ast_contexts -- feeds dialplan to asterisk */ 04119 destroy_extensions(exten_list); /* all that remains is an empty husk, discard of it as is proper */ 04120 04121 }
int ast_expr | ( | char * | expr, | |
char * | buf, | |||
int | length | |||
) |
Definition at line 2288 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().
02289 { 02290 struct parse_io io; 02291 int return_value = 0; 02292 02293 memset(&io, 0, sizeof(io)); 02294 io.string = expr; /* to pass to the error routine */ 02295 02296 ast_yylex_init(&io.scanner); 02297 02298 ast_yy_scan_string(expr, io.scanner); 02299 02300 ast_yyparse ((void *) &io); 02301 02302 ast_yylex_destroy(io.scanner); 02303 02304 if (!io.val) { 02305 if (length > 1) { 02306 strcpy(buf, "0"); 02307 return_value = 1; 02308 } 02309 } else { 02310 if (io.val->type == AST_EXPR_integer) { 02311 int res_length; 02312 02313 res_length = snprintf(buf, length, "%ld", (long int) io.val->u.i); 02314 return_value = (res_length <= length) ? res_length : length; 02315 } else { 02316 #if defined(STANDALONE) || defined(LOW_MEMORY) || defined(STANDALONE_AEL) 02317 strncpy(buf, io.val->u.s, length - 1); 02318 #else /* !STANDALONE && !LOW_MEMORY */ 02319 ast_copy_string(buf, io.val->u.s, length); 02320 #endif /* STANDALONE || LOW_MEMORY */ 02321 return_value = strlen(buf); 02322 free(io.val->u.s); 02323 } 02324 free(io.val); 02325 } 02326 return return_value; 02327 }
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 3832 of file pbx_ael.c.
References ael_extension::next_exten.
03833 { 03834 /* travel to the end of the list... */ 03835 struct ael_extension *lptr; 03836 if( !*list ) { 03837 *list = newmem; 03838 return; 03839 } 03840 lptr = *list; 03841 03842 while( lptr->next_exten ) { 03843 lptr = lptr->next_exten; 03844 } 03845 /* lptr should now pointing to the last element in the list; it has a null next_exten pointer */ 03846 lptr->next_exten = newmem; 03847 }
static void check_abstract_reference | ( | pval * | abstract_context | ) | [static] |
Definition at line 2261 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().
02262 { 02263 pval *i,*j; 02264 /* find some context includes that reference this context */ 02265 02266 02267 /* otherwise, print out a warning */ 02268 for (i=current_db; i; i=i->next) { 02269 if (i->type == PV_CONTEXT) { 02270 for (j=i->u2. statements; j; j=j->next) { 02271 if ( j->type == PV_INCLUDES ) { 02272 struct pval *p4; 02273 for (p4=j->u1.list; p4; p4=p4->next) { 02274 /* for each context pointed to, find it, then find a context/label that matches the 02275 target here! */ 02276 if ( !strcmp(p4->u1.str, abstract_context->u1.str) ) 02277 return; /* found a match! */ 02278 } 02279 } 02280 } 02281 } 02282 } 02283 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", 02284 abstract_context->filename, abstract_context->startline, abstract_context->endline, abstract_context->u1.str); 02285 warns++; 02286 }
Definition at line 2062 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().
02063 { 02064 #ifdef AAL_ARGCHECK 02065 struct argdesc *ad = app->args; 02066 pval *pa; 02067 int z; 02068 02069 for (pa = arglist; pa; pa=pa->next) { 02070 if (!ad) { 02071 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Extra argument %s not in application call to %s !\n", 02072 arglist->filename, arglist->startline, arglist->endline, pa->u1.str, app->name); 02073 warns++; 02074 return 1; 02075 } else { 02076 /* find the first entry in the ad list that will match */ 02077 do { 02078 if ( ad->dtype == ARGD_VARARG ) /* once we hit the VARARG, all bets are off. Discontinue the comparisons */ 02079 break; 02080 02081 z= option_matches( ad, pa, app); 02082 if (!z) { 02083 if ( !arglist ) 02084 arglist=appcall; 02085 02086 if (ad->type == ARGD_REQUIRED) { 02087 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", 02088 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); 02089 warns++; 02090 return 1; 02091 } 02092 } else if (z && ad->dtype == ARGD_OPTIONSET) { 02093 option_matches_j( ad, pa, app); 02094 } 02095 ad = ad->next; 02096 } while (ad && !z); 02097 } 02098 } 02099 /* any app nodes left, that are not optional? */ 02100 for ( ; ad; ad=ad->next) { 02101 if (ad->type == ARGD_REQUIRED && ad->dtype != ARGD_VARARG) { 02102 if ( !arglist ) 02103 arglist=appcall; 02104 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", 02105 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); 02106 warns++; 02107 return 1; 02108 } 02109 } 02110 return 0; 02111 #else 02112 return 0; 02113 #endif 02114 }
static int check_break | ( | pval * | item | ) | [static] |
Definition at line 1055 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().
01056 { 01057 pval *p = item; 01058 01059 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ { 01060 /* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make 01061 no sense */ 01062 if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN 01063 || p->type == PV_WHILE || p->type == PV_FOR ) { 01064 return 1; 01065 } 01066 p = p->dad; 01067 } 01068 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'break' not in switch, for, or while statement!\n", 01069 item->filename, item->startline, item->endline); 01070 errs++; 01071 01072 return 0; 01073 }
static void check_context_names | ( | void | ) | [static] |
Definition at line 2242 of file pbx_ael.c.
References pval::abstract, ast_log(), current_db, pval::endline, pval::filename, LOG_ERROR, pval::next, PV_CONTEXT, PV_MACRO, pval::startline, pval::str, pval::type, pval::u1, and pval::u3.
Referenced by ael2_semantic_check().
02243 { 02244 pval *i,*j; 02245 for (i=current_db; i; i=i->next) { 02246 if (i->type == PV_CONTEXT || i->type == PV_MACRO) { 02247 for (j=i->next; j; j=j->next) { 02248 if ( j->type == PV_CONTEXT || j->type == PV_MACRO ) { 02249 if ( !strcmp(i->u1.str, j->u1.str) && !(i->u3.abstract&2) && !(j->u3.abstract&2) ) 02250 { 02251 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: The context name (%s) is also declared in file %s, line %d-%d! (and neither is marked 'extend')\n", 02252 i->filename, i->startline, i->endline, i->u1.str, j->filename, j->startline, j->endline); 02253 errs++; 02254 } 02255 } 02256 } 02257 } 02258 } 02259 }
static int check_continue | ( | pval * | item | ) | [static] |
Definition at line 1075 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().
01076 { 01077 pval *p = item; 01078 01079 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ { 01080 /* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make 01081 no sense */ 01082 if( p->type == PV_WHILE || p->type == PV_FOR ) { 01083 return 1; 01084 } 01085 p = p->dad; 01086 } 01087 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'continue' not in 'for' or 'while' statement!\n", 01088 item->filename, item->startline, item->endline); 01089 errs++; 01090 01091 return 0; 01092 }
static void check_day | ( | pval * | DAY | ) | [static] |
Definition at line 954 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().
00955 { 00956 char *day; 00957 char *c; 00958 /* The following line is coincidence, really! */ 00959 int s, e; 00960 00961 day = ast_strdupa(DAY->u1.str); 00962 00963 /* Check for all days */ 00964 if (ast_strlen_zero(day) || !strcmp(day, "*")) { 00965 return; 00966 } 00967 /* Get start and ending days */ 00968 c = strchr(day, '-'); 00969 if (c) { 00970 *c = '\0'; 00971 c++; 00972 } 00973 /* Find the start */ 00974 if (sscanf(day, "%d", &s) != 1) { 00975 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start day of month (%s) must be a number!\n", 00976 DAY->filename, DAY->startline, DAY->endline, day); 00977 warns++; 00978 } 00979 else if ((s < 1) || (s > 31)) { 00980 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", 00981 DAY->filename, DAY->startline, DAY->endline, day); 00982 warns++; 00983 } 00984 s--; 00985 if (c) { 00986 if (sscanf(c, "%d", &e) != 1) { 00987 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end day of month (%s) must be a number!\n", 00988 DAY->filename, DAY->startline, DAY->endline, c); 00989 warns++; 00990 } 00991 else if ((e < 1) || (e > 31)) { 00992 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", 00993 DAY->filename, DAY->startline, DAY->endline, day); 00994 warns++; 00995 } 00996 e--; 00997 } else 00998 e = s; 00999 }
static void check_dow | ( | pval * | DOW | ) | [static] |
get_dow: Get day of week
Definition at line 915 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().
00916 { 00917 char *dow; 00918 char *c; 00919 /* The following line is coincidence, really! */ 00920 int s, e; 00921 00922 dow = ast_strdupa(DOW->u1.str); 00923 00924 /* Check for all days */ 00925 if (ast_strlen_zero(dow) || !strcmp(dow, "*")) 00926 return; 00927 /* Get start and ending days */ 00928 c = strchr(dow, '-'); 00929 if (c) { 00930 *c = '\0'; 00931 c++; 00932 } else 00933 c = NULL; 00934 /* Find the start */ 00935 s = 0; 00936 while ((s < 7) && strcasecmp(dow, days[s])) s++; 00937 if (s >= 7) { 00938 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", 00939 DOW->filename, DOW->startline, DOW->endline, dow); 00940 warns++; 00941 } 00942 if (c) { 00943 e = 0; 00944 while ((e < 7) && strcasecmp(c, days[e])) e++; 00945 if (e >= 7) { 00946 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", 00947 DOW->filename, DOW->startline, DOW->endline, c); 00948 warns++; 00949 } 00950 } else 00951 e = s; 00952 }
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 1190 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().
01191 { 01192 /* check for the target of the goto-- does it exist? */ 01193 if ( !(item->u1.list)->next && !(item->u1.list)->u1.str ) { 01194 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: empty label reference found!\n", 01195 item->filename, item->startline, item->endline); 01196 errs++; 01197 } 01198 01199 /* just one item-- the label should be in the current extension */ 01200 01201 if (item->u1.list && !item->u1.list->next && !strstr((item->u1.list)->u1.str,"${")) { 01202 struct pval *z = get_extension_or_contxt(item); 01203 struct pval *x = 0; 01204 if (z) 01205 x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), z); /* if in macro, use current context instead */ 01206 /* printf("Called find_label_in_current_extension with arg %s; current_extension is %x: %d\n", 01207 (char*)((item->u1.list)->u1.str), current_extension?current_extension:current_context, current_extension?current_extension->type:current_context->type); */ 01208 if (!x) { 01209 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s exists in the current extension!\n", 01210 item->filename, item->startline, item->endline, item->u1.list->u1.str); 01211 errs++; 01212 } 01213 else 01214 return; 01215 } 01216 01217 /* TWO items */ 01218 if (item->u1.list->next && !item->u1.list->next->next) { 01219 /* two items */ 01220 /* printf("Calling find_label_in_current_context with args %s, %s\n", 01221 (char*)((item->u1.list)->u1.str), (char *)item->u1.list->next->u1.str); */ 01222 if (!strstr((item->u1.list)->u1.str,"${") 01223 && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ { 01224 struct pval *z = get_contxt(item); 01225 struct pval *x = 0; 01226 01227 if (z) 01228 x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, z); 01229 01230 if (!x) { 01231 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", 01232 item->filename, item->startline, item->endline, item->u1.list->u1.str, item->u1.list->next->u1.str ); 01233 errs++; 01234 } 01235 else 01236 return; 01237 } 01238 } 01239 01240 /* All 3 items! */ 01241 if (item->u1.list->next && item->u1.list->next->next) { 01242 /* all three */ 01243 pval *first = item->u1.list; 01244 pval *second = item->u1.list->next; 01245 pval *third = item->u1.list->next->next; 01246 01247 /* printf("Calling find_label_in_current_db with args %s, %s, %s\n", 01248 (char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); */ 01249 if (!strstr((item->u1.list)->u1.str,"${") 01250 && !strstr(item->u1.list->next->u1.str,"${") 01251 && !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ { 01252 struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); 01253 if (!x) { 01254 struct pval *p3; 01255 struct pval *found = 0; 01256 struct pval *that_context = find_context(item->u1.list->u1.str); 01257 01258 /* the target of the goto could be in an included context!! Fancy that!! */ 01259 /* look for includes in the current context */ 01260 if (that_context) { 01261 for (p3=that_context->u2.statements; p3; p3=p3->next) { 01262 if (p3->type == PV_INCLUDES) { 01263 struct pval *p4; 01264 for (p4=p3->u1.list; p4; p4=p4->next) { 01265 /* for each context pointed to, find it, then find a context/label that matches the 01266 target here! */ 01267 char *incl_context = p4->u1.str; 01268 /* find a matching context name */ 01269 struct pval *that_other_context = find_context(incl_context); 01270 if (that_other_context) { 01271 struct pval *x3; 01272 x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context); 01273 if (x3) { 01274 found = x3; 01275 break; 01276 } 01277 } 01278 } 01279 } 01280 } 01281 if (!found) { 01282 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s|%s exists in the context %s or its inclusions!\n", 01283 item->filename, item->startline, item->endline, item->u1.list->next->u1.str, item->u1.list->next->next->u1.str, item->u1.list->u1.str ); 01284 errs++; 01285 } 01286 } else { 01287 /* here is where code would go to check for target existence in extensions.conf files */ 01288 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: goto: no context %s could be found that matches the goto target!\n", 01289 item->filename, item->startline, item->endline, item->u1.list->u1.str); 01290 warns++; /* this is just a warning, because this context could be in extensions.conf or somewhere */ 01291 } 01292 } 01293 } 01294 } 01295 }
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 (You may ignore this warning if '%s' exists in extensions.conf, or is created by another module. I cannot check for those.)\n", 00840 includes->filename, includes->startline, includes->endline, incl_context, incl_context); 00841 warns++; 00842 } 00843 } 00844 }
static void check_label | ( | pval * | item | ) | [static] |
Definition at line 1097 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().
01098 { 01099 /* basically, ensure that a label is not repeated in a context. Period. 01100 The method: well, for each label, find the first label in the context 01101 with the same name. If it's not the current label, then throw an error. */ 01102 struct pval *curr; 01103 struct pval *x; 01104 01105 /* printf("==== check_label: ====\n"); */ 01106 if( !current_extension ) 01107 curr = current_context; 01108 else 01109 curr = current_extension; 01110 01111 x = find_first_label_in_current_context((char *)item->u1.str, curr); 01112 /* 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); */ 01113 if( x && x != item ) 01114 { 01115 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: Duplicate label %s! Previously defined at file %s, line %d.\n", 01116 item->filename, item->startline, item->endline, item->u1.str, x->filename, x->startline); 01117 errs++; 01118 } 01119 /* printf("<<<<< check_label: ====\n"); */ 01120 }
static void check_month | ( | pval * | MON | ) | [static] |
Definition at line 1017 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().
01018 { 01019 char *mon; 01020 char *c; 01021 /* The following line is coincidence, really! */ 01022 int s, e; 01023 01024 mon = ast_strdupa(MON->u1.str); 01025 01026 /* Check for all days */ 01027 if (ast_strlen_zero(mon) || !strcmp(mon, "*")) 01028 return ; 01029 /* Get start and ending days */ 01030 c = strchr(mon, '-'); 01031 if (c) { 01032 *c = '\0'; 01033 c++; 01034 } 01035 /* Find the start */ 01036 s = 0; 01037 while ((s < 12) && strcasecmp(mon, months[s])) s++; 01038 if (s >= 12) { 01039 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n", 01040 MON->filename, MON->startline, MON->endline, mon); 01041 warns++; 01042 } 01043 if (c) { 01044 e = 0; 01045 while ((e < 12) && strcasecmp(mon, months[e])) e++; 01046 if (e >= 12) { 01047 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n", 01048 MON->filename, MON->startline, MON->endline, c); 01049 warns++; 01050 } 01051 } else 01052 e = s; 01053 }
Definition at line 2708 of file pbx_ael.c.
References check_pval_item(), and pval::next.
Referenced by ael2_semantic_check(), and check_pval_item().
02709 { 02710 pval *i; 02711 02712 /* checks to do: 02713 1. Do goto's point to actual labels? 02714 2. Do macro calls reference a macro? 02715 3. Does the number of macro args match the definition? 02716 4. Is a macro call missing its & at the front? 02717 5. Application calls-- we could check syntax for existing applications, 02718 but I need some some sort of universal description bnf for a general 02719 sort of method for checking arguments, in number, maybe even type, at least. 02720 Don't want to hand code checks for hundreds of applications. 02721 */ 02722 02723 for (i=item; i; i=i->next) { 02724 check_pval_item(i,apps,in_globals); 02725 } 02726 }
Definition at line 2289 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().
02290 { 02291 pval *lp; 02292 #ifdef AAL_ARGCHECK 02293 struct argapp *app, *found; 02294 #endif 02295 struct pval *macro_def; 02296 struct pval *app_def; 02297 02298 char errmsg[4096]; 02299 char *strp; 02300 02301 switch (item->type) { 02302 case PV_WORD: 02303 /* fields: item->u1.str == string associated with this (word). 02304 item->u2.arglist == pval list of 4 PV_WORD elements for time values (only in PV_INCLUDES) */ 02305 break; 02306 02307 case PV_MACRO: 02308 /* fields: item->u1.str == name of macro 02309 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 02310 item->u2.arglist->u1.str == argument 02311 item->u2.arglist->next == next arg 02312 02313 item->u3.macro_statements == pval list of statements in macro body. 02314 */ 02315 in_abstract_context = 0; 02316 current_context = item; 02317 current_extension = 0; 02318 for (lp=item->u2.arglist; lp; lp=lp->next) { 02319 02320 } 02321 check_pval(item->u3.macro_statements, apps,in_globals); 02322 break; 02323 02324 case PV_CONTEXT: 02325 /* fields: item->u1.str == name of context 02326 item->u2.statements == pval list of statements in context body 02327 item->u3.abstract == int 1 if an abstract keyword were present 02328 */ 02329 current_context = item; 02330 current_extension = 0; 02331 if ( item->u3.abstract ) { 02332 in_abstract_context = 1; 02333 check_abstract_reference(item); 02334 } else 02335 in_abstract_context = 0; 02336 check_pval(item->u2.statements, apps,in_globals); 02337 break; 02338 02339 case PV_MACRO_CALL: 02340 /* fields: item->u1.str == name of macro to call 02341 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 02342 item->u2.arglist->u1.str == argument 02343 item->u2.arglist->next == next arg 02344 */ 02345 macro_def = find_macro(item->u1.str); 02346 if (!macro_def) { 02347 /* here is a good place to check to see if the definition is in extensions.conf! */ 02348 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to non-existent %s ! Hopefully it is present in extensions.conf! \n", 02349 item->filename, item->startline, item->endline, item->u1.str); 02350 warns++; 02351 } else if (macro_def->type != PV_MACRO) { 02352 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: macro call to %s references a context, not a macro!\n", 02353 item->filename, item->startline, item->endline, item->u1.str); 02354 errs++; 02355 } else { 02356 /* macro_def is a MACRO, so do the args match in number? */ 02357 int hereargs = 0; 02358 int thereargs = 0; 02359 02360 for (lp=item->u2.arglist; lp; lp=lp->next) { 02361 hereargs++; 02362 } 02363 for (lp=macro_def->u2.arglist; lp; lp=lp->next) { 02364 thereargs++; 02365 } 02366 if (hereargs != thereargs ) { 02367 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", 02368 item->filename, item->startline, item->endline, item->u1.str, hereargs, thereargs); 02369 errs++; 02370 } 02371 } 02372 break; 02373 02374 case PV_APPLICATION_CALL: 02375 /* fields: item->u1.str == name of application to call 02376 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 02377 item->u2.arglist->u1.str == argument 02378 item->u2.arglist->next == next arg 02379 */ 02380 /* Need to check to see if the application is available! */ 02381 app_def = find_context(item->u1.str); 02382 if (app_def && app_def->type == PV_MACRO) { 02383 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: application call to %s references an existing macro, but had no & preceding it!\n", 02384 item->filename, item->startline, item->endline, item->u1.str); 02385 errs++; 02386 } 02387 if (strcasecmp(item->u1.str,"GotoIf") == 0 02388 || strcasecmp(item->u1.str,"GotoIfTime") == 0 02389 || strcasecmp(item->u1.str,"while") == 0 02390 || strcasecmp(item->u1.str,"endwhile") == 0 02391 || strcasecmp(item->u1.str,"random") == 0 02392 || strcasecmp(item->u1.str,"execIf") == 0 ) { 02393 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", 02394 item->filename, item->startline, item->endline, item->u1.str); 02395 warns++; 02396 } 02397 #ifdef AAL_ARGCHECK 02398 found = 0; 02399 for (app=apps; app; app=app->next) { 02400 if (strcasecmp(app->name, item->u1.str) == 0) { 02401 found =app; 02402 break; 02403 } 02404 } 02405 if (!found) { 02406 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: application call to %s not listed in applist database!\n", 02407 item->filename, item->startline, item->endline, item->u1.str); 02408 warns++; 02409 } else 02410 check_app_args(item, item->u2.arglist, app); 02411 #endif 02412 break; 02413 02414 case PV_CASE: 02415 /* fields: item->u1.str == value of case 02416 item->u2.statements == pval list of statements under the case 02417 */ 02418 /* Make sure sequence of statements under case is terminated with goto, return, or break */ 02419 /* find the last statement */ 02420 check_pval(item->u2.statements, apps,in_globals); 02421 break; 02422 02423 case PV_PATTERN: 02424 /* fields: item->u1.str == value of case 02425 item->u2.statements == pval list of statements under the case 02426 */ 02427 /* Make sure sequence of statements under case is terminated with goto, return, or break */ 02428 /* find the last statement */ 02429 02430 check_pval(item->u2.statements, apps,in_globals); 02431 break; 02432 02433 case PV_DEFAULT: 02434 /* fields: 02435 item->u2.statements == pval list of statements under the case 02436 */ 02437 02438 check_pval(item->u2.statements, apps,in_globals); 02439 break; 02440 02441 case PV_CATCH: 02442 /* fields: item->u1.str == name of extension to catch 02443 item->u2.statements == pval list of statements in context body 02444 */ 02445 check_pval(item->u2.statements, apps,in_globals); 02446 break; 02447 02448 case PV_SWITCHES: 02449 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02450 */ 02451 check_pval(item->u1.list, apps,in_globals); 02452 break; 02453 02454 case PV_ESWITCHES: 02455 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02456 */ 02457 check_pval(item->u1.list, apps,in_globals); 02458 break; 02459 02460 case PV_INCLUDES: 02461 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02462 */ 02463 check_pval(item->u1.list, apps,in_globals); 02464 check_includes(item); 02465 for (lp=item->u1.list; lp; lp=lp->next){ 02466 char *incl_context = lp->u1.str; 02467 struct pval *that_context = find_context(incl_context); 02468 02469 if ( lp->u2.arglist ) { 02470 check_timerange(lp->u2.arglist); 02471 check_dow(lp->u2.arglist->next); 02472 check_day(lp->u2.arglist->next->next); 02473 check_month(lp->u2.arglist->next->next->next); 02474 } 02475 02476 if (that_context) { 02477 find_pval_gotos(that_context->u2.statements,0); 02478 02479 } 02480 } 02481 break; 02482 02483 case PV_STATEMENTBLOCK: 02484 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 02485 */ 02486 check_pval(item->u1.list, apps,in_globals); 02487 break; 02488 02489 case PV_VARDEC: 02490 /* fields: item->u1.str == variable name 02491 item->u2.val == variable value to assign 02492 */ 02493 /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */ 02494 if( !in_globals ) { /* don't check stuff inside the globals context; no wrapping in $[ ] there... */ 02495 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); 02496 ast_expr_register_extra_error_info(errmsg); 02497 ast_expr(item->u2.val, expr_output, sizeof(expr_output)); 02498 ast_expr_clear_extra_error_info(); 02499 if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) { 02500 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02501 item->filename, item->startline, item->endline, item->u2.val); 02502 warns++; 02503 } 02504 check_expr2_input(item,item->u2.val); 02505 } 02506 break; 02507 02508 case PV_GOTO: 02509 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 02510 item->u1.list->u1.str == where the data on a PV_WORD will always be. 02511 */ 02512 /* don't check goto's in abstract contexts */ 02513 if ( in_abstract_context ) 02514 break; 02515 02516 check_goto(item); 02517 break; 02518 02519 case PV_LABEL: 02520 /* fields: item->u1.str == label name 02521 */ 02522 if ( strspn(item->u1.str, "0123456789") == strlen(item->u1.str) ) { 02523 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: label '%s' is numeric, this is bad practice!\n", 02524 item->filename, item->startline, item->endline, item->u1.str); 02525 warns++; 02526 } 02527 02528 check_label(item); 02529 break; 02530 02531 case PV_FOR: 02532 /* fields: item->u1.for_init == a string containing the initalizer 02533 item->u2.for_test == a string containing the loop test 02534 item->u3.for_inc == a string containing the loop increment 02535 02536 item->u4.for_statements == a pval list of statements in the for () 02537 */ 02538 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); 02539 ast_expr_register_extra_error_info(errmsg); 02540 02541 strp = strchr(item->u1.for_init, '='); 02542 if (strp) { 02543 ast_expr(strp+1, expr_output, sizeof(expr_output)); 02544 } 02545 ast_expr(item->u2.for_test, expr_output, sizeof(expr_output)); 02546 strp = strchr(item->u3.for_inc, '='); 02547 if (strp) { 02548 ast_expr(strp+1, expr_output, sizeof(expr_output)); 02549 } 02550 if ( strpbrk(item->u2.for_test,"~!-+<>=*/&^") && !strstr(item->u2.for_test,"${") ) { 02551 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02552 item->filename, item->startline, item->endline, item->u2.for_test); 02553 warns++; 02554 } 02555 if ( strpbrk(item->u3.for_inc,"~!-+<>=*/&^") && !strstr(item->u3.for_inc,"${") ) { 02556 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02557 item->filename, item->startline, item->endline, item->u3.for_inc); 02558 warns++; 02559 } 02560 check_expr2_input(item,item->u2.for_test); 02561 check_expr2_input(item,item->u3.for_inc); 02562 02563 ast_expr_clear_extra_error_info(); 02564 check_pval(item->u4.for_statements, apps,in_globals); 02565 break; 02566 02567 case PV_WHILE: 02568 /* fields: item->u1.str == the while conditional, as supplied by user 02569 02570 item->u2.statements == a pval list of statements in the while () 02571 */ 02572 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, while expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str); 02573 ast_expr_register_extra_error_info(errmsg); 02574 ast_expr(item->u1.str, expr_output, sizeof(expr_output)); 02575 ast_expr_clear_extra_error_info(); 02576 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02577 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02578 item->filename, item->startline, item->endline, item->u1.str); 02579 warns++; 02580 } 02581 check_expr2_input(item,item->u1.str); 02582 check_pval(item->u2.statements, apps,in_globals); 02583 break; 02584 02585 case PV_BREAK: 02586 /* fields: none 02587 */ 02588 check_break(item); 02589 break; 02590 02591 case PV_RETURN: 02592 /* fields: none 02593 */ 02594 break; 02595 02596 case PV_CONTINUE: 02597 /* fields: none 02598 */ 02599 check_continue(item); 02600 break; 02601 02602 case PV_RANDOM: 02603 /* fields: item->u1.str == the random number expression, as supplied by user 02604 02605 item->u2.statements == a pval list of statements in the if () 02606 item->u3.else_statements == a pval list of statements in the else 02607 (could be zero) 02608 */ 02609 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, random expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str); 02610 ast_expr_register_extra_error_info(errmsg); 02611 ast_expr(item->u1.str, expr_output, sizeof(expr_output)); 02612 ast_expr_clear_extra_error_info(); 02613 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02614 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: random expression '%s' has operators, but no variables. Interesting...\n", 02615 item->filename, item->startline, item->endline, item->u1.str); 02616 warns++; 02617 } 02618 check_expr2_input(item,item->u1.str); 02619 check_pval(item->u2.statements, apps,in_globals); 02620 if (item->u3.else_statements) { 02621 check_pval(item->u3.else_statements, apps,in_globals); 02622 } 02623 break; 02624 02625 case PV_IFTIME: 02626 /* fields: item->u1.list == the if time values, 4 of them, each in PV_WORD, linked list 02627 02628 item->u2.statements == a pval list of statements in the if () 02629 item->u3.else_statements == a pval list of statements in the else 02630 (could be zero) 02631 */ 02632 if ( item->u2.arglist ) { 02633 check_timerange(item->u1.list); 02634 check_dow(item->u1.list->next); 02635 check_day(item->u1.list->next->next); 02636 check_month(item->u1.list->next->next->next); 02637 } 02638 02639 check_pval(item->u2.statements, apps,in_globals); 02640 if (item->u3.else_statements) { 02641 check_pval(item->u3.else_statements, apps,in_globals); 02642 } 02643 break; 02644 02645 case PV_IF: 02646 /* fields: item->u1.str == the if conditional, as supplied by user 02647 02648 item->u2.statements == a pval list of statements in the if () 02649 item->u3.else_statements == a pval list of statements in the else 02650 (could be zero) 02651 */ 02652 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, if expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str); 02653 ast_expr_register_extra_error_info(errmsg); 02654 ast_expr(item->u1.str, expr_output, sizeof(expr_output)); 02655 ast_expr_clear_extra_error_info(); 02656 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02657 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression '%s' has operators, but no variables. Interesting...\n", 02658 item->filename, item->startline, item->endline, item->u1.str); 02659 warns++; 02660 } 02661 check_expr2_input(item,item->u1.str); 02662 check_pval(item->u2.statements, apps,in_globals); 02663 if (item->u3.else_statements) { 02664 check_pval(item->u3.else_statements, apps,in_globals); 02665 } 02666 break; 02667 02668 case PV_SWITCH: 02669 /* fields: item->u1.str == the switch expression 02670 02671 item->u2.statements == a pval list of statements in the switch, 02672 (will be case statements, most likely!) 02673 */ 02674 /* we can check the switch expression, see if it matches any of the app variables... 02675 if it does, then, are all the possible cases accounted for? */ 02676 check_switch_expr(item, apps); 02677 check_pval(item->u2.statements, apps,in_globals); 02678 break; 02679 02680 case PV_EXTENSION: 02681 /* fields: item->u1.str == the extension name, label, whatever it's called 02682 02683 item->u2.statements == a pval list of statements in the extension 02684 item->u3.hints == a char * hint argument 02685 item->u4.regexten == an int boolean. non-zero says that regexten was specified 02686 */ 02687 current_extension = item ; 02688 02689 check_pval(item->u2.statements, apps,in_globals); 02690 break; 02691 02692 case PV_IGNOREPAT: 02693 /* fields: item->u1.str == the ignorepat data 02694 */ 02695 break; 02696 02697 case PV_GLOBALS: 02698 /* fields: item->u1.statements == pval list of statements, usually vardecs 02699 */ 02700 in_abstract_context = 0; 02701 check_pval(item->u1.statements, apps, 1); 02702 break; 02703 default: 02704 break; 02705 } 02706 }
Definition at line 2116 of file pbx_ael.c.
References ast_strdupa, argapp::next, pval::str, t, and pval::u1.
Referenced by check_pval_item().
02117 { 02118 #ifdef AAL_ARGCHECK 02119 /* get and clean the variable name */ 02120 char *buff1, *p; 02121 struct argapp *a,*a2; 02122 struct appsetvar *v,*v2; 02123 struct argchoice *c; 02124 pval *t; 02125 02126 p = item->u1.str; 02127 while (p && *p && (*p == ' ' || *p == '\t' || *p == '$' || *p == '{' ) ) 02128 p++; 02129 02130 buff1 = ast_strdupa(p); 02131 02132 while (strlen(buff1) > 0 && ( buff1[strlen(buff1)-1] == '}' || buff1[strlen(buff1)-1] == ' ' || buff1[strlen(buff1)-1] == '\t')) 02133 buff1[strlen(buff1)-1] = 0; 02134 /* buff1 now contains the variable name */ 02135 v = 0; 02136 for (a=apps; a; a=a->next) { 02137 for (v=a->setvars;v;v=v->next) { 02138 if (strcmp(v->name,buff1) == 0) { 02139 break; 02140 } 02141 } 02142 if ( v ) 02143 break; 02144 } 02145 if (v && v->vals) { 02146 /* we have a match, to a variable that has a set of determined values */ 02147 int def= 0; 02148 int pat = 0; 02149 int f1 = 0; 02150 02151 /* first of all, does this switch have a default case ? */ 02152 for (t=item->u2.statements; t; t=t->next) { 02153 if (t->type == PV_DEFAULT) { 02154 def =1; 02155 break; 02156 } 02157 if (t->type == PV_PATTERN) { 02158 pat++; 02159 } 02160 } 02161 if (def || pat) /* nothing to check. All cases accounted for! */ 02162 return; 02163 for (c=v->vals; c; c=c->next) { 02164 f1 = 0; 02165 for (t=item->u2.statements; t; t=t->next) { 02166 if (t->type == PV_CASE || t->type == PV_PATTERN) { 02167 if (!strcmp(t->u1.str,c->name)) { 02168 f1 = 1; 02169 break; 02170 } 02171 } 02172 } 02173 if (!f1) { 02174 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: switch with expression(%s) does not handle the case of %s !\n", 02175 item->filename, item->startline, item->endline, item->u1.str, c->name); 02176 warns++; 02177 } 02178 } 02179 /* next, is there an app call in the current exten, that would set this var? */ 02180 f1 = 0; 02181 t = current_extension->u2.statements; 02182 if ( t && t->type == PV_STATEMENTBLOCK ) 02183 t = t->u1.statements; 02184 for (; t && t != item; t=t->next) { 02185 if (t->type == PV_APPLICATION_CALL) { 02186 /* find the application that matches the u1.str */ 02187 for (a2=apps; a2; a2=a2->next) { 02188 if (strcasecmp(a2->name, t->u1.str)==0) { 02189 for (v2=a2->setvars; v2; v2=v2->next) { 02190 if (strcmp(v2->name, buff1) == 0) { 02191 /* found an app that sets the var */ 02192 f1 = 1; 02193 break; 02194 } 02195 } 02196 } 02197 if (f1) 02198 break; 02199 } 02200 } 02201 if (f1) 02202 break; 02203 } 02204 02205 /* see if it sets the var */ 02206 if (!f1) { 02207 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", 02208 item->filename, item->startline, item->endline, item->u1.str); 02209 warns++; 02210 } 02211 } 02212 #else 02213 pval *t,*tl=0,*p2; 02214 int def= 0; 02215 02216 /* first of all, does this switch have a default case ? */ 02217 for (t=item->u2.statements; t; t=t->next) { 02218 if (t->type == PV_DEFAULT) { 02219 def =1; 02220 break; 02221 } 02222 tl = t; 02223 } 02224 if (def) /* nothing to check. All cases accounted for! */ 02225 return; 02226 /* if no default, warn and insert a default case at the end */ 02227 p2 = tl->next = calloc(1, sizeof(struct pval)); 02228 02229 p2->type = PV_DEFAULT; 02230 p2->startline = tl->startline; 02231 p2->endline = tl->endline; 02232 p2->startcol = tl->startcol; 02233 p2->endcol = tl->endcol; 02234 p2->filename = strdup(tl->filename); 02235 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: A default case was automatically added to the switch.\n", 02236 p2->filename, p2->startline, p2->endline); 02237 warns++; 02238 02239 #endif 02240 }
static void check_timerange | ( | pval * | p | ) | [static] |
Definition at line 847 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().
00848 { 00849 char *times; 00850 char *e; 00851 int s1, s2; 00852 int e1, e2; 00853 00854 times = ast_strdupa(p->u1.str); 00855 00856 /* Star is all times */ 00857 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 00858 return; 00859 } 00860 /* Otherwise expect a range */ 00861 e = strchr(times, '-'); 00862 if (!e) { 00863 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", 00864 p->filename, p->startline, p->endline, times); 00865 warns++; 00866 return; 00867 } 00868 *e = '\0'; 00869 e++; 00870 while (*e && !isdigit(*e)) 00871 e++; 00872 if (!*e) { 00873 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The time range format (%s) is missing the end time!\n", 00874 p->filename, p->startline, p->endline, p->u1.str); 00875 warns++; 00876 } 00877 if (sscanf(times, "%d:%d", &s1, &s2) != 2) { 00878 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) isn't quite right!\n", 00879 p->filename, p->startline, p->endline, times); 00880 warns++; 00881 } 00882 if (sscanf(e, "%d:%d", &e1, &e2) != 2) { 00883 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) isn't quite right!\n", 00884 p->filename, p->startline, p->endline, times); 00885 warns++; 00886 } 00887 00888 s1 = s1 * 30 + s2/2; 00889 if ((s1 < 0) || (s1 >= 24*30)) { 00890 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) is out of range!\n", 00891 p->filename, p->startline, p->endline, times); 00892 warns++; 00893 } 00894 e1 = e1 * 30 + e2/2; 00895 if ((e1 < 0) || (e1 >= 24*30)) { 00896 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) is out of range!\n", 00897 p->filename, p->startline, p->endline, e); 00898 warns++; 00899 } 00900 return; 00901 }
void destroy_extensions | ( | struct ael_extension * | exten | ) |
Definition at line 2821 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.
02822 { 02823 struct ael_extension *ne, *nen; 02824 for (ne=exten; ne; ne=nen) { 02825 struct ael_priority *pe, *pen; 02826 02827 if (ne->name) 02828 free(ne->name); 02829 02830 /* cidmatch fields are allocated with name, and freed when 02831 the name field is freed. Don't do a free for this field, 02832 unless you LIKE to see a crash! */ 02833 02834 if (ne->hints) 02835 free(ne->hints); 02836 02837 for (pe=ne->plist; pe; pe=pen) { 02838 pen = pe->next; 02839 if (pe->app) 02840 free(pe->app); 02841 pe->app = 0; 02842 if (pe->appargs) 02843 free(pe->appargs); 02844 pe->appargs = 0; 02845 pe->origin = 0; 02846 pe->goto_true = 0; 02847 pe->goto_false = 0; 02848 free(pe); 02849 } 02850 nen = ne->next_exten; 02851 ne->next_exten = 0; 02852 ne->plist =0; 02853 ne->plist_last = 0; 02854 ne->next_exten = 0; 02855 ne->loop_break = 0; 02856 ne->loop_continue = 0; 02857 free(ne); 02858 } 02859 }
void destroy_pval | ( | pval * | item | ) |
void destroy_pval_item | ( | pval * | item | ) |
Definition at line 4275 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().
04276 { 04277 if (item == NULL) { 04278 ast_log(LOG_WARNING, "null item\n"); 04279 return; 04280 } 04281 04282 if (item->filename) 04283 free(item->filename); 04284 04285 switch (item->type) { 04286 case PV_WORD: 04287 /* fields: item->u1.str == string associated with this (word). */ 04288 if (item->u1.str ) 04289 free(item->u1.str); 04290 if ( item->u2.arglist ) 04291 destroy_pval(item->u2.arglist); 04292 break; 04293 04294 case PV_MACRO: 04295 /* fields: item->u1.str == name of macro 04296 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 04297 item->u2.arglist->u1.str == argument 04298 item->u2.arglist->next == next arg 04299 04300 item->u3.macro_statements == pval list of statements in macro body. 04301 */ 04302 destroy_pval(item->u2.arglist); 04303 if (item->u1.str ) 04304 free(item->u1.str); 04305 destroy_pval(item->u3.macro_statements); 04306 break; 04307 04308 case PV_CONTEXT: 04309 /* fields: item->u1.str == name of context 04310 item->u2.statements == pval list of statements in context body 04311 item->u3.abstract == int 1 if an abstract keyword were present 04312 */ 04313 if (item->u1.str) 04314 free(item->u1.str); 04315 destroy_pval(item->u2.statements); 04316 break; 04317 04318 case PV_MACRO_CALL: 04319 /* fields: item->u1.str == name of macro to call 04320 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 04321 item->u2.arglist->u1.str == argument 04322 item->u2.arglist->next == next arg 04323 */ 04324 if (item->u1.str) 04325 free(item->u1.str); 04326 destroy_pval(item->u2.arglist); 04327 break; 04328 04329 case PV_APPLICATION_CALL: 04330 /* fields: item->u1.str == name of application to call 04331 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 04332 item->u2.arglist->u1.str == argument 04333 item->u2.arglist->next == next arg 04334 */ 04335 if (item->u1.str) 04336 free(item->u1.str); 04337 destroy_pval(item->u2.arglist); 04338 break; 04339 04340 case PV_CASE: 04341 /* fields: item->u1.str == value of case 04342 item->u2.statements == pval list of statements under the case 04343 */ 04344 if (item->u1.str) 04345 free(item->u1.str); 04346 destroy_pval(item->u2.statements); 04347 break; 04348 04349 case PV_PATTERN: 04350 /* fields: item->u1.str == value of case 04351 item->u2.statements == pval list of statements under the case 04352 */ 04353 if (item->u1.str) 04354 free(item->u1.str); 04355 destroy_pval(item->u2.statements); 04356 break; 04357 04358 case PV_DEFAULT: 04359 /* fields: 04360 item->u2.statements == pval list of statements under the case 04361 */ 04362 destroy_pval(item->u2.statements); 04363 break; 04364 04365 case PV_CATCH: 04366 /* fields: item->u1.str == name of extension to catch 04367 item->u2.statements == pval list of statements in context body 04368 */ 04369 if (item->u1.str) 04370 free(item->u1.str); 04371 destroy_pval(item->u2.statements); 04372 break; 04373 04374 case PV_SWITCHES: 04375 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04376 */ 04377 destroy_pval(item->u1.list); 04378 break; 04379 04380 case PV_ESWITCHES: 04381 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04382 */ 04383 destroy_pval(item->u1.list); 04384 break; 04385 04386 case PV_INCLUDES: 04387 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04388 item->u2.arglist == pval list of 4 PV_WORD elements for time values 04389 */ 04390 destroy_pval(item->u1.list); 04391 break; 04392 04393 case PV_STATEMENTBLOCK: 04394 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 04395 */ 04396 destroy_pval(item->u1.list); 04397 break; 04398 04399 case PV_VARDEC: 04400 /* fields: item->u1.str == variable name 04401 item->u2.val == variable value to assign 04402 */ 04403 if (item->u1.str) 04404 free(item->u1.str); 04405 if (item->u2.val) 04406 free(item->u2.val); 04407 break; 04408 04409 case PV_GOTO: 04410 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 04411 item->u1.list->u1.str == where the data on a PV_WORD will always be. 04412 */ 04413 04414 destroy_pval(item->u1.list); 04415 break; 04416 04417 case PV_LABEL: 04418 /* fields: item->u1.str == label name 04419 */ 04420 if (item->u1.str) 04421 free(item->u1.str); 04422 break; 04423 04424 case PV_FOR: 04425 /* fields: item->u1.for_init == a string containing the initalizer 04426 item->u2.for_test == a string containing the loop test 04427 item->u3.for_inc == a string containing the loop increment 04428 04429 item->u4.for_statements == a pval list of statements in the for () 04430 */ 04431 if (item->u1.for_init) 04432 free(item->u1.for_init); 04433 if (item->u2.for_test) 04434 free(item->u2.for_test); 04435 if (item->u3.for_inc) 04436 free(item->u3.for_inc); 04437 destroy_pval(item->u4.for_statements); 04438 break; 04439 04440 case PV_WHILE: 04441 /* fields: item->u1.str == the while conditional, as supplied by user 04442 04443 item->u2.statements == a pval list of statements in the while () 04444 */ 04445 if (item->u1.str) 04446 free(item->u1.str); 04447 destroy_pval(item->u2.statements); 04448 break; 04449 04450 case PV_BREAK: 04451 /* fields: none 04452 */ 04453 break; 04454 04455 case PV_RETURN: 04456 /* fields: none 04457 */ 04458 break; 04459 04460 case PV_CONTINUE: 04461 /* fields: none 04462 */ 04463 break; 04464 04465 case PV_IFTIME: 04466 /* fields: item->u1.list == the 4 time values, in PV_WORD structs, linked list 04467 04468 item->u2.statements == a pval list of statements in the if () 04469 item->u3.else_statements == a pval list of statements in the else 04470 (could be zero) 04471 */ 04472 destroy_pval(item->u1.list); 04473 destroy_pval(item->u2.statements); 04474 if (item->u3.else_statements) { 04475 destroy_pval(item->u3.else_statements); 04476 } 04477 break; 04478 04479 case PV_RANDOM: 04480 /* fields: item->u1.str == the random percentage, as supplied by user 04481 04482 item->u2.statements == a pval list of statements in the true part () 04483 item->u3.else_statements == a pval list of statements in the else 04484 (could be zero) 04485 fall thru to If */ 04486 case PV_IF: 04487 /* fields: item->u1.str == the if conditional, as supplied by user 04488 04489 item->u2.statements == a pval list of statements in the if () 04490 item->u3.else_statements == a pval list of statements in the else 04491 (could be zero) 04492 */ 04493 if (item->u1.str) 04494 free(item->u1.str); 04495 destroy_pval(item->u2.statements); 04496 if (item->u3.else_statements) { 04497 destroy_pval(item->u3.else_statements); 04498 } 04499 break; 04500 04501 case PV_SWITCH: 04502 /* fields: item->u1.str == the switch expression 04503 04504 item->u2.statements == a pval list of statements in the switch, 04505 (will be case statements, most likely!) 04506 */ 04507 if (item->u1.str) 04508 free(item->u1.str); 04509 destroy_pval(item->u2.statements); 04510 break; 04511 04512 case PV_EXTENSION: 04513 /* fields: item->u1.str == the extension name, label, whatever it's called 04514 04515 item->u2.statements == a pval list of statements in the extension 04516 item->u3.hints == a char * hint argument 04517 item->u4.regexten == an int boolean. non-zero says that regexten was specified 04518 */ 04519 if (item->u1.str) 04520 free(item->u1.str); 04521 if (item->u3.hints) 04522 free(item->u3.hints); 04523 destroy_pval(item->u2.statements); 04524 break; 04525 04526 case PV_IGNOREPAT: 04527 /* fields: item->u1.str == the ignorepat data 04528 */ 04529 if (item->u1.str) 04530 free(item->u1.str); 04531 break; 04532 04533 case PV_GLOBALS: 04534 /* fields: item->u1.statements == pval list of statements, usually vardecs 04535 */ 04536 destroy_pval(item->u1.statements); 04537 break; 04538 } 04539 free(item); 04540 }
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 1885 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().
01886 { 01887 return_on_context_match = 1; 01888 count_labels = 0; 01889 match_context = name; 01890 match_exten = "*"; /* don't really need to set these, shouldn't be reached */ 01891 match_label = "*"; 01892 return match_pval(current_db); 01893 }
Definition at line 1764 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().
01765 { 01766 /* printf(" --- Got args %s, %s\n", exten, label); */ 01767 struct pval *ret; 01768 struct pval *p3; 01769 struct pval *startpt = ((curr_cont->type==PV_MACRO)?curr_cont->u3.macro_statements: curr_cont->u2.statements); 01770 01771 count_labels = 0; 01772 return_on_context_match = 0; 01773 match_context = "*"; 01774 match_exten = "*"; 01775 match_label = label; 01776 01777 ret = match_pval(curr_cont); 01778 if (ret) 01779 return ret; 01780 01781 /* the target of the goto could be in an included context!! Fancy that!! */ 01782 /* look for includes in the current context */ 01783 for (p3=startpt; p3; p3=p3->next) { 01784 if (p3->type == PV_INCLUDES) { 01785 struct pval *p4; 01786 for (p4=p3->u1.list; p4; p4=p4->next) { 01787 /* for each context pointed to, find it, then find a context/label that matches the 01788 target here! */ 01789 char *incl_context = p4->u1.str; 01790 /* find a matching context name */ 01791 struct pval *that_context = find_context(incl_context); 01792 if (that_context) { 01793 struct pval *x3; 01794 x3 = find_first_label_in_current_context(label, that_context); 01795 if (x3) { 01796 return x3; 01797 } 01798 } 01799 } 01800 } 01801 } 01802 return 0; 01803 }
struct pval * find_label_in_current_context | ( | char * | exten, | |
char * | label, | |||
pval * | curr_cont | |||
) | [static] |
Definition at line 1805 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().
01806 { 01807 /* printf(" --- Got args %s, %s\n", exten, label); */ 01808 struct pval *ret; 01809 struct pval *p3; 01810 struct pval *startpt; 01811 01812 count_labels = 0; 01813 return_on_context_match = 0; 01814 match_context = "*"; 01815 match_exten = exten; 01816 match_label = label; 01817 if (curr_cont->type == PV_MACRO) 01818 startpt = curr_cont->u3.macro_statements; 01819 else 01820 startpt = curr_cont->u2.statements; 01821 01822 ret = match_pval(startpt); 01823 if (ret) 01824 return ret; 01825 01826 /* the target of the goto could be in an included context!! Fancy that!! */ 01827 /* look for includes in the current context */ 01828 for (p3=startpt; p3; p3=p3->next) { 01829 if (p3->type == PV_INCLUDES) { 01830 struct pval *p4; 01831 for (p4=p3->u1.list; p4; p4=p4->next) { 01832 /* for each context pointed to, find it, then find a context/label that matches the 01833 target here! */ 01834 char *incl_context = p4->u1.str; 01835 /* find a matching context name */ 01836 struct pval *that_context = find_context(incl_context); 01837 if (that_context) { 01838 struct pval *x3; 01839 x3 = find_label_in_current_context(exten, label, that_context); 01840 if (x3) { 01841 return x3; 01842 } 01843 } 01844 } 01845 } 01846 } 01847 return 0; 01848 }
static struct pval * find_label_in_current_db | ( | const char * | context, | |
const char * | exten, | |||
const char * | label | |||
) | [static] |
Definition at line 1861 of file pbx_ael.c.
References current_db, and match_pval().
Referenced by check_goto(), and get_goto_target().
01862 { 01863 /* printf(" --- Got args %s, %s, %s\n", context, exten, label); */ 01864 count_labels = 0; 01865 return_on_context_match = 0; 01866 01867 match_context = context; 01868 match_exten = exten; 01869 match_label = label; 01870 01871 return match_pval(current_db); 01872 }
static struct pval * find_label_in_current_extension | ( | const char * | label, | |
pval * | curr_ext | |||
) | [static] |
Definition at line 1850 of file pbx_ael.c.
References match_pval().
Referenced by check_goto(), and get_goto_target().
01851 { 01852 /* printf(" --- Got args %s\n", label); */ 01853 count_labels = 0; 01854 return_on_context_match = 0; 01855 match_context = "*"; 01856 match_exten = "*"; 01857 match_label = label; 01858 return match_pval(curr_ext); 01859 }
struct pval * find_macro | ( | char * | name | ) |
Definition at line 1875 of file pbx_ael.c.
References current_db, and match_pval().
Referenced by check_pval_item().
01876 { 01877 return_on_context_match = 1; 01878 count_labels = 0; 01879 match_context = name; 01880 match_exten = "*"; /* don't really need to set these, shouldn't be reached */ 01881 match_label = "*"; 01882 return match_pval(current_db); 01883 }
static void find_pval_goto_item | ( | pval * | item, | |
int | lev | |||
) | [static] |
Definition at line 1298 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().
01299 { 01300 struct pval *p4; 01301 if (lev>100) { 01302 ast_log(LOG_ERROR,"find_pval_goto in infinite loop!\n\n"); 01303 return; 01304 } 01305 01306 switch ( item->type ) { 01307 case PV_MACRO: 01308 /* fields: item->u1.str == name of macro 01309 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 01310 item->u2.arglist->u1.str == argument 01311 item->u2.arglist->next == next arg 01312 01313 item->u3.macro_statements == pval list of statements in macro body. 01314 */ 01315 01316 /* printf("Descending into matching macro %s\n", match_context); */ 01317 find_pval_gotos(item->u3.macro_statements,lev+1); /* if we're just searching for a context, don't bother descending into them */ 01318 01319 break; 01320 01321 case PV_CONTEXT: 01322 /* fields: item->u1.str == name of context 01323 item->u2.statements == pval list of statements in context body 01324 item->u3.abstract == int 1 if an abstract keyword were present 01325 */ 01326 break; 01327 01328 case PV_CASE: 01329 /* fields: item->u1.str == value of case 01330 item->u2.statements == pval list of statements under the case 01331 */ 01332 find_pval_gotos(item->u2.statements,lev+1); 01333 break; 01334 01335 case PV_PATTERN: 01336 /* fields: item->u1.str == value of case 01337 item->u2.statements == pval list of statements under the case 01338 */ 01339 find_pval_gotos(item->u2.statements,lev+1); 01340 break; 01341 01342 case PV_DEFAULT: 01343 /* fields: 01344 item->u2.statements == pval list of statements under the case 01345 */ 01346 find_pval_gotos(item->u2.statements,lev+1); 01347 break; 01348 01349 case PV_CATCH: 01350 /* fields: item->u1.str == name of extension to catch 01351 item->u2.statements == pval list of statements in context body 01352 */ 01353 find_pval_gotos(item->u2.statements,lev+1); 01354 break; 01355 01356 case PV_STATEMENTBLOCK: 01357 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 01358 */ 01359 find_pval_gotos(item->u1.list,lev+1); 01360 break; 01361 01362 case PV_GOTO: 01363 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 01364 item->u1.list->u1.str == where the data on a PV_WORD will always be. 01365 */ 01366 check_goto(item); /* THE WHOLE FUNCTION OF THIS ENTIRE ROUTINE!!!! */ 01367 break; 01368 01369 case PV_INCLUDES: 01370 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 01371 */ 01372 for (p4=item->u1.list; p4; p4=p4->next) { 01373 /* for each context pointed to, find it, then find a context/label that matches the 01374 target here! */ 01375 char *incl_context = p4->u1.str; 01376 /* find a matching context name */ 01377 struct pval *that_context = find_context(incl_context); 01378 if (that_context) { 01379 find_pval_gotos(that_context,lev+1); /* keep working up the includes */ 01380 } 01381 } 01382 break; 01383 01384 case PV_FOR: 01385 /* fields: item->u1.for_init == a string containing the initalizer 01386 item->u2.for_test == a string containing the loop test 01387 item->u3.for_inc == a string containing the loop increment 01388 01389 item->u4.for_statements == a pval list of statements in the for () 01390 */ 01391 find_pval_gotos(item->u4.for_statements,lev+1); 01392 break; 01393 01394 case PV_WHILE: 01395 /* fields: item->u1.str == the while conditional, as supplied by user 01396 01397 item->u2.statements == a pval list of statements in the while () 01398 */ 01399 find_pval_gotos(item->u2.statements,lev+1); 01400 break; 01401 01402 case PV_RANDOM: 01403 /* fields: item->u1.str == the random number expression, as supplied by user 01404 01405 item->u2.statements == a pval list of statements in the if () 01406 item->u3.else_statements == a pval list of statements in the else 01407 (could be zero) 01408 fall thru to PV_IF */ 01409 01410 case PV_IFTIME: 01411 /* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list 01412 01413 item->u2.statements == a pval list of statements in the if () 01414 item->u3.else_statements == a pval list of statements in the else 01415 (could be zero) 01416 fall thru to PV_IF*/ 01417 case PV_IF: 01418 /* fields: item->u1.str == the if conditional, as supplied by user 01419 01420 item->u2.statements == a pval list of statements in the if () 01421 item->u3.else_statements == a pval list of statements in the else 01422 (could be zero) 01423 */ 01424 find_pval_gotos(item->u2.statements,lev+1); 01425 01426 if (item->u3.else_statements) { 01427 find_pval_gotos(item->u3.else_statements,lev+1); 01428 } 01429 break; 01430 01431 case PV_SWITCH: 01432 /* fields: item->u1.str == the switch expression 01433 01434 item->u2.statements == a pval list of statements in the switch, 01435 (will be case statements, most likely!) 01436 */ 01437 find_pval_gotos(item->u3.else_statements,lev+1); 01438 break; 01439 01440 case PV_EXTENSION: 01441 /* fields: item->u1.str == the extension name, label, whatever it's called 01442 01443 item->u2.statements == a pval list of statements in the extension 01444 item->u3.hints == a char * hint argument 01445 item->u4.regexten == an int boolean. non-zero says that regexten was specified 01446 */ 01447 01448 find_pval_gotos(item->u2.statements,lev+1); 01449 break; 01450 01451 default: 01452 break; 01453 } 01454 }
static void find_pval_gotos | ( | pval * | item, | |
int | lev | |||
) | [static] |
Definition at line 1456 of file pbx_ael.c.
References find_pval_goto_item(), and pval::next.
Referenced by check_pval_item(), and find_pval_goto_item().
01457 { 01458 pval *i; 01459 01460 for (i=item; i; i=i->next) { 01461 01462 find_pval_goto_item(i, lev); 01463 } 01464 }
static void fix_gotos_in_extensions | ( | struct ael_extension * | exten | ) | [static] |
Definition at line 3869 of file pbx_ael.c.
References exten, ael_priority::next, ael_extension::next_exten, ael_extension::plist, PV_GOTO, and strdup.
03870 { 03871 struct ael_extension *e; 03872 for(e=exten;e;e=e->next_exten) { 03873 03874 struct ael_priority *p; 03875 for(p=e->plist;p;p=p->next) { 03876 03877 if( p->origin && p->origin->type == PV_GOTO && p->origin->u3.goto_target_in_case ) { 03878 03879 /* fix the extension of the goto target to the actual extension in the post-compiled dialplan */ 03880 03881 pval *target = p->origin->u2.goto_target; 03882 struct ael_extension *z = target->u3.compiled_label; 03883 pval *pv2 = p->origin; 03884 char buf1[500]; 03885 char *apparg_save = p->appargs; 03886 03887 p->appargs = 0; 03888 if (!pv2->u1.list->next) /* just one -- it won't hurt to repeat the extension */ { 03889 snprintf(buf1,sizeof(buf1),"%s|%s", z->name, pv2->u1.list->u1.str); 03890 p->appargs = strdup(buf1); 03891 03892 } else if (pv2->u1.list->next && !pv2->u1.list->next->next) /* two */ { 03893 snprintf(buf1,sizeof(buf1),"%s|%s", z->name, pv2->u1.list->next->u1.str); 03894 p->appargs = strdup(buf1); 03895 } else if (pv2->u1.list->next && pv2->u1.list->next->next) { 03896 snprintf(buf1,sizeof(buf1),"%s|%s|%s", pv2->u1.list->u1.str, 03897 z->name, 03898 pv2->u1.list->next->next->u1.str); 03899 p->appargs = strdup(buf1); 03900 } 03901 else 03902 printf("WHAT? The goto doesn't fall into one of three cases for GOTO????\n"); 03903 03904 if( apparg_save ) { 03905 free(apparg_save); 03906 } 03907 } 03908 } 03909 } 03910 }
static void gen_match_to_pattern | ( | char * | pattern, | |
char * | result | |||
) | [static] |
Definition at line 2900 of file pbx_ael.c.
References t.
Referenced by gen_prios().
02901 { 02902 /* the result will be a string that will be matched by pattern */ 02903 char *p=pattern, *t=result; 02904 while (*p) { 02905 if (*p == 'x' || *p == 'n' || *p == 'z' || *p == 'X' || *p == 'N' || *p == 'Z') 02906 *t++ = '9'; 02907 else if (*p == '[') { 02908 char *z = p+1; 02909 while (*z != ']') 02910 z++; 02911 if (*(z+1)== ']') 02912 z++; 02913 *t++=*(p+1); /* use the first char in the set */ 02914 p = z; 02915 } else { 02916 *t++ = *p; 02917 } 02918 p++; 02919 } 02920 *t++ = 0; /* cap it off */ 02921 }
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 2923 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, free, 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::has_switch, 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.
02924 { 02925 pval *p,*p2,*p3; 02926 struct ael_priority *pr; 02927 struct ael_priority *for_init, *for_test, *for_inc, *for_loop, *for_end; 02928 struct ael_priority *while_test, *while_loop, *while_end; 02929 struct ael_priority *switch_set, *switch_test, *switch_end, *fall_thru, *switch_empty; 02930 struct ael_priority *if_test, *if_end, *if_skip, *if_false; 02931 #ifdef OLD_RAND_ACTION 02932 struct ael_priority *rand_test, *rand_end, *rand_skip; 02933 #endif 02934 char buf1[2000]; 02935 char buf2[2000]; 02936 char *strp, *strp2; 02937 char new_label[2000]; 02938 int default_exists; 02939 int local_control_statement_count; 02940 struct ael_priority *loop_break_save; 02941 struct ael_priority *loop_continue_save; 02942 struct ael_extension *switch_case,*switch_null; 02943 02944 for (p=statement; p; p=p->next) { 02945 switch (p->type) { 02946 case PV_VARDEC: 02947 pr = new_prio(); 02948 pr->type = AEL_APPCALL; 02949 snprintf(buf1,sizeof(buf1),"%s=$[%s]", p->u1.str, p->u2.val); 02950 pr->app = strdup("Set"); 02951 remove_spaces_before_equals(buf1); 02952 pr->appargs = strdup(buf1); 02953 pr->origin = p; 02954 linkprio(exten, pr, mother_exten); 02955 break; 02956 02957 case PV_GOTO: 02958 pr = new_prio(); 02959 pr->type = AEL_APPCALL; 02960 p->u2.goto_target = get_goto_target(p); 02961 if( p->u2.goto_target ) { 02962 p->u3.goto_target_in_case = p->u2.goto_target->u2.label_in_case = label_inside_case(p->u2.goto_target); 02963 } 02964 02965 if (!p->u1.list->next) /* just one */ { 02966 pr->app = strdup("Goto"); 02967 if (!mother_exten) 02968 pr->appargs = strdup(p->u1.list->u1.str); 02969 else { /* for the case of simple within-extension gotos in case/pattern/default statement blocks: */ 02970 snprintf(buf1,sizeof(buf1),"%s|%s", mother_exten->name, p->u1.list->u1.str); 02971 pr->appargs = strdup(buf1); 02972 } 02973 02974 } else if (p->u1.list->next && !p->u1.list->next->next) /* two */ { 02975 snprintf(buf1,sizeof(buf1),"%s|%s", p->u1.list->u1.str, p->u1.list->next->u1.str); 02976 pr->app = strdup("Goto"); 02977 pr->appargs = strdup(buf1); 02978 } else if (p->u1.list->next && p->u1.list->next->next) { 02979 snprintf(buf1,sizeof(buf1),"%s|%s|%s", p->u1.list->u1.str, 02980 p->u1.list->next->u1.str, 02981 p->u1.list->next->next->u1.str); 02982 pr->app = strdup("Goto"); 02983 pr->appargs = strdup(buf1); 02984 } 02985 pr->origin = p; 02986 linkprio(exten, pr, mother_exten); 02987 break; 02988 02989 case PV_LABEL: 02990 pr = new_prio(); 02991 pr->type = AEL_LABEL; 02992 pr->origin = p; 02993 p->u3.compiled_label = exten; 02994 linkprio(exten, pr, mother_exten); 02995 break; 02996 02997 case PV_FOR: 02998 control_statement_count++; 02999 loop_break_save = exten->loop_break; /* save them, then restore before leaving */ 03000 loop_continue_save = exten->loop_continue; 03001 snprintf(new_label,sizeof(new_label),"for-%s-%d", label, control_statement_count); 03002 for_init = new_prio(); 03003 for_inc = new_prio(); 03004 for_test = new_prio(); 03005 for_loop = new_prio(); 03006 for_end = new_prio(); 03007 for_init->type = AEL_APPCALL; 03008 for_inc->type = AEL_APPCALL; 03009 for_test->type = AEL_FOR_CONTROL; 03010 for_test->goto_false = for_end; 03011 for_loop->type = AEL_CONTROL1; /* simple goto */ 03012 for_end->type = AEL_APPCALL; 03013 for_init->app = strdup("Set"); 03014 03015 strcpy(buf2,p->u1.for_init); 03016 remove_spaces_before_equals(buf2); 03017 strp = strchr(buf2, '='); 03018 if (strp) { 03019 strp2 = strchr(p->u1.for_init, '='); 03020 *(strp+1) = 0; 03021 strcat(buf2,"$["); 03022 strncat(buf2,strp2+1, sizeof(buf2)-strlen(strp2+1)-2); 03023 strcat(buf2,"]"); 03024 for_init->appargs = strdup(buf2); 03025 /* for_init->app = strdup("Set"); just set! */ 03026 } else { 03027 strp2 = p->u1.for_init; 03028 while (*strp2 && isspace(*strp2)) 03029 strp2++; 03030 if (*strp2 == '&') { /* itsa macro call */ 03031 char *strp3 = strp2+1; 03032 while (*strp3 && isspace(*strp3)) 03033 strp3++; 03034 strcpy(buf2, strp3); 03035 strp3 = strchr(buf2,'('); 03036 if (strp3) { 03037 *strp3 = '|'; 03038 } 03039 while ((strp3=strchr(buf2,','))) { 03040 *strp3 = '|'; 03041 } 03042 strp3 = strrchr(buf2, ')'); 03043 if (strp3) 03044 *strp3 = 0; /* remove the closing paren */ 03045 03046 for_init->appargs = strdup(buf2); 03047 if (for_init->app) 03048 free(for_init->app); 03049 for_init->app = strdup("Macro"); 03050 } else { /* must be a regular app call */ 03051 char *strp3; 03052 strcpy(buf2, strp2); 03053 strp3 = strchr(buf2,'('); 03054 if (strp3) { 03055 *strp3 = 0; 03056 if (for_init->app) 03057 free(for_init->app); 03058 for_init->app = strdup(buf2); 03059 for_init->appargs = strdup(strp3+1); 03060 strp3 = strrchr(for_init->appargs, ')'); 03061 if (strp3) 03062 *strp3 = 0; /* remove the closing paren */ 03063 } 03064 } 03065 } 03066 03067 strcpy(buf2,p->u3.for_inc); 03068 remove_spaces_before_equals(buf2); 03069 strp = strchr(buf2, '='); 03070 if (strp) { /* there's an = in this part; that means an assignment. set it up */ 03071 strp2 = strchr(p->u3.for_inc, '='); 03072 *(strp+1) = 0; 03073 strcat(buf2,"$["); 03074 strncat(buf2,strp2+1, sizeof(buf2)-strlen(strp2+1)-2); 03075 strcat(buf2,"]"); 03076 for_inc->appargs = strdup(buf2); 03077 for_inc->app = strdup("Set"); 03078 } else { 03079 strp2 = p->u3.for_inc; 03080 while (*strp2 && isspace(*strp2)) 03081 strp2++; 03082 if (*strp2 == '&') { /* itsa macro call */ 03083 char *strp3 = strp2+1; 03084 while (*strp3 && isspace(*strp3)) 03085 strp3++; 03086 strcpy(buf2, strp3); 03087 strp3 = strchr(buf2,'('); 03088 if (strp3) { 03089 *strp3 = '|'; 03090 } 03091 while ((strp3=strchr(buf2,','))) { 03092 *strp3 = '|'; 03093 } 03094 strp3 = strrchr(buf2, ')'); 03095 if (strp3) 03096 *strp3 = 0; /* remove the closing paren */ 03097 03098 for_inc->appargs = strdup(buf2); 03099 03100 for_inc->app = strdup("Macro"); 03101 } else { /* must be a regular app call */ 03102 char *strp3; 03103 strcpy(buf2, strp2); 03104 strp3 = strchr(buf2,'('); 03105 if (strp3) { 03106 *strp3 = 0; 03107 for_inc->app = strdup(buf2); 03108 for_inc->appargs = strdup(strp3+1); 03109 strp3 = strrchr(for_inc->appargs, ')'); 03110 if (strp3) 03111 *strp3 = 0; /* remove the closing paren */ 03112 } 03113 } 03114 } 03115 snprintf(buf1,sizeof(buf1),"$[%s]",p->u2.for_test); 03116 for_test->app = 0; 03117 for_test->appargs = strdup(buf1); 03118 for_loop->goto_true = for_test; 03119 snprintf(buf1,sizeof(buf1),"Finish for-%s-%d", label, control_statement_count); 03120 for_end->app = strdup("NoOp"); 03121 for_end->appargs = strdup(buf1); 03122 /* link & load! */ 03123 linkprio(exten, for_init, mother_exten); 03124 linkprio(exten, for_test, mother_exten); 03125 03126 /* now, put the body of the for loop here */ 03127 exten->loop_break = for_end; 03128 exten->loop_continue = for_inc; 03129 03130 gen_prios(exten, new_label, p->u4.for_statements, mother_exten, this_context); /* this will link in all the statements here */ 03131 03132 linkprio(exten, for_inc, mother_exten); 03133 linkprio(exten, for_loop, mother_exten); 03134 linkprio(exten, for_end, mother_exten); 03135 03136 03137 exten->loop_break = loop_break_save; 03138 exten->loop_continue = loop_continue_save; 03139 for_loop->origin = p; 03140 break; 03141 03142 case PV_WHILE: 03143 control_statement_count++; 03144 loop_break_save = exten->loop_break; /* save them, then restore before leaving */ 03145 loop_continue_save = exten->loop_continue; 03146 snprintf(new_label,sizeof(new_label),"while-%s-%d", label, control_statement_count); 03147 while_test = new_prio(); 03148 while_loop = new_prio(); 03149 while_end = new_prio(); 03150 while_test->type = AEL_FOR_CONTROL; 03151 while_test->goto_false = while_end; 03152 while_loop->type = AEL_CONTROL1; /* simple goto */ 03153 while_end->type = AEL_APPCALL; 03154 snprintf(buf1,sizeof(buf1),"$[%s]",p->u1.str); 03155 while_test->app = 0; 03156 while_test->appargs = strdup(buf1); 03157 while_loop->goto_true = while_test; 03158 snprintf(buf1,sizeof(buf1),"Finish while-%s-%d", label, control_statement_count); 03159 while_end->app = strdup("NoOp"); 03160 while_end->appargs = strdup(buf1); 03161 03162 linkprio(exten, while_test, mother_exten); 03163 03164 /* now, put the body of the for loop here */ 03165 exten->loop_break = while_end; 03166 exten->loop_continue = while_test; 03167 03168 gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the while body statements here */ 03169 03170 linkprio(exten, while_loop, mother_exten); 03171 linkprio(exten, while_end, mother_exten); 03172 03173 03174 exten->loop_break = loop_break_save; 03175 exten->loop_continue = loop_continue_save; 03176 while_loop->origin = p; 03177 break; 03178 03179 case PV_SWITCH: 03180 control_statement_count++; 03181 local_control_statement_count = control_statement_count; 03182 loop_break_save = exten->loop_break; /* save them, then restore before leaving */ 03183 loop_continue_save = exten->loop_continue; 03184 snprintf(new_label,sizeof(new_label),"sw-%s-%d", label, control_statement_count); 03185 if ((mother_exten && !mother_exten->has_switch)) { 03186 switch_set = new_prio(); 03187 switch_set->type = AEL_APPCALL; 03188 switch_set->app = strdup("Set"); 03189 switch_set->appargs = strdup("~~EXTEN~~=${EXTEN}"); 03190 linkprio(exten, switch_set, mother_exten); 03191 mother_exten->has_switch = 1; 03192 } else if ((exten && !exten->has_switch)) { 03193 switch_set = new_prio(); 03194 switch_set->type = AEL_APPCALL; 03195 switch_set->app = strdup("Set"); 03196 switch_set->appargs = strdup("~~EXTEN~~=${EXTEN}"); 03197 linkprio(exten, switch_set, exten); 03198 exten->has_switch = 1; 03199 } 03200 switch_test = new_prio(); 03201 switch_end = new_prio(); 03202 switch_test->type = AEL_APPCALL; 03203 switch_end->type = AEL_APPCALL; 03204 strncpy(buf2,p->u1.str,sizeof(buf2)); 03205 buf2[sizeof(buf2)-1] = 0; /* just in case */ 03206 substitute_commas(buf2); 03207 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",control_statement_count, buf2); 03208 switch_test->app = strdup("Goto"); 03209 switch_test->appargs = strdup(buf1); 03210 snprintf(buf1,sizeof(buf1),"Finish switch-%s-%d", label, control_statement_count); 03211 switch_end->app = strdup("NoOp"); 03212 switch_end->appargs = strdup(buf1); 03213 switch_end->origin = p; 03214 switch_end->exten = exten; 03215 03216 linkprio(exten, switch_test, mother_exten); 03217 linkprio(exten, switch_end, mother_exten); 03218 03219 exten->loop_break = switch_end; 03220 exten->loop_continue = 0; 03221 default_exists = 0; 03222 03223 for (p2=p->u2.statements; p2; p2=p2->next) { 03224 /* now, for each case/default put the body of the for loop here */ 03225 if (p2->type == PV_CASE) { 03226 /* ok, generate a extension and link it in */ 03227 switch_case = new_exten(); 03228 switch_case->context = this_context; 03229 switch_case->is_switch = 1; 03230 /* the break/continue locations are inherited from parent */ 03231 switch_case->loop_break = exten->loop_break; 03232 switch_case->loop_continue = exten->loop_continue; 03233 03234 linkexten(exten,switch_case); 03235 strncpy(buf2,p2->u1.str,sizeof(buf2)); 03236 buf2[sizeof(buf2)-1] = 0; /* just in case */ 03237 substitute_commas(buf2); 03238 snprintf(buf1,sizeof(buf1),"sw-%d-%s", local_control_statement_count, buf2); 03239 switch_case->name = strdup(buf1); 03240 snprintf(new_label,sizeof(new_label),"sw-%s-%s-%d", label, buf2, local_control_statement_count); 03241 03242 gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context); /* this will link in all the case body statements here */ 03243 03244 /* here is where we write code to "fall thru" to the next case... if there is one... */ 03245 for (p3=p2->u2.statements; p3; p3=p3->next) { 03246 if (!p3->next) 03247 break; 03248 } 03249 /* p3 now points the last statement... */ 03250 if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN) ) { 03251 /* is there a following CASE/PATTERN/DEFAULT? */ 03252 if (p2->next && p2->next->type == PV_CASE) { 03253 fall_thru = new_prio(); 03254 fall_thru->type = AEL_APPCALL; 03255 fall_thru->app = strdup("Goto"); 03256 strncpy(buf2,p2->next->u1.str,sizeof(buf2)); 03257 buf2[sizeof(buf2)-1] = 0; /* just in case */ 03258 substitute_commas(buf2); 03259 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, buf2); 03260 fall_thru->appargs = strdup(buf1); 03261 linkprio(switch_case, fall_thru, mother_exten); 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 substitute_commas(buf2); 03268 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10", local_control_statement_count, buf2); 03269 fall_thru->appargs = strdup(buf1); 03270 linkprio(switch_case, fall_thru, mother_exten); 03271 } else if (p2->next && p2->next->type == PV_DEFAULT) { 03272 fall_thru = new_prio(); 03273 fall_thru->type = AEL_APPCALL; 03274 fall_thru->app = strdup("Goto"); 03275 snprintf(buf1,sizeof(buf1),"sw-%d-.|10",local_control_statement_count); 03276 fall_thru->appargs = strdup(buf1); 03277 linkprio(switch_case, fall_thru, mother_exten); 03278 } else if (!p2->next) { 03279 fall_thru = new_prio(); 03280 fall_thru->type = AEL_CONTROL1; 03281 fall_thru->goto_true = switch_end; 03282 fall_thru->app = strdup("Goto"); 03283 linkprio(switch_case, fall_thru, mother_exten); 03284 } 03285 } 03286 if (switch_case->return_needed) { 03287 char buf[2000]; 03288 struct ael_priority *np2 = new_prio(); 03289 np2->type = AEL_APPCALL; 03290 np2->app = strdup("NoOp"); 03291 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); 03292 np2->appargs = strdup(buf); 03293 linkprio(switch_case, np2, mother_exten); 03294 switch_case-> return_target = np2; 03295 } 03296 } else if (p2->type == PV_PATTERN) { 03297 /* ok, generate a extension and link it in */ 03298 switch_case = new_exten(); 03299 switch_case->context = this_context; 03300 switch_case->is_switch = 1; 03301 /* the break/continue locations are inherited from parent */ 03302 switch_case->loop_break = exten->loop_break; 03303 switch_case->loop_continue = exten->loop_continue; 03304 03305 linkexten(exten,switch_case); 03306 strncpy(buf2,p2->u1.str,sizeof(buf2)); 03307 buf2[sizeof(buf2)-1] = 0; /* just in case */ 03308 substitute_commas(buf2); 03309 snprintf(buf1,sizeof(buf1),"_sw-%d-%s", local_control_statement_count, buf2); 03310 switch_case->name = strdup(buf1); 03311 snprintf(new_label,sizeof(new_label),"sw-%s-%s-%d", label, buf2, local_control_statement_count); 03312 03313 gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context); /* this will link in all the while body statements here */ 03314 /* here is where we write code to "fall thru" to the next case... if there is one... */ 03315 for (p3=p2->u2.statements; p3; p3=p3->next) { 03316 if (!p3->next) 03317 break; 03318 } 03319 /* p3 now points the last statement... */ 03320 if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) { 03321 /* is there a following CASE/PATTERN/DEFAULT? */ 03322 if (p2->next && p2->next->type == PV_CASE) { 03323 fall_thru = new_prio(); 03324 fall_thru->type = AEL_APPCALL; 03325 fall_thru->app = strdup("Goto"); 03326 strncpy(buf2,p2->next->u1.str,sizeof(buf2)); 03327 buf2[sizeof(buf2)-1] = 0; /* just in case */ 03328 substitute_commas(buf2); 03329 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, buf2); 03330 fall_thru->appargs = strdup(buf1); 03331 linkprio(switch_case, fall_thru, mother_exten); 03332 } else if (p2->next && p2->next->type == PV_PATTERN) { 03333 fall_thru = new_prio(); 03334 fall_thru->type = AEL_APPCALL; 03335 fall_thru->app = strdup("Goto"); 03336 gen_match_to_pattern(p2->next->u1.str, buf2); 03337 substitute_commas(buf2); 03338 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, buf2); 03339 fall_thru->appargs = strdup(buf1); 03340 linkprio(switch_case, fall_thru, mother_exten); 03341 } else if (p2->next && p2->next->type == PV_DEFAULT) { 03342 fall_thru = new_prio(); 03343 fall_thru->type = AEL_APPCALL; 03344 fall_thru->app = strdup("Goto"); 03345 snprintf(buf1,sizeof(buf1),"sw-%d-.|10",local_control_statement_count); 03346 fall_thru->appargs = strdup(buf1); 03347 linkprio(switch_case, fall_thru, mother_exten); 03348 } else if (!p2->next) { 03349 fall_thru = new_prio(); 03350 fall_thru->type = AEL_CONTROL1; 03351 fall_thru->goto_true = switch_end; 03352 fall_thru->app = strdup("Goto"); 03353 linkprio(switch_case, fall_thru, mother_exten); 03354 } 03355 } 03356 if (switch_case->return_needed) { 03357 char buf[2000]; 03358 struct ael_priority *np2 = new_prio(); 03359 np2->type = AEL_APPCALL; 03360 np2->app = strdup("NoOp"); 03361 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); 03362 np2->appargs = strdup(buf); 03363 linkprio(switch_case, np2, mother_exten); 03364 switch_case-> return_target = np2; 03365 } 03366 } else if (p2->type == PV_DEFAULT) { 03367 /* ok, generate a extension and link it in */ 03368 switch_case = new_exten(); 03369 switch_case->context = this_context; 03370 switch_case->is_switch = 1; 03371 03372 /* new: the default case intros a pattern with ., which covers ALMOST everything. 03373 but it doesn't cover a NULL pattern. So, we'll define a null extension to match 03374 that goto's the default extension. */ 03375 03376 default_exists++; 03377 switch_null = new_exten(); 03378 switch_null->context = this_context; 03379 switch_null->is_switch = 1; 03380 switch_empty = new_prio(); 03381 snprintf(buf1,sizeof(buf1),"sw-%d-.|10",local_control_statement_count); 03382 switch_empty->app = strdup("Goto"); 03383 switch_empty->appargs = strdup(buf1); 03384 linkprio(switch_null, switch_empty, mother_exten); 03385 snprintf(buf1,sizeof(buf1),"sw-%d-", local_control_statement_count); 03386 switch_null->name = strdup(buf1); 03387 switch_null->loop_break = exten->loop_break; 03388 switch_null->loop_continue = exten->loop_continue; 03389 linkexten(exten,switch_null); 03390 03391 /* the break/continue locations are inherited from parent */ 03392 switch_case->loop_break = exten->loop_break; 03393 switch_case->loop_continue = exten->loop_continue; 03394 linkexten(exten,switch_case); 03395 snprintf(buf1,sizeof(buf1),"_sw-%d-.", local_control_statement_count); 03396 switch_case->name = strdup(buf1); 03397 03398 snprintf(new_label,sizeof(new_label),"sw-%s-default-%d", label, local_control_statement_count); 03399 03400 gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context); /* this will link in all the default: body statements here */ 03401 03402 /* here is where we write code to "fall thru" to the next case... if there is one... */ 03403 for (p3=p2->u2.statements; p3; p3=p3->next) { 03404 if (!p3->next) 03405 break; 03406 } 03407 /* p3 now points the last statement... */ 03408 if (!p3 || (p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) { 03409 /* is there a following CASE/PATTERN/DEFAULT? */ 03410 if (p2->next && p2->next->type == PV_CASE) { 03411 fall_thru = new_prio(); 03412 fall_thru->type = AEL_APPCALL; 03413 fall_thru->app = strdup("Goto"); 03414 strncpy(buf2,p2->next->u1.str,sizeof(buf2)); 03415 buf2[sizeof(buf2)-1] = 0; /* just in case */ 03416 substitute_commas(buf2); 03417 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, buf2); 03418 fall_thru->appargs = strdup(buf1); 03419 linkprio(switch_case, fall_thru, mother_exten); 03420 } else if (p2->next && p2->next->type == PV_PATTERN) { 03421 fall_thru = new_prio(); 03422 fall_thru->type = AEL_APPCALL; 03423 fall_thru->app = strdup("Goto"); 03424 gen_match_to_pattern(p2->next->u1.str, buf2); 03425 substitute_commas(buf2); 03426 snprintf(buf1,sizeof(buf1),"sw-%d-%s|10",local_control_statement_count, buf2); 03427 fall_thru->appargs = strdup(buf1); 03428 linkprio(switch_case, fall_thru, mother_exten); 03429 } else if (p2->next && p2->next->type == PV_DEFAULT) { 03430 fall_thru = new_prio(); 03431 fall_thru->type = AEL_APPCALL; 03432 fall_thru->app = strdup("Goto"); 03433 snprintf(buf1,sizeof(buf1),"sw-%d-.|10",local_control_statement_count); 03434 fall_thru->appargs = strdup(buf1); 03435 linkprio(switch_case, fall_thru, mother_exten); 03436 } else if (!p2->next) { 03437 fall_thru = new_prio(); 03438 fall_thru->type = AEL_CONTROL1; 03439 fall_thru->goto_true = switch_end; 03440 fall_thru->app = strdup("Goto"); 03441 linkprio(switch_case, fall_thru, mother_exten); 03442 } 03443 } 03444 if (switch_case->return_needed) { 03445 char buf[2000]; 03446 struct ael_priority *np2 = new_prio(); 03447 np2->type = AEL_APPCALL; 03448 np2->app = strdup("NoOp"); 03449 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); 03450 np2->appargs = strdup(buf); 03451 linkprio(switch_case, np2, mother_exten); 03452 switch_case-> return_target = np2; 03453 } 03454 } else { 03455 /* what could it be??? */ 03456 } 03457 } 03458 03459 exten->loop_break = loop_break_save; 03460 exten->loop_continue = loop_continue_save; 03461 switch_test->origin = p; 03462 switch_end->origin = p; 03463 break; 03464 03465 case PV_MACRO_CALL: 03466 pr = new_prio(); 03467 pr->type = AEL_APPCALL; 03468 snprintf(buf1,sizeof(buf1),"%s", p->u1.str); 03469 for (p2 = p->u2.arglist; p2; p2 = p2->next) { 03470 strcat(buf1,"|"); 03471 strcat(buf1,p2->u1.str); 03472 } 03473 pr->app = strdup("Macro"); 03474 pr->appargs = strdup(buf1); 03475 pr->origin = p; 03476 linkprio(exten, pr, mother_exten); 03477 break; 03478 03479 case PV_APPLICATION_CALL: 03480 pr = new_prio(); 03481 pr->type = AEL_APPCALL; 03482 buf1[0] = 0; 03483 for (p2 = p->u2.arglist; p2; p2 = p2->next) { 03484 if (p2 != p->u2.arglist ) 03485 strcat(buf1,"|"); 03486 substitute_commas(p2->u1.str); 03487 strcat(buf1,p2->u1.str); 03488 } 03489 pr->app = strdup(p->u1.str); 03490 pr->appargs = strdup(buf1); 03491 pr->origin = p; 03492 linkprio(exten, pr, mother_exten); 03493 break; 03494 03495 case PV_BREAK: 03496 pr = new_prio(); 03497 pr->type = AEL_CONTROL1; /* simple goto */ 03498 pr->goto_true = exten->loop_break; 03499 pr->origin = p; 03500 linkprio(exten, pr, mother_exten); 03501 break; 03502 03503 case PV_RETURN: /* hmmmm */ 03504 pr = new_prio(); 03505 pr->type = AEL_RETURN; /* simple goto */ 03506 exten->return_needed++; 03507 pr->app = strdup("Goto"); 03508 pr->appargs = strdup(""); 03509 pr->origin = p; 03510 linkprio(exten, pr, mother_exten); 03511 break; 03512 03513 case PV_CONTINUE: 03514 pr = new_prio(); 03515 pr->type = AEL_CONTROL1; /* simple goto */ 03516 pr->goto_true = exten->loop_continue; 03517 pr->origin = p; 03518 linkprio(exten, pr, mother_exten); 03519 break; 03520 03521 #ifdef OLD_RAND_ACTION 03522 case PV_RANDOM: 03523 control_statement_count++; 03524 snprintf(new_label,sizeof(new_label),"rand-%s-%d", label, control_statement_count); 03525 rand_test = new_prio(); 03526 rand_test->type = AEL_RAND_CONTROL; 03527 snprintf(buf1,sizeof(buf1),"$[%s]", 03528 p->u1.str ); 03529 rand_test->app = 0; 03530 rand_test->appargs = strdup(buf1); 03531 rand_test->origin = p; 03532 03533 rand_end = new_prio(); 03534 rand_end->type = AEL_APPCALL; 03535 snprintf(buf1,sizeof(buf1),"Finish rand-%s-%d", label, control_statement_count); 03536 rand_end->app = strdup("NoOp"); 03537 rand_end->appargs = strdup(buf1); 03538 03539 rand_skip = new_prio(); 03540 rand_skip->type = AEL_CONTROL1; /* simple goto */ 03541 rand_skip->goto_true = rand_end; 03542 rand_skip->origin = p; 03543 03544 rand_test->goto_true = rand_skip; /* +1, really */ 03545 03546 linkprio(exten, rand_test, mother_exten); 03547 03548 if (p->u3.else_statements) { 03549 gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the else statements here */ 03550 } 03551 03552 linkprio(exten, rand_skip, mother_exten); 03553 03554 gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the "true" statements here */ 03555 03556 linkprio(exten, rand_end, mother_exten); 03557 03558 break; 03559 #endif 03560 03561 case PV_IFTIME: 03562 control_statement_count++; 03563 snprintf(new_label,sizeof(new_label),"iftime-%s-%d", label, control_statement_count); 03564 03565 if_test = new_prio(); 03566 if_test->type = AEL_IFTIME_CONTROL; 03567 snprintf(buf1,sizeof(buf1),"%s|%s|%s|%s", 03568 p->u1.list->u1.str, 03569 p->u1.list->next->u1.str, 03570 p->u1.list->next->next->u1.str, 03571 p->u1.list->next->next->next->u1.str); 03572 if_test->app = 0; 03573 if_test->appargs = strdup(buf1); 03574 if_test->origin = p; 03575 03576 if_end = new_prio(); 03577 if_end->type = AEL_APPCALL; 03578 snprintf(buf1,sizeof(buf1),"Finish iftime-%s-%d", label, control_statement_count); 03579 if_end->app = strdup("NoOp"); 03580 if_end->appargs = strdup(buf1); 03581 03582 if (p->u3.else_statements) { 03583 if_skip = new_prio(); 03584 if_skip->type = AEL_CONTROL1; /* simple goto */ 03585 if_skip->goto_true = if_end; 03586 if_skip->origin = p; 03587 03588 } else { 03589 if_skip = 0; 03590 03591 if_test->goto_false = if_end; 03592 } 03593 03594 if_false = new_prio(); 03595 if_false->type = AEL_CONTROL1; 03596 if (p->u3.else_statements) { 03597 if_false->goto_true = if_skip; /* +1 */ 03598 } else { 03599 if_false->goto_true = if_end; 03600 } 03601 03602 /* link & load! */ 03603 linkprio(exten, if_test, mother_exten); 03604 linkprio(exten, if_false, mother_exten); 03605 03606 /* now, put the body of the if here */ 03607 03608 gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the statements here */ 03609 03610 if (p->u3.else_statements) { 03611 linkprio(exten, if_skip, mother_exten); 03612 gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the statements here */ 03613 03614 } 03615 03616 linkprio(exten, if_end, mother_exten); 03617 03618 break; 03619 03620 case PV_RANDOM: 03621 case PV_IF: 03622 control_statement_count++; 03623 snprintf(new_label,sizeof(new_label),"if-%s-%d", label, control_statement_count); 03624 03625 if_test = new_prio(); 03626 if_end = new_prio(); 03627 if_test->type = AEL_IF_CONTROL; 03628 if_end->type = AEL_APPCALL; 03629 if ( p->type == PV_RANDOM ) 03630 snprintf(buf1,sizeof(buf1),"$[${RAND(0,99)} < (%s)]",p->u1.str); 03631 else 03632 snprintf(buf1,sizeof(buf1),"$[%s]",p->u1.str); 03633 if_test->app = 0; 03634 if_test->appargs = strdup(buf1); 03635 snprintf(buf1,sizeof(buf1),"Finish if-%s-%d", label, control_statement_count); 03636 if_end->app = strdup("NoOp"); 03637 if_end->appargs = strdup(buf1); 03638 if_test->origin = p; 03639 03640 if (p->u3.else_statements) { 03641 if_skip = new_prio(); 03642 if_skip->type = AEL_CONTROL1; /* simple goto */ 03643 if_skip->goto_true = if_end; 03644 if_test->goto_false = if_skip;; 03645 } else { 03646 if_skip = 0; 03647 if_test->goto_false = if_end;; 03648 } 03649 03650 /* link & load! */ 03651 linkprio(exten, if_test, mother_exten); 03652 03653 /* now, put the body of the if here */ 03654 03655 gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the statements here */ 03656 03657 if (p->u3.else_statements) { 03658 linkprio(exten, if_skip, mother_exten); 03659 gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the statements here */ 03660 03661 } 03662 03663 linkprio(exten, if_end, mother_exten); 03664 03665 break; 03666 03667 case PV_STATEMENTBLOCK: 03668 gen_prios(exten, label, p->u1.list, mother_exten, this_context ); /* recurse into the block */ 03669 break; 03670 03671 case PV_CATCH: 03672 control_statement_count++; 03673 /* generate an extension with name of catch, put all catch stats 03674 into this exten! */ 03675 switch_case = new_exten(); 03676 switch_case->context = this_context; 03677 linkexten(exten,switch_case); 03678 switch_case->name = strdup(p->u1.str); 03679 snprintf(new_label,sizeof(new_label),"catch-%s-%d",p->u1.str, control_statement_count); 03680 03681 gen_prios(switch_case, new_label, p->u2.statements,mother_exten,this_context); /* this will link in all the catch body statements here */ 03682 if (switch_case->return_needed) { 03683 char buf[2000]; 03684 struct ael_priority *np2 = new_prio(); 03685 np2->type = AEL_APPCALL; 03686 np2->app = strdup("NoOp"); 03687 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); 03688 np2->appargs = strdup(buf); 03689 linkprio(switch_case, np2, mother_exten); 03690 switch_case-> return_target = np2; 03691 } 03692 03693 break; 03694 default: 03695 break; 03696 } 03697 } 03698 }
Definition at line 3859 of file pbx_ael.c.
References pval::dad, PV_CONTEXT, PV_MACRO, and pval::type.
Referenced by check_goto(), and get_goto_target().
03860 { 03861 while( p && p->type != PV_CONTEXT && p->type != PV_MACRO ) { 03862 03863 p = p->dad; 03864 } 03865 03866 return p; 03867 }
Definition at line 3849 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().
03850 { 03851 while( p && p->type != PV_EXTENSION && p->type != PV_CONTEXT && p->type != PV_MACRO ) { 03852 03853 p = p->dad; 03854 } 03855 03856 return p; 03857 }
Definition at line 1122 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().
01123 { 01124 /* just one item-- the label should be in the current extension */ 01125 pval *curr_ext = get_extension_or_contxt(item); /* containing exten, or macro */ 01126 pval *curr_cont; 01127 01128 if (item->u1.list && !item->u1.list->next && !strstr((item->u1.list)->u1.str,"${")) { 01129 struct pval *x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), curr_ext); 01130 return x; 01131 } 01132 01133 curr_cont = get_contxt(item); 01134 01135 /* TWO items */ 01136 if (item->u1.list->next && !item->u1.list->next->next) { 01137 if (!strstr((item->u1.list)->u1.str,"${") 01138 && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ { 01139 struct pval *x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, curr_cont); 01140 return x; 01141 } 01142 } 01143 01144 /* All 3 items! */ 01145 if (item->u1.list->next && item->u1.list->next->next) { 01146 /* all three */ 01147 pval *first = item->u1.list; 01148 pval *second = item->u1.list->next; 01149 pval *third = item->u1.list->next->next; 01150 01151 if (!strstr((item->u1.list)->u1.str,"${") 01152 && !strstr(item->u1.list->next->u1.str,"${") 01153 && !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ { 01154 struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); 01155 if (!x) { 01156 01157 struct pval *p3; 01158 struct pval *that_context = find_context(item->u1.list->u1.str); 01159 01160 /* the target of the goto could be in an included context!! Fancy that!! */ 01161 /* look for includes in the current context */ 01162 if (that_context) { 01163 for (p3=that_context->u2.statements; p3; p3=p3->next) { 01164 if (p3->type == PV_INCLUDES) { 01165 struct pval *p4; 01166 for (p4=p3->u1.list; p4; p4=p4->next) { 01167 /* for each context pointed to, find it, then find a context/label that matches the 01168 target here! */ 01169 char *incl_context = p4->u1.str; 01170 /* find a matching context name */ 01171 struct pval *that_other_context = find_context(incl_context); 01172 if (that_other_context) { 01173 struct pval *x3; 01174 x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context); 01175 if (x3) { 01176 return x3; 01177 } 01178 } 01179 } 01180 } 01181 } 01182 } 01183 } 01184 return x; 01185 } 01186 } 01187 return 0; 01188 }
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 2861 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().
02862 { 02863 pval *p = label; 02864 02865 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ { 02866 if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN ) { 02867 return 1; 02868 } 02869 02870 p = p->dad; 02871 } 02872 return 0; 02873 }
static void linkexten | ( | struct ael_extension * | exten, | |
struct ael_extension * | add | |||
) | [static] |
Definition at line 2875 of file pbx_ael.c.
References exten, and ael_extension::next_exten.
Referenced by gen_prios().
02876 { 02877 add->next_exten = exten->next_exten; /* this will reverse the order. Big deal. */ 02878 exten->next_exten = add; 02879 }
void linkprio | ( | struct ael_extension * | exten, | |
struct ael_priority * | prio, | |||
struct ael_extension * | mother_exten | |||
) |
Definition at line 2779 of file pbx_ael.c.
References ael_priority::appargs, ael_priority::exten, exten, free, ael_extension::has_switch, and malloc.
Referenced by gen_prios().
02780 { 02781 char *p1, *p2; 02782 02783 if (!exten->plist) { 02784 exten->plist = prio; 02785 exten->plist_last = prio; 02786 } else { 02787 exten->plist_last->next = prio; 02788 exten->plist_last = prio; 02789 } 02790 if( !prio->exten ) 02791 prio->exten = exten; /* don't override the switch value */ 02792 /* The following code will cause all priorities within an extension 02793 to have ${EXTEN} or ${EXTEN: replaced with ~~EXTEN~~, which is 02794 set just before the first switch in an exten. The switches 02795 will muck up the original ${EXTEN} value, so we save it away 02796 and the user accesses this copy instead. */ 02797 if (prio->appargs && ((mother_exten && mother_exten->has_switch) || exten->has_switch) ) { 02798 while ((p1 = strstr(prio->appargs, "${EXTEN}"))) { 02799 p2 = malloc(strlen(prio->appargs)+5); 02800 *p1 = 0; 02801 strcpy(p2, prio->appargs); 02802 strcat(p2, "${~~EXTEN~~}"); 02803 if (*(p1+8)) 02804 strcat(p2, p1+8); 02805 free(prio->appargs); 02806 prio->appargs = p2; 02807 } 02808 while ((p1 = strstr(prio->appargs, "${EXTEN:"))) { 02809 p2 = malloc(strlen(prio->appargs)+5); 02810 *p1 = 0; 02811 strcpy(p2, prio->appargs); 02812 strcat(p2, "${~~EXTEN~~:"); 02813 if (*(p1+8)) 02814 strcat(p2, p1+8); 02815 free(prio->appargs); 02816 prio->appargs = p2; 02817 } 02818 } 02819 }
static int load_module | ( | void | ) | [static] |
Definition at line 4243 of file pbx_ael.c.
References ast_cli_register_multiple(), cli_ael, and pbx_load_module().
04244 { 04245 ast_cli_register_multiple(cli_ael, sizeof(cli_ael) / sizeof(struct ast_cli_entry)); 04246 return (pbx_load_module()); 04247 }
Definition at line 1736 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().
01737 { 01738 pval *i; 01739 01740 for (i=item; i; i=i->next) { 01741 pval *x; 01742 /* printf(" -- match pval: item %d\n", i->type); */ 01743 01744 if ((x = match_pval_item(i))) { 01745 /* printf("match_pval: returning x=%x\n", (int)x); */ 01746 return x; /* cut the search short */ 01747 } 01748 } 01749 return 0; 01750 }
Definition at line 1469 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().
01470 { 01471 pval *x; 01472 01473 switch ( item->type ) { 01474 case PV_MACRO: 01475 /* fields: item->u1.str == name of macro 01476 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 01477 item->u2.arglist->u1.str == argument 01478 item->u2.arglist->next == next arg 01479 01480 item->u3.macro_statements == pval list of statements in macro body. 01481 */ 01482 /* printf(" matching in MACRO %s, match_context=%s; retoncontmtch=%d; \n", item->u1.str, match_context, return_on_context_match); */ 01483 if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) { 01484 01485 /* printf("MACRO: match context is: %s\n", match_context); */ 01486 01487 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 */ { 01488 /* printf("Returning on matching macro %s\n", match_context); */ 01489 return item; 01490 } 01491 01492 01493 if (!return_on_context_match) { 01494 /* printf("Descending into matching macro %s/%s\n", match_context, item->u1.str); */ 01495 if ((x=match_pval(item->u3.macro_statements))) { 01496 /* printf("Responded with pval match %x\n", x); */ 01497 return x; 01498 } 01499 } 01500 } else { 01501 /* printf("Skipping context/macro %s\n", item->u1.str); */ 01502 } 01503 01504 break; 01505 01506 case PV_CONTEXT: 01507 /* fields: item->u1.str == name of context 01508 item->u2.statements == pval list of statements in context body 01509 item->u3.abstract == int 1 if an abstract keyword were present 01510 */ 01511 /* printf(" matching in CONTEXT\n"); */ 01512 if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) { 01513 if (return_on_context_match && !strcmp(item->u1.str, match_context)) { 01514 /* printf("Returning on matching context %s\n", match_context); */ 01515 /* printf("non-CONTEXT: Responded with pval match %x\n", x); */ 01516 return item; 01517 } 01518 01519 if (!return_on_context_match ) { 01520 /* printf("Descending into matching context %s\n", match_context); */ 01521 if ((x=match_pval(item->u2.statements))) /* if we're just searching for a context, don't bother descending into them */ { 01522 /* printf("CONTEXT: Responded with pval match %x\n", x); */ 01523 return x; 01524 } 01525 } 01526 } else { 01527 /* printf("Skipping context/macro %s\n", item->u1.str); */ 01528 } 01529 break; 01530 01531 case PV_CASE: 01532 /* fields: item->u1.str == value of case 01533 item->u2.statements == pval list of statements under the case 01534 */ 01535 /* printf(" matching in CASE\n"); */ 01536 if ((x=match_pval(item->u2.statements))) { 01537 /* printf("CASE: Responded with pval match %x\n", x); */ 01538 return x; 01539 } 01540 break; 01541 01542 case PV_PATTERN: 01543 /* fields: item->u1.str == value of case 01544 item->u2.statements == pval list of statements under the case 01545 */ 01546 /* printf(" matching in PATTERN\n"); */ 01547 if ((x=match_pval(item->u2.statements))) { 01548 /* printf("PATTERN: Responded with pval match %x\n", x); */ 01549 return x; 01550 } 01551 break; 01552 01553 case PV_DEFAULT: 01554 /* fields: 01555 item->u2.statements == pval list of statements under the case 01556 */ 01557 /* printf(" matching in DEFAULT\n"); */ 01558 if ((x=match_pval(item->u2.statements))) { 01559 /* printf("DEFAULT: Responded with pval match %x\n", x); */ 01560 return x; 01561 } 01562 break; 01563 01564 case PV_CATCH: 01565 /* fields: item->u1.str == name of extension to catch 01566 item->u2.statements == pval list of statements in context body 01567 */ 01568 /* printf(" matching in CATCH\n"); */ 01569 if (!strcmp(match_exten,"*") || extension_matches(item, match_exten, item->u1.str) ) { 01570 /* printf("Descending into matching catch %s => %s\n", match_exten, item->u1.str); */ 01571 if (strcmp(match_label,"1") == 0) { 01572 if (item->u2.statements) { 01573 struct pval *p5 = item->u2.statements; 01574 while (p5 && p5->type == PV_LABEL) /* find the first non-label statement in this context. If it exists, there's a "1" */ 01575 p5 = p5->next; 01576 if (p5) 01577 return p5; 01578 else 01579 return 0; 01580 } 01581 else 01582 return 0; 01583 } 01584 01585 if ((x=match_pval(item->u2.statements))) { 01586 /* printf("CATCH: Responded with pval match %x\n", (unsigned int)x); */ 01587 return x; 01588 } 01589 } else { 01590 /* printf("Skipping catch %s\n", item->u1.str); */ 01591 } 01592 break; 01593 01594 case PV_STATEMENTBLOCK: 01595 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 01596 */ 01597 /* printf(" matching in STATEMENTBLOCK\n"); */ 01598 if ((x=match_pval(item->u1.list))) { 01599 /* printf("STATEMENTBLOCK: Responded with pval match %x\n", x); */ 01600 return x; 01601 } 01602 break; 01603 01604 case PV_LABEL: 01605 /* fields: item->u1.str == label name 01606 */ 01607 /* printf("PV_LABEL %s (cont=%s, exten=%s\n", 01608 item->u1.str, current_context->u1.str, (current_extension?current_extension->u1.str:"<macro>"));*/ 01609 01610 if (count_labels) { 01611 if (!strcmp(match_label, item->u1.str)) { 01612 label_count++; 01613 last_matched_label = item; 01614 } 01615 01616 } else { 01617 if (!strcmp(match_label, item->u1.str)) { 01618 /* printf("LABEL: Responded with pval match %x\n", x); */ 01619 return item; 01620 } 01621 } 01622 break; 01623 01624 case PV_FOR: 01625 /* fields: item->u1.for_init == a string containing the initalizer 01626 item->u2.for_test == a string containing the loop test 01627 item->u3.for_inc == a string containing the loop increment 01628 01629 item->u4.for_statements == a pval list of statements in the for () 01630 */ 01631 /* printf(" matching in FOR\n"); */ 01632 if ((x=match_pval(item->u4.for_statements))) { 01633 /* printf("FOR: Responded with pval match %x\n", x);*/ 01634 return x; 01635 } 01636 break; 01637 01638 case PV_WHILE: 01639 /* fields: item->u1.str == the while conditional, as supplied by user 01640 01641 item->u2.statements == a pval list of statements in the while () 01642 */ 01643 /* printf(" matching in WHILE\n"); */ 01644 if ((x=match_pval(item->u2.statements))) { 01645 /* printf("WHILE: Responded with pval match %x\n", x); */ 01646 return x; 01647 } 01648 break; 01649 01650 case PV_RANDOM: 01651 /* fields: item->u1.str == the random number expression, as supplied by user 01652 01653 item->u2.statements == a pval list of statements in the if () 01654 item->u3.else_statements == a pval list of statements in the else 01655 (could be zero) 01656 fall thru to PV_IF */ 01657 01658 case PV_IFTIME: 01659 /* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list 01660 01661 item->u2.statements == a pval list of statements in the if () 01662 item->u3.else_statements == a pval list of statements in the else 01663 (could be zero) 01664 fall thru to PV_IF*/ 01665 case PV_IF: 01666 /* fields: item->u1.str == the if conditional, as supplied by user 01667 01668 item->u2.statements == a pval list of statements in the if () 01669 item->u3.else_statements == a pval list of statements in the else 01670 (could be zero) 01671 */ 01672 /* printf(" matching in IF/IFTIME/RANDOM\n"); */ 01673 if ((x=match_pval(item->u2.statements))) { 01674 return x; 01675 } 01676 if (item->u3.else_statements) { 01677 if ((x=match_pval(item->u3.else_statements))) { 01678 /* printf("IF/IFTIME/RANDOM: Responded with pval match %x\n", x); */ 01679 return x; 01680 } 01681 } 01682 break; 01683 01684 case PV_SWITCH: 01685 /* fields: item->u1.str == the switch expression 01686 01687 item->u2.statements == a pval list of statements in the switch, 01688 (will be case statements, most likely!) 01689 */ 01690 /* printf(" matching in SWITCH\n"); */ 01691 if ((x=match_pval(item->u2.statements))) { 01692 /* printf("SWITCH: Responded with pval match %x\n", x); */ 01693 return x; 01694 } 01695 break; 01696 01697 case PV_EXTENSION: 01698 /* fields: item->u1.str == the extension name, label, whatever it's called 01699 01700 item->u2.statements == a pval list of statements in the extension 01701 item->u3.hints == a char * hint argument 01702 item->u4.regexten == an int boolean. non-zero says that regexten was specified 01703 */ 01704 /* printf(" matching in EXTENSION\n"); */ 01705 if (!strcmp(match_exten,"*") || extension_matches(item, match_exten, item->u1.str) ) { 01706 /* printf("Descending into matching exten %s => %s\n", match_exten, item->u1.str); */ 01707 if (strcmp(match_label,"1") == 0) { 01708 if (item->u2.statements) { 01709 struct pval *p5 = item->u2.statements; 01710 while (p5 && p5->type == PV_LABEL) /* find the first non-label statement in this context. If it exists, there's a "1" */ 01711 p5 = p5->next; 01712 if (p5) 01713 return p5; 01714 else 01715 return 0; 01716 } 01717 else 01718 return 0; 01719 } 01720 01721 if ((x=match_pval(item->u2.statements))) { 01722 /* printf("EXTENSION: Responded with pval match %x\n", x); */ 01723 return x; 01724 } 01725 } else { 01726 /* printf("Skipping exten %s\n", item->u1.str); */ 01727 } 01728 break; 01729 default: 01730 /* printf(" matching in default = %d\n", item->type); */ 01731 break; 01732 } 01733 return 0; 01734 }
struct ael_extension * new_exten | ( | void | ) |
Definition at line 2773 of file pbx_ael.c.
References calloc.
Referenced by gen_prios().
02774 { 02775 struct ael_extension *x = (struct ael_extension *)calloc(sizeof(struct ael_extension),1); 02776 return x; 02777 }
struct ael_priority * new_prio | ( | void | ) |
Definition at line 2767 of file pbx_ael.c.
References calloc.
Referenced by gen_prios().
02768 { 02769 struct ael_priority *x = (struct ael_priority *)calloc(sizeof(struct ael_priority),1); 02770 return x; 02771 }
static int pbx_load_module | ( | void | ) | [static] |
Definition at line 4130 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().
04131 { 04132 int errs=0, sem_err=0, sem_warn=0, sem_note=0; 04133 char *rfilename; 04134 struct ast_context *local_contexts=NULL, *con; 04135 struct pval *parse_tree; 04136 04137 ast_log(LOG_NOTICE, "Starting AEL load process.\n"); 04138 if (config[0] == '/') 04139 rfilename = (char *)config; 04140 else { 04141 rfilename = alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2); 04142 sprintf(rfilename, "%s/%s", ast_config_AST_CONFIG_DIR, config); 04143 } 04144 ast_log(LOG_NOTICE, "AEL load process: calculated config file name '%s'.\n", rfilename); 04145 04146 if (access(rfilename,R_OK) != 0) { 04147 ast_log(LOG_NOTICE, "File %s not found; AEL declining load\n", rfilename); 04148 return AST_MODULE_LOAD_DECLINE; 04149 } 04150 04151 parse_tree = ael2_parse(rfilename, &errs); 04152 ast_log(LOG_NOTICE, "AEL load process: parsed config file name '%s'.\n", rfilename); 04153 ael2_semantic_check(parse_tree, &sem_err, &sem_warn, &sem_note); 04154 if (errs == 0 && sem_err == 0) { 04155 ast_log(LOG_NOTICE, "AEL load process: checked config file name '%s'.\n", rfilename); 04156 ast_compile_ael2(&local_contexts, parse_tree); 04157 ast_log(LOG_NOTICE, "AEL load process: compiled config file name '%s'.\n", rfilename); 04158 04159 ast_merge_contexts_and_delete(&local_contexts, registrar); 04160 ast_log(LOG_NOTICE, "AEL load process: merged config file name '%s'.\n", rfilename); 04161 for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con)) 04162 ast_context_verify_includes(con); 04163 ast_log(LOG_NOTICE, "AEL load process: verified config file name '%s'.\n", rfilename); 04164 } else { 04165 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); 04166 destroy_pval(parse_tree); /* free up the memory */ 04167 return AST_MODULE_LOAD_DECLINE; 04168 } 04169 destroy_pval(parse_tree); /* free up the memory */ 04170 04171 return AST_MODULE_LOAD_SUCCESS; 04172 }
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 4249 of file pbx_ael.c.
References pbx_load_module().
04250 { 04251 return pbx_load_module(); 04252 }
static void remove_spaces_before_equals | ( | char * | str | ) | [static] |
Definition at line 2881 of file pbx_ael.c.
Referenced by gen_prios().
02882 { 02883 char *p; 02884 while( str && *str && *str != '=' ) 02885 { 02886 if( *str == ' ' || *str == '\n' || *str == '\r' || *str == '\t' ) 02887 { 02888 p = str; 02889 while( *p ) 02890 { 02891 *p = *(p+1); 02892 p++; 02893 } 02894 } 02895 else 02896 str++; 02897 } 02898 }
void set_priorities | ( | struct ael_extension * | exten | ) |
Definition at line 3700 of file pbx_ael.c.
References exten, ael_priority::next, ael_priority::origin, ael_priority::priority_num, PV_LABEL, and pval::type.
03701 { 03702 int i; 03703 struct ael_priority *pr; 03704 do { 03705 if (exten->is_switch) 03706 i = 10; 03707 else if (exten->regexten) 03708 i=2; 03709 else 03710 i=1; 03711 03712 for (pr=exten->plist; pr; pr=pr->next) { 03713 pr->priority_num = i; 03714 03715 if (!pr->origin || (pr->origin && pr->origin->type != PV_LABEL) ) /* Labels don't show up in the dialplan, 03716 but we want them to point to the right 03717 priority, which would be the next line 03718 after the label; */ 03719 i++; 03720 } 03721 03722 exten = exten->next_exten; 03723 } while ( exten ); 03724 }
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 4236 of file pbx_ael.c.
References ast_cli_unregister_multiple(), ast_context_destroy(), and cli_ael.
04237 { 04238 ast_context_destroy(NULL, registrar); 04239 ast_cli_unregister_multiple(cli_ael, sizeof(cli_ael) / sizeof(struct ast_cli_entry)); 04240 return 0; 04241 }
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 = 0 [static] |
pval* current_db = 0 [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 = 0 [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] |