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