Compile symbolic Asterisk Extension Logic into Asterisk extensions, version 2. More...
#include "asterisk.h"
#include <ctype.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/hashtab.h"
#include "asterisk/ael_structs.h"
#include "asterisk/pval.h"
Go to the source code of this file.
Defines | |
#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 | aelsub_exec (struct ast_channel *chan, const char *vdata) |
int | ast_compile_ael2 (struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root) |
void | ast_expr_clear_extra_error_info (void) |
void | ast_expr_register_extra_error_info (char *errmsg) |
int | check_app_args (pval *appcall, pval *arglist, struct argapp *app) |
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) |
void | destroy_extensions (struct ael_extension *exten) |
void | destroy_pval (pval *item) |
void | destroy_pval_item (pval *item) |
struct pval * | find_context (char *name) |
struct pval * | find_macro (char *name) |
static char * | handle_cli_ael_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_ael_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
int | is_empty (char *arg) |
int | is_float (char *arg) |
int | is_int (char *arg) |
static int | load_module (void) |
struct ael_extension * | new_exten (void) |
struct ael_priority * | new_prio (void) |
static int | pbx_load_module (void) |
static int | reload (void) |
void | set_priorities (struct ael_extension *exten) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, } |
static int | aeldebug = 0 |
static char * | aelsub = "AELSub" |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_cli_entry | cli_ael [] |
static char * | config = "extensions.ael" |
static char * | registrar = "pbx_ael" |
Compile symbolic Asterisk Extension Logic into Asterisk extensions, version 2.
Definition in file pbx_ael.c.
#define DEBUG_CONTEXTS (1 << 3) |
Definition at line 84 of file pbx_ael.c.
Referenced by handle_cli_ael_set_debug().
#define DEBUG_MACROS (1 << 2) |
Definition at line 83 of file pbx_ael.c.
Referenced by handle_cli_ael_set_debug().
#define DEBUG_READ (1 << 0) |
Definition at line 81 of file pbx_ael.c.
Referenced by handle_cli_ael_set_debug().
#define DEBUG_TOKENS (1 << 1) |
Definition at line 82 of file pbx_ael.c.
Referenced by handle_cli_ael_set_debug().
void add_extensions | ( | struct ael_extension * | exten | ) |
Definition at line 4251 of file pval.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, ast_add_extension2(), ast_free_ptr(), ast_log(), AST_MAX_EXTENSION, ael_extension::cidmatch, ael_extension::context, pval::else_statements, ael_priority::exten, ael_priority::goto_false, ael_priority::goto_true, ael_extension::hints, last, LOG_WARNING, ael_extension::name, ael_priority::next, ael_extension::next_exten, ael_priority::origin, pbx_substitute_variables_helper(), ael_extension::plist, PRIORITY_HINT, ael_priority::priority_num, PV_IFTIME, PV_SWITCH, pval::str, strdup, pval::type, ael_priority::type, pval::u1, and pval::u3.
04252 { 04253 struct ael_priority *pr; 04254 char *label=0; 04255 char realext[AST_MAX_EXTENSION]; 04256 if (!exten) { 04257 ast_log(LOG_WARNING, "This file is Empty!\n" ); 04258 return; 04259 } 04260 do { 04261 struct ael_priority *last = 0; 04262 04263 pbx_substitute_variables_helper(NULL, exten->name, realext, sizeof(realext) - 1); 04264 if (exten->hints) { 04265 if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, PRIORITY_HINT, NULL, exten->cidmatch, 04266 exten->hints, NULL, ast_free_ptr, registrar)) { 04267 ast_log(LOG_WARNING, "Unable to add step at priority 'hint' of extension '%s'\n", 04268 exten->name); 04269 } 04270 } 04271 04272 for (pr=exten->plist; pr; pr=pr->next) { 04273 char app[2000]; 04274 char appargs[2000]; 04275 04276 /* before we can add the extension, we need to prep the app/appargs; 04277 the CONTROL types need to be done after the priority numbers are calculated. 04278 */ 04279 if (pr->type == AEL_LABEL) /* don't try to put labels in the dialplan! */ { 04280 last = pr; 04281 continue; 04282 } 04283 04284 if (pr->app) 04285 strcpy(app, pr->app); 04286 else 04287 app[0] = 0; 04288 if (pr->appargs ) 04289 strcpy(appargs, pr->appargs); 04290 else 04291 appargs[0] = 0; 04292 switch( pr->type ) { 04293 case AEL_APPCALL: 04294 /* easy case. Everything is all set up */ 04295 break; 04296 04297 case AEL_CONTROL1: /* FOR loop, WHILE loop, BREAK, CONTINUE, IF, IFTIME */ 04298 /* simple, unconditional goto. */ 04299 strcpy(app,"Goto"); 04300 if (pr->goto_true->origin && pr->goto_true->origin->type == PV_SWITCH ) { 04301 snprintf(appargs,sizeof(appargs),"%s,%d", pr->goto_true->exten->name, pr->goto_true->priority_num); 04302 } else if (pr->goto_true->origin && pr->goto_true->origin->type == PV_IFTIME && pr->goto_true->origin->u3.else_statements ) { 04303 snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num+1); 04304 } else 04305 snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num); 04306 break; 04307 04308 case AEL_FOR_CONTROL: /* WHILE loop test, FOR loop test */ 04309 strcpy(app,"GotoIf"); 04310 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); 04311 break; 04312 04313 case AEL_IF_CONTROL: 04314 strcpy(app,"GotoIf"); 04315 if (pr->origin->u3.else_statements ) 04316 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num+1); 04317 else 04318 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); 04319 break; 04320 04321 case AEL_RAND_CONTROL: 04322 strcpy(app,"Random"); 04323 snprintf(appargs,sizeof(appargs),"%s:%d", pr->appargs, pr->goto_true->priority_num+1); 04324 break; 04325 04326 case AEL_IFTIME_CONTROL: 04327 strcpy(app,"GotoIfTime"); 04328 snprintf(appargs,sizeof(appargs),"%s?%d", pr->appargs, pr->priority_num+2); 04329 break; 04330 04331 case AEL_RETURN: 04332 strcpy(app,"Return"); 04333 appargs[0] = 0; 04334 break; 04335 04336 default: 04337 break; 04338 } 04339 if (last && last->type == AEL_LABEL ) { 04340 label = last->origin->u1.str; 04341 } 04342 else 04343 label = 0; 04344 04345 if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, pr->priority_num, (label?label:NULL), exten->cidmatch, 04346 app, strdup(appargs), ast_free_ptr, registrar)) { 04347 ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num, 04348 exten->name); 04349 } 04350 last = pr; 04351 } 04352 exten = exten->next_exten; 04353 } while ( exten ); 04354 }
static int aelsub_exec | ( | struct ast_channel * | chan, | |
const char * | vdata | |||
) | [static] |
Definition at line 135 of file pbx_ael.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_STANDARD_RAW_ARGS, ast_strdupa, name, pbx_exec(), and pbx_findapp().
Referenced by load_module().
00136 { 00137 char buf[256], *data = ast_strdupa(vdata); 00138 struct ast_app *gosub = pbx_findapp("Gosub"); 00139 AST_DECLARE_APP_ARGS(args, 00140 AST_APP_ARG(name); 00141 AST_APP_ARG(args); 00142 ); 00143 00144 if (gosub) { 00145 AST_STANDARD_RAW_ARGS(args, data); 00146 snprintf(buf, sizeof(buf), "%s,~~s~~,1(%s)", args.name, args.args); 00147 return pbx_exec(chan, gosub, buf); 00148 } 00149 return -1; 00150 }
int ast_compile_ael2 | ( | struct ast_context ** | local_contexts, | |
struct ast_hashtab * | local_table, | |||
struct pval * | root | |||
) |
Definition at line 4451 of file pval.c.
References add_extensions(), AEL_APPCALL, AEL_LABEL, ael_priority::app, ael_priority::appargs, pval::arglist, ARRAY_LEN, ast_compat_app_set, ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_find_or_create(), ast_custom_function_find(), ast_get_context_name(), attach_exten(), ael_extension::cidmatch, ael_extension::context, context, context_used(), destroy_extensions(), exten, fix_gotos_in_extensions(), gen_prios(), ael_extension::hints, pval::hints, linkprio(), pval::list, pval::macro_statements, ael_extension::name, new_exten(), new_prio(), pval::next, ael_extension::next_exten, ael_priority::origin, pbx_builtin_setvar(), ael_extension::plist_last, ael_priority::priority_num, PV_CONTEXT, PV_ESWITCHES, PV_EXTENSION, PV_GLOBALS, PV_IGNOREPAT, PV_INCLUDES, PV_MACRO, PV_SWITCHES, pval::regexten, ael_extension::regexten, remove_spaces_before_equals(), ael_extension::return_needed, set_priorities(), pval::statements, pval::str, strdup, ael_priority::type, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.
04452 { 04453 pval *p,*p2; 04454 struct ast_context *context; 04455 char buf[2000]; 04456 struct ael_extension *exten; 04457 struct ael_extension *exten_list = 0; 04458 04459 for (p=root; p; p=p->next ) { /* do the globals first, so they'll be there 04460 when we try to eval them */ 04461 switch (p->type) { 04462 case PV_GLOBALS: 04463 /* just VARDEC elements */ 04464 for (p2=p->u1.list; p2; p2=p2->next) { 04465 char buf2[2000]; 04466 snprintf(buf2,sizeof(buf2),"%s=%s", p2->u1.str, p2->u2.val); 04467 pbx_builtin_setvar(NULL, buf2); 04468 } 04469 break; 04470 default: 04471 break; 04472 } 04473 } 04474 04475 for (p=root; p; p=p->next ) { 04476 pval *lp; 04477 int argc; 04478 04479 switch (p->type) { 04480 case PV_MACRO: 04481 04482 context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar); 04483 04484 exten = new_exten(); 04485 exten->context = context; 04486 exten->name = strdup("~~s~~"); 04487 argc = 1; 04488 for (lp=p->u2.arglist; lp; lp=lp->next) { 04489 /* for each arg, set up a "Set" command */ 04490 struct ael_priority *np2 = new_prio(); 04491 np2->type = AEL_APPCALL; 04492 if (!ast_compat_app_set) { 04493 np2->app = strdup("MSet"); 04494 } else { 04495 np2->app = strdup("Set"); 04496 } 04497 snprintf(buf,sizeof(buf),"LOCAL(%s)=${ARG%d}", lp->u1.str, argc++); 04498 remove_spaces_before_equals(buf); 04499 np2->appargs = strdup(buf); 04500 linkprio(exten, np2, NULL); 04501 } 04502 04503 /* CONTAINS APPCALLS, CATCH, just like extensions... */ 04504 if (gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context)) { 04505 return -1; 04506 } 04507 if (exten->return_needed) { /* most likely, this will go away */ 04508 struct ael_priority *np2 = new_prio(); 04509 np2->type = AEL_APPCALL; 04510 np2->app = strdup("NoOp"); 04511 snprintf(buf,sizeof(buf),"End of Macro %s-%s",p->u1.str, exten->name); 04512 np2->appargs = strdup(buf); 04513 linkprio(exten, np2, NULL); 04514 exten-> return_target = np2; 04515 } 04516 04517 set_priorities(exten); 04518 attach_exten(&exten_list, exten); 04519 break; 04520 04521 case PV_GLOBALS: 04522 /* already done */ 04523 break; 04524 04525 case PV_CONTEXT: 04526 context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar); 04527 04528 /* contexts contain: ignorepat, includes, switches, eswitches, extensions, */ 04529 for (p2=p->u2.statements; p2; p2=p2->next) { 04530 pval *p3; 04531 char *s3; 04532 04533 switch (p2->type) { 04534 case PV_EXTENSION: 04535 exten = new_exten(); 04536 exten->name = strdup(p2->u1.str); 04537 exten->context = context; 04538 04539 if( (s3=strchr(exten->name, '/') ) != 0 ) 04540 { 04541 *s3 = 0; 04542 exten->cidmatch = s3+1; 04543 } 04544 04545 if ( p2->u3.hints ) 04546 exten->hints = strdup(p2->u3.hints); 04547 exten->regexten = p2->u4.regexten; 04548 if (gen_prios(exten, p->u1.str, p2->u2.statements, 0, context)) { 04549 return -1; 04550 } 04551 if (exten->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */ 04552 struct ael_priority *np2 = new_prio(); 04553 np2->type = AEL_APPCALL; 04554 np2->app = strdup("NoOp"); 04555 snprintf(buf,sizeof(buf),"End of Extension %s", exten->name); 04556 np2->appargs = strdup(buf); 04557 linkprio(exten, np2, NULL); 04558 exten-> return_target = np2; 04559 } 04560 /* is the last priority in the extension a label? Then add a trailing no-op */ 04561 if ( exten->plist_last && exten->plist_last->type == AEL_LABEL ) { 04562 struct ael_priority *np2 = new_prio(); 04563 np2->type = AEL_APPCALL; 04564 np2->app = strdup("NoOp"); 04565 snprintf(buf,sizeof(buf),"A NoOp to follow a trailing label %s", exten->plist_last->origin->u1.str); 04566 np2->appargs = strdup(buf); 04567 linkprio(exten, np2, NULL); 04568 } 04569 04570 set_priorities(exten); 04571 attach_exten(&exten_list, exten); 04572 break; 04573 04574 case PV_IGNOREPAT: 04575 ast_context_add_ignorepat2(context, p2->u1.str, registrar); 04576 break; 04577 04578 case PV_INCLUDES: 04579 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 04580 if ( p3->u2.arglist ) { 04581 snprintf(buf,sizeof(buf), "%s,%s,%s,%s,%s", 04582 p3->u1.str, 04583 p3->u2.arglist->u1.str, 04584 p3->u2.arglist->next->u1.str, 04585 p3->u2.arglist->next->next->u1.str, 04586 p3->u2.arglist->next->next->next->u1.str); 04587 ast_context_add_include2(context, buf, registrar); 04588 } else 04589 ast_context_add_include2(context, p3->u1.str, registrar); 04590 } 04591 break; 04592 04593 case PV_SWITCHES: 04594 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 04595 char *c = strchr(p3->u1.str, '/'); 04596 if (c) { 04597 *c = '\0'; 04598 c++; 04599 } else 04600 c = ""; 04601 04602 ast_context_add_switch2(context, p3->u1.str, c, 0, registrar); 04603 } 04604 break; 04605 04606 case PV_ESWITCHES: 04607 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 04608 char *c = strchr(p3->u1.str, '/'); 04609 if (c) { 04610 *c = '\0'; 04611 c++; 04612 } else 04613 c = ""; 04614 04615 ast_context_add_switch2(context, p3->u1.str, c, 1, registrar); 04616 } 04617 break; 04618 default: 04619 break; 04620 } 04621 } 04622 04623 break; 04624 04625 default: 04626 /* huh? what? */ 04627 break; 04628 04629 } 04630 } 04631 04632 /* Create default "h" bubble context */ 04633 if (ast_custom_function_find("DIALPLAN_EXISTS") && ast_custom_function_find("STACK_PEEK")) { 04634 int i; 04635 const char *h_context = "ael-builtin-h-bubble"; 04636 struct ael_priority *np; 04637 struct { 04638 int priority; 04639 const char *app; 04640 const char *arg; 04641 } steps[] = { 04642 /* Start high, to avoid conflict with existing h extensions */ 04643 { 1, "Goto", "9991" }, 04644 /* Save the context, because after the StackPop, it disappears */ 04645 { 9991, "Set", "~~parentcxt~~=${STACK_PEEK(1,c,1)}" }, 04646 /* If we're not in a Gosub frame, exit */ 04647 { 9992, "GotoIf", "$[\"${~~parentcxt~~}\"=\"\"]?9996" }, 04648 /* Check for an "h" extension in that context */ 04649 { 9993, "GotoIf", "${DIALPLAN_EXISTS(${~~parentcxt~~},h,1)}?9994:9996" }, 04650 /* Pop off the stack frame to prevent an infinite loop */ 04651 { 9994, "StackPop", "" }, 04652 /* Finally, go there. */ 04653 { 9995, "Goto", "${~~parentcxt~~},h,1" }, 04654 /* Just an empty priority for jumping out early */ 04655 { 9996, "NoOp", "" } 04656 }; 04657 context = ast_context_find_or_create(local_contexts, local_table, h_context, registrar); 04658 if (context_used(exten_list, context)) { 04659 int found = 0; 04660 while (!found) { 04661 /* Pick a new context name that is not used. */ 04662 char h_context_template[] = "/tmp/ael-builtin-h-bubble-XXXXXX"; 04663 int fd = mkstemp(h_context_template); 04664 unlink(h_context_template); 04665 close(fd); 04666 context = ast_context_find_or_create(local_contexts, local_table, h_context_template + 5, registrar); 04667 found = !context_used(exten_list, context); 04668 } 04669 h_context = ast_get_context_name(context); 04670 } 04671 exten = new_exten(); 04672 exten->context = context; 04673 exten->name = strdup("h"); 04674 04675 for (i = 0; i < ARRAY_LEN(steps); i++) { 04676 np = new_prio(); 04677 np->type = AEL_APPCALL; 04678 np->priority_num = steps[i].priority; 04679 np->app = strdup(steps[i].app); 04680 np->appargs = strdup(steps[i].arg); 04681 linkprio(exten, np, NULL); 04682 } 04683 attach_exten(&exten_list, exten); 04684 04685 /* Include the default "h" bubble context in each macro context */ 04686 for (exten = exten_list; exten; exten = exten->next_exten) { 04687 /* All macros contain a "~~s~~" extension, and it's the first created. If 04688 * we perchance get a non-macro context, it's no big deal; the logic is 04689 * designed to exit out smoothly if not called from within a Gosub. */ 04690 if (!strcmp(exten->name, "~~s~~")) { 04691 ast_context_add_include2(exten->context, h_context, registrar); 04692 } 04693 } 04694 } 04695 04696 /* moved these from being done after a macro or extension were processed, 04697 to after all processing is done, for the sake of fixing gotos to labels inside cases... */ 04698 /* I guess this would be considered 2nd pass of compiler now... */ 04699 fix_gotos_in_extensions(exten_list); /* find and fix extension ref in gotos to labels that are in case statements */ 04700 add_extensions(exten_list); /* actually makes calls to create priorities in ast_contexts -- feeds dialplan to asterisk */ 04701 destroy_extensions(exten_list); /* all that remains is an empty husk, discard of it as is proper */ 04702 04703 return 0; 04704 }
void ast_expr_clear_extra_error_info | ( | void | ) |
Definition at line 2475 of file ast_expr2f.c.
02476 { 02477 extra_error_message_supplied=0; 02478 extra_error_message[0] = 0; 02479 }
void ast_expr_register_extra_error_info | ( | char * | errmsg | ) |
Definition at line 2469 of file ast_expr2f.c.
02470 { 02471 extra_error_message_supplied=1; 02472 strcpy(extra_error_message, message); 02473 }
Definition at line 2137 of file pval.c.
References ast_log(), pval::endline, pval::filename, LOG_WARNING, pval::next, pval::startline, pval::str, and pval::u1.
02138 { 02139 #ifdef AAL_ARGCHECK 02140 struct argdesc *ad = app->args; 02141 pval *pa; 02142 int z; 02143 02144 for (pa = arglist; pa; pa=pa->next) { 02145 if (!ad) { 02146 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Extra argument %s not in application call to %s !\n", 02147 arglist->filename, arglist->startline, arglist->endline, pa->u1.str, app->name); 02148 warns++; 02149 return 1; 02150 } else { 02151 /* find the first entry in the ad list that will match */ 02152 do { 02153 if ( ad->dtype == ARGD_VARARG ) /* once we hit the VARARG, all bets are off. Discontinue the comparisons */ 02154 break; 02155 02156 z= option_matches( ad, pa, app); 02157 if (!z) { 02158 if ( !arglist ) 02159 arglist=appcall; 02160 02161 if (ad->type == ARGD_REQUIRED) { 02162 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", 02163 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); 02164 warns++; 02165 return 1; 02166 } 02167 } else if (z && ad->dtype == ARGD_OPTIONSET) { 02168 option_matches_j( ad, pa, app); 02169 } 02170 ad = ad->next; 02171 } while (ad && !z); 02172 } 02173 } 02174 /* any app nodes left, that are not optional? */ 02175 for ( ; ad; ad=ad->next) { 02176 if (ad->type == ARGD_REQUIRED && ad->dtype != ARGD_VARARG) { 02177 if ( !arglist ) 02178 arglist=appcall; 02179 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", 02180 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); 02181 warns++; 02182 return 1; 02183 } 02184 } 02185 return 0; 02186 #else 02187 return 0; 02188 #endif 02189 }
Definition at line 2872 of file pval.c.
References check_pval_item(), and pval::next.
02873 { 02874 pval *i; 02875 02876 /* checks to do: 02877 1. Do goto's point to actual labels? 02878 2. Do macro calls reference a macro? 02879 3. Does the number of macro args match the definition? 02880 4. Is a macro call missing its & at the front? 02881 5. Application calls-- we could check syntax for existing applications, 02882 but I need some some sort of universal description bnf for a general 02883 sort of method for checking arguments, in number, maybe even type, at least. 02884 Don't want to hand code checks for hundreds of applications. 02885 */ 02886 02887 for (i=item; i; i=i->next) { 02888 check_pval_item(i,apps,in_globals); 02889 } 02890 }
Definition at line 2364 of file pval.c.
References pval::abstract, 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_macro_returns(), check_month(), check_pval(), check_switch_expr(), check_timerange(), E_MATCH, 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, free, pval::list, localized_pbx_load_module(), LOG_ERROR, LOG_WARNING, pval::macro_statements, argapp::next, pval::next, pbx_find_extension(), 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_LOCALVARDEC, PV_MACRO, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_SWITCHES, PV_VARDEC, PV_WHILE, PV_WORD, pbx_find_info::stacklen, pval::startcol, pval::startline, pval::statements, pbx_find_info::status, STATUS_SUCCESS, pval::str, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.
02365 { 02366 pval *lp; 02367 #ifdef AAL_ARGCHECK 02368 struct argapp *app, *found; 02369 #endif 02370 struct pval *macro_def; 02371 struct pval *app_def; 02372 02373 char errmsg[4096]; 02374 char *strp; 02375 02376 switch (item->type) { 02377 case PV_WORD: 02378 /* fields: item->u1.str == string associated with this (word). 02379 item->u2.arglist == pval list of 4 PV_WORD elements for time values (only in PV_INCLUDES) */ 02380 break; 02381 02382 case PV_MACRO: 02383 /* fields: item->u1.str == name of macro 02384 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 02385 item->u2.arglist->u1.str == argument 02386 item->u2.arglist->next == next arg 02387 02388 item->u3.macro_statements == pval list of statements in macro body. 02389 */ 02390 in_abstract_context = 0; 02391 current_context = item; 02392 current_extension = 0; 02393 02394 check_macro_returns(item); 02395 02396 for (lp=item->u2.arglist; lp; lp=lp->next) { 02397 02398 } 02399 check_pval(item->u3.macro_statements, apps,in_globals); 02400 break; 02401 02402 case PV_CONTEXT: 02403 /* fields: item->u1.str == name of context 02404 item->u2.statements == pval list of statements in context body 02405 item->u3.abstract == int 1 if an abstract keyword were present 02406 */ 02407 current_context = item; 02408 current_extension = 0; 02409 if ( item->u3.abstract ) { 02410 in_abstract_context = 1; 02411 check_abstract_reference(item); 02412 } else 02413 in_abstract_context = 0; 02414 check_pval(item->u2.statements, apps,in_globals); 02415 break; 02416 02417 case PV_MACRO_CALL: 02418 /* fields: item->u1.str == name of macro to call 02419 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 02420 item->u2.arglist->u1.str == argument 02421 item->u2.arglist->next == next arg 02422 */ 02423 #ifdef STANDALONE 02424 /* if this is a standalone, we will need to make sure the 02425 localized load of extensions.conf is done */ 02426 if (!extensions_dot_conf_loaded) { 02427 localized_pbx_load_module(); 02428 extensions_dot_conf_loaded++; 02429 } 02430 #endif 02431 macro_def = find_macro(item->u1.str); 02432 if (!macro_def) { 02433 #ifdef STANDALONE 02434 struct pbx_find_info pfiq = {.stacklen = 0 }; 02435 struct pbx_find_info pfiq2 = {.stacklen = 0 }; 02436 02437 /* look for the macro in the extensions.conf world */ 02438 pbx_find_extension(NULL, NULL, &pfiq, item->u1.str, "s", 1, NULL, NULL, E_MATCH); 02439 02440 if (pfiq.status != STATUS_SUCCESS) { 02441 char namebuf2[256]; 02442 snprintf(namebuf2, 256, "macro-%s", item->u1.str); 02443 02444 /* look for the macro in the extensions.conf world */ 02445 pbx_find_extension(NULL, NULL, &pfiq2, namebuf2, "s", 1, NULL, NULL, E_MATCH); 02446 02447 if (pfiq2.status == STATUS_SUCCESS) { 02448 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to non-existent %s! (macro-%s was found in the extensions.conf stuff, but we are using gosubs!)\n", 02449 item->filename, item->startline, item->endline, item->u1.str, item->u1.str); 02450 warns++; 02451 } else { 02452 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to non-existent %s! (Not even in the extensions.conf stuff!)\n", 02453 item->filename, item->startline, item->endline, item->u1.str); 02454 warns++; 02455 } 02456 } 02457 #else 02458 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to %s cannot be found in the AEL code!\n", 02459 item->filename, item->startline, item->endline, item->u1.str); 02460 warns++; 02461 02462 #endif 02463 #ifdef THIS_IS_1DOT4 02464 char namebuf2[256]; 02465 snprintf(namebuf2, 256, "macro-%s", item->u1.str); 02466 02467 /* look for the macro in the extensions.conf world */ 02468 pbx_find_extension(NULL, NULL, &pfiq, namebuf2, "s", 1, NULL, NULL, E_MATCH); 02469 02470 if (pfiq.status != STATUS_SUCCESS) { 02471 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to %s was not found in the AEL, nor the extensions.conf !\n", 02472 item->filename, item->startline, item->endline, item->u1.str); 02473 warns++; 02474 } 02475 02476 #endif 02477 02478 } else if (macro_def->type != PV_MACRO) { 02479 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: macro call to %s references a context, not a macro!\n", 02480 item->filename, item->startline, item->endline, item->u1.str); 02481 errs++; 02482 } else { 02483 /* macro_def is a MACRO, so do the args match in number? */ 02484 int hereargs = 0; 02485 int thereargs = 0; 02486 02487 for (lp=item->u2.arglist; lp; lp=lp->next) { 02488 hereargs++; 02489 } 02490 for (lp=macro_def->u2.arglist; lp; lp=lp->next) { 02491 thereargs++; 02492 } 02493 if (hereargs != thereargs ) { 02494 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", 02495 item->filename, item->startline, item->endline, item->u1.str, hereargs, thereargs); 02496 errs++; 02497 } 02498 } 02499 break; 02500 02501 case PV_APPLICATION_CALL: 02502 /* fields: item->u1.str == name of application to call 02503 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 02504 item->u2.arglist->u1.str == argument 02505 item->u2.arglist->next == next arg 02506 */ 02507 /* Need to check to see if the application is available! */ 02508 app_def = find_context(item->u1.str); 02509 if (app_def && app_def->type == PV_MACRO) { 02510 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: application call to %s references an existing macro, but had no & preceding it!\n", 02511 item->filename, item->startline, item->endline, item->u1.str); 02512 errs++; 02513 } 02514 if (strcasecmp(item->u1.str,"GotoIf") == 0 02515 || strcasecmp(item->u1.str,"GotoIfTime") == 0 02516 || strcasecmp(item->u1.str,"while") == 0 02517 || strcasecmp(item->u1.str,"endwhile") == 0 02518 || strcasecmp(item->u1.str,"random") == 0 02519 || strcasecmp(item->u1.str,"gosub") == 0 02520 || strcasecmp(item->u1.str,"gosubif") == 0 02521 || strcasecmp(item->u1.str,"continuewhile") == 0 02522 || strcasecmp(item->u1.str,"endwhile") == 0 02523 || strcasecmp(item->u1.str,"execif") == 0 02524 || strcasecmp(item->u1.str,"execiftime") == 0 02525 || strcasecmp(item->u1.str,"exitwhile") == 0 02526 || strcasecmp(item->u1.str,"goto") == 0 02527 || strcasecmp(item->u1.str,"macro") == 0 02528 || strcasecmp(item->u1.str,"macroexclusive") == 0 02529 || strcasecmp(item->u1.str,"macroif") == 0 02530 || strcasecmp(item->u1.str,"stackpop") == 0 02531 || strcasecmp(item->u1.str,"execIf") == 0 ) { 02532 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: application call to %s affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead!\n", 02533 item->filename, item->startline, item->endline, item->u1.str); 02534 warns++; 02535 } 02536 if (strcasecmp(item->u1.str,"macroexit") == 0) { 02537 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: I am converting the MacroExit call here to a return statement.\n", 02538 item->filename, item->startline, item->endline); 02539 item->type = PV_RETURN; 02540 free(item->u1.str); 02541 item->u1.str = 0; 02542 } 02543 02544 #ifdef AAL_ARGCHECK 02545 found = 0; 02546 for (app=apps; app; app=app->next) { 02547 if (strcasecmp(app->name, item->u1.str) == 0) { 02548 found =app; 02549 break; 02550 } 02551 } 02552 if (!found) { 02553 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: application call to %s not listed in applist database!\n", 02554 item->filename, item->startline, item->endline, item->u1.str); 02555 warns++; 02556 } else 02557 check_app_args(item, item->u2.arglist, app); 02558 #endif 02559 break; 02560 02561 case PV_CASE: 02562 /* fields: item->u1.str == value of case 02563 item->u2.statements == pval list of statements under the case 02564 */ 02565 /* Make sure sequence of statements under case is terminated with goto, return, or break */ 02566 /* find the last statement */ 02567 check_pval(item->u2.statements, apps,in_globals); 02568 break; 02569 02570 case PV_PATTERN: 02571 /* fields: item->u1.str == value of case 02572 item->u2.statements == pval list of statements under the case 02573 */ 02574 /* Make sure sequence of statements under case is terminated with goto, return, or break */ 02575 /* find the last statement */ 02576 02577 check_pval(item->u2.statements, apps,in_globals); 02578 break; 02579 02580 case PV_DEFAULT: 02581 /* fields: 02582 item->u2.statements == pval list of statements under the case 02583 */ 02584 02585 check_pval(item->u2.statements, apps,in_globals); 02586 break; 02587 02588 case PV_CATCH: 02589 /* fields: item->u1.str == name of extension to catch 02590 item->u2.statements == pval list of statements in context body 02591 */ 02592 check_pval(item->u2.statements, apps,in_globals); 02593 break; 02594 02595 case PV_SWITCHES: 02596 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02597 */ 02598 check_pval(item->u1.list, apps,in_globals); 02599 break; 02600 02601 case PV_ESWITCHES: 02602 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02603 */ 02604 check_pval(item->u1.list, apps,in_globals); 02605 break; 02606 02607 case PV_INCLUDES: 02608 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02609 */ 02610 check_pval(item->u1.list, apps,in_globals); 02611 check_includes(item); 02612 for (lp=item->u1.list; lp; lp=lp->next){ 02613 char *incl_context = lp->u1.str; 02614 struct pval *that_context = find_context(incl_context); 02615 02616 if ( lp->u2.arglist ) { 02617 check_timerange(lp->u2.arglist); 02618 check_dow(lp->u2.arglist->next); 02619 check_day(lp->u2.arglist->next->next); 02620 check_month(lp->u2.arglist->next->next->next); 02621 } 02622 02623 if (that_context) { 02624 find_pval_gotos(that_context->u2.statements,0); 02625 02626 } 02627 } 02628 break; 02629 02630 case PV_STATEMENTBLOCK: 02631 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 02632 */ 02633 check_pval(item->u1.list, apps,in_globals); 02634 break; 02635 02636 case PV_VARDEC: 02637 /* fields: item->u1.str == variable name 02638 item->u2.val == variable value to assign 02639 */ 02640 /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */ 02641 if( !in_globals ) { /* don't check stuff inside the globals context; no wrapping in $[ ] there... */ 02642 snprintf(errmsg,sizeof(errmsg), "file %s, line %d, columns %d-%d, variable declaration expr '%s':", item->filename, item->startline, item->startcol, item->endcol, item->u2.val); 02643 ast_expr_register_extra_error_info(errmsg); 02644 ast_expr(item->u2.val, expr_output, sizeof(expr_output),NULL); 02645 ast_expr_clear_extra_error_info(); 02646 if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) { 02647 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02648 item->filename, item->startline, item->endline, item->u2.val); 02649 warns++; 02650 } 02651 check_expr2_input(item,item->u2.val); 02652 } 02653 break; 02654 02655 case PV_LOCALVARDEC: 02656 /* fields: item->u1.str == variable name 02657 item->u2.val == variable value to assign 02658 */ 02659 /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */ 02660 snprintf(errmsg,sizeof(errmsg), "file %s, line %d, columns %d-%d, variable declaration expr '%s':", item->filename, item->startline, item->startcol, item->endcol, item->u2.val); 02661 ast_expr_register_extra_error_info(errmsg); 02662 ast_expr(item->u2.val, expr_output, sizeof(expr_output),NULL); 02663 ast_expr_clear_extra_error_info(); 02664 if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) { 02665 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02666 item->filename, item->startline, item->endline, item->u2.val); 02667 warns++; 02668 } 02669 check_expr2_input(item,item->u2.val); 02670 break; 02671 02672 case PV_GOTO: 02673 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 02674 item->u1.list->u1.str == where the data on a PV_WORD will always be. 02675 */ 02676 /* don't check goto's in abstract contexts */ 02677 if ( in_abstract_context ) 02678 break; 02679 02680 check_goto(item); 02681 break; 02682 02683 case PV_LABEL: 02684 /* fields: item->u1.str == label name 02685 */ 02686 if ( strspn(item->u1.str, "0123456789") == strlen(item->u1.str) ) { 02687 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: label '%s' is numeric, this is bad practice!\n", 02688 item->filename, item->startline, item->endline, item->u1.str); 02689 warns++; 02690 } 02691 02692 check_label(item); 02693 break; 02694 02695 case PV_FOR: 02696 /* fields: item->u1.for_init == a string containing the initalizer 02697 item->u2.for_test == a string containing the loop test 02698 item->u3.for_inc == a string containing the loop increment 02699 02700 item->u4.for_statements == a pval list of statements in the for () 02701 */ 02702 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, for test expr '%s':", item->filename, item->startline, item->startcol, item->endcol, item->u2.for_test); 02703 ast_expr_register_extra_error_info(errmsg); 02704 02705 strp = strchr(item->u1.for_init, '='); 02706 if (strp) { 02707 ast_expr(strp+1, expr_output, sizeof(expr_output),NULL); 02708 } 02709 ast_expr(item->u2.for_test, expr_output, sizeof(expr_output),NULL); 02710 strp = strchr(item->u3.for_inc, '='); 02711 if (strp) { 02712 ast_expr(strp+1, expr_output, sizeof(expr_output),NULL); 02713 } 02714 if ( strpbrk(item->u2.for_test,"~!-+<>=*/&^") && !strstr(item->u2.for_test,"${") ) { 02715 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02716 item->filename, item->startline, item->endline, item->u2.for_test); 02717 warns++; 02718 } 02719 if ( strpbrk(item->u3.for_inc,"~!-+<>=*/&^") && !strstr(item->u3.for_inc,"${") ) { 02720 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02721 item->filename, item->startline, item->endline, item->u3.for_inc); 02722 warns++; 02723 } 02724 check_expr2_input(item,item->u2.for_test); 02725 check_expr2_input(item,item->u3.for_inc); 02726 02727 ast_expr_clear_extra_error_info(); 02728 check_pval(item->u4.for_statements, apps,in_globals); 02729 break; 02730 02731 case PV_WHILE: 02732 /* fields: item->u1.str == the while conditional, as supplied by user 02733 02734 item->u2.statements == a pval list of statements in the while () 02735 */ 02736 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, while expr '%s':", item->filename, item->startline, item->startcol, item->endcol, item->u1.str); 02737 ast_expr_register_extra_error_info(errmsg); 02738 ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL); 02739 ast_expr_clear_extra_error_info(); 02740 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02741 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02742 item->filename, item->startline, item->endline, item->u1.str); 02743 warns++; 02744 } 02745 check_expr2_input(item,item->u1.str); 02746 check_pval(item->u2.statements, apps,in_globals); 02747 break; 02748 02749 case PV_BREAK: 02750 /* fields: none 02751 */ 02752 check_break(item); 02753 break; 02754 02755 case PV_RETURN: 02756 /* fields: none 02757 */ 02758 break; 02759 02760 case PV_CONTINUE: 02761 /* fields: none 02762 */ 02763 check_continue(item); 02764 break; 02765 02766 case PV_RANDOM: 02767 /* fields: item->u1.str == the random number expression, as supplied by user 02768 02769 item->u2.statements == a pval list of statements in the if () 02770 item->u3.else_statements == a pval list of statements in the else 02771 (could be zero) 02772 */ 02773 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, random expr '%s':", item->filename, item->startline, item->startcol, item->endcol, item->u1.str); 02774 ast_expr_register_extra_error_info(errmsg); 02775 ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL); 02776 ast_expr_clear_extra_error_info(); 02777 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02778 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: random expression '%s' has operators, but no variables. Interesting...\n", 02779 item->filename, item->startline, item->endline, item->u1.str); 02780 warns++; 02781 } 02782 check_expr2_input(item,item->u1.str); 02783 check_pval(item->u2.statements, apps,in_globals); 02784 if (item->u3.else_statements) { 02785 check_pval(item->u3.else_statements, apps,in_globals); 02786 } 02787 break; 02788 02789 case PV_IFTIME: 02790 /* fields: item->u1.list == the if time values, 4 of them, each in PV_WORD, linked list 02791 02792 item->u2.statements == a pval list of statements in the if () 02793 item->u3.else_statements == a pval list of statements in the else 02794 (could be zero) 02795 */ 02796 if ( item->u2.arglist ) { 02797 check_timerange(item->u1.list); 02798 check_dow(item->u1.list->next); 02799 check_day(item->u1.list->next->next); 02800 check_month(item->u1.list->next->next->next); 02801 } 02802 02803 check_pval(item->u2.statements, apps,in_globals); 02804 if (item->u3.else_statements) { 02805 check_pval(item->u3.else_statements, apps,in_globals); 02806 } 02807 break; 02808 02809 case PV_IF: 02810 /* fields: item->u1.str == the if conditional, as supplied by user 02811 02812 item->u2.statements == a pval list of statements in the if () 02813 item->u3.else_statements == a pval list of statements in the else 02814 (could be zero) 02815 */ 02816 snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, if expr '%s':", item->filename, item->startline, item->startcol, item->endcol, item->u1.str); 02817 ast_expr_register_extra_error_info(errmsg); 02818 ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL); 02819 ast_expr_clear_extra_error_info(); 02820 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02821 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression '%s' has operators, but no variables. Interesting...\n", 02822 item->filename, item->startline, item->endline, item->u1.str); 02823 warns++; 02824 } 02825 check_expr2_input(item,item->u1.str); 02826 check_pval(item->u2.statements, apps,in_globals); 02827 if (item->u3.else_statements) { 02828 check_pval(item->u3.else_statements, apps,in_globals); 02829 } 02830 break; 02831 02832 case PV_SWITCH: 02833 /* fields: item->u1.str == the switch expression 02834 02835 item->u2.statements == a pval list of statements in the switch, 02836 (will be case statements, most likely!) 02837 */ 02838 /* we can check the switch expression, see if it matches any of the app variables... 02839 if it does, then, are all the possible cases accounted for? */ 02840 check_switch_expr(item, apps); 02841 check_pval(item->u2.statements, apps,in_globals); 02842 break; 02843 02844 case PV_EXTENSION: 02845 /* fields: item->u1.str == the extension name, label, whatever it's called 02846 02847 item->u2.statements == a pval list of statements in the extension 02848 item->u3.hints == a char * hint argument 02849 item->u4.regexten == an int boolean. non-zero says that regexten was specified 02850 */ 02851 current_extension = item ; 02852 02853 check_pval(item->u2.statements, apps,in_globals); 02854 break; 02855 02856 case PV_IGNOREPAT: 02857 /* fields: item->u1.str == the ignorepat data 02858 */ 02859 break; 02860 02861 case PV_GLOBALS: 02862 /* fields: item->u1.statements == pval list of statements, usually vardecs 02863 */ 02864 in_abstract_context = 0; 02865 check_pval(item->u1.statements, apps, 1); 02866 break; 02867 default: 02868 break; 02869 } 02870 }
Definition at line 2191 of file pval.c.
References ast_log(), ast_strdupa, calloc, pval::endcol, pval::endline, pval::filename, LOG_WARNING, pval::next, argapp::next, PV_APPLICATION_CALL, PV_CASE, PV_DEFAULT, PV_PATTERN, PV_STATEMENTBLOCK, pval::startcol, pval::startline, pval::statements, pval::str, strdup, pval::type, pval::u1, and pval::u2.
02192 { 02193 #ifdef AAL_ARGCHECK 02194 /* get and clean the variable name */ 02195 char *buff1, *p; 02196 struct argapp *a,*a2; 02197 struct appsetvar *v,*v2; 02198 struct argchoice *c; 02199 pval *t; 02200 02201 p = item->u1.str; 02202 while (p && *p && (*p == ' ' || *p == '\t' || *p == '$' || *p == '{' ) ) 02203 p++; 02204 02205 buff1 = ast_strdupa(p); 02206 02207 while (strlen(buff1) > 0 && ( buff1[strlen(buff1)-1] == '}' || buff1[strlen(buff1)-1] == ' ' || buff1[strlen(buff1)-1] == '\t')) 02208 buff1[strlen(buff1)-1] = 0; 02209 /* buff1 now contains the variable name */ 02210 v = 0; 02211 for (a=apps; a; a=a->next) { 02212 for (v=a->setvars;v;v=v->next) { 02213 if (strcmp(v->name,buff1) == 0) { 02214 break; 02215 } 02216 } 02217 if ( v ) 02218 break; 02219 } 02220 if (v && v->vals) { 02221 /* we have a match, to a variable that has a set of determined values */ 02222 int def= 0; 02223 int pat = 0; 02224 int f1 = 0; 02225 02226 /* first of all, does this switch have a default case ? */ 02227 for (t=item->u2.statements; t; t=t->next) { 02228 if (t->type == PV_DEFAULT) { 02229 def =1; 02230 break; 02231 } 02232 if (t->type == PV_PATTERN) { 02233 pat++; 02234 } 02235 } 02236 if (def || pat) /* nothing to check. All cases accounted for! */ 02237 return; 02238 for (c=v->vals; c; c=c->next) { 02239 f1 = 0; 02240 for (t=item->u2.statements; t; t=t->next) { 02241 if (t->type == PV_CASE || t->type == PV_PATTERN) { 02242 if (!strcmp(t->u1.str,c->name)) { 02243 f1 = 1; 02244 break; 02245 } 02246 } 02247 } 02248 if (!f1) { 02249 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: switch with expression(%s) does not handle the case of %s !\n", 02250 item->filename, item->startline, item->endline, item->u1.str, c->name); 02251 warns++; 02252 } 02253 } 02254 /* next, is there an app call in the current exten, that would set this var? */ 02255 f1 = 0; 02256 t = current_extension->u2.statements; 02257 if ( t && t->type == PV_STATEMENTBLOCK ) 02258 t = t->u1.statements; 02259 for (; t && t != item; t=t->next) { 02260 if (t->type == PV_APPLICATION_CALL) { 02261 /* find the application that matches the u1.str */ 02262 for (a2=apps; a2; a2=a2->next) { 02263 if (strcasecmp(a2->name, t->u1.str)==0) { 02264 for (v2=a2->setvars; v2; v2=v2->next) { 02265 if (strcmp(v2->name, buff1) == 0) { 02266 /* found an app that sets the var */ 02267 f1 = 1; 02268 break; 02269 } 02270 } 02271 } 02272 if (f1) 02273 break; 02274 } 02275 } 02276 if (f1) 02277 break; 02278 } 02279 02280 /* see if it sets the var */ 02281 if (!f1) { 02282 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", 02283 item->filename, item->startline, item->endline, item->u1.str); 02284 warns++; 02285 } 02286 } 02287 #else 02288 pval *t,*tl=0,*p2; 02289 int def= 0; 02290 02291 /* first of all, does this switch have a default case ? */ 02292 for (t=item->u2.statements; t; t=t->next) { 02293 if (t->type == PV_DEFAULT) { 02294 def =1; 02295 break; 02296 } 02297 tl = t; 02298 } 02299 if (def) /* nothing to check. All cases accounted for! */ 02300 return; 02301 /* if no default, warn and insert a default case at the end */ 02302 p2 = tl->next = calloc(1, sizeof(struct pval)); 02303 02304 p2->type = PV_DEFAULT; 02305 p2->startline = tl->startline; 02306 p2->endline = tl->endline; 02307 p2->startcol = tl->startcol; 02308 p2->endcol = tl->endcol; 02309 p2->filename = strdup(tl->filename); 02310 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: A default case was automatically added to the switch.\n", 02311 p2->filename, p2->startline, p2->endline); 02312 warns++; 02313 02314 #endif 02315 }
void destroy_extensions | ( | struct ael_extension * | exten | ) |
Definition at line 2985 of file pval.c.
References ael_priority::app, ael_priority::appargs, 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.
02986 { 02987 struct ael_extension *ne, *nen; 02988 for (ne=exten; ne; ne=nen) { 02989 struct ael_priority *pe, *pen; 02990 02991 if (ne->name) 02992 free(ne->name); 02993 02994 /* cidmatch fields are allocated with name, and freed when 02995 the name field is freed. Don't do a free for this field, 02996 unless you LIKE to see a crash! */ 02997 02998 if (ne->hints) 02999 free(ne->hints); 03000 03001 for (pe=ne->plist; pe; pe=pen) { 03002 pen = pe->next; 03003 if (pe->app) 03004 free(pe->app); 03005 pe->app = 0; 03006 if (pe->appargs) 03007 free(pe->appargs); 03008 pe->appargs = 0; 03009 pe->origin = 0; 03010 pe->goto_true = 0; 03011 pe->goto_false = 0; 03012 free(pe); 03013 } 03014 nen = ne->next_exten; 03015 ne->next_exten = 0; 03016 ne->plist =0; 03017 ne->plist_last = 0; 03018 ne->next_exten = 0; 03019 ne->loop_break = 0; 03020 ne->loop_continue = 0; 03021 free(ne); 03022 } 03023 }
void destroy_pval | ( | pval * | item | ) |
Definition at line 4979 of file pval.c.
References destroy_pval_item(), and pval::next.
04980 { 04981 pval *i,*nxt; 04982 04983 for (i=item; i; i=nxt) { 04984 nxt = i->next; 04985 04986 destroy_pval_item(i); 04987 } 04988 }
void destroy_pval_item | ( | pval * | item | ) |
Definition at line 4711 of file pval.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_LOCALVARDEC, 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.
04712 { 04713 if (item == NULL) { 04714 ast_log(LOG_WARNING, "null item\n"); 04715 return; 04716 } 04717 04718 if (item->filename) 04719 free(item->filename); 04720 04721 switch (item->type) { 04722 case PV_WORD: 04723 /* fields: item->u1.str == string associated with this (word). */ 04724 if (item->u1.str ) 04725 free(item->u1.str); 04726 if ( item->u2.arglist ) 04727 destroy_pval(item->u2.arglist); 04728 break; 04729 04730 case PV_MACRO: 04731 /* fields: item->u1.str == name of macro 04732 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 04733 item->u2.arglist->u1.str == argument 04734 item->u2.arglist->next == next arg 04735 04736 item->u3.macro_statements == pval list of statements in macro body. 04737 */ 04738 destroy_pval(item->u2.arglist); 04739 if (item->u1.str ) 04740 free(item->u1.str); 04741 destroy_pval(item->u3.macro_statements); 04742 break; 04743 04744 case PV_CONTEXT: 04745 /* fields: item->u1.str == name of context 04746 item->u2.statements == pval list of statements in context body 04747 item->u3.abstract == int 1 if an abstract keyword were present 04748 */ 04749 if (item->u1.str) 04750 free(item->u1.str); 04751 destroy_pval(item->u2.statements); 04752 break; 04753 04754 case PV_MACRO_CALL: 04755 /* fields: item->u1.str == name of macro to call 04756 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 04757 item->u2.arglist->u1.str == argument 04758 item->u2.arglist->next == next arg 04759 */ 04760 if (item->u1.str) 04761 free(item->u1.str); 04762 destroy_pval(item->u2.arglist); 04763 break; 04764 04765 case PV_APPLICATION_CALL: 04766 /* fields: item->u1.str == name of application to call 04767 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 04768 item->u2.arglist->u1.str == argument 04769 item->u2.arglist->next == next arg 04770 */ 04771 if (item->u1.str) 04772 free(item->u1.str); 04773 destroy_pval(item->u2.arglist); 04774 break; 04775 04776 case PV_CASE: 04777 /* fields: item->u1.str == value of case 04778 item->u2.statements == pval list of statements under the case 04779 */ 04780 if (item->u1.str) 04781 free(item->u1.str); 04782 destroy_pval(item->u2.statements); 04783 break; 04784 04785 case PV_PATTERN: 04786 /* fields: item->u1.str == value of case 04787 item->u2.statements == pval list of statements under the case 04788 */ 04789 if (item->u1.str) 04790 free(item->u1.str); 04791 destroy_pval(item->u2.statements); 04792 break; 04793 04794 case PV_DEFAULT: 04795 /* fields: 04796 item->u2.statements == pval list of statements under the case 04797 */ 04798 destroy_pval(item->u2.statements); 04799 break; 04800 04801 case PV_CATCH: 04802 /* fields: item->u1.str == name of extension to catch 04803 item->u2.statements == pval list of statements in context body 04804 */ 04805 if (item->u1.str) 04806 free(item->u1.str); 04807 destroy_pval(item->u2.statements); 04808 break; 04809 04810 case PV_SWITCHES: 04811 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04812 */ 04813 destroy_pval(item->u1.list); 04814 break; 04815 04816 case PV_ESWITCHES: 04817 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04818 */ 04819 destroy_pval(item->u1.list); 04820 break; 04821 04822 case PV_INCLUDES: 04823 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04824 item->u2.arglist == pval list of 4 PV_WORD elements for time values 04825 */ 04826 destroy_pval(item->u1.list); 04827 break; 04828 04829 case PV_STATEMENTBLOCK: 04830 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 04831 */ 04832 destroy_pval(item->u1.list); 04833 break; 04834 04835 case PV_LOCALVARDEC: 04836 case PV_VARDEC: 04837 /* fields: item->u1.str == variable name 04838 item->u2.val == variable value to assign 04839 */ 04840 if (item->u1.str) 04841 free(item->u1.str); 04842 if (item->u2.val) 04843 free(item->u2.val); 04844 break; 04845 04846 case PV_GOTO: 04847 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 04848 item->u1.list->u1.str == where the data on a PV_WORD will always be. 04849 */ 04850 04851 destroy_pval(item->u1.list); 04852 break; 04853 04854 case PV_LABEL: 04855 /* fields: item->u1.str == label name 04856 */ 04857 if (item->u1.str) 04858 free(item->u1.str); 04859 break; 04860 04861 case PV_FOR: 04862 /* fields: item->u1.for_init == a string containing the initalizer 04863 item->u2.for_test == a string containing the loop test 04864 item->u3.for_inc == a string containing the loop increment 04865 04866 item->u4.for_statements == a pval list of statements in the for () 04867 */ 04868 if (item->u1.for_init) 04869 free(item->u1.for_init); 04870 if (item->u2.for_test) 04871 free(item->u2.for_test); 04872 if (item->u3.for_inc) 04873 free(item->u3.for_inc); 04874 destroy_pval(item->u4.for_statements); 04875 break; 04876 04877 case PV_WHILE: 04878 /* fields: item->u1.str == the while conditional, as supplied by user 04879 04880 item->u2.statements == a pval list of statements in the while () 04881 */ 04882 if (item->u1.str) 04883 free(item->u1.str); 04884 destroy_pval(item->u2.statements); 04885 break; 04886 04887 case PV_BREAK: 04888 /* fields: none 04889 */ 04890 break; 04891 04892 case PV_RETURN: 04893 /* fields: none 04894 */ 04895 break; 04896 04897 case PV_CONTINUE: 04898 /* fields: none 04899 */ 04900 break; 04901 04902 case PV_IFTIME: 04903 /* fields: item->u1.list == the 4 time values, in PV_WORD structs, linked list 04904 04905 item->u2.statements == a pval list of statements in the if () 04906 item->u3.else_statements == a pval list of statements in the else 04907 (could be zero) 04908 */ 04909 destroy_pval(item->u1.list); 04910 destroy_pval(item->u2.statements); 04911 if (item->u3.else_statements) { 04912 destroy_pval(item->u3.else_statements); 04913 } 04914 break; 04915 04916 case PV_RANDOM: 04917 /* fields: item->u1.str == the random percentage, as supplied by user 04918 04919 item->u2.statements == a pval list of statements in the true part () 04920 item->u3.else_statements == a pval list of statements in the else 04921 (could be zero) 04922 fall thru to If */ 04923 case PV_IF: 04924 /* fields: item->u1.str == the if conditional, as supplied by user 04925 04926 item->u2.statements == a pval list of statements in the if () 04927 item->u3.else_statements == a pval list of statements in the else 04928 (could be zero) 04929 */ 04930 if (item->u1.str) 04931 free(item->u1.str); 04932 destroy_pval(item->u2.statements); 04933 if (item->u3.else_statements) { 04934 destroy_pval(item->u3.else_statements); 04935 } 04936 break; 04937 04938 case PV_SWITCH: 04939 /* fields: item->u1.str == the switch expression 04940 04941 item->u2.statements == a pval list of statements in the switch, 04942 (will be case statements, most likely!) 04943 */ 04944 if (item->u1.str) 04945 free(item->u1.str); 04946 destroy_pval(item->u2.statements); 04947 break; 04948 04949 case PV_EXTENSION: 04950 /* fields: item->u1.str == the extension name, label, whatever it's called 04951 04952 item->u2.statements == a pval list of statements in the extension 04953 item->u3.hints == a char * hint argument 04954 item->u4.regexten == an int boolean. non-zero says that regexten was specified 04955 */ 04956 if (item->u1.str) 04957 free(item->u1.str); 04958 if (item->u3.hints) 04959 free(item->u3.hints); 04960 destroy_pval(item->u2.statements); 04961 break; 04962 04963 case PV_IGNOREPAT: 04964 /* fields: item->u1.str == the ignorepat data 04965 */ 04966 if (item->u1.str) 04967 free(item->u1.str); 04968 break; 04969 04970 case PV_GLOBALS: 04971 /* fields: item->u1.statements == pval list of statements, usually vardecs 04972 */ 04973 destroy_pval(item->u1.statements); 04974 break; 04975 } 04976 free(item); 04977 }
struct pval* find_context | ( | char * | name | ) | [read] |
Definition at line 1960 of file pval.c.
References match_pval().
01961 { 01962 return_on_context_match = 1; 01963 count_labels = 0; 01964 match_context = name; 01965 match_exten = "*"; /* don't really need to set these, shouldn't be reached */ 01966 match_label = "*"; 01967 return match_pval(current_db); 01968 }
struct pval* find_macro | ( | char * | name | ) | [read] |
Definition at line 1950 of file pval.c.
References match_pval().
01951 { 01952 return_on_context_match = 1; 01953 count_labels = 0; 01954 match_context = name; 01955 match_exten = "*"; /* don't really need to set these, shouldn't be reached */ 01956 match_label = "*"; 01957 return match_pval(current_db); 01958 }
static char* handle_cli_ael_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 241 of file pbx_ael.c.
References ast_cli_args::argc, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, pbx_load_module(), and ast_cli_entry::usage.
00242 { 00243 switch (cmd) { 00244 case CLI_INIT: 00245 e->command = "ael reload"; 00246 e->usage = 00247 "Usage: ael reload\n" 00248 " Reloads AEL configuration.\n"; 00249 return NULL; 00250 case CLI_GENERATE: 00251 return NULL; 00252 } 00253 00254 if (a->argc != 2) 00255 return CLI_SHOWUSAGE; 00256 00257 return (pbx_load_module() ? CLI_FAILURE : CLI_SUCCESS); 00258 }
static char* handle_cli_ael_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 207 of file pbx_ael.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, DEBUG_CONTEXTS, DEBUG_MACROS, DEBUG_READ, DEBUG_TOKENS, and ast_cli_entry::usage.
00208 { 00209 switch (cmd) { 00210 case CLI_INIT: 00211 e->command = "ael set debug {read|tokens|macros|contexts|off}"; 00212 e->usage = 00213 "Usage: ael set debug {read|tokens|macros|contexts|off}\n" 00214 " Enable AEL read, token, macro, or context debugging,\n" 00215 " or disable all AEL debugging messages. Note: this\n" 00216 " currently does nothing.\n"; 00217 return NULL; 00218 case CLI_GENERATE: 00219 return NULL; 00220 } 00221 00222 if (a->argc != e->args) 00223 return CLI_SHOWUSAGE; 00224 00225 if (!strcasecmp(a->argv[3], "read")) 00226 aeldebug |= DEBUG_READ; 00227 else if (!strcasecmp(a->argv[3], "tokens")) 00228 aeldebug |= DEBUG_TOKENS; 00229 else if (!strcasecmp(a->argv[3], "macros")) 00230 aeldebug |= DEBUG_MACROS; 00231 else if (!strcasecmp(a->argv[3], "contexts")) 00232 aeldebug |= DEBUG_CONTEXTS; 00233 else if (!strcasecmp(a->argv[3], "off")) 00234 aeldebug = 0; 00235 else 00236 return CLI_SHOWUSAGE; 00237 00238 return CLI_SUCCESS; 00239 }
int is_empty | ( | char * | arg | ) |
int is_float | ( | char * | arg | ) |
int is_int | ( | char * | arg | ) |
static int load_module | ( | void | ) | [static] |
Definition at line 275 of file pbx_ael.c.
References aelsub_exec(), ARRAY_LEN, ast_cli_register_multiple(), ast_register_application_xml, and pbx_load_module().
00276 { 00277 ast_cli_register_multiple(cli_ael, ARRAY_LEN(cli_ael)); 00278 #ifndef STANDALONE 00279 ast_register_application_xml(aelsub, aelsub_exec); 00280 #endif 00281 return (pbx_load_module()); 00282 }
struct ael_extension* new_exten | ( | void | ) | [read] |
Definition at line 2937 of file pval.c.
References calloc.
02938 { 02939 struct ael_extension *x = (struct ael_extension *)calloc(sizeof(struct ael_extension),1); 02940 return x; 02941 }
struct ael_priority* new_prio | ( | void | ) | [read] |
Definition at line 2931 of file pval.c.
References calloc.
02932 { 02933 struct ael_priority *x = (struct ael_priority *)calloc(sizeof(struct ael_priority),1); 02934 return x; 02935 }
static int pbx_load_module | ( | void | ) | [static] |
Definition at line 155 of file pbx_ael.c.
References ael2_parse(), ael2_semantic_check(), ast_alloca, ast_compile_ael2(), ast_config_AST_CONFIG_DIR, ast_context_verify_includes(), ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_merge_contexts_and_delete(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_walk_contexts(), destroy_pval(), errs, local_contexts, local_table, LOG_ERROR, and LOG_NOTICE.
Referenced by handle_cli_ael_reload(), load_module(), and reload().
00156 { 00157 int errs=0, sem_err=0, sem_warn=0, sem_note=0; 00158 char *rfilename; 00159 struct ast_context *local_contexts=NULL, *con; 00160 struct ast_hashtab *local_table=NULL; 00161 00162 struct pval *parse_tree; 00163 00164 ast_log(LOG_NOTICE, "Starting AEL load process.\n"); 00165 if (config[0] == '/') 00166 rfilename = (char *)config; 00167 else { 00168 rfilename = ast_alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2); 00169 sprintf(rfilename, "%s/%s", ast_config_AST_CONFIG_DIR, config); 00170 } 00171 if (access(rfilename,R_OK) != 0) { 00172 ast_log(LOG_NOTICE, "File %s not found; AEL declining load\n", rfilename); 00173 return AST_MODULE_LOAD_DECLINE; 00174 } 00175 00176 parse_tree = ael2_parse(rfilename, &errs); 00177 ast_log(LOG_NOTICE, "AEL load process: parsed config file name '%s'.\n", rfilename); 00178 ael2_semantic_check(parse_tree, &sem_err, &sem_warn, &sem_note); 00179 if (errs == 0 && sem_err == 0) { 00180 ast_log(LOG_NOTICE, "AEL load process: checked config file name '%s'.\n", rfilename); 00181 local_table = ast_hashtab_create(11, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0); 00182 if (ast_compile_ael2(&local_contexts, local_table, parse_tree)) { 00183 ast_log(LOG_ERROR, "AEL compile failed! Aborting.\n"); 00184 destroy_pval(parse_tree); /* free up the memory */ 00185 return AST_MODULE_LOAD_DECLINE; 00186 } 00187 ast_log(LOG_NOTICE, "AEL load process: compiled config file name '%s'.\n", rfilename); 00188 00189 ast_merge_contexts_and_delete(&local_contexts, local_table, registrar); 00190 local_table = NULL; /* it's the dialplan global now */ 00191 local_contexts = NULL; 00192 ast_log(LOG_NOTICE, "AEL load process: merged config file name '%s'.\n", rfilename); 00193 for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con)) 00194 ast_context_verify_includes(con); 00195 ast_log(LOG_NOTICE, "AEL load process: verified config file name '%s'.\n", rfilename); 00196 } else { 00197 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); 00198 destroy_pval(parse_tree); /* free up the memory */ 00199 return AST_MODULE_LOAD_DECLINE; 00200 } 00201 destroy_pval(parse_tree); /* free up the memory */ 00202 00203 return AST_MODULE_LOAD_SUCCESS; 00204 }
static int reload | ( | void | ) | [static] |
Definition at line 284 of file pbx_ael.c.
References pbx_load_module().
00285 { 00286 return pbx_load_module(); 00287 }
void set_priorities | ( | struct ael_extension * | exten | ) |
Definition at line 4225 of file pval.c.
References ael_extension::is_switch, ael_priority::next, ael_extension::next_exten, ael_priority::origin, ael_extension::plist, ael_priority::priority_num, PV_LABEL, ael_extension::regexten, and pval::type.
04226 { 04227 int i; 04228 struct ael_priority *pr; 04229 do { 04230 if (exten->is_switch) 04231 i = 10; 04232 else if (exten->regexten) 04233 i=2; 04234 else 04235 i=1; 04236 04237 for (pr=exten->plist; pr; pr=pr->next) { 04238 pr->priority_num = i; 04239 04240 if (!pr->origin || (pr->origin && pr->origin->type != PV_LABEL) ) /* Labels don't show up in the dialplan, 04241 but we want them to point to the right 04242 priority, which would be the next line 04243 after the label; */ 04244 i++; 04245 } 04246 04247 exten = exten->next_exten; 04248 } while ( exten ); 04249 }
static int unload_module | ( | void | ) | [static] |
Definition at line 265 of file pbx_ael.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_context_destroy(), and ast_unregister_application().
00266 { 00267 ast_context_destroy(NULL, registrar); 00268 ast_cli_unregister_multiple(cli_ael, ARRAY_LEN(cli_ael)); 00269 #ifndef STANDALONE 00270 ast_unregister_application(aelsub); 00271 #endif 00272 return 0; 00273 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
struct ast_module_info* ast_module_info = &__mod_info [static] |
struct ast_cli_entry cli_ael[] [static] |
{ AST_CLI_DEFINE(handle_cli_ael_reload, "Reload AEL configuration"), AST_CLI_DEFINE(handle_cli_ael_set_debug, "Enable AEL debugging flags") }