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) |
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 __MODULE_INFO_SECTION | __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Asterisk Extension Language Compiler" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } |
static int | aeldebug = 0 |
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 63 of file pbx_ael.c.
Referenced by handle_cli_ael_set_debug().
#define DEBUG_MACROS (1 << 2) |
Definition at line 62 of file pbx_ael.c.
Referenced by handle_cli_ael_set_debug().
#define DEBUG_READ (1 << 0) |
Definition at line 60 of file pbx_ael.c.
Referenced by handle_cli_ael_set_debug().
#define DEBUG_TOKENS (1 << 1) |
Definition at line 61 of file pbx_ael.c.
Referenced by handle_cli_ael_set_debug().
void add_extensions | ( | struct ael_extension * | exten | ) |
Definition at line 4241 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.
{ struct ael_priority *pr; char *label=0; char realext[AST_MAX_EXTENSION]; if (!exten) { ast_log(LOG_WARNING, "This file is Empty!\n" ); return; } do { struct ael_priority *last = 0; pbx_substitute_variables_helper(NULL, exten->name, realext, sizeof(realext) - 1); if (exten->hints) { if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, PRIORITY_HINT, NULL, exten->cidmatch, exten->hints, NULL, ast_free_ptr, registrar)) { ast_log(LOG_WARNING, "Unable to add step at priority 'hint' of extension '%s'\n", exten->name); } } for (pr=exten->plist; pr; pr=pr->next) { char app[2000]; char appargs[2000]; /* before we can add the extension, we need to prep the app/appargs; the CONTROL types need to be done after the priority numbers are calculated. */ if (pr->type == AEL_LABEL) /* don't try to put labels in the dialplan! */ { last = pr; continue; } if (pr->app) strcpy(app, pr->app); else app[0] = 0; if (pr->appargs ) strcpy(appargs, pr->appargs); else appargs[0] = 0; switch( pr->type ) { case AEL_APPCALL: /* easy case. Everything is all set up */ break; case AEL_CONTROL1: /* FOR loop, WHILE loop, BREAK, CONTINUE, IF, IFTIME */ /* simple, unconditional goto. */ strcpy(app,"Goto"); if (pr->goto_true->origin && pr->goto_true->origin->type == PV_SWITCH ) { snprintf(appargs,sizeof(appargs),"%s,%d", pr->goto_true->exten->name, pr->goto_true->priority_num); } else if (pr->goto_true->origin && pr->goto_true->origin->type == PV_IFTIME && pr->goto_true->origin->u3.else_statements ) { snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num+1); } else snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num); break; case AEL_FOR_CONTROL: /* WHILE loop test, FOR loop test */ strcpy(app,"GotoIf"); snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); break; case AEL_IF_CONTROL: strcpy(app,"GotoIf"); if (pr->origin->u3.else_statements ) snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num+1); else snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); break; case AEL_RAND_CONTROL: strcpy(app,"Random"); snprintf(appargs,sizeof(appargs),"%s:%d", pr->appargs, pr->goto_true->priority_num+1); break; case AEL_IFTIME_CONTROL: strcpy(app,"GotoIfTime"); snprintf(appargs,sizeof(appargs),"%s?%d", pr->appargs, pr->priority_num+2); break; case AEL_RETURN: strcpy(app,"Return"); appargs[0] = 0; break; default: break; } if (last && last->type == AEL_LABEL ) { label = last->origin->u1.str; } else label = 0; if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, pr->priority_num, (label?label:NULL), exten->cidmatch, app, strdup(appargs), ast_free_ptr, registrar)) { ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num, exten->name); } last = pr; } exten = exten->next_exten; } while ( exten ); }
int ast_compile_ael2 | ( | struct ast_context ** | local_contexts, |
struct ast_hashtab * | local_table, | ||
struct pval * | root | ||
) |
Definition at line 4427 of file pval.c.
References add_extensions(), AEL_APPCALL, AEL_LABEL, ael_priority::app, ael_priority::appargs, pval::arglist, ast_compat_app_set, ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_find_or_create(), attach_exten(), buf, ael_extension::cidmatch, ael_extension::context, context, 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_priority::origin, pbx_builtin_setvar(), ael_extension::plist_last, 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.
{ pval *p,*p2; struct ast_context *context; char buf[2000]; struct ael_extension *exten; struct ael_extension *exten_list = 0; for (p=root; p; p=p->next ) { /* do the globals first, so they'll be there when we try to eval them */ switch (p->type) { case PV_GLOBALS: /* just VARDEC elements */ for (p2=p->u1.list; p2; p2=p2->next) { char buf2[2000]; snprintf(buf2,sizeof(buf2),"%s=%s", p2->u1.str, p2->u2.val); pbx_builtin_setvar(NULL, buf2); } break; default: break; } } for (p=root; p; p=p->next ) { pval *lp; int argc; switch (p->type) { case PV_MACRO: context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar); exten = new_exten(); exten->context = context; exten->name = strdup("~~s~~"); argc = 1; for (lp=p->u2.arglist; lp; lp=lp->next) { /* for each arg, set up a "Set" command */ struct ael_priority *np2 = new_prio(); np2->type = AEL_APPCALL; if (!ast_compat_app_set) { np2->app = strdup("MSet"); } else { np2->app = strdup("Set"); } snprintf(buf,sizeof(buf),"LOCAL(%s)=${ARG%d}", lp->u1.str, argc++); remove_spaces_before_equals(buf); np2->appargs = strdup(buf); linkprio(exten, np2, NULL); } /* CONTAINS APPCALLS, CATCH, just like extensions... */ if (gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context)) { return -1; } if (exten->return_needed) { /* most likely, this will go away */ struct ael_priority *np2 = new_prio(); np2->type = AEL_APPCALL; np2->app = strdup("NoOp"); snprintf(buf,sizeof(buf),"End of Macro %s-%s",p->u1.str, exten->name); np2->appargs = strdup(buf); linkprio(exten, np2, NULL); exten-> return_target = np2; } set_priorities(exten); attach_exten(&exten_list, exten); break; case PV_GLOBALS: /* already done */ break; case PV_CONTEXT: context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar); /* contexts contain: ignorepat, includes, switches, eswitches, extensions, */ for (p2=p->u2.statements; p2; p2=p2->next) { pval *p3; char *s3; switch (p2->type) { case PV_EXTENSION: exten = new_exten(); exten->name = strdup(p2->u1.str); exten->context = context; if( (s3=strchr(exten->name, '/') ) != 0 ) { *s3 = 0; exten->cidmatch = s3+1; } if ( p2->u3.hints ) exten->hints = strdup(p2->u3.hints); exten->regexten = p2->u4.regexten; if (gen_prios(exten, p->u1.str, p2->u2.statements, 0, context)) { return -1; } if (exten->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */ struct ael_priority *np2 = new_prio(); np2->type = AEL_APPCALL; np2->app = strdup("NoOp"); snprintf(buf,sizeof(buf),"End of Extension %s", exten->name); np2->appargs = strdup(buf); linkprio(exten, np2, NULL); exten-> return_target = np2; } /* is the last priority in the extension a label? Then add a trailing no-op */ if ( exten->plist_last && exten->plist_last->type == AEL_LABEL ) { struct ael_priority *np2 = new_prio(); np2->type = AEL_APPCALL; np2->app = strdup("NoOp"); snprintf(buf,sizeof(buf),"A NoOp to follow a trailing label %s", exten->plist_last->origin->u1.str); np2->appargs = strdup(buf); linkprio(exten, np2, NULL); } set_priorities(exten); attach_exten(&exten_list, exten); break; case PV_IGNOREPAT: ast_context_add_ignorepat2(context, p2->u1.str, registrar); break; case PV_INCLUDES: for (p3 = p2->u1.list; p3 ;p3=p3->next) { if ( p3->u2.arglist ) { snprintf(buf,sizeof(buf), "%s,%s,%s,%s,%s", p3->u1.str, p3->u2.arglist->u1.str, p3->u2.arglist->next->u1.str, p3->u2.arglist->next->next->u1.str, p3->u2.arglist->next->next->next->u1.str); ast_context_add_include2(context, buf, registrar); } else ast_context_add_include2(context, p3->u1.str, registrar); } break; case PV_SWITCHES: for (p3 = p2->u1.list; p3 ;p3=p3->next) { char *c = strchr(p3->u1.str, '/'); if (c) { *c = '\0'; c++; } else c = ""; ast_context_add_switch2(context, p3->u1.str, c, 0, registrar); } break; case PV_ESWITCHES: for (p3 = p2->u1.list; p3 ;p3=p3->next) { char *c = strchr(p3->u1.str, '/'); if (c) { *c = '\0'; c++; } else c = ""; ast_context_add_switch2(context, p3->u1.str, c, 1, registrar); } break; default: break; } } break; default: /* huh? what? */ break; } } /* moved these from being done after a macro or extension were processed, to after all processing is done, for the sake of fixing gotos to labels inside cases... */ /* I guess this would be considered 2nd pass of compiler now... */ fix_gotos_in_extensions(exten_list); /* find and fix extension ref in gotos to labels that are in case statements */ add_extensions(exten_list); /* actually makes calls to create priorities in ast_contexts -- feeds dialplan to asterisk */ destroy_extensions(exten_list); /* all that remains is an empty husk, discard of it as is proper */ return 0; }
void ast_expr_clear_extra_error_info | ( | void | ) |
Definition at line 2456 of file ast_expr2f.c.
{ extra_error_message_supplied=0; extra_error_message[0] = 0; }
void ast_expr_register_extra_error_info | ( | char * | errmsg | ) |
Definition at line 2450 of file ast_expr2f.c.
{ extra_error_message_supplied=1; strcpy(extra_error_message, message); }
Definition at line 2127 of file pval.c.
References ast_log(), pval::endline, pval::filename, LOG_WARNING, pval::next, pval::startline, pval::str, and pval::u1.
{ #ifdef AAL_ARGCHECK struct argdesc *ad = app->args; pval *pa; int z; for (pa = arglist; pa; pa=pa->next) { if (!ad) { ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Extra argument %s not in application call to %s !\n", arglist->filename, arglist->startline, arglist->endline, pa->u1.str, app->name); warns++; return 1; } else { /* find the first entry in the ad list that will match */ do { if ( ad->dtype == ARGD_VARARG ) /* once we hit the VARARG, all bets are off. Discontinue the comparisons */ break; z= option_matches( ad, pa, app); if (!z) { if ( !arglist ) arglist=appcall; if (ad->type == ARGD_REQUIRED) { ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); warns++; return 1; } } else if (z && ad->dtype == ARGD_OPTIONSET) { option_matches_j( ad, pa, app); } ad = ad->next; } while (ad && !z); } } /* any app nodes left, that are not optional? */ for ( ; ad; ad=ad->next) { if (ad->type == ARGD_REQUIRED && ad->dtype != ARGD_VARARG) { if ( !arglist ) arglist=appcall; ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); warns++; return 1; } } return 0; #else return 0; #endif }
Definition at line 2862 of file pval.c.
References check_pval_item(), and pval::next.
{ pval *i; /* checks to do: 1. Do goto's point to actual labels? 2. Do macro calls reference a macro? 3. Does the number of macro args match the definition? 4. Is a macro call missing its & at the front? 5. Application calls-- we could check syntax for existing applications, but I need some some sort of universal description bnf for a general sort of method for checking arguments, in number, maybe even type, at least. Don't want to hand code checks for hundreds of applications. */ for (i=item; i; i=i->next) { check_pval_item(i,apps,in_globals); } }
Definition at line 2354 of file pval.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_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.
{ pval *lp; #ifdef AAL_ARGCHECK struct argapp *app, *found; #endif struct pval *macro_def; struct pval *app_def; char errmsg[4096]; char *strp; switch (item->type) { case PV_WORD: /* fields: item->u1.str == string associated with this (word). item->u2.arglist == pval list of 4 PV_WORD elements for time values (only in PV_INCLUDES) */ break; case PV_MACRO: /* fields: item->u1.str == name of macro item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user item->u2.arglist->u1.str == argument item->u2.arglist->next == next arg item->u3.macro_statements == pval list of statements in macro body. */ in_abstract_context = 0; current_context = item; current_extension = 0; check_macro_returns(item); for (lp=item->u2.arglist; lp; lp=lp->next) { } check_pval(item->u3.macro_statements, apps,in_globals); break; case PV_CONTEXT: /* fields: item->u1.str == name of context item->u2.statements == pval list of statements in context body item->u3.abstract == int 1 if an abstract keyword were present */ current_context = item; current_extension = 0; if ( item->u3.abstract ) { in_abstract_context = 1; check_abstract_reference(item); } else in_abstract_context = 0; check_pval(item->u2.statements, apps,in_globals); break; case PV_MACRO_CALL: /* fields: item->u1.str == name of macro to call item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user item->u2.arglist->u1.str == argument item->u2.arglist->next == next arg */ #ifdef STANDALONE /* if this is a standalone, we will need to make sure the localized load of extensions.conf is done */ if (!extensions_dot_conf_loaded) { localized_pbx_load_module(); extensions_dot_conf_loaded++; } #endif macro_def = find_macro(item->u1.str); if (!macro_def) { #ifdef STANDALONE struct pbx_find_info pfiq = {.stacklen = 0 }; struct pbx_find_info pfiq2 = {.stacklen = 0 }; /* look for the macro in the extensions.conf world */ pbx_find_extension(NULL, NULL, &pfiq, item->u1.str, "s", 1, NULL, NULL, E_MATCH); if (pfiq.status != STATUS_SUCCESS) { char namebuf2[256]; snprintf(namebuf2, 256, "macro-%s", item->u1.str); /* look for the macro in the extensions.conf world */ pbx_find_extension(NULL, NULL, &pfiq2, namebuf2, "s", 1, NULL, NULL, E_MATCH); if (pfiq2.status == STATUS_SUCCESS) { 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", item->filename, item->startline, item->endline, item->u1.str, item->u1.str); warns++; } else { ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to non-existent %s! (Not even in the extensions.conf stuff!)\n", item->filename, item->startline, item->endline, item->u1.str); warns++; } } #else ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to %s cannot be found in the AEL code!\n", item->filename, item->startline, item->endline, item->u1.str); warns++; #endif #ifdef THIS_IS_1DOT4 char namebuf2[256]; snprintf(namebuf2, 256, "macro-%s", item->u1.str); /* look for the macro in the extensions.conf world */ pbx_find_extension(NULL, NULL, &pfiq, namebuf2, "s", 1, NULL, NULL, E_MATCH); if (pfiq.status != STATUS_SUCCESS) { 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", item->filename, item->startline, item->endline, item->u1.str); warns++; } #endif } else if (macro_def->type != PV_MACRO) { ast_log(LOG_ERROR,"Error: file %s, line %d-%d: macro call to %s references a context, not a macro!\n", item->filename, item->startline, item->endline, item->u1.str); errs++; } else { /* macro_def is a MACRO, so do the args match in number? */ int hereargs = 0; int thereargs = 0; for (lp=item->u2.arglist; lp; lp=lp->next) { hereargs++; } for (lp=macro_def->u2.arglist; lp; lp=lp->next) { thereargs++; } if (hereargs != thereargs ) { 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", item->filename, item->startline, item->endline, item->u1.str, hereargs, thereargs); errs++; } } break; case PV_APPLICATION_CALL: /* fields: item->u1.str == name of application to call item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user item->u2.arglist->u1.str == argument item->u2.arglist->next == next arg */ /* Need to check to see if the application is available! */ app_def = find_context(item->u1.str); if (app_def && app_def->type == PV_MACRO) { ast_log(LOG_ERROR,"Error: file %s, line %d-%d: application call to %s references an existing macro, but had no & preceding it!\n", item->filename, item->startline, item->endline, item->u1.str); errs++; } if (strcasecmp(item->u1.str,"GotoIf") == 0 || strcasecmp(item->u1.str,"GotoIfTime") == 0 || strcasecmp(item->u1.str,"while") == 0 || strcasecmp(item->u1.str,"endwhile") == 0 || strcasecmp(item->u1.str,"random") == 0 || strcasecmp(item->u1.str,"gosub") == 0 || strcasecmp(item->u1.str,"gosubif") == 0 || strcasecmp(item->u1.str,"continuewhile") == 0 || strcasecmp(item->u1.str,"endwhile") == 0 || strcasecmp(item->u1.str,"execif") == 0 || strcasecmp(item->u1.str,"execiftime") == 0 || strcasecmp(item->u1.str,"exitwhile") == 0 || strcasecmp(item->u1.str,"goto") == 0 || strcasecmp(item->u1.str,"macro") == 0 || strcasecmp(item->u1.str,"macroexclusive") == 0 || strcasecmp(item->u1.str,"macroif") == 0 || strcasecmp(item->u1.str,"stackpop") == 0 || strcasecmp(item->u1.str,"execIf") == 0 ) { 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", item->filename, item->startline, item->endline, item->u1.str); warns++; } if (strcasecmp(item->u1.str,"macroexit") == 0) { ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: I am converting the MacroExit call here to a return statement.\n", item->filename, item->startline, item->endline); item->type = PV_RETURN; free(item->u1.str); item->u1.str = 0; } #ifdef AAL_ARGCHECK found = 0; for (app=apps; app; app=app->next) { if (strcasecmp(app->name, item->u1.str) == 0) { found =app; break; } } if (!found) { ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: application call to %s not listed in applist database!\n", item->filename, item->startline, item->endline, item->u1.str); warns++; } else check_app_args(item, item->u2.arglist, app); #endif break; case PV_CASE: /* fields: item->u1.str == value of case item->u2.statements == pval list of statements under the case */ /* Make sure sequence of statements under case is terminated with goto, return, or break */ /* find the last statement */ check_pval(item->u2.statements, apps,in_globals); break; case PV_PATTERN: /* fields: item->u1.str == value of case item->u2.statements == pval list of statements under the case */ /* Make sure sequence of statements under case is terminated with goto, return, or break */ /* find the last statement */ check_pval(item->u2.statements, apps,in_globals); break; case PV_DEFAULT: /* fields: item->u2.statements == pval list of statements under the case */ check_pval(item->u2.statements, apps,in_globals); break; case PV_CATCH: /* fields: item->u1.str == name of extension to catch item->u2.statements == pval list of statements in context body */ check_pval(item->u2.statements, apps,in_globals); break; case PV_SWITCHES: /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list */ check_pval(item->u1.list, apps,in_globals); break; case PV_ESWITCHES: /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list */ check_pval(item->u1.list, apps,in_globals); break; case PV_INCLUDES: /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list */ check_pval(item->u1.list, apps,in_globals); check_includes(item); for (lp=item->u1.list; lp; lp=lp->next){ char *incl_context = lp->u1.str; struct pval *that_context = find_context(incl_context); if ( lp->u2.arglist ) { check_timerange(lp->u2.arglist); check_dow(lp->u2.arglist->next); check_day(lp->u2.arglist->next->next); check_month(lp->u2.arglist->next->next->next); } if (that_context) { find_pval_gotos(that_context->u2.statements,0); } } break; case PV_STATEMENTBLOCK: /* fields: item->u1.list == pval list of statements in block, one per entry in the list */ check_pval(item->u1.list, apps,in_globals); break; case PV_VARDEC: /* fields: item->u1.str == variable name item->u2.val == variable value to assign */ /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */ if( !in_globals ) { /* don't check stuff inside the globals context; no wrapping in $[ ] there... */ 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); ast_expr_register_extra_error_info(errmsg); ast_expr(item->u2.val, expr_output, sizeof(expr_output),NULL); ast_expr_clear_extra_error_info(); if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) { ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", item->filename, item->startline, item->endline, item->u2.val); warns++; } check_expr2_input(item,item->u2.val); } break; case PV_LOCALVARDEC: /* fields: item->u1.str == variable name item->u2.val == variable value to assign */ /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */ 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); ast_expr_register_extra_error_info(errmsg); ast_expr(item->u2.val, expr_output, sizeof(expr_output),NULL); ast_expr_clear_extra_error_info(); if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) { ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", item->filename, item->startline, item->endline, item->u2.val); warns++; } check_expr2_input(item,item->u2.val); break; case PV_GOTO: /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. item->u1.list->u1.str == where the data on a PV_WORD will always be. */ /* don't check goto's in abstract contexts */ if ( in_abstract_context ) break; check_goto(item); break; case PV_LABEL: /* fields: item->u1.str == label name */ if ( strspn(item->u1.str, "0123456789") == strlen(item->u1.str) ) { ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: label '%s' is numeric, this is bad practice!\n", item->filename, item->startline, item->endline, item->u1.str); warns++; } check_label(item); break; case PV_FOR: /* fields: item->u1.for_init == a string containing the initalizer item->u2.for_test == a string containing the loop test item->u3.for_inc == a string containing the loop increment item->u4.for_statements == a pval list of statements in the for () */ 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); ast_expr_register_extra_error_info(errmsg); strp = strchr(item->u1.for_init, '='); if (strp) { ast_expr(strp+1, expr_output, sizeof(expr_output),NULL); } ast_expr(item->u2.for_test, expr_output, sizeof(expr_output),NULL); strp = strchr(item->u3.for_inc, '='); if (strp) { ast_expr(strp+1, expr_output, sizeof(expr_output),NULL); } if ( strpbrk(item->u2.for_test,"~!-+<>=*/&^") && !strstr(item->u2.for_test,"${") ) { ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", item->filename, item->startline, item->endline, item->u2.for_test); warns++; } if ( strpbrk(item->u3.for_inc,"~!-+<>=*/&^") && !strstr(item->u3.for_inc,"${") ) { ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", item->filename, item->startline, item->endline, item->u3.for_inc); warns++; } check_expr2_input(item,item->u2.for_test); check_expr2_input(item,item->u3.for_inc); ast_expr_clear_extra_error_info(); check_pval(item->u4.for_statements, apps,in_globals); break; case PV_WHILE: /* fields: item->u1.str == the while conditional, as supplied by user item->u2.statements == a pval list of statements in the while () */ 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); ast_expr_register_extra_error_info(errmsg); ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL); ast_expr_clear_extra_error_info(); if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", item->filename, item->startline, item->endline, item->u1.str); warns++; } check_expr2_input(item,item->u1.str); check_pval(item->u2.statements, apps,in_globals); break; case PV_BREAK: /* fields: none */ check_break(item); break; case PV_RETURN: /* fields: none */ break; case PV_CONTINUE: /* fields: none */ check_continue(item); break; case PV_RANDOM: /* fields: item->u1.str == the random number expression, as supplied by user item->u2.statements == a pval list of statements in the if () item->u3.else_statements == a pval list of statements in the else (could be zero) */ 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); ast_expr_register_extra_error_info(errmsg); ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL); ast_expr_clear_extra_error_info(); if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: random expression '%s' has operators, but no variables. Interesting...\n", item->filename, item->startline, item->endline, item->u1.str); warns++; } check_expr2_input(item,item->u1.str); check_pval(item->u2.statements, apps,in_globals); if (item->u3.else_statements) { check_pval(item->u3.else_statements, apps,in_globals); } break; case PV_IFTIME: /* fields: item->u1.list == the if time values, 4 of them, each in PV_WORD, linked list item->u2.statements == a pval list of statements in the if () item->u3.else_statements == a pval list of statements in the else (could be zero) */ if ( item->u2.arglist ) { check_timerange(item->u1.list); check_dow(item->u1.list->next); check_day(item->u1.list->next->next); check_month(item->u1.list->next->next->next); } check_pval(item->u2.statements, apps,in_globals); if (item->u3.else_statements) { check_pval(item->u3.else_statements, apps,in_globals); } break; case PV_IF: /* fields: item->u1.str == the if conditional, as supplied by user item->u2.statements == a pval list of statements in the if () item->u3.else_statements == a pval list of statements in the else (could be zero) */ 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); ast_expr_register_extra_error_info(errmsg); ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL); ast_expr_clear_extra_error_info(); if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression '%s' has operators, but no variables. Interesting...\n", item->filename, item->startline, item->endline, item->u1.str); warns++; } check_expr2_input(item,item->u1.str); check_pval(item->u2.statements, apps,in_globals); if (item->u3.else_statements) { check_pval(item->u3.else_statements, apps,in_globals); } break; case PV_SWITCH: /* fields: item->u1.str == the switch expression item->u2.statements == a pval list of statements in the switch, (will be case statements, most likely!) */ /* we can check the switch expression, see if it matches any of the app variables... if it does, then, are all the possible cases accounted for? */ check_switch_expr(item, apps); check_pval(item->u2.statements, apps,in_globals); break; case PV_EXTENSION: /* fields: item->u1.str == the extension name, label, whatever it's called item->u2.statements == a pval list of statements in the extension item->u3.hints == a char * hint argument item->u4.regexten == an int boolean. non-zero says that regexten was specified */ current_extension = item ; check_pval(item->u2.statements, apps,in_globals); break; case PV_IGNOREPAT: /* fields: item->u1.str == the ignorepat data */ break; case PV_GLOBALS: /* fields: item->u1.statements == pval list of statements, usually vardecs */ in_abstract_context = 0; check_pval(item->u1.statements, apps, 1); break; default: break; } }
Definition at line 2181 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.
{ #ifdef AAL_ARGCHECK /* get and clean the variable name */ char *buff1, *p; struct argapp *a,*a2; struct appsetvar *v,*v2; struct argchoice *c; pval *t; p = item->u1.str; while (p && *p && (*p == ' ' || *p == '\t' || *p == '$' || *p == '{' ) ) p++; buff1 = ast_strdupa(p); while (strlen(buff1) > 0 && ( buff1[strlen(buff1)-1] == '}' || buff1[strlen(buff1)-1] == ' ' || buff1[strlen(buff1)-1] == '\t')) buff1[strlen(buff1)-1] = 0; /* buff1 now contains the variable name */ v = 0; for (a=apps; a; a=a->next) { for (v=a->setvars;v;v=v->next) { if (strcmp(v->name,buff1) == 0) { break; } } if ( v ) break; } if (v && v->vals) { /* we have a match, to a variable that has a set of determined values */ int def= 0; int pat = 0; int f1 = 0; /* first of all, does this switch have a default case ? */ for (t=item->u2.statements; t; t=t->next) { if (t->type == PV_DEFAULT) { def =1; break; } if (t->type == PV_PATTERN) { pat++; } } if (def || pat) /* nothing to check. All cases accounted for! */ return; for (c=v->vals; c; c=c->next) { f1 = 0; for (t=item->u2.statements; t; t=t->next) { if (t->type == PV_CASE || t->type == PV_PATTERN) { if (!strcmp(t->u1.str,c->name)) { f1 = 1; break; } } } if (!f1) { ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: switch with expression(%s) does not handle the case of %s !\n", item->filename, item->startline, item->endline, item->u1.str, c->name); warns++; } } /* next, is there an app call in the current exten, that would set this var? */ f1 = 0; t = current_extension->u2.statements; if ( t && t->type == PV_STATEMENTBLOCK ) t = t->u1.statements; for (; t && t != item; t=t->next) { if (t->type == PV_APPLICATION_CALL) { /* find the application that matches the u1.str */ for (a2=apps; a2; a2=a2->next) { if (strcasecmp(a2->name, t->u1.str)==0) { for (v2=a2->setvars; v2; v2=v2->next) { if (strcmp(v2->name, buff1) == 0) { /* found an app that sets the var */ f1 = 1; break; } } } if (f1) break; } } if (f1) break; } /* see if it sets the var */ if (!f1) { 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", item->filename, item->startline, item->endline, item->u1.str); warns++; } } #else pval *t,*tl=0,*p2; int def= 0; /* first of all, does this switch have a default case ? */ for (t=item->u2.statements; t; t=t->next) { if (t->type == PV_DEFAULT) { def =1; break; } tl = t; } if (def) /* nothing to check. All cases accounted for! */ return; /* if no default, warn and insert a default case at the end */ p2 = tl->next = calloc(1, sizeof(struct pval)); p2->type = PV_DEFAULT; p2->startline = tl->startline; p2->endline = tl->endline; p2->startcol = tl->startcol; p2->endcol = tl->endcol; p2->filename = strdup(tl->filename); ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: A default case was automatically added to the switch.\n", p2->filename, p2->startline, p2->endline); warns++; #endif }
void destroy_extensions | ( | struct ael_extension * | exten | ) |
Definition at line 2975 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.
{ struct ael_extension *ne, *nen; for (ne=exten; ne; ne=nen) { struct ael_priority *pe, *pen; if (ne->name) free(ne->name); /* cidmatch fields are allocated with name, and freed when the name field is freed. Don't do a free for this field, unless you LIKE to see a crash! */ if (ne->hints) free(ne->hints); for (pe=ne->plist; pe; pe=pen) { pen = pe->next; if (pe->app) free(pe->app); pe->app = 0; if (pe->appargs) free(pe->appargs); pe->appargs = 0; pe->origin = 0; pe->goto_true = 0; pe->goto_false = 0; free(pe); } nen = ne->next_exten; ne->next_exten = 0; ne->plist =0; ne->plist_last = 0; ne->next_exten = 0; ne->loop_break = 0; ne->loop_continue = 0; free(ne); } }
void destroy_pval | ( | pval * | item | ) |
Definition at line 4890 of file pval.c.
References destroy_pval_item(), and pval::next.
{ pval *i,*nxt; for (i=item; i; i=nxt) { nxt = i->next; destroy_pval_item(i); } }
void destroy_pval_item | ( | pval * | item | ) |
Definition at line 4622 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.
{ if (item == NULL) { ast_log(LOG_WARNING, "null item\n"); return; } if (item->filename) free(item->filename); switch (item->type) { case PV_WORD: /* fields: item->u1.str == string associated with this (word). */ if (item->u1.str ) free(item->u1.str); if ( item->u2.arglist ) destroy_pval(item->u2.arglist); break; case PV_MACRO: /* fields: item->u1.str == name of macro item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user item->u2.arglist->u1.str == argument item->u2.arglist->next == next arg item->u3.macro_statements == pval list of statements in macro body. */ destroy_pval(item->u2.arglist); if (item->u1.str ) free(item->u1.str); destroy_pval(item->u3.macro_statements); break; case PV_CONTEXT: /* fields: item->u1.str == name of context item->u2.statements == pval list of statements in context body item->u3.abstract == int 1 if an abstract keyword were present */ if (item->u1.str) free(item->u1.str); destroy_pval(item->u2.statements); break; case PV_MACRO_CALL: /* fields: item->u1.str == name of macro to call item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user item->u2.arglist->u1.str == argument item->u2.arglist->next == next arg */ if (item->u1.str) free(item->u1.str); destroy_pval(item->u2.arglist); break; case PV_APPLICATION_CALL: /* fields: item->u1.str == name of application to call item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user item->u2.arglist->u1.str == argument item->u2.arglist->next == next arg */ if (item->u1.str) free(item->u1.str); destroy_pval(item->u2.arglist); break; case PV_CASE: /* fields: item->u1.str == value of case item->u2.statements == pval list of statements under the case */ if (item->u1.str) free(item->u1.str); destroy_pval(item->u2.statements); break; case PV_PATTERN: /* fields: item->u1.str == value of case item->u2.statements == pval list of statements under the case */ if (item->u1.str) free(item->u1.str); destroy_pval(item->u2.statements); break; case PV_DEFAULT: /* fields: item->u2.statements == pval list of statements under the case */ destroy_pval(item->u2.statements); break; case PV_CATCH: /* fields: item->u1.str == name of extension to catch item->u2.statements == pval list of statements in context body */ if (item->u1.str) free(item->u1.str); destroy_pval(item->u2.statements); break; case PV_SWITCHES: /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list */ destroy_pval(item->u1.list); break; case PV_ESWITCHES: /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list */ destroy_pval(item->u1.list); break; case PV_INCLUDES: /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list item->u2.arglist == pval list of 4 PV_WORD elements for time values */ destroy_pval(item->u1.list); break; case PV_STATEMENTBLOCK: /* fields: item->u1.list == pval list of statements in block, one per entry in the list */ destroy_pval(item->u1.list); break; case PV_LOCALVARDEC: case PV_VARDEC: /* fields: item->u1.str == variable name item->u2.val == variable value to assign */ if (item->u1.str) free(item->u1.str); if (item->u2.val) free(item->u2.val); break; case PV_GOTO: /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. item->u1.list->u1.str == where the data on a PV_WORD will always be. */ destroy_pval(item->u1.list); break; case PV_LABEL: /* fields: item->u1.str == label name */ if (item->u1.str) free(item->u1.str); break; case PV_FOR: /* fields: item->u1.for_init == a string containing the initalizer item->u2.for_test == a string containing the loop test item->u3.for_inc == a string containing the loop increment item->u4.for_statements == a pval list of statements in the for () */ if (item->u1.for_init) free(item->u1.for_init); if (item->u2.for_test) free(item->u2.for_test); if (item->u3.for_inc) free(item->u3.for_inc); destroy_pval(item->u4.for_statements); break; case PV_WHILE: /* fields: item->u1.str == the while conditional, as supplied by user item->u2.statements == a pval list of statements in the while () */ if (item->u1.str) free(item->u1.str); destroy_pval(item->u2.statements); break; case PV_BREAK: /* fields: none */ break; case PV_RETURN: /* fields: none */ break; case PV_CONTINUE: /* fields: none */ break; case PV_IFTIME: /* fields: item->u1.list == the 4 time values, in PV_WORD structs, linked list item->u2.statements == a pval list of statements in the if () item->u3.else_statements == a pval list of statements in the else (could be zero) */ destroy_pval(item->u1.list); destroy_pval(item->u2.statements); if (item->u3.else_statements) { destroy_pval(item->u3.else_statements); } break; case PV_RANDOM: /* fields: item->u1.str == the random percentage, as supplied by user item->u2.statements == a pval list of statements in the true part () item->u3.else_statements == a pval list of statements in the else (could be zero) fall thru to If */ case PV_IF: /* fields: item->u1.str == the if conditional, as supplied by user item->u2.statements == a pval list of statements in the if () item->u3.else_statements == a pval list of statements in the else (could be zero) */ if (item->u1.str) free(item->u1.str); destroy_pval(item->u2.statements); if (item->u3.else_statements) { destroy_pval(item->u3.else_statements); } break; case PV_SWITCH: /* fields: item->u1.str == the switch expression item->u2.statements == a pval list of statements in the switch, (will be case statements, most likely!) */ if (item->u1.str) free(item->u1.str); destroy_pval(item->u2.statements); break; case PV_EXTENSION: /* fields: item->u1.str == the extension name, label, whatever it's called item->u2.statements == a pval list of statements in the extension item->u3.hints == a char * hint argument item->u4.regexten == an int boolean. non-zero says that regexten was specified */ if (item->u1.str) free(item->u1.str); if (item->u3.hints) free(item->u3.hints); destroy_pval(item->u2.statements); break; case PV_IGNOREPAT: /* fields: item->u1.str == the ignorepat data */ if (item->u1.str) free(item->u1.str); break; case PV_GLOBALS: /* fields: item->u1.statements == pval list of statements, usually vardecs */ destroy_pval(item->u1.statements); break; } free(item); }
struct pval* find_context | ( | char * | name | ) | [read] |
Definition at line 1950 of file pval.c.
References match_pval(), and name.
{ return_on_context_match = 1; count_labels = 0; match_context = name; match_exten = "*"; /* don't really need to set these, shouldn't be reached */ match_label = "*"; return match_pval(current_db); }
struct pval* find_macro | ( | char * | name | ) | [read] |
Definition at line 1940 of file pval.c.
References match_pval(), and name.
{ return_on_context_match = 1; count_labels = 0; match_context = name; match_exten = "*"; /* don't really need to set these, shouldn't be reached */ match_label = "*"; return match_pval(current_db); }
static char* handle_cli_ael_reload | ( | struct ast_cli_entry * | e, |
int | cmd, | ||
struct ast_cli_args * | a | ||
) | [static] |
Definition at line 199 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.
{ switch (cmd) { case CLI_INIT: e->command = "ael reload"; e->usage = "Usage: ael reload\n" " Reloads AEL configuration.\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != 2) return CLI_SHOWUSAGE; return (pbx_load_module() ? CLI_FAILURE : CLI_SUCCESS); }
static char* handle_cli_ael_set_debug | ( | struct ast_cli_entry * | e, |
int | cmd, | ||
struct ast_cli_args * | a | ||
) | [static] |
Definition at line 165 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.
{ switch (cmd) { case CLI_INIT: e->command = "ael set debug {read|tokens|macros|contexts|off}"; e->usage = "Usage: ael set debug {read|tokens|macros|contexts|off}\n" " Enable AEL read, token, macro, or context debugging,\n" " or disable all AEL debugging messages. Note: this\n" " currently does nothing.\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != e->args) return CLI_SHOWUSAGE; if (!strcasecmp(a->argv[3], "read")) aeldebug |= DEBUG_READ; else if (!strcasecmp(a->argv[3], "tokens")) aeldebug |= DEBUG_TOKENS; else if (!strcasecmp(a->argv[3], "macros")) aeldebug |= DEBUG_MACROS; else if (!strcasecmp(a->argv[3], "contexts")) aeldebug |= DEBUG_CONTEXTS; else if (!strcasecmp(a->argv[3], "off")) aeldebug = 0; else return CLI_SHOWUSAGE; return CLI_SUCCESS; }
int is_empty | ( | char * | arg | ) |
int is_float | ( | char * | arg | ) |
int is_int | ( | char * | arg | ) |
static int load_module | ( | void | ) | [static] |
Definition at line 230 of file pbx_ael.c.
References ARRAY_LEN, ast_cli_register_multiple(), and pbx_load_module().
{ ast_cli_register_multiple(cli_ael, ARRAY_LEN(cli_ael)); return (pbx_load_module()); }
struct ael_extension* new_exten | ( | void | ) | [read] |
Definition at line 2927 of file pval.c.
References calloc.
{ struct ael_extension *x = (struct ael_extension *)calloc(sizeof(struct ael_extension),1); return x; }
struct ael_priority* new_prio | ( | void | ) | [read] |
Definition at line 2921 of file pval.c.
References calloc.
{ struct ael_priority *x = (struct ael_priority *)calloc(sizeof(struct ael_priority),1); return x; }
static int pbx_load_module | ( | void | ) | [static] |
Definition at line 113 of file pbx_ael.c.
References ael2_parse(), ael2_semantic_check(), 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, LOG_NOTICE, and R_OK.
Referenced by handle_cli_ael_reload(), load_module(), and reload().
{ int errs=0, sem_err=0, sem_warn=0, sem_note=0; char *rfilename; struct ast_context *local_contexts=NULL, *con; struct ast_hashtab *local_table=NULL; struct pval *parse_tree; ast_log(LOG_NOTICE, "Starting AEL load process.\n"); if (config[0] == '/') rfilename = (char *)config; else { rfilename = alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2); sprintf(rfilename, "%s/%s", ast_config_AST_CONFIG_DIR, config); } if (access(rfilename,R_OK) != 0) { ast_log(LOG_NOTICE, "File %s not found; AEL declining load\n", rfilename); return AST_MODULE_LOAD_DECLINE; } parse_tree = ael2_parse(rfilename, &errs); ast_log(LOG_NOTICE, "AEL load process: parsed config file name '%s'.\n", rfilename); ael2_semantic_check(parse_tree, &sem_err, &sem_warn, &sem_note); if (errs == 0 && sem_err == 0) { ast_log(LOG_NOTICE, "AEL load process: checked config file name '%s'.\n", rfilename); local_table = ast_hashtab_create(11, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0); if (ast_compile_ael2(&local_contexts, local_table, parse_tree)) { ast_log(LOG_ERROR, "AEL compile failed! Aborting.\n"); destroy_pval(parse_tree); /* free up the memory */ return AST_MODULE_LOAD_DECLINE; } ast_log(LOG_NOTICE, "AEL load process: compiled config file name '%s'.\n", rfilename); ast_merge_contexts_and_delete(&local_contexts, local_table, registrar); local_table = NULL; /* it's the dialplan global now */ local_contexts = NULL; ast_log(LOG_NOTICE, "AEL load process: merged config file name '%s'.\n", rfilename); for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con)) ast_context_verify_includes(con); ast_log(LOG_NOTICE, "AEL load process: verified config file name '%s'.\n", rfilename); } else { 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); destroy_pval(parse_tree); /* free up the memory */ return AST_MODULE_LOAD_DECLINE; } destroy_pval(parse_tree); /* free up the memory */ return AST_MODULE_LOAD_SUCCESS; }
static int reload | ( | void | ) | [static] |
Definition at line 236 of file pbx_ael.c.
References pbx_load_module().
{ return pbx_load_module(); }
void set_priorities | ( | struct ael_extension * | exten | ) |
Definition at line 4215 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.
{ int i; struct ael_priority *pr; do { if (exten->is_switch) i = 10; else if (exten->regexten) i=2; else i=1; for (pr=exten->plist; pr; pr=pr->next) { pr->priority_num = i; if (!pr->origin || (pr->origin && pr->origin->type != PV_LABEL) ) /* Labels don't show up in the dialplan, but we want them to point to the right priority, which would be the next line after the label; */ i++; } exten = exten->next_exten; } while ( exten ); }
static int unload_module | ( | void | ) | [static] |
Definition at line 223 of file pbx_ael.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), and ast_context_destroy().
{ ast_context_destroy(NULL, registrar); ast_cli_unregister_multiple(cli_ael, ARRAY_LEN(cli_ael)); return 0; }
struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Asterisk Extension Language Compiler" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .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") }