Mon Oct 8 12:39:26 2012

Asterisk developer's documentation


pbx_ael.c File Reference

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)
pvalfind_context (char *name)
pvalfind_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)
ael_extensionnew_exten (void)
ael_prioritynew_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_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_ael []
static char * config = "extensions.ael"
static char * registrar = "pbx_ael"


Detailed Description

Compile symbolic Asterisk Extension Logic into Asterisk extensions, version 2.

Definition in file pbx_ael.c.


Define Documentation

#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().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 303 of file pbx_ael.c.

00307 {

static void __unreg_module ( void   )  [static]

Definition at line 303 of file pbx_ael.c.

00307 {

void add_extensions ( struct ael_extension exten  ) 

Definition at line 4252 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, app, ael_priority::app, ael_priority::appargs, ast_add_extension2(), ast_free_ptr, ast_log(), AST_MAX_EXTENSION, pval::else_statements, exten, ael_priority::exten, ael_priority::goto_false, ael_priority::goto_true, last, LOG_WARNING, ael_extension::name, ael_priority::next, ael_priority::origin, pbx_substitute_variables_helper(), PRIORITY_HINT, ael_priority::priority_num, PV_IFTIME, PV_SWITCH, strdup, ael_priority::type, pval::type, and pval::u3.

04253 {
04254    struct ael_priority *pr;
04255    char *label=0;
04256    char realext[AST_MAX_EXTENSION];
04257    if (!exten) {
04258       ast_log(LOG_WARNING, "This file is Empty!\n" );
04259       return;
04260    }
04261    do {
04262       struct ael_priority *last = 0;
04263       
04264       pbx_substitute_variables_helper(NULL, exten->name, realext, sizeof(realext) - 1);
04265       if (exten->hints) {
04266          if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, PRIORITY_HINT, NULL, exten->cidmatch, 
04267                           exten->hints, NULL, ast_free_ptr, registrar)) {
04268             ast_log(LOG_WARNING, "Unable to add step at priority 'hint' of extension '%s'\n",
04269                   exten->name);
04270          }
04271       }
04272       
04273       for (pr=exten->plist; pr; pr=pr->next) {
04274          char app[2000];
04275          char appargs[2000];
04276 
04277          /* before we can add the extension, we need to prep the app/appargs;
04278             the CONTROL types need to be done after the priority numbers are calculated.
04279          */
04280          if (pr->type == AEL_LABEL) /* don't try to put labels in the dialplan! */ {
04281             last = pr;
04282             continue;
04283          }
04284          
04285          if (pr->app)
04286             strcpy(app, pr->app);
04287          else
04288             app[0] = 0;
04289          if (pr->appargs )
04290             strcpy(appargs, pr->appargs);
04291          else
04292             appargs[0] = 0;
04293          switch( pr->type ) {
04294          case AEL_APPCALL:
04295             /* easy case. Everything is all set up */
04296             break;
04297             
04298          case AEL_CONTROL1: /* FOR loop, WHILE loop, BREAK, CONTINUE, IF, IFTIME */
04299             /* simple, unconditional goto. */
04300             strcpy(app,"Goto");
04301             if (pr->goto_true->origin && pr->goto_true->origin->type == PV_SWITCH ) {
04302                snprintf(appargs,sizeof(appargs),"%s,%d", pr->goto_true->exten->name, pr->goto_true->priority_num);
04303             } else if (pr->goto_true->origin && pr->goto_true->origin->type == PV_IFTIME && pr->goto_true->origin->u3.else_statements ) {
04304                snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num+1);
04305             } else
04306                snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num);
04307             break;
04308             
04309          case AEL_FOR_CONTROL:  /* WHILE loop test, FOR loop test */
04310             strcpy(app,"GotoIf");
04311             snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num);
04312             break;
04313             
04314          case AEL_IF_CONTROL:
04315             strcpy(app,"GotoIf");
04316             if (pr->origin->u3.else_statements )
04317                snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num+1);
04318             else
04319                snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num);
04320             break;
04321 
04322          case AEL_RAND_CONTROL:
04323             strcpy(app,"Random");
04324             snprintf(appargs,sizeof(appargs),"%s:%d", pr->appargs, pr->goto_true->priority_num+1);
04325             break;
04326 
04327          case AEL_IFTIME_CONTROL:
04328             strcpy(app,"GotoIfTime");
04329             snprintf(appargs,sizeof(appargs),"%s?%d", pr->appargs, pr->priority_num+2);
04330             break;
04331 
04332          case AEL_RETURN:
04333             strcpy(app,"Return");
04334             appargs[0] = 0;
04335             break;
04336             
04337          default:
04338             break;
04339          }
04340          if (last && last->type == AEL_LABEL ) {
04341             label = last->origin->u1.str;
04342          }
04343          else
04344             label = 0;
04345          
04346          if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, pr->priority_num, (label?label:NULL), exten->cidmatch, 
04347                           app, strdup(appargs), ast_free_ptr, registrar)) {
04348             ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num, 
04349                   exten->name);
04350          }
04351          last = pr;
04352       }
04353       exten = exten->next_exten;
04354    } while ( exten );
04355 }

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 4452 of file pval.c.

References buf2, context, exten, pval::list, pval::next, pbx_builtin_setvar(), PV_GLOBALS, pval::str, pval::type, pval::u1, pval::u2, and pval::val.

04453 {
04454    pval *p,*p2;
04455    struct ast_context *context;
04456    char buf[2000];
04457    struct ael_extension *exten;
04458    struct ael_extension *exten_list = 0;
04459 
04460    for (p=root; p; p=p->next ) { /* do the globals first, so they'll be there
04461                             when we try to eval them */
04462       switch (p->type) {
04463       case PV_GLOBALS:
04464          /* just VARDEC elements */
04465          for (p2=p->u1.list; p2; p2=p2->next) {
04466             char buf2[2000];
04467             snprintf(buf2,sizeof(buf2),"%s=%s", p2->u1.str, p2->u2.val);
04468             pbx_builtin_setvar(NULL, buf2);
04469          }
04470          break;
04471       default:
04472          break;
04473       }
04474    }
04475 
04476    for (p=root; p; p=p->next ) {
04477       pval *lp;
04478       int argc;
04479       
04480       switch (p->type) {
04481       case PV_MACRO:
04482          
04483          context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar);
04484          
04485          exten = new_exten();
04486          exten->context = context;
04487          exten->name = strdup("~~s~~");
04488          argc = 1;
04489          for (lp=p->u2.arglist; lp; lp=lp->next) {
04490             /* for each arg, set up a "Set" command */
04491             struct ael_priority *np2 = new_prio();
04492             np2->type = AEL_APPCALL;
04493             if (!ast_compat_app_set) {
04494                np2->app = strdup("MSet");
04495             } else {
04496                np2->app = strdup("Set");
04497             }
04498             snprintf(buf,sizeof(buf),"LOCAL(%s)=${ARG%d}", lp->u1.str, argc++);
04499             remove_spaces_before_equals(buf);
04500             np2->appargs = strdup(buf);
04501             linkprio(exten, np2, NULL);
04502          }
04503          
04504          /* CONTAINS APPCALLS, CATCH, just like extensions... */
04505          if (gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context)) {
04506             return -1;
04507          }
04508          if (exten->return_needed) {  /* most likely, this will go away */
04509             struct ael_priority *np2 = new_prio();
04510             np2->type = AEL_APPCALL;
04511             np2->app = strdup("NoOp");
04512             snprintf(buf,sizeof(buf),"End of Macro %s-%s",p->u1.str, exten->name);
04513             np2->appargs = strdup(buf);
04514             linkprio(exten, np2, NULL);
04515             exten-> return_target = np2;
04516          }
04517          
04518          set_priorities(exten);
04519          attach_exten(&exten_list, exten);
04520          break;
04521          
04522       case PV_GLOBALS:
04523          /* already done */
04524          break;
04525          
04526       case PV_CONTEXT:
04527          context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar);
04528          
04529          /* contexts contain: ignorepat, includes, switches, eswitches, extensions,  */
04530          for (p2=p->u2.statements; p2; p2=p2->next) {
04531             pval *p3;
04532             char *s3;
04533             
04534             switch (p2->type) {
04535             case PV_EXTENSION:
04536                exten = new_exten();
04537                exten->name = strdup(p2->u1.str);
04538                exten->context = context;
04539                
04540                if( (s3=strchr(exten->name, '/') ) != 0 )
04541                {
04542                   *s3 = 0;
04543                   exten->cidmatch = s3+1;
04544                }
04545                
04546                if ( p2->u3.hints )
04547                   exten->hints = strdup(p2->u3.hints);
04548                exten->regexten = p2->u4.regexten;
04549                if (gen_prios(exten, p->u1.str, p2->u2.statements, 0, context)) {
04550                   return -1;
04551                }
04552                if (exten->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */
04553                   struct ael_priority *np2 = new_prio();
04554                   np2->type = AEL_APPCALL;
04555                   np2->app = strdup("NoOp");
04556                   snprintf(buf,sizeof(buf),"End of Extension %s", exten->name);
04557                   np2->appargs = strdup(buf);
04558                   linkprio(exten, np2, NULL);
04559                   exten-> return_target = np2;
04560                }
04561                /* is the last priority in the extension a label? Then add a trailing no-op */
04562                if ( exten->plist_last && exten->plist_last->type == AEL_LABEL ) {
04563                   struct ael_priority *np2 = new_prio();
04564                   np2->type = AEL_APPCALL;
04565                   np2->app = strdup("NoOp");
04566                   snprintf(buf,sizeof(buf),"A NoOp to follow a trailing label %s", exten->plist_last->origin->u1.str);
04567                   np2->appargs = strdup(buf);
04568                   linkprio(exten, np2, NULL);
04569                }
04570 
04571                set_priorities(exten);
04572                attach_exten(&exten_list, exten);
04573                break;
04574                
04575             case PV_IGNOREPAT:
04576                ast_context_add_ignorepat2(context, p2->u1.str, registrar);
04577                break;
04578                
04579             case PV_INCLUDES:
04580                for (p3 = p2->u1.list; p3 ;p3=p3->next) {
04581                   if ( p3->u2.arglist ) {
04582                      snprintf(buf,sizeof(buf), "%s,%s,%s,%s,%s", 
04583                             p3->u1.str,
04584                             p3->u2.arglist->u1.str,
04585                             p3->u2.arglist->next->u1.str,
04586                             p3->u2.arglist->next->next->u1.str,
04587                             p3->u2.arglist->next->next->next->u1.str);
04588                      ast_context_add_include2(context, buf, registrar);
04589                   } else
04590                      ast_context_add_include2(context, p3->u1.str, registrar);
04591                }
04592                break;
04593                
04594             case PV_SWITCHES:
04595                for (p3 = p2->u1.list; p3 ;p3=p3->next) {
04596                   char *c = strchr(p3->u1.str, '/');
04597                   if (c) {
04598                      *c = '\0';
04599                      c++;
04600                   } else
04601                      c = "";
04602 
04603                   ast_context_add_switch2(context, p3->u1.str, c, 0, registrar);
04604                }
04605                break;
04606 
04607             case PV_ESWITCHES:
04608                for (p3 = p2->u1.list; p3 ;p3=p3->next) {
04609                   char *c = strchr(p3->u1.str, '/');
04610                   if (c) {
04611                      *c = '\0';
04612                      c++;
04613                   } else
04614                      c = "";
04615 
04616                   ast_context_add_switch2(context, p3->u1.str, c, 1, registrar);
04617                }
04618                break;
04619             default:
04620                break;
04621             }
04622          }
04623          
04624          break;
04625          
04626       default:
04627          /* huh? what? */
04628          break;
04629          
04630       }
04631    }
04632 
04633    /* Create default "h" bubble context */
04634    if (ast_custom_function_find("DIALPLAN_EXISTS") && ast_custom_function_find("STACK_PEEK")) {
04635       int i;
04636       const char *h_context = "ael-builtin-h-bubble";
04637       struct ael_priority *np;
04638       struct {
04639          int priority;
04640          const char *app;
04641          const char *arg;
04642       } steps[] = {
04643          /* Start high, to avoid conflict with existing h extensions */
04644          { 1, "Goto", "9991" },
04645          /* Save the context, because after the StackPop, it disappears */
04646          { 9991, "Set", "~~parentcxt~~=${STACK_PEEK(1,c,1)}" },
04647          /* If we're not in a Gosub frame, exit */
04648          { 9992, "GotoIf", "$[\"${~~parentcxt~~}\"=\"\"]?9996" },
04649          /* Check for an "h" extension in that context */
04650          { 9993, "GotoIf", "${DIALPLAN_EXISTS(${~~parentcxt~~},h,1)}?9994:9996" },
04651          /* Pop off the stack frame to prevent an infinite loop */
04652          { 9994, "StackPop", "" },
04653          /* Finally, go there. */
04654          { 9995, "Goto", "${~~parentcxt~~},h,1" },
04655          /* Just an empty priority for jumping out early */
04656          { 9996, "NoOp", "" }
04657       };
04658       context = ast_context_find_or_create(local_contexts, local_table, h_context, registrar);
04659       if (context_used(exten_list, context)) {
04660          int found = 0;
04661          while (!found) {
04662             /* Pick a new context name that is not used. */
04663             char h_context_template[] = "/tmp/ael-builtin-h-bubble-XXXXXX";
04664             int fd = mkstemp(h_context_template);
04665             unlink(h_context_template);
04666             close(fd);
04667             context = ast_context_find_or_create(local_contexts, local_table, h_context_template + 5, registrar);
04668             found = !context_used(exten_list, context);
04669          }
04670          h_context = ast_get_context_name(context);
04671       }
04672       exten = new_exten();
04673       exten->context = context;
04674       exten->name = strdup("h");
04675 
04676       for (i = 0; i < ARRAY_LEN(steps); i++) {
04677          np = new_prio();
04678          np->type = AEL_APPCALL;
04679          np->priority_num = steps[i].priority;
04680          np->app = strdup(steps[i].app);
04681          np->appargs = strdup(steps[i].arg);
04682          linkprio(exten, np, NULL);
04683       }
04684       attach_exten(&exten_list, exten);
04685 
04686       /* Include the default "h" bubble context in each macro context */
04687       for (exten = exten_list; exten; exten = exten->next_exten) {
04688          /* All macros contain a "~~s~~" extension, and it's the first created.  If
04689           * we perchance get a non-macro context, it's no big deal; the logic is
04690           * designed to exit out smoothly if not called from within a Gosub. */
04691          if (!strcmp(exten->name, "~~s~~")) {
04692             ast_context_add_include2(exten->context, h_context, registrar);
04693          }
04694       }
04695    }
04696 
04697    /* moved these from being done after a macro or extension were processed,
04698       to after all processing is done, for the sake of fixing gotos to labels inside cases... */
04699    /* I guess this would be considered 2nd pass of compiler now... */
04700    fix_gotos_in_extensions(exten_list); /* find and fix extension ref in gotos to labels that are in case statements */
04701    add_extensions(exten_list);   /* actually makes calls to create priorities in ast_contexts -- feeds dialplan to asterisk */
04702    destroy_extensions(exten_list);  /* all that remains is an empty husk, discard of it as is proper */
04703    
04704    return 0;
04705 }

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 
)

Definition at line 2138 of file pval.c.

References app, ast_log(), pval::endline, pval::filename, LOG_WARNING, pval::next, pval::startline, pval::str, and pval::u1.

02139 {
02140 #ifdef AAL_ARGCHECK
02141    struct argdesc *ad = app->args;
02142    pval *pa;
02143    int z;
02144    
02145    for (pa = arglist; pa; pa=pa->next) {
02146       if (!ad) {
02147          ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Extra argument %s not in application call to %s !\n",
02148                arglist->filename, arglist->startline, arglist->endline, pa->u1.str, app->name);
02149          warns++;
02150          return 1;
02151       } else {
02152          /* find the first entry in the ad list that will match */
02153          do {
02154             if ( ad->dtype == ARGD_VARARG ) /* once we hit the VARARG, all bets are off. Discontinue the comparisons */
02155                break;
02156             
02157             z= option_matches( ad, pa, app);
02158             if (!z) {
02159                if ( !arglist )
02160                   arglist=appcall;
02161                
02162                if (ad->type == ARGD_REQUIRED) {
02163                   ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n",
02164                         arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name);
02165                   warns++;
02166                   return 1;
02167                }
02168             } else if (z && ad->dtype == ARGD_OPTIONSET) {
02169                option_matches_j( ad, pa, app);
02170             }
02171             ad = ad->next;
02172          } while (ad && !z);
02173       }
02174    }
02175    /* any app nodes left, that are not optional? */
02176    for ( ; ad; ad=ad->next) {
02177       if (ad->type == ARGD_REQUIRED && ad->dtype != ARGD_VARARG) {
02178          if ( !arglist ) 
02179             arglist=appcall;
02180          ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n",
02181                arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name);
02182          warns++;
02183          return 1;
02184       }
02185    }
02186    return 0;
02187 #else
02188    return 0;
02189 #endif
02190 }

void check_pval ( pval item,
struct argapp apps,
int  in_globals 
)

Definition at line 2873 of file pval.c.

References check_pval_item(), and pval::next.

02874 {
02875    pval *i;
02876 
02877    /* checks to do:
02878       1. Do goto's point to actual labels? 
02879       2. Do macro calls reference a macro?
02880       3. Does the number of macro args match the definition?
02881       4. Is a macro call missing its & at the front?
02882       5. Application calls-- we could check syntax for existing applications,
02883          but I need some some sort of universal description bnf for a general
02884         sort of method for checking arguments, in number, maybe even type, at least. 
02885         Don't want to hand code checks for hundreds of applications.
02886    */
02887    
02888    for (i=item; i; i=i->next) {
02889       check_pval_item(i,apps,in_globals);
02890    }
02891 }

void check_pval_item ( pval item,
struct argapp apps,
int  in_globals 
)

Definition at line 2365 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(), current_context, current_extension, 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, 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.

02366 {
02367    pval *lp;
02368 #ifdef AAL_ARGCHECK
02369    struct argapp *app, *found;
02370 #endif
02371    struct pval *macro_def;
02372    struct pval *app_def;
02373 
02374    char errmsg[4096];
02375    char *strp;
02376    
02377    switch (item->type) {
02378    case PV_WORD:
02379       /* fields: item->u1.str == string associated with this (word).
02380                  item->u2.arglist  == pval list of 4 PV_WORD elements for time values (only in PV_INCLUDES) */
02381       break;
02382       
02383    case PV_MACRO:
02384       /* fields: item->u1.str     == name of macro
02385                  item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
02386                item->u2.arglist->u1.str  == argument
02387                item->u2.arglist->next   == next arg
02388 
02389                item->u3.macro_statements == pval list of statements in macro body.
02390       */
02391       in_abstract_context = 0;
02392       current_context = item;
02393       current_extension = 0;
02394 
02395       check_macro_returns(item);
02396       
02397       for (lp=item->u2.arglist; lp; lp=lp->next) {
02398       
02399       }
02400       check_pval(item->u3.macro_statements, apps,in_globals);
02401       break;
02402          
02403    case PV_CONTEXT:
02404       /* fields: item->u1.str     == name of context
02405                  item->u2.statements == pval list of statements in context body
02406                item->u3.abstract == int 1 if an abstract keyword were present
02407       */
02408       current_context = item;
02409       current_extension = 0;
02410       if ( item->u3.abstract ) {
02411          in_abstract_context = 1;
02412          check_abstract_reference(item);
02413       } else
02414          in_abstract_context = 0;
02415       check_pval(item->u2.statements, apps,in_globals);
02416       break;
02417          
02418    case PV_MACRO_CALL:
02419       /* fields: item->u1.str     == name of macro to call
02420                  item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
02421                item->u2.arglist->u1.str  == argument
02422                item->u2.arglist->next   == next arg
02423       */
02424 #ifdef STANDALONE
02425       /* if this is a standalone, we will need to make sure the 
02426          localized load of extensions.conf is done */
02427       if (!extensions_dot_conf_loaded) {
02428          localized_pbx_load_module();
02429          extensions_dot_conf_loaded++;
02430       }
02431 #endif
02432       macro_def = find_macro(item->u1.str);
02433       if (!macro_def) {
02434 #ifdef STANDALONE
02435          struct pbx_find_info pfiq = {.stacklen = 0 };
02436          struct pbx_find_info pfiq2 = {.stacklen = 0 };
02437 
02438          /* look for the macro in the extensions.conf world */
02439          pbx_find_extension(NULL, NULL, &pfiq, item->u1.str, "s", 1, NULL, NULL, E_MATCH);
02440          
02441          if (pfiq.status != STATUS_SUCCESS) {
02442             char namebuf2[256];
02443             snprintf(namebuf2, 256, "macro-%s", item->u1.str);
02444             
02445             /* look for the macro in the extensions.conf world */
02446             pbx_find_extension(NULL, NULL, &pfiq2, namebuf2, "s", 1, NULL, NULL, E_MATCH);
02447             
02448             if (pfiq2.status == STATUS_SUCCESS) {
02449                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",
02450                      item->filename, item->startline, item->endline, item->u1.str, item->u1.str);
02451                warns++;
02452             } else {
02453                ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to non-existent %s! (Not even in the extensions.conf stuff!)\n",
02454                      item->filename, item->startline, item->endline, item->u1.str);
02455                warns++;
02456             }
02457          }
02458 #else
02459          ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to %s cannot be found in the AEL code!\n",
02460                item->filename, item->startline, item->endline, item->u1.str);
02461          warns++;
02462          
02463 #endif
02464 #ifdef THIS_IS_1DOT4
02465          char namebuf2[256];
02466          snprintf(namebuf2, 256, "macro-%s", item->u1.str);
02467 
02468          /* look for the macro in the extensions.conf world */
02469          pbx_find_extension(NULL, NULL, &pfiq, namebuf2, "s", 1, NULL, NULL, E_MATCH);
02470          
02471          if (pfiq.status != STATUS_SUCCESS) {
02472             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",
02473                   item->filename, item->startline, item->endline, item->u1.str);
02474             warns++;
02475          }
02476          
02477 #endif
02478 
02479       } else if (macro_def->type != PV_MACRO) {
02480          ast_log(LOG_ERROR,"Error: file %s, line %d-%d: macro call to %s references a context, not a macro!\n",
02481                item->filename, item->startline, item->endline, item->u1.str);
02482          errs++;
02483       } else {
02484          /* macro_def is a MACRO, so do the args match in number? */
02485          int hereargs = 0;
02486          int thereargs = 0;
02487          
02488          for (lp=item->u2.arglist; lp; lp=lp->next) {
02489             hereargs++;
02490          }
02491          for (lp=macro_def->u2.arglist; lp; lp=lp->next) {
02492             thereargs++;
02493          }
02494          if (hereargs != thereargs ) {
02495             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",
02496                   item->filename, item->startline, item->endline, item->u1.str, hereargs, thereargs);
02497             errs++;
02498          }
02499       }
02500       break;
02501          
02502    case PV_APPLICATION_CALL:
02503       /* fields: item->u1.str     == name of application to call
02504                  item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
02505                item->u2.arglist->u1.str  == argument
02506                item->u2.arglist->next   == next arg
02507       */
02508       /* Need to check to see if the application is available! */
02509       app_def = find_context(item->u1.str);
02510       if (app_def && app_def->type == PV_MACRO) {
02511          ast_log(LOG_ERROR,"Error: file %s, line %d-%d: application call to %s references an existing macro, but had no & preceding it!\n",
02512                item->filename, item->startline, item->endline, item->u1.str);
02513          errs++;
02514       }
02515       if (strcasecmp(item->u1.str,"GotoIf") == 0
02516          || strcasecmp(item->u1.str,"GotoIfTime") == 0
02517          || strcasecmp(item->u1.str,"while") == 0
02518          || strcasecmp(item->u1.str,"endwhile") == 0
02519          || strcasecmp(item->u1.str,"random") == 0
02520          || strcasecmp(item->u1.str,"gosub") == 0
02521          || strcasecmp(item->u1.str,"gosubif") == 0
02522          || strcasecmp(item->u1.str,"continuewhile") == 0
02523          || strcasecmp(item->u1.str,"endwhile") == 0
02524          || strcasecmp(item->u1.str,"execif") == 0
02525          || strcasecmp(item->u1.str,"execiftime") == 0
02526          || strcasecmp(item->u1.str,"exitwhile") == 0
02527          || strcasecmp(item->u1.str,"goto") == 0
02528          || strcasecmp(item->u1.str,"macro") == 0
02529          || strcasecmp(item->u1.str,"macroexclusive") == 0
02530          || strcasecmp(item->u1.str,"macroif") == 0
02531          || strcasecmp(item->u1.str,"stackpop") == 0
02532          || strcasecmp(item->u1.str,"execIf") == 0 ) {
02533          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",
02534                item->filename, item->startline, item->endline, item->u1.str);
02535          warns++;
02536       }
02537       if (strcasecmp(item->u1.str,"macroexit") == 0) {
02538             ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: I am converting the MacroExit call here to a return statement.\n",
02539                   item->filename, item->startline, item->endline);
02540             item->type = PV_RETURN;
02541             free(item->u1.str);
02542             item->u1.str = 0;
02543       }
02544       
02545 #ifdef AAL_ARGCHECK
02546       found = 0;
02547       for (app=apps; app; app=app->next) {
02548          if (strcasecmp(app->name, item->u1.str) == 0) {
02549             found =app;
02550             break;
02551          }
02552       }
02553       if (!found) {
02554          ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: application call to %s not listed in applist database!\n",
02555                item->filename, item->startline, item->endline, item->u1.str);
02556          warns++;
02557       } else
02558          check_app_args(item, item->u2.arglist, app);
02559 #endif
02560       break;
02561       
02562    case PV_CASE:
02563       /* fields: item->u1.str     == value of case
02564                  item->u2.statements == pval list of statements under the case
02565       */
02566       /* Make sure sequence of statements under case is terminated with  goto, return, or break */
02567       /* find the last statement */
02568       check_pval(item->u2.statements, apps,in_globals);
02569       break;
02570          
02571    case PV_PATTERN:
02572       /* fields: item->u1.str     == value of case
02573                  item->u2.statements == pval list of statements under the case
02574       */
02575       /* Make sure sequence of statements under case is terminated with  goto, return, or break */
02576       /* find the last statement */
02577       
02578       check_pval(item->u2.statements, apps,in_globals);
02579       break;
02580          
02581    case PV_DEFAULT:
02582       /* fields: 
02583                  item->u2.statements == pval list of statements under the case
02584       */
02585 
02586       check_pval(item->u2.statements, apps,in_globals);
02587       break;
02588          
02589    case PV_CATCH:
02590       /* fields: item->u1.str     == name of extension to catch
02591                  item->u2.statements == pval list of statements in context body
02592       */
02593       check_pval(item->u2.statements, apps,in_globals);
02594       break;
02595          
02596    case PV_SWITCHES:
02597       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
02598       */
02599       check_pval(item->u1.list, apps,in_globals);
02600       break;
02601          
02602    case PV_ESWITCHES:
02603       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
02604       */
02605       check_pval(item->u1.list, apps,in_globals);
02606       break;
02607          
02608    case PV_INCLUDES:
02609       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
02610       */
02611       check_pval(item->u1.list, apps,in_globals);
02612       check_includes(item);
02613       for (lp=item->u1.list; lp; lp=lp->next){
02614          char *incl_context = lp->u1.str;
02615          struct pval *that_context = find_context(incl_context);
02616 
02617          if ( lp->u2.arglist ) {
02618             check_timerange(lp->u2.arglist);
02619             check_dow(lp->u2.arglist->next);
02620             check_day(lp->u2.arglist->next->next);
02621             check_month(lp->u2.arglist->next->next->next);
02622          }
02623          
02624          if (that_context) {
02625             find_pval_gotos(that_context->u2.statements,0);
02626             
02627          }
02628       }
02629       break;
02630          
02631    case PV_STATEMENTBLOCK:
02632       /* fields: item->u1.list     == pval list of statements in block, one per entry in the list
02633       */
02634       check_pval(item->u1.list, apps,in_globals);
02635       break;
02636          
02637    case PV_VARDEC:
02638       /* fields: item->u1.str     == variable name
02639                  item->u2.val     == variable value to assign
02640       */
02641       /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */
02642       if( !in_globals ) { /* don't check stuff inside the globals context; no wrapping in $[ ] there... */
02643          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);
02644          ast_expr_register_extra_error_info(errmsg);
02645          ast_expr(item->u2.val, expr_output, sizeof(expr_output),NULL);
02646          ast_expr_clear_extra_error_info();
02647          if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) {
02648             ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
02649                   item->filename, item->startline, item->endline, item->u2.val);
02650             warns++;
02651          }
02652          check_expr2_input(item,item->u2.val);
02653       }
02654       break;
02655          
02656    case PV_LOCALVARDEC:
02657       /* fields: item->u1.str     == variable name
02658                  item->u2.val     == variable value to assign
02659       */
02660       /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */
02661       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);
02662       ast_expr_register_extra_error_info(errmsg);
02663       ast_expr(item->u2.val, expr_output, sizeof(expr_output),NULL);
02664       ast_expr_clear_extra_error_info();
02665       if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) {
02666          ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
02667                item->filename, item->startline, item->endline, item->u2.val);
02668          warns++;
02669       }
02670       check_expr2_input(item,item->u2.val);
02671       break;
02672          
02673    case PV_GOTO:
02674       /* fields: item->u1.list     == pval list of PV_WORD target names, up to 3, in order as given by user.
02675                  item->u1.list->u1.str  == where the data on a PV_WORD will always be.
02676       */
02677       /* don't check goto's in abstract contexts */
02678       if ( in_abstract_context )
02679          break;
02680       
02681       check_goto(item);
02682       break;
02683          
02684    case PV_LABEL:
02685       /* fields: item->u1.str     == label name
02686       */
02687       if ( strspn(item->u1.str, "0123456789") == strlen(item->u1.str) ) {
02688          ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: label '%s' is numeric, this is bad practice!\n",
02689                item->filename, item->startline, item->endline, item->u1.str);
02690          warns++;
02691       }
02692 
02693       check_label(item);
02694       break;
02695          
02696    case PV_FOR:
02697       /* fields: item->u1.for_init     == a string containing the initalizer
02698                  item->u2.for_test     == a string containing the loop test
02699                  item->u3.for_inc      == a string containing the loop increment
02700 
02701                item->u4.for_statements == a pval list of statements in the for ()
02702       */
02703       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);
02704       ast_expr_register_extra_error_info(errmsg);
02705 
02706       strp = strchr(item->u1.for_init, '=');
02707       if (strp) {
02708          ast_expr(strp+1, expr_output, sizeof(expr_output),NULL);
02709       }
02710       ast_expr(item->u2.for_test, expr_output, sizeof(expr_output),NULL);
02711       strp = strchr(item->u3.for_inc, '=');
02712       if (strp) {
02713          ast_expr(strp+1, expr_output, sizeof(expr_output),NULL);
02714       }
02715       if ( strpbrk(item->u2.for_test,"~!-+<>=*/&^") && !strstr(item->u2.for_test,"${") ) {
02716          ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
02717                item->filename, item->startline, item->endline, item->u2.for_test);
02718          warns++;
02719       }
02720       if ( strpbrk(item->u3.for_inc,"~!-+<>=*/&^") && !strstr(item->u3.for_inc,"${") ) {
02721          ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
02722                item->filename, item->startline, item->endline, item->u3.for_inc);
02723          warns++;
02724       }
02725       check_expr2_input(item,item->u2.for_test);
02726       check_expr2_input(item,item->u3.for_inc);
02727       
02728       ast_expr_clear_extra_error_info();
02729       check_pval(item->u4.for_statements, apps,in_globals);
02730       break;
02731          
02732    case PV_WHILE:
02733       /* fields: item->u1.str        == the while conditional, as supplied by user
02734 
02735                item->u2.statements == a pval list of statements in the while ()
02736       */
02737       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);
02738       ast_expr_register_extra_error_info(errmsg);
02739       ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL);
02740       ast_expr_clear_extra_error_info();
02741       if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) {
02742          ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
02743                item->filename, item->startline, item->endline, item->u1.str);
02744          warns++;
02745       }
02746       check_expr2_input(item,item->u1.str);
02747       check_pval(item->u2.statements, apps,in_globals);
02748       break;
02749          
02750    case PV_BREAK:
02751       /* fields: none
02752       */
02753       check_break(item);
02754       break;
02755          
02756    case PV_RETURN:
02757       /* fields: none
02758       */
02759       break;
02760          
02761    case PV_CONTINUE:
02762       /* fields: none
02763       */
02764       check_continue(item);
02765       break;
02766          
02767    case PV_RANDOM:
02768       /* fields: item->u1.str        == the random number expression, as supplied by user
02769 
02770                item->u2.statements == a pval list of statements in the if ()
02771                item->u3.else_statements == a pval list of statements in the else
02772                                     (could be zero)
02773       */
02774       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);
02775       ast_expr_register_extra_error_info(errmsg);
02776       ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL);
02777       ast_expr_clear_extra_error_info();
02778       if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) {
02779          ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: random expression '%s' has operators, but no variables. Interesting...\n",
02780                item->filename, item->startline, item->endline, item->u1.str);
02781          warns++;
02782       }
02783       check_expr2_input(item,item->u1.str);
02784       check_pval(item->u2.statements, apps,in_globals);
02785       if (item->u3.else_statements) {
02786          check_pval(item->u3.else_statements, apps,in_globals);
02787       }
02788       break;
02789 
02790    case PV_IFTIME:
02791       /* fields: item->u1.list        == the if time values, 4 of them, each in PV_WORD, linked list 
02792 
02793                item->u2.statements == a pval list of statements in the if ()
02794                item->u3.else_statements == a pval list of statements in the else
02795                                     (could be zero)
02796       */
02797       if ( item->u2.arglist ) {
02798          check_timerange(item->u1.list);
02799          check_dow(item->u1.list->next);
02800          check_day(item->u1.list->next->next);
02801          check_month(item->u1.list->next->next->next);
02802       }
02803 
02804       check_pval(item->u2.statements, apps,in_globals);
02805       if (item->u3.else_statements) {
02806          check_pval(item->u3.else_statements, apps,in_globals);
02807       }
02808       break;
02809          
02810    case PV_IF:
02811       /* fields: item->u1.str        == the if conditional, as supplied by user
02812 
02813                item->u2.statements == a pval list of statements in the if ()
02814                item->u3.else_statements == a pval list of statements in the else
02815                                     (could be zero)
02816       */
02817       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);
02818       ast_expr_register_extra_error_info(errmsg);
02819       ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL);
02820       ast_expr_clear_extra_error_info();
02821       if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) {
02822          ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression '%s' has operators, but no variables. Interesting...\n",
02823                item->filename, item->startline, item->endline, item->u1.str);
02824          warns++;
02825       }
02826       check_expr2_input(item,item->u1.str);
02827       check_pval(item->u2.statements, apps,in_globals);
02828       if (item->u3.else_statements) {
02829          check_pval(item->u3.else_statements, apps,in_globals);
02830       }
02831       break;
02832          
02833    case PV_SWITCH:
02834       /* fields: item->u1.str        == the switch expression
02835 
02836                item->u2.statements == a pval list of statements in the switch, 
02837                                     (will be case statements, most likely!)
02838       */
02839       /* we can check the switch expression, see if it matches any of the app variables...
02840            if it does, then, are all the possible cases accounted for? */
02841       check_switch_expr(item, apps);
02842       check_pval(item->u2.statements, apps,in_globals);
02843       break;
02844          
02845    case PV_EXTENSION:
02846       /* fields: item->u1.str        == the extension name, label, whatever it's called
02847 
02848                item->u2.statements == a pval list of statements in the extension
02849                item->u3.hints      == a char * hint argument
02850                item->u4.regexten   == an int boolean. non-zero says that regexten was specified
02851       */
02852       current_extension = item ;
02853       
02854       check_pval(item->u2.statements, apps,in_globals);
02855       break;
02856          
02857    case PV_IGNOREPAT:
02858       /* fields: item->u1.str        == the ignorepat data
02859       */
02860       break;
02861          
02862    case PV_GLOBALS:
02863       /* fields: item->u1.statements     == pval list of statements, usually vardecs
02864       */
02865       in_abstract_context = 0;
02866       check_pval(item->u1.statements, apps, 1);
02867       break;
02868    default:
02869       break;
02870    }
02871 }

void check_switch_expr ( pval item,
struct argapp apps 
)

Definition at line 2192 of file pval.c.

References ast_strdupa, argapp::next, pval::str, and pval::u1.

02193 {
02194 #ifdef AAL_ARGCHECK
02195    /* get and clean the variable name */
02196    char *buff1, *p;
02197    struct argapp *a,*a2;
02198    struct appsetvar *v,*v2;
02199    struct argchoice *c;
02200    pval *t;
02201    
02202    p = item->u1.str;
02203    while (p && *p && (*p == ' ' || *p == '\t' || *p == '$' || *p == '{' ) )
02204       p++;
02205    
02206    buff1 = ast_strdupa(p);
02207 
02208    while (strlen(buff1) > 0 && ( buff1[strlen(buff1)-1] == '}' || buff1[strlen(buff1)-1] == ' ' || buff1[strlen(buff1)-1] == '\t'))
02209       buff1[strlen(buff1)-1] = 0;
02210    /* buff1 now contains the variable name */
02211    v = 0;
02212    for (a=apps; a; a=a->next) {
02213       for (v=a->setvars;v;v=v->next) {
02214          if (strcmp(v->name,buff1) == 0) {
02215             break;
02216          }
02217       }
02218       if ( v )
02219          break;
02220    }
02221    if (v && v->vals) {
02222       /* we have a match, to a variable that has a set of determined values */
02223       int def= 0;
02224       int pat = 0;
02225       int f1 = 0;
02226       
02227       /* first of all, does this switch have a default case ? */
02228       for (t=item->u2.statements; t; t=t->next) {
02229          if (t->type == PV_DEFAULT) {
02230             def =1;
02231             break;
02232          }
02233          if (t->type == PV_PATTERN) {
02234             pat++;
02235          }
02236       }
02237       if (def || pat) /* nothing to check. All cases accounted for! */
02238          return;
02239       for (c=v->vals; c; c=c->next) {
02240          f1 = 0;
02241          for (t=item->u2.statements; t; t=t->next) {
02242             if (t->type == PV_CASE || t->type == PV_PATTERN) {
02243                if (!strcmp(t->u1.str,c->name)) {
02244                   f1 = 1;
02245                   break;
02246                }
02247             }
02248          }
02249          if (!f1) {
02250             ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: switch with expression(%s) does not handle the case of %s !\n",
02251                   item->filename, item->startline, item->endline, item->u1.str, c->name);
02252             warns++;
02253          }
02254       }
02255       /* next, is there an app call in the current exten, that would set this var? */
02256       f1 = 0;
02257       t = current_extension->u2.statements;
02258       if ( t && t->type == PV_STATEMENTBLOCK )
02259          t = t->u1.statements;
02260       for (; t && t != item; t=t->next) {
02261          if (t->type == PV_APPLICATION_CALL) {
02262             /* find the application that matches the u1.str */
02263             for (a2=apps; a2; a2=a2->next) {
02264                if (strcasecmp(a2->name, t->u1.str)==0) {
02265                   for (v2=a2->setvars; v2; v2=v2->next) {
02266                      if (strcmp(v2->name, buff1) == 0) {
02267                         /* found an app that sets the var */
02268                         f1 = 1;
02269                         break;
02270                      }
02271                   }
02272                }
02273                if (f1)
02274                   break;
02275             }
02276          }
02277          if (f1)
02278             break;
02279       }
02280             
02281       /* see if it sets the var */
02282       if (!f1) {
02283          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",
02284                item->filename, item->startline, item->endline, item->u1.str);
02285          warns++;
02286       }
02287    }
02288 #else
02289    pval *t,*tl=0,*p2;
02290    int def= 0;
02291    
02292    /* first of all, does this switch have a default case ? */
02293    for (t=item->u2.statements; t; t=t->next) {
02294       if (t->type == PV_DEFAULT) {
02295          def =1;
02296          break;
02297       }
02298       tl = t;
02299    }
02300    if (def) /* nothing to check. All cases accounted for! */
02301       return;
02302    /* if no default, warn and insert a default case at the end */
02303    p2 = tl->next = calloc(1, sizeof(struct pval));
02304    
02305    p2->type = PV_DEFAULT;
02306    p2->startline = tl->startline;
02307    p2->endline = tl->endline;
02308    p2->startcol = tl->startcol;
02309    p2->endcol = tl->endcol;
02310    p2->filename = strdup(tl->filename);
02311    ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: A default case was automatically added to the switch.\n",
02312          p2->filename, p2->startline, p2->endline);
02313    warns++;
02314    
02315 #endif
02316 }

void destroy_extensions ( struct ael_extension exten  ) 

Definition at line 2986 of file pval.c.

References ael_priority::app, ael_priority::appargs, exten, free, ael_priority::goto_false, ael_priority::goto_true, ael_extension::hints, ael_extension::loop_break, ael_extension::loop_continue, ael_extension::name, ael_priority::next, ael_extension::next_exten, ael_priority::origin, ael_extension::plist, and ael_extension::plist_last.

02987 {
02988    struct ael_extension *ne, *nen;
02989    for (ne=exten; ne; ne=nen) {
02990       struct ael_priority *pe, *pen;
02991       
02992       if (ne->name)
02993          free(ne->name);
02994       
02995       /* cidmatch fields are allocated with name, and freed when
02996          the name field is freed. Don't do a free for this field,
02997          unless you LIKE to see a crash! */
02998 
02999       if (ne->hints)
03000          free(ne->hints);
03001       
03002       for (pe=ne->plist; pe; pe=pen) {
03003          pen = pe->next;
03004          if (pe->app)
03005             free(pe->app);
03006          pe->app = 0;
03007          if (pe->appargs)
03008             free(pe->appargs);
03009          pe->appargs = 0;
03010          pe->origin = 0;
03011          pe->goto_true = 0;
03012          pe->goto_false = 0;
03013          free(pe);
03014       }
03015       nen = ne->next_exten;
03016       ne->next_exten = 0;
03017       ne->plist =0;
03018       ne->plist_last = 0;
03019       ne->next_exten = 0;
03020       ne->loop_break = 0;
03021       ne->loop_continue = 0;
03022       free(ne);
03023    }
03024 }

void destroy_pval ( pval item  ) 

Definition at line 4980 of file pval.c.

References destroy_pval_item(), and pval::next.

04981 {
04982    pval *i,*nxt;
04983    
04984    for (i=item; i; i=nxt) {
04985       nxt = i->next;
04986       
04987       destroy_pval_item(i);
04988    }
04989 }

void destroy_pval_item ( pval item  ) 

Definition at line 4712 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.

04713 {
04714    if (item == NULL) {
04715       ast_log(LOG_WARNING, "null item\n");
04716       return;
04717    }
04718 
04719    if (item->filename)
04720       free(item->filename);
04721    
04722    switch (item->type) {
04723    case PV_WORD:
04724       /* fields: item->u1.str == string associated with this (word). */
04725       if (item->u1.str )
04726          free(item->u1.str);
04727       if ( item->u2.arglist )
04728          destroy_pval(item->u2.arglist);
04729       break;
04730       
04731    case PV_MACRO:
04732       /* fields: item->u1.str     == name of macro
04733                  item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
04734                item->u2.arglist->u1.str  == argument
04735                item->u2.arglist->next   == next arg
04736 
04737                item->u3.macro_statements == pval list of statements in macro body.
04738       */
04739       destroy_pval(item->u2.arglist);
04740       if (item->u1.str )
04741          free(item->u1.str);
04742       destroy_pval(item->u3.macro_statements);
04743       break;
04744          
04745    case PV_CONTEXT:
04746       /* fields: item->u1.str     == name of context
04747                  item->u2.statements == pval list of statements in context body
04748                item->u3.abstract == int 1 if an abstract keyword were present
04749       */
04750       if (item->u1.str)
04751          free(item->u1.str);
04752       destroy_pval(item->u2.statements);
04753       break;
04754          
04755    case PV_MACRO_CALL:
04756       /* fields: item->u1.str     == name of macro to call
04757                  item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
04758                item->u2.arglist->u1.str  == argument
04759                item->u2.arglist->next   == next arg
04760       */
04761       if (item->u1.str)
04762          free(item->u1.str);
04763       destroy_pval(item->u2.arglist);
04764       break;
04765          
04766    case PV_APPLICATION_CALL:
04767       /* fields: item->u1.str     == name of application to call
04768                  item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
04769                item->u2.arglist->u1.str  == argument
04770                item->u2.arglist->next   == next arg
04771       */
04772       if (item->u1.str)
04773          free(item->u1.str);
04774       destroy_pval(item->u2.arglist);
04775       break;
04776          
04777    case PV_CASE:
04778       /* fields: item->u1.str     == value of case
04779                  item->u2.statements == pval list of statements under the case
04780       */
04781       if (item->u1.str)
04782          free(item->u1.str);
04783       destroy_pval(item->u2.statements);
04784       break;
04785          
04786    case PV_PATTERN:
04787       /* fields: item->u1.str     == value of case
04788                  item->u2.statements == pval list of statements under the case
04789       */
04790       if (item->u1.str)
04791          free(item->u1.str);
04792       destroy_pval(item->u2.statements);
04793       break;
04794          
04795    case PV_DEFAULT:
04796       /* fields: 
04797                  item->u2.statements == pval list of statements under the case
04798       */
04799       destroy_pval(item->u2.statements);
04800       break;
04801          
04802    case PV_CATCH:
04803       /* fields: item->u1.str     == name of extension to catch
04804                  item->u2.statements == pval list of statements in context body
04805       */
04806       if (item->u1.str)
04807          free(item->u1.str);
04808       destroy_pval(item->u2.statements);
04809       break;
04810          
04811    case PV_SWITCHES:
04812       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
04813       */
04814       destroy_pval(item->u1.list);
04815       break;
04816          
04817    case PV_ESWITCHES:
04818       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
04819       */
04820       destroy_pval(item->u1.list);
04821       break;
04822          
04823    case PV_INCLUDES:
04824       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
04825                  item->u2.arglist  == pval list of 4 PV_WORD elements for time values
04826       */
04827       destroy_pval(item->u1.list);
04828       break;
04829          
04830    case PV_STATEMENTBLOCK:
04831       /* fields: item->u1.list     == pval list of statements in block, one per entry in the list
04832       */
04833       destroy_pval(item->u1.list);
04834       break;
04835          
04836    case PV_LOCALVARDEC:
04837    case PV_VARDEC:
04838       /* fields: item->u1.str     == variable name
04839                  item->u2.val     == variable value to assign
04840       */
04841       if (item->u1.str)
04842          free(item->u1.str);
04843       if (item->u2.val)
04844          free(item->u2.val);
04845       break;
04846          
04847    case PV_GOTO:
04848       /* fields: item->u1.list     == pval list of PV_WORD target names, up to 3, in order as given by user.
04849                  item->u1.list->u1.str  == where the data on a PV_WORD will always be.
04850       */
04851       
04852       destroy_pval(item->u1.list);
04853       break;
04854          
04855    case PV_LABEL:
04856       /* fields: item->u1.str     == label name
04857       */
04858       if (item->u1.str)
04859          free(item->u1.str);
04860       break;
04861          
04862    case PV_FOR:
04863       /* fields: item->u1.for_init     == a string containing the initalizer
04864                  item->u2.for_test     == a string containing the loop test
04865                  item->u3.for_inc      == a string containing the loop increment
04866 
04867                item->u4.for_statements == a pval list of statements in the for ()
04868       */
04869       if (item->u1.for_init)
04870          free(item->u1.for_init);
04871       if (item->u2.for_test)
04872          free(item->u2.for_test);
04873       if (item->u3.for_inc)
04874          free(item->u3.for_inc);
04875       destroy_pval(item->u4.for_statements);
04876       break;
04877          
04878    case PV_WHILE:
04879       /* fields: item->u1.str        == the while conditional, as supplied by user
04880 
04881                item->u2.statements == a pval list of statements in the while ()
04882       */
04883       if (item->u1.str)
04884          free(item->u1.str);
04885       destroy_pval(item->u2.statements);
04886       break;
04887          
04888    case PV_BREAK:
04889       /* fields: none
04890       */
04891       break;
04892          
04893    case PV_RETURN:
04894       /* fields: none
04895       */
04896       break;
04897          
04898    case PV_CONTINUE:
04899       /* fields: none
04900       */
04901       break;
04902          
04903    case PV_IFTIME:
04904       /* fields: item->u1.list        == the 4 time values, in PV_WORD structs, linked list
04905 
04906                item->u2.statements == a pval list of statements in the if ()
04907                item->u3.else_statements == a pval list of statements in the else
04908                                     (could be zero)
04909       */
04910       destroy_pval(item->u1.list);
04911       destroy_pval(item->u2.statements);
04912       if (item->u3.else_statements) {
04913          destroy_pval(item->u3.else_statements);
04914       }
04915       break;
04916          
04917    case PV_RANDOM:
04918       /* fields: item->u1.str        == the random percentage, as supplied by user
04919 
04920                item->u2.statements == a pval list of statements in the true part ()
04921                item->u3.else_statements == a pval list of statements in the else
04922                                     (could be zero)
04923       fall thru to If */
04924    case PV_IF:
04925       /* fields: item->u1.str        == the if conditional, as supplied by user
04926 
04927                item->u2.statements == a pval list of statements in the if ()
04928                item->u3.else_statements == a pval list of statements in the else
04929                                     (could be zero)
04930       */
04931       if (item->u1.str)
04932          free(item->u1.str);
04933       destroy_pval(item->u2.statements);
04934       if (item->u3.else_statements) {
04935          destroy_pval(item->u3.else_statements);
04936       }
04937       break;
04938          
04939    case PV_SWITCH:
04940       /* fields: item->u1.str        == the switch expression
04941 
04942                item->u2.statements == a pval list of statements in the switch, 
04943                                     (will be case statements, most likely!)
04944       */
04945       if (item->u1.str)
04946          free(item->u1.str);
04947       destroy_pval(item->u2.statements);
04948       break;
04949          
04950    case PV_EXTENSION:
04951       /* fields: item->u1.str        == the extension name, label, whatever it's called
04952 
04953                item->u2.statements == a pval list of statements in the extension
04954                item->u3.hints      == a char * hint argument
04955                item->u4.regexten   == an int boolean. non-zero says that regexten was specified
04956       */
04957       if (item->u1.str)
04958          free(item->u1.str);
04959       if (item->u3.hints)
04960          free(item->u3.hints);
04961       destroy_pval(item->u2.statements);
04962       break;
04963          
04964    case PV_IGNOREPAT:
04965       /* fields: item->u1.str        == the ignorepat data
04966       */
04967       if (item->u1.str)
04968          free(item->u1.str);
04969       break;
04970          
04971    case PV_GLOBALS:
04972       /* fields: item->u1.statements     == pval list of statements, usually vardecs
04973       */
04974       destroy_pval(item->u1.statements);
04975       break;
04976    }
04977    free(item);
04978 }

struct pval* find_context ( char *  name  ) 

Definition at line 1961 of file pval.c.

References current_db, and match_pval().

01962 {
01963    return_on_context_match = 1;
01964    count_labels = 0;
01965    match_context = name;
01966    match_exten = "*";  /* don't really need to set these, shouldn't be reached */
01967    match_label = "*";
01968    return match_pval(current_db);
01969 }

struct pval* find_macro ( char *  name  ) 

Definition at line 1951 of file pval.c.

References current_db, and match_pval().

01952 {
01953    return_on_context_match = 1;
01954    count_labels = 0;
01955    match_context = name;
01956    match_exten = "*";  /* don't really need to set these, shouldn't be reached */
01957    match_label = "*";
01958    return match_pval(current_db);
01959 }

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  ) 

Definition at line 1989 of file pval.c.

01990 {
01991    if (!arg)
01992       return 1;
01993    if (*arg == 0)
01994       return 1;
01995    while (*arg) {
01996       if (*arg != ' ' && *arg != '\t')
01997          return 0;
01998       arg++;
01999    }
02000    return 1;
02001 }

int is_float ( char *  arg  ) 

Definition at line 1971 of file pval.c.

01972 {
01973    char *s;
01974    for (s=arg; *s; s++) {
01975       if (*s != '.' && (*s < '0' || *s > '9'))
01976          return 0;
01977    }
01978    return 1;
01979 }

int is_int ( char *  arg  ) 

Definition at line 1980 of file pval.c.

01981 {
01982    char *s;
01983    for (s=arg; *s; s++) {
01984       if (*s < '0' || *s > '9')
01985          return 0;
01986    }
01987    return 1;
01988 }

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, cli_ael, 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   ) 

Definition at line 2938 of file pval.c.

References calloc.

02939 {
02940    struct ael_extension *x = (struct ael_extension *)calloc(sizeof(struct ael_extension),1);
02941    return x;
02942 }

struct ael_priority* new_prio ( void   ) 

Definition at line 2932 of file pval.c.

References calloc.

02933 {
02934    struct ael_priority *x = (struct ael_priority *)calloc(sizeof(struct ael_priority),1);
02935    return x;
02936 }

static int pbx_load_module ( void   )  [static]

Definition at line 155 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, and LOG_NOTICE.

Referenced by handle_cli_ael_reload(), handle_cli_dialplan_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 = 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 4226 of file pval.c.

References exten, ael_priority::next, ael_priority::origin, ael_priority::priority_num, PV_LABEL, and pval::type.

04227 {
04228    int i;
04229    struct ael_priority *pr;
04230    do {
04231       if (exten->is_switch)
04232          i = 10;
04233       else if (exten->regexten)
04234          i=2;
04235       else
04236          i=1;
04237       
04238       for (pr=exten->plist; pr; pr=pr->next) {
04239          pr->priority_num = i;
04240          
04241          if (!pr->origin || (pr->origin && pr->origin->type != PV_LABEL) ) /* Labels don't show up in the dialplan,
04242                                       but we want them to point to the right
04243                                       priority, which would be the next line
04244                                       after the label; */
04245             i++;
04246       }
04247       
04248       exten = exten->next_exten;
04249    } while ( exten );
04250 }

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(), ast_unregister_application(), and cli_ael.

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 }


Variable Documentation

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]

Definition at line 303 of file pbx_ael.c.

int aeldebug = 0 [static]

Definition at line 128 of file pbx_ael.c.

char* aelsub = "AELSub" [static]

Definition at line 133 of file pbx_ael.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 303 of file pbx_ael.c.

struct ast_cli_entry cli_ael[] [static]

Initial value:

 {
   { .handler =  handle_cli_ael_reload , .summary =  "Reload AEL configuration" ,__VA_ARGS__ },
   { .handler =  handle_cli_ael_set_debug , .summary =  "Enable AEL debugging flags" ,__VA_ARGS__ }
}

Definition at line 260 of file pbx_ael.c.

Referenced by load_module(), and unload_module().

char* config = "extensions.ael" [static]

Definition at line 86 of file pbx_ael.c.

char* registrar = "pbx_ael" [static]

Definition at line 87 of file pbx_ael.c.


Generated on Mon Oct 8 12:39:26 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7