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