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