Mon Oct 8 12:39:26 2012

Asterisk developer's documentation


pval.c File Reference

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

#include "asterisk.h"
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <regex.h>
#include <sys/stat.h>
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/channel.h"
#include "asterisk/callerid.h"
#include "asterisk/pval.h"
#include "asterisk/ael_structs.h"
#include "asterisk/utils.h"

Go to the source code of this file.

Defines

#define AST_PBX_MAX_STACK   128
#define BUF_SIZE   2000

Functions

void add_extensions (struct ael_extension *exten)
void ael2_print (char *fname, pval *tree)
void ael2_semantic_check (pval *item, int *arg_errs, int *arg_warns, int *arg_notes)
int ast_compile_ael2 (struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root)
static void attach_exten (struct ael_extension **list, struct ael_extension *newmem)
static void check_abstract_reference (pval *abstract_context)
int check_app_args (pval *appcall, pval *arglist, struct argapp *app)
static int check_break (pval *item)
static void check_context_names (void)
static int check_continue (pval *item)
static void check_day (pval *DAY)
static void check_dow (pval *DOW)
 get_dow: Get day of week
static void check_expr2_input (pval *expr, char *str)
static void check_goto (pval *item)
static void check_includes (pval *includes)
static void check_label (pval *item)
static void check_macro_returns (pval *macro)
static void check_month (pval *MON)
void check_pval (pval *item, struct argapp *apps, int in_globals)
void check_pval_item (pval *item, struct argapp *apps, int in_globals)
void check_switch_expr (pval *item, struct argapp *apps)
static void check_timerange (pval *p)
int contains_switch (pval *item)
static int context_used (struct ael_extension *exten_list, struct ast_context *context)
void destroy_extensions (struct ael_extension *exten)
void destroy_pval (pval *item)
void destroy_pval_item (pval *item)
static int extension_matches (pval *here, const char *exten, const char *pattern)
pvalfind_context (char *name)
static struct pvalfind_first_label_in_current_context (char *label, pval *curr_cont)
static struct pvalfind_label_in_current_context (char *exten, char *label, pval *curr_cont)
static struct pvalfind_label_in_current_db (const char *context, const char *exten, const char *label)
static struct pvalfind_label_in_current_extension (const char *label, pval *curr_ext)
pvalfind_macro (char *name)
static void find_pval_goto_item (pval *item, int lev)
static void find_pval_gotos (pval *item, int lev)
int find_switch_item (pval *item)
static void fix_gotos_in_extensions (struct ael_extension *exten)
static void gen_match_to_pattern (char *pattern, char *result)
static int gen_prios (struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *this_context)
static pvalget_contxt (pval *p)
static pvalget_extension_or_contxt (pval *p)
static pvalget_goto_target (pval *item)
static struct pvalin_context (pval *item)
static struct pvalin_macro (pval *item)
int is_empty (char *arg)
int is_float (char *arg)
int is_int (char *arg)
static int label_inside_case (pval *label)
static void linkexten (struct ael_extension *exten, struct ael_extension *add)
void linkprio (struct ael_extension *exten, struct ael_priority *prio, struct ael_extension *mother_exten)
pvallinku1 (pval *head, pval *tail)
int localized_pbx_load_module (void)
pvalmatch_pval (pval *item)
static struct pvalmatch_pval_item (pval *item)
ael_extensionnew_exten (void)
ael_prioritynew_prio (void)
static void print_pval (FILE *fin, pval *item, int depth)
static void print_pval_list (FILE *fin, pval *item, int depth)
void pvalAppCallAddArg (pval *p, pval *arg)
char * pvalAppCallGetAppName (pval *p)
void pvalAppCallSetAppName (pval *p, char *name)
void pvalAppCallSetArglist (pval *p, pval *arglist)
pvalpvalAppCallWalkArgs (pval *p, pval **args)
void pvalCasePatDefAddStatement (pval *p, pval *statement)
pvalpvalCasePatDefWalkStatements (pval *p, pval **statement)
char * pvalCasePatGetVal (pval *p)
void pvalCasePatSetVal (pval *p, char *val)
char * pvalCatchGetExtName (pval *p)
pvalpvalCatchGetStatement (pval *p)
void pvalCatchSetExtName (pval *p, char *name)
void pvalCatchSetStatement (pval *p, pval *statement)
int pvalCheckType (pval *p, char *funcname, pvaltype type)
pvalpvalConditionalGetElseStatement (pval *p)
pvalpvalConditionalGetThenStatement (pval *p)
void pvalConditionalSetElseStatement (pval *p, pval *statement)
void pvalConditionalSetThenStatement (pval *p, pval *statement)
void pvalContextAddStatement (pval *p, pval *statement)
int pvalContextGetAbstract (pval *p)
char * pvalContextGetName (pval *p)
void pvalContextSetAbstract (pval *p)
void pvalContextSetName (pval *p, char *name)
void pvalContextUnsetAbstract (pval *p)
pvalpvalContextWalkStatements (pval *p, pval **statements)
pvalpvalCreateNode (pvaltype type)
void pvalESwitchesAddSwitch (pval *p, char *name)
char * pvalESwitchesWalkNames (pval *p, pval **next_item)
char * pvalExtenGetHints (pval *p)
char * pvalExtenGetName (pval *p)
int pvalExtenGetRegexten (pval *p)
pvalpvalExtenGetStatement (pval *p)
void pvalExtenSetHints (pval *p, char *hints)
void pvalExtenSetName (pval *p, char *name)
void pvalExtenSetRegexten (pval *p)
void pvalExtenSetStatement (pval *p, pval *statement)
void pvalExtenUnSetRegexten (pval *p)
char * pvalForGetInc (pval *p)
char * pvalForGetInit (pval *p)
pvalpvalForGetStatement (pval *p)
char * pvalForGetTest (pval *p)
void pvalForSetInc (pval *p, char *inc)
void pvalForSetInit (pval *p, char *init)
void pvalForSetStatement (pval *p, pval *statement)
void pvalForSetTest (pval *p, char *test)
void pvalGlobalsAddStatement (pval *p, pval *statement)
pvalpvalGlobalsWalkStatements (pval *p, pval **next_statement)
void pvalGotoGetTarget (pval *p, char **context, char **exten, char **label)
void pvalGotoSetTarget (pval *p, char *context, char *exten, char *label)
char * pvalIfGetCondition (pval *p)
void pvalIfSetCondition (pval *p, char *expr)
void pvalIfTimeGetCondition (pval *p, char **hour_range, char **dow_range, char **dom_range, char **month_range)
void pvalIfTimeSetCondition (pval *p, char *hour_range, char *dow_range, char *dom_range, char *mon_range)
char * pvalIgnorePatGetPattern (pval *p)
void pvalIgnorePatSetPattern (pval *p, char *pat)
void pvalIncludeGetTimeConstraints (pval *p, char **hour_range, char **dom_range, char **dow_range, char **month_range)
void pvalIncludesAddInclude (pval *p, const char *include)
void pvalIncludesAddIncludeWithTimeConstraints (pval *p, const char *include, char *hour_range, char *dom_range, char *dow_range, char *month_range)
char * pvalIncludesWalk (pval *p, pval **next_item)
char * pvalLabelGetName (pval *p)
void pvalLabelSetName (pval *p, char *name)
void pvalMacroAddArg (pval *p, pval *arg)
void pvalMacroAddStatement (pval *p, pval *statement)
void pvalMacroCallAddArg (pval *p, pval *arg)
char * pvalMacroCallGetMacroName (pval *p)
void pvalMacroCallSetArglist (pval *p, pval *arglist)
void pvalMacroCallSetMacroName (pval *p, char *name)
pvalpvalMacroCallWalkArgs (pval *p, pval **args)
char * pvalMacroGetName (pval *p)
void pvalMacroSetArglist (pval *p, pval *arglist)
void pvalMacroSetName (pval *p, char *name)
pvalpvalMacroWalkArgs (pval *p, pval **arg)
pvalpvalMacroWalkStatements (pval *p, pval **next_statement)
pvaltype pvalObjectGetType (pval *p)
char * pvalRandomGetCondition (pval *p)
void pvalRandomSetCondition (pval *p, char *percent)
void pvalStatementBlockAddStatement (pval *p, pval *statement)
pvalpvalStatementBlockWalkStatements (pval *p, pval **next_statement)
void pvalSwitchAddCase (pval *p, pval *Case)
void pvalSwitchesAddSwitch (pval *p, char *name)
char * pvalSwitchesWalkNames (pval *p, pval **next_item)
char * pvalSwitchGetTestexpr (pval *p)
void pvalSwitchSetTestexpr (pval *p, char *expr)
pvalpvalSwitchWalkCases (pval *p, pval **next_case)
void pvalTopLevAddObject (pval *p, pval *contextOrObj)
pvalpvalTopLevWalkObjects (pval *p, pval **next_obj)
char * pvalVarDecGetValue (pval *p)
char * pvalVarDecGetVarname (pval *p)
void pvalVarDecSetValue (pval *p, char *value)
void pvalVarDecSetVarname (pval *p, char *name)
char * pvalWordGetString (pval *p)
void pvalWordSetString (pval *p, char *str)
static void remove_spaces_before_equals (char *str)
void set_priorities (struct ael_extension *exten)
void traverse_pval_item_template (pval *item, int depth)
void traverse_pval_template (pval *item, int depth)

Variables

ast_flags ast_compat
static int control_statement_count = 0
static int count_labels
static pvalcurrent_context
static pvalcurrent_db
static pvalcurrent_extension
static char * days []
static int errs
static char expr_output [2096]
static int in_abstract_context
static int label_count
static pvallast_matched_label
static const char * match_context
static const char * match_exten
static const char * match_label
static char * months []
static int notes
static char * registrar = "pbx_ael"
static int return_on_context_match
static int warns


Detailed Description

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

Definition in file pval.c.


Define Documentation

#define AST_PBX_MAX_STACK   128

Definition at line 63 of file pval.c.

#define BUF_SIZE   2000

Definition at line 64 of file pval.c.


Function Documentation

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

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 }

void ael2_print ( char *  fname,
pval tree 
)

Definition at line 385 of file pval.c.

References ast_log(), LOG_ERROR, and print_pval_list().

00386 {
00387    FILE *fin = fopen(fname,"w");
00388    if ( !fin ) {
00389       ast_log(LOG_ERROR, "Couldn't open %s for writing.\n", fname);
00390       return;
00391    }
00392    print_pval_list(fin, tree, 0);
00393    fclose(fin);
00394 }

void ael2_semantic_check ( pval item,
int *  arg_errs,
int *  arg_warns,
int *  arg_notes 
)

Definition at line 2893 of file pval.c.

References ast_config_AST_VAR_DIR, check_context_names(), check_pval(), and current_db.

Referenced by pbx_load_module().

02894 {
02895    
02896 #ifdef AAL_ARGCHECK
02897    int argapp_errs =0;
02898    char *rfilename;
02899 #endif
02900    struct argapp *apps=0;
02901 
02902    if (!item)
02903       return; /* don't check an empty tree */
02904 #ifdef AAL_ARGCHECK
02905    rfilename = alloca(10 + strlen(ast_config_AST_VAR_DIR));
02906    sprintf(rfilename, "%s/applist", ast_config_AST_VAR_DIR);
02907    
02908    apps = argdesc_parse(rfilename, &argapp_errs); /* giveth */
02909 #endif
02910    current_db = item;
02911    errs = warns = notes = 0;
02912 
02913    check_context_names();
02914    check_pval(item, apps, 0);
02915 
02916 #ifdef AAL_ARGCHECK
02917    argdesc_destroy(apps);  /* taketh away */
02918 #endif
02919    current_db = 0;
02920 
02921    *arg_errs = errs;
02922    *arg_warns = warns;
02923    *arg_notes = notes;
02924 }

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 }

static void attach_exten ( struct ael_extension **  list,
struct ael_extension newmem 
) [static]

Definition at line 4357 of file pval.c.

References ael_extension::next_exten.

04358 {
04359    /* travel to the end of the list... */
04360    struct ael_extension *lptr;
04361    if( !*list ) {
04362       *list = newmem;
04363       return;
04364    }
04365    lptr = *list;
04366    
04367    while( lptr->next_exten ) {
04368       lptr = lptr->next_exten;
04369    }
04370    /* lptr should now pointing to the last element in the list; it has a null next_exten pointer */
04371    lptr->next_exten = newmem;
04372 }

static void check_abstract_reference ( pval abstract_context  )  [static]

Definition at line 2337 of file pval.c.

References current_db, pval::list, pval::next, PV_CONTEXT, PV_INCLUDES, pval::str, pval::type, pval::u1, and pval::u2.

Referenced by check_pval_item().

02338 {
02339    pval *i,*j;
02340    /* find some context includes that reference this context */
02341    
02342 
02343    /* otherwise, print out a warning */
02344    for (i=current_db; i; i=i->next) {
02345       if (i->type == PV_CONTEXT) {
02346          for (j=i->u2. statements; j; j=j->next) {
02347             if ( j->type == PV_INCLUDES ) {
02348                struct pval *p4;
02349                for (p4=j->u1.list; p4; p4=p4->next) {
02350                   /* for each context pointed to, find it, then find a context/label that matches the
02351                      target here! */
02352                   if ( !strcmp(p4->u1.str, abstract_context->u1.str) )
02353                      return; /* found a match! */
02354                }
02355             }
02356          }
02357       }
02358    }
02359    ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: Couldn't find a reference to this abstract context (%s) in any other context!\n",
02360          abstract_context->filename, abstract_context->startline, abstract_context->endline, abstract_context->u1.str);
02361    warns++;
02362 }

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 }

static int check_break ( pval item  )  [static]

Definition at line 1046 of file pval.c.

References ast_log(), pval::dad, pval::endline, pval::filename, LOG_ERROR, PV_CASE, PV_CONTEXT, PV_DEFAULT, PV_FOR, PV_MACRO, PV_PATTERN, PV_WHILE, pval::startline, and pval::type.

Referenced by check_pval_item().

01047 {
01048    pval *p = item;
01049    
01050    while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ {
01051       /* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make
01052          no sense */
01053       if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN 
01054          || p->type == PV_WHILE || p->type == PV_FOR   ) {
01055          return 1;
01056       }
01057       p = p->dad;
01058    }
01059    ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'break' not in switch, for, or while statement!\n",
01060          item->filename, item->startline, item->endline);
01061    errs++;
01062    
01063    return 0;
01064 }

static void check_context_names ( void   )  [static]

Definition at line 2318 of file pval.c.

References pval::abstract, ast_log(), current_db, pval::endline, pval::filename, LOG_WARNING, pval::next, PV_CONTEXT, PV_MACRO, pval::startline, pval::str, pval::type, pval::u1, and pval::u3.

Referenced by ael2_semantic_check().

02319 {
02320    pval *i,*j;
02321    for (i=current_db; i; i=i->next) {
02322       if (i->type == PV_CONTEXT || i->type == PV_MACRO) {
02323          for (j=i->next; j; j=j->next) {
02324             if ( j->type == PV_CONTEXT || j->type == PV_MACRO ) {
02325                if ( !strcmp(i->u1.str, j->u1.str) && !(i->u3.abstract&2) && !(j->u3.abstract&2) )
02326                {
02327                   ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: The context name (%s) is also declared in file %s, line %d-%d! (and neither is marked 'extend')\n",
02328                         i->filename, i->startline, i->endline, i->u1.str,  j->filename, j->startline, j->endline);
02329                   warns++;
02330                }
02331             }
02332          }
02333       }
02334    }
02335 }

static int check_continue ( pval item  )  [static]

Definition at line 1066 of file pval.c.

References ast_log(), pval::dad, pval::endline, pval::filename, LOG_ERROR, PV_CONTEXT, PV_FOR, PV_MACRO, PV_WHILE, pval::startline, and pval::type.

Referenced by check_pval_item().

01067 {
01068    pval *p = item;
01069    
01070    while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ {
01071       /* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make
01072          no sense */
01073       if( p->type == PV_WHILE || p->type == PV_FOR   ) {
01074          return 1;
01075       }
01076       p = p->dad;
01077    }
01078    ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'continue' not in 'for' or 'while' statement!\n",
01079          item->filename, item->startline, item->endline);
01080    errs++;
01081    
01082    return 0;
01083 }

static void check_day ( pval DAY  )  [static]

Definition at line 945 of file pval.c.

References ast_log(), ast_strdupa, ast_strlen_zero(), pval::endline, pval::filename, LOG_WARNING, pval::startline, pval::str, and pval::u1.

Referenced by check_pval_item().

00946 {
00947    char *day;
00948    char *c;
00949    /* The following line is coincidence, really! */
00950    int s, e;
00951 
00952    day = ast_strdupa(DAY->u1.str);
00953 
00954    /* Check for all days */
00955    if (ast_strlen_zero(day) || !strcmp(day, "*")) {
00956       return;
00957    }
00958    /* Get start and ending days */
00959    c = strchr(day, '-');
00960    if (c) {
00961       *c = '\0';
00962       c++;
00963    }
00964    /* Find the start */
00965    if (sscanf(day, "%2d", &s) != 1) {
00966       ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start day of month (%s) must be a number!\n",
00967             DAY->filename, DAY->startline, DAY->endline, day);
00968       warns++;
00969    }
00970    else if ((s < 1) || (s > 31)) {
00971       ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start day of month (%s) must be a number in the range [1-31]!\n",
00972             DAY->filename, DAY->startline, DAY->endline, day);
00973       warns++;
00974    }
00975    s--;
00976    if (c) {
00977       if (sscanf(c, "%2d", &e) != 1) {
00978          ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end day of month (%s) must be a number!\n",
00979                DAY->filename, DAY->startline, DAY->endline, c);
00980          warns++;
00981       }
00982       else if ((e < 1) || (e > 31)) {
00983          ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end day of month (%s) must be a number in the range [1-31]!\n",
00984                DAY->filename, DAY->startline, DAY->endline, day);
00985          warns++;
00986       }
00987       e--;
00988    } else
00989       e = s;
00990 }

static void check_dow ( pval DOW  )  [static]

get_dow: Get day of week

Definition at line 906 of file pval.c.

References ast_log(), ast_strdupa, ast_strlen_zero(), pval::endline, pval::filename, LOG_WARNING, pval::startline, pval::str, and pval::u1.

Referenced by check_pval_item().

00907 {
00908    char *dow;
00909    char *c;
00910    /* The following line is coincidence, really! */
00911    int s, e;
00912    
00913    dow = ast_strdupa(DOW->u1.str);
00914 
00915    /* Check for all days */
00916    if (ast_strlen_zero(dow) || !strcmp(dow, "*"))
00917       return;
00918    /* Get start and ending days */
00919    c = strchr(dow, '-');
00920    if (c) {
00921       *c = '\0';
00922       c++;
00923    } else
00924       c = NULL;
00925    /* Find the start */
00926    s = 0;
00927    while ((s < 7) && strcasecmp(dow, days[s])) s++;
00928    if (s >= 7) {
00929       ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The day (%s) must be one of 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', or 'sat'!\n",
00930             DOW->filename, DOW->startline, DOW->endline, dow);
00931       warns++;
00932    }
00933    if (c) {
00934       e = 0;
00935       while ((e < 7) && strcasecmp(c, days[e])) e++;
00936       if (e >= 7) {
00937          ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end day (%s) must be one of 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', or 'sat'!\n",
00938                DOW->filename, DOW->startline, DOW->endline, c);
00939          warns++;
00940       }
00941    } else
00942       e = s;
00943 }

static void check_expr2_input ( pval expr,
char *  str 
) [static]

Definition at line 809 of file pval.c.

References ast_log(), pval::endline, pval::filename, LOG_WARNING, and pval::startline.

Referenced by check_pval_item().

00810 {
00811    int spaces = strspn(str,"\t \n");
00812    if ( !strncmp(str+spaces,"$[",2) ) {
00813       ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The expression '%s' is redundantly wrapped in '$[ ]'. \n",
00814             expr->filename, expr->startline, expr->endline, str);
00815       warns++;
00816    }
00817 }

static void check_goto ( pval item  )  [static]

Definition at line 1233 of file pval.c.

References ast_log(), E_FINDLABEL, E_MATCH, pval::endline, pval::filename, find_context(), find_label_in_current_context(), find_label_in_current_db(), find_label_in_current_extension(), first, get_contxt(), get_extension_or_contxt(), in_context(), in_macro(), pval::list, localized_pbx_load_module(), LOG_ERROR, LOG_WARNING, pval::next, pbx_find_extension(), PV_INCLUDES, pbx_find_info::stacklen, pval::startline, pval::statements, pbx_find_info::status, STATUS_SUCCESS, pval::str, pval::type, pval::u1, and pval::u2.

Referenced by check_pval_item(), and find_pval_goto_item().

01234 {
01235    if (!item->u1.list) {
01236       return;
01237    }
01238 
01239    /* check for the target of the goto-- does it exist? */
01240    if ( !(item->u1.list)->next && !(item->u1.list)->u1.str ) {
01241       ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto:  empty label reference found!\n",
01242             item->filename, item->startline, item->endline);
01243       errs++;
01244    }
01245 
01246    /* just one item-- the label should be in the current extension */
01247    if (!item->u1.list->next && !strstr(item->u1.list->u1.str,"${")) {
01248       struct pval *z = get_extension_or_contxt(item);
01249       struct pval *x = 0;
01250       if (z)
01251          x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), z); /* if in macro, use current context instead */
01252       /* printf("Called find_label_in_current_extension with arg %s; current_extension is %x: %d\n",
01253          (char*)((item->u1.list)->u1.str), current_extension?current_extension:current_context, current_extension?current_extension->type:current_context->type); */
01254       if (!x) {
01255          ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto:  no label %s exists in the current extension!\n",
01256                item->filename, item->startline, item->endline, item->u1.list->u1.str);
01257          errs++;
01258       }
01259       else
01260          return;
01261    }
01262    
01263    /* TWO items */
01264    if (item->u1.list->next && !item->u1.list->next->next) {
01265       /* two items */
01266       /* printf("Calling find_label_in_current_context with args %s, %s\n",
01267          (char*)((item->u1.list)->u1.str), (char *)item->u1.list->next->u1.str); */
01268       if (!strstr((item->u1.list)->u1.str,"${") 
01269          && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ {
01270          struct pval *z = get_contxt(item);
01271          struct pval *x = 0;
01272          
01273          if (z)
01274             x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, z);
01275 
01276          if (!x) {
01277             ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto:  no label '%s,%s' exists in the current context, or any of its inclusions!\n",
01278                   item->filename, item->startline, item->endline, item->u1.list->u1.str, item->u1.list->next->u1.str );
01279             errs++;
01280          }
01281          else
01282             return;
01283       }
01284    }
01285    
01286    /* All 3 items! */
01287    if (item->u1.list->next && item->u1.list->next->next) {
01288       /* all three */
01289       pval *first = item->u1.list;
01290       pval *second = item->u1.list->next;
01291       pval *third = item->u1.list->next->next;
01292       
01293       /* printf("Calling find_label_in_current_db with args %s, %s, %s\n",
01294          (char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); */
01295       if (!strstr((item->u1.list)->u1.str,"${") 
01296          && !strstr(item->u1.list->next->u1.str,"${")
01297          && !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ {
01298          struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str);
01299          if (!x) {
01300             struct pval *p3;
01301             struct pval *found = 0;
01302             struct pval *that_context = find_context(item->u1.list->u1.str);
01303             
01304             /* the target of the goto could be in an included context!! Fancy that!! */
01305             /* look for includes in the current context */
01306             if (that_context) {
01307                for (p3=that_context->u2.statements; p3; p3=p3->next) {
01308                   if (p3->type == PV_INCLUDES) {
01309                      struct pval *p4;
01310                      for (p4=p3->u1.list; p4; p4=p4->next) {
01311                         /* for each context pointed to, find it, then find a context/label that matches the
01312                            target here! */
01313                         char *incl_context = p4->u1.str;
01314                         /* find a matching context name */
01315                         struct pval *that_other_context = find_context(incl_context);
01316                         if (that_other_context) {
01317                            struct pval *x3;
01318                            x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context);
01319                            if (x3) {
01320                               found = x3;
01321                               break;
01322                            }
01323                         }
01324                      }
01325                   }
01326                }
01327                if (!found) {
01328                   ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto:  no label %s|%s exists in the context %s or its inclusions!\n",
01329                         item->filename, item->startline, item->endline, item->u1.list->next->u1.str, item->u1.list->next->next->u1.str, item->u1.list->u1.str );
01330                   errs++;
01331                } else {
01332                   struct pval *mac = in_macro(item); /* is this goto inside a macro? */
01333                   if( mac ) {    /* yes! */
01334                      struct pval *targ = in_context(found);
01335                      if( mac != targ )
01336                      {
01337                         ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: It's bad form to have a goto in a macro to a target outside the macro!\n",
01338                               item->filename, item->startline, item->endline);
01339                         warns++;                      
01340                      }
01341                   }
01342                }
01343             } else {
01344                /* here is where code would go to check for target existence in extensions.conf files */
01345 #ifdef STANDALONE
01346                struct pbx_find_info pfiq = {.stacklen = 0 };
01347                extern int localized_pbx_load_module(void);
01348                /* if this is a standalone, we will need to make sure the 
01349                   localized load of extensions.conf is done */
01350                if (!extensions_dot_conf_loaded) {
01351                   localized_pbx_load_module();
01352                   extensions_dot_conf_loaded++;
01353                }
01354 
01355                pbx_find_extension(NULL, NULL, &pfiq, first->u1.str, second->u1.str, atoi(third->u1.str),
01356                                  atoi(third->u1.str) ? NULL : third->u1.str, NULL, 
01357                                  atoi(third->u1.str) ? E_MATCH : E_FINDLABEL);
01358                
01359                if (pfiq.status != STATUS_SUCCESS) {
01360                   ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: goto:  Couldn't find goto target %s|%s|%s, not even in extensions.conf!\n",
01361                         item->filename, item->startline, item->endline, first->u1.str, second->u1.str, third->u1.str);
01362                   warns++;
01363                }
01364 #else
01365                ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: goto:  Couldn't find goto target %s|%s|%s in the AEL code!\n",
01366                      item->filename, item->startline, item->endline, first->u1.str, second->u1.str, third->u1.str);
01367                warns++;
01368 #endif
01369             }
01370          } else {
01371             struct pval *mac = in_macro(item); /* is this goto inside a macro? */
01372             if( mac ) {    /* yes! */
01373                struct pval *targ = in_context(x);
01374                if( mac != targ )
01375                {
01376                   ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: It's bad form to have a goto in a macro to a target outside the macro!\n",
01377                         item->filename, item->startline, item->endline);
01378                   warns++;                      
01379                }
01380             }
01381          }
01382       }
01383    }
01384 }

static void check_includes ( pval includes  )  [static]

Definition at line 819 of file pval.c.

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

Referenced by check_pval_item().

00820 {
00821    struct pval *p4;
00822    for (p4=includes->u1.list; p4; p4=p4->next) {
00823       /* for each context pointed to, find it, then find a context/label that matches the
00824          target here! */
00825       char *incl_context = p4->u1.str;
00826       /* find a matching context name */
00827       struct pval *that_other_context = find_context(incl_context);
00828       if (!that_other_context && strcmp(incl_context, "parkedcalls") != 0) {
00829          ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The included context '%s' cannot be found.\n\
00830  (You may ignore this warning if '%s' exists in extensions.conf, or is created by another module. I cannot check for those.)\n",
00831                includes->filename, includes->startline, includes->endline, incl_context, incl_context);
00832          warns++;
00833       }
00834    }
00835 }

static void check_label ( pval item  )  [static]

Definition at line 1114 of file pval.c.

References ast_log(), current_context, current_extension, pval::dad, pval::endline, pval::filename, find_first_label_in_current_context(), LOG_ERROR, PV_EXTENSION, PV_MACRO, pval::startline, pval::str, pval::type, and pval::u1.

Referenced by check_pval_item().

01115 {
01116    struct pval *curr;
01117    struct pval *x;
01118    int alright = 0;
01119    
01120    /* A label outside an extension just plain does not make sense! */
01121    
01122    curr = item;
01123    
01124    while( curr ) {
01125       if( curr->type == PV_MACRO || curr->type == PV_EXTENSION   ) {
01126          alright = 1;
01127          break;
01128       }
01129       curr = curr->dad;
01130    }
01131    if( !alright )
01132    {
01133       ast_log(LOG_ERROR,"Error: file %s, line %d-%d: Label %s is not within an extension or macro!\n",
01134             item->filename, item->startline, item->endline, item->u1.str);
01135       errs++;  
01136    }
01137    
01138    
01139    /* basically, ensure that a label is not repeated in a context. Period.
01140       The method:  well, for each label, find the first label in the context
01141       with the same name. If it's not the current label, then throw an error. */
01142 
01143    
01144    /* printf("==== check_label:   ====\n"); */
01145    if( !current_extension )
01146       curr = current_context;
01147    else
01148       curr = current_extension;
01149    
01150    x = find_first_label_in_current_context((char *)item->u1.str, curr);
01151    /* printf("Hey, check_label found with item = %x, and x is %x, and currcont is %x, label name is %s\n", item,x, current_context, (char *)item->u1.str); */
01152    if( x && x != item )
01153    {
01154       ast_log(LOG_ERROR,"Error: file %s, line %d-%d: Duplicate label %s! Previously defined at file %s, line %d.\n",
01155             item->filename, item->startline, item->endline, item->u1.str, x->filename, x->startline);
01156       errs++;
01157    }
01158    /* printf("<<<<< check_label:   ====\n"); */
01159 }

static void check_macro_returns ( pval macro  )  [static]

Definition at line 653 of file pval.c.

References ast_log(), calloc, pval::endcol, pval::endline, pval::filename, LOG_WARNING, pval::macro_statements, pval::next, PV_RETURN, pval::startcol, pval::startline, pval::str, strdup, pval::type, pval::u1, and pval::u3.

Referenced by check_pval_item().

00654 {
00655    pval *i;
00656    if (!macro->u3.macro_statements)
00657    {
00658       pval *z = calloc(1, sizeof(struct pval));
00659       ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The macro %s is empty! I will insert a return.\n",
00660             macro->filename, macro->startline, macro->endline, macro->u1.str);
00661 
00662       z->type = PV_RETURN;
00663       z->startline = macro->startline;
00664       z->endline = macro->endline;
00665       z->startcol = macro->startcol;
00666       z->endcol = macro->endcol;
00667       z->filename = strdup(macro->filename);
00668 
00669       macro->u3.macro_statements = z;
00670       return;
00671    }
00672    for (i=macro->u3.macro_statements; i; i=i->next) {
00673       /* if the last statement in the list is not return, then insert a return there */
00674       if (i->next == NULL) {
00675          if (i->type != PV_RETURN) {
00676             pval *z = calloc(1, sizeof(struct pval));
00677             ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The macro %s does not end with a return; I will insert one.\n",
00678                   macro->filename, macro->startline, macro->endline, macro->u1.str);
00679 
00680             z->type = PV_RETURN;
00681             z->startline = macro->startline;
00682             z->endline = macro->endline;
00683             z->startcol = macro->startcol;
00684             z->endcol = macro->endcol;
00685             z->filename = strdup(macro->filename);
00686 
00687             i->next = z;
00688             return;
00689          }
00690       }
00691    }
00692    return;
00693 }

static void check_month ( pval MON  )  [static]

Definition at line 1008 of file pval.c.

References ast_log(), ast_strdupa, ast_strlen_zero(), pval::endline, pval::filename, LOG_WARNING, pval::startline, pval::str, and pval::u1.

Referenced by check_pval_item().

01009 {
01010    char *mon;
01011    char *c;
01012    /* The following line is coincidence, really! */
01013    int s, e;
01014 
01015    mon = ast_strdupa(MON->u1.str);
01016 
01017    /* Check for all days */
01018    if (ast_strlen_zero(mon) || !strcmp(mon, "*")) 
01019       return ;
01020    /* Get start and ending days */
01021    c = strchr(mon, '-');
01022    if (c) {
01023       *c = '\0';
01024       c++;
01025    }
01026    /* Find the start */
01027    s = 0;
01028    while ((s < 12) && strcasecmp(mon, months[s])) s++;
01029    if (s >= 12) {
01030       ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n",
01031             MON->filename, MON->startline, MON->endline, mon);
01032       warns++;
01033    }
01034    if (c) {
01035       e = 0;
01036       while ((e < 12) && strcasecmp(mon, months[e])) e++;
01037       if (e >= 12) {
01038          ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n",
01039                MON->filename, MON->startline, MON->endline, c);
01040          warns++;
01041       }
01042    } else
01043       e = s;
01044 }

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 }

static void check_timerange ( pval p  )  [static]

Definition at line 838 of file pval.c.

References ast_log(), ast_strdupa, ast_strlen_zero(), pval::endline, pval::filename, LOG_WARNING, pval::startline, pval::str, and pval::u1.

Referenced by check_pval_item().

00839 {
00840    char *times;
00841    char *e;
00842    int s1, s2;
00843    int e1, e2;
00844 
00845    times = ast_strdupa(p->u1.str);
00846 
00847    /* Star is all times */
00848    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
00849       return;
00850    }
00851    /* Otherwise expect a range */
00852    e = strchr(times, '-');
00853    if (!e) {
00854       ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The time range format (%s) requires a '-' surrounded by two 24-hour times of day!\n",
00855             p->filename, p->startline, p->endline, times);
00856       warns++;
00857       return;
00858    }
00859    *e = '\0';
00860    e++;
00861    while (*e && !isdigit(*e)) 
00862       e++;
00863    if (!*e) {
00864       ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The time range format (%s) is missing the end time!\n",
00865             p->filename, p->startline, p->endline, p->u1.str);
00866       warns++;
00867    }
00868    if (sscanf(times, "%2d:%2d", &s1, &s2) != 2) {
00869       ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) isn't quite right!\n",
00870             p->filename, p->startline, p->endline, times);
00871       warns++;
00872    }
00873    if (sscanf(e, "%2d:%2d", &e1, &e2) != 2) {
00874       ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) isn't quite right!\n",
00875             p->filename, p->startline, p->endline, times);
00876       warns++;
00877    }
00878 
00879    s1 = s1 * 30 + s2/2;
00880    if ((s1 < 0) || (s1 >= 24*30)) {
00881       ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) is out of range!\n",
00882             p->filename, p->startline, p->endline, times);
00883       warns++;
00884    }
00885    e1 = e1 * 30 + e2/2;
00886    if ((e1 < 0) || (e1 >= 24*30)) {
00887       ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) is out of range!\n",
00888             p->filename, p->startline, p->endline, e);
00889       warns++;
00890    }
00891    return;
00892 }

int contains_switch ( pval item  ) 

Definition at line 3337 of file pval.c.

References find_switch_item(), and pval::next.

Referenced by find_switch_item(), and gen_prios().

03338 {
03339    pval *i;
03340    
03341    for (i=item; i; i=i->next) {
03342       if (find_switch_item(i))
03343          return 1;
03344    }
03345    return 0;
03346 }

static int context_used ( struct ael_extension exten_list,
struct ast_context context 
) [static]

Definition at line 4437 of file pval.c.

References ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), context, and exten.

04438 {
04439    struct ael_extension *exten;
04440    /* Check the simple elements first */
04441    if (ast_walk_context_extensions(context, NULL) || ast_walk_context_includes(context, NULL) || ast_walk_context_ignorepats(context, NULL) || ast_walk_context_switches(context, NULL)) {
04442       return 1;
04443    }
04444    for (exten = exten_list; exten; exten = exten->next_exten) {
04445       if (exten->context == context) {
04446          return 1;
04447       }
04448    }
04449    return 0;
04450 }

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 }

static int extension_matches ( pval here,
const char *  exten,
const char *  pattern 
) [static]

Definition at line 697 of file pval.c.

References ast_log(), pval::endline, pval::filename, LOG_ERROR, LOG_WARNING, and pval::startline.

Referenced by match_pval_item().

00698 {
00699    int err1;
00700    regex_t preg;
00701    
00702    /* simple case, they match exactly, the pattern and exten name */
00703    if (strcmp(pattern,exten) == 0)
00704       return 1;
00705    
00706    if (pattern[0] == '_') {
00707       char reg1[2000];
00708       const char *p;
00709       char *r = reg1;
00710       
00711       if ( strlen(pattern)*5 >= 2000 ) /* safety valve */ {
00712          ast_log(LOG_ERROR,"Error: The pattern %s is way too big. Pattern matching cancelled.\n",
00713                pattern);
00714          return 0;
00715       }
00716       /* form a regular expression from the pattern, and then match it against exten */
00717       *r++ = '^'; /* what if the extension is a pattern ?? */
00718       *r++ = '_'; /* what if the extension is a pattern ?? */
00719       *r++ = '?';
00720       for (p=pattern+1; *p; p++) {
00721          switch ( *p ) {
00722          case 'X':
00723             *r++ = '[';
00724             *r++ = '0';
00725             *r++ = '-';
00726             *r++ = '9';
00727             *r++ = 'X';
00728             *r++ = ']';
00729             break;
00730             
00731          case 'Z':
00732             *r++ = '[';
00733             *r++ = '1';
00734             *r++ = '-';
00735             *r++ = '9';
00736             *r++ = 'Z';
00737             *r++ = ']';
00738             break;
00739             
00740          case 'N':
00741             *r++ = '[';
00742             *r++ = '2';
00743             *r++ = '-';
00744             *r++ = '9';
00745             *r++ = 'N';
00746             *r++ = ']';
00747             break;
00748             
00749          case '[':
00750             while ( *p && *p != ']' ) {
00751                *r++ = *p++;
00752             }
00753             *r++ = ']';
00754             if ( *p != ']') {
00755                ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The extension pattern '%s' is missing a closing bracket \n",
00756                      here->filename, here->startline, here->endline, pattern);
00757             }
00758             break;
00759             
00760          case '.':
00761          case '!':
00762             *r++ = '.';
00763             *r++ = '*';
00764             break;
00765          case '*':
00766             *r++ = '\\';
00767             *r++ = '*';
00768             break;
00769          default:
00770             *r++ = *p;
00771             break;
00772             
00773          }
00774       }
00775       *r++ = '$'; /* what if the extension is a pattern ?? */
00776       *r++ = *p++; /* put in the closing null */
00777       err1 = regcomp(&preg, reg1, REG_NOSUB|REG_EXTENDED);
00778       if ( err1 ) {
00779          char errmess[500];
00780          regerror(err1,&preg,errmess,sizeof(errmess));
00781          regfree(&preg);
00782          ast_log(LOG_WARNING, "Regcomp of %s failed, error code %d\n",
00783                reg1, err1);
00784          return 0;
00785       }
00786       err1 = regexec(&preg, exten, 0, 0, 0);
00787       regfree(&preg);
00788       
00789       if ( err1 ) {
00790          /* ast_log(LOG_NOTICE,"*****************************[%d]Extension %s did not match %s(%s)\n",
00791             err1,exten, pattern, reg1); */
00792          return 0; /* no match */
00793       } else {
00794          /* ast_log(LOG_NOTICE,"*****************************Extension %s matched %s\n",
00795             exten, pattern); */
00796          return 1;
00797       }
00798       
00799       
00800    } else {
00801       if ( strcmp(exten,pattern) == 0 ) {
00802          return 1;
00803       } else
00804          return 0;
00805    }
00806 }

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_first_label_in_current_context ( char *  label,
pval curr_cont 
) [static]

Definition at line 1847 of file pval.c.

References find_context(), pval::list, match_pval(), pval::next, PV_INCLUDES, pval::statements, pval::str, pval::type, pval::u1, and pval::u2.

Referenced by check_label().

01848 {
01849    /* printf("  --- Got args %s, %s\n", exten, label); */
01850    struct pval *ret;
01851    struct pval *p3;
01852    
01853    count_labels = 0;
01854    return_on_context_match = 0;
01855    match_context = "*";
01856    match_exten = "*";
01857    match_label = label;
01858    
01859    ret =  match_pval(curr_cont);
01860    if (ret)
01861       return ret;
01862                
01863    /* the target of the goto could be in an included context!! Fancy that!! */
01864    /* look for includes in the current context */
01865    for (p3=curr_cont->u2.statements; p3; p3=p3->next) {
01866       if (p3->type == PV_INCLUDES) {
01867          struct pval *p4;
01868          for (p4=p3->u1.list; p4; p4=p4->next) {
01869             /* for each context pointed to, find it, then find a context/label that matches the
01870                target here! */
01871             char *incl_context = p4->u1.str;
01872             /* find a matching context name */
01873             struct pval *that_context = find_context(incl_context);
01874             if (that_context) {
01875                struct pval *x3;
01876                x3 = find_first_label_in_current_context(label, that_context);
01877                if (x3) {
01878                   return x3;
01879                }
01880             }
01881          }
01882       }
01883    }
01884    return 0;
01885 }

struct pval * find_label_in_current_context ( char *  exten,
char *  label,
pval curr_cont 
) [static]

Definition at line 1887 of file pval.c.

References find_context(), pval::list, match_pval(), pval::next, PV_INCLUDES, pval::statements, pval::str, pval::type, pval::u1, and pval::u2.

Referenced by check_goto(), and get_goto_target().

01888 {
01889    /* printf("  --- Got args %s, %s\n", exten, label); */
01890    struct pval *ret;
01891    struct pval *p3;
01892    
01893    count_labels = 0;
01894    return_on_context_match = 0;
01895    match_context = "*";
01896    match_exten = exten;
01897    match_label = label;
01898    ret =  match_pval(curr_cont->u2.statements);
01899    if (ret)
01900       return ret;
01901                
01902    /* the target of the goto could be in an included context!! Fancy that!! */
01903    /* look for includes in the current context */
01904    for (p3=curr_cont->u2.statements; p3; p3=p3->next) {
01905       if (p3->type == PV_INCLUDES) {
01906          struct pval *p4;
01907          for (p4=p3->u1.list; p4; p4=p4->next) {
01908             /* for each context pointed to, find it, then find a context/label that matches the
01909                target here! */
01910             char *incl_context = p4->u1.str;
01911             /* find a matching context name */
01912             struct pval *that_context = find_context(incl_context);
01913             if (that_context) {
01914                struct pval *x3;
01915                x3 = find_label_in_current_context(exten, label, that_context);
01916                if (x3) {
01917                   return x3;
01918                }
01919             }
01920          }
01921       }
01922    }
01923    return 0;
01924 }

static struct pval * find_label_in_current_db ( const char *  context,
const char *  exten,
const char *  label 
) [static]

Definition at line 1937 of file pval.c.

References current_db, and match_pval().

Referenced by check_goto(), and get_goto_target().

01938 {
01939    /* printf("  --- Got args %s, %s, %s\n", context, exten, label); */
01940    count_labels = 0;
01941    return_on_context_match = 0;
01942 
01943    match_context = context;
01944    match_exten = exten;
01945    match_label = label;
01946    
01947    return match_pval(current_db);
01948 }

static struct pval * find_label_in_current_extension ( const char *  label,
pval curr_ext 
) [static]

Definition at line 1926 of file pval.c.

References match_pval().

Referenced by check_goto(), and get_goto_target().

01927 {
01928    /* printf("  --- Got args %s\n", label); */
01929    count_labels = 0;
01930    return_on_context_match = 0;
01931    match_context = "*";
01932    match_exten = "*";
01933    match_label = label;
01934    return match_pval(curr_ext);
01935 }

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 void find_pval_goto_item ( pval item,
int  lev 
) [static]

Definition at line 1387 of file pval.c.

References ast_log(), check_goto(), pval::else_statements, find_context(), find_pval_gotos(), pval::for_statements, pval::list, LOG_ERROR, pval::macro_statements, pval::next, PV_CASE, PV_CATCH, PV_CONTEXT, PV_DEFAULT, PV_EXTENSION, PV_FOR, PV_GOTO, PV_IF, PV_IFTIME, PV_INCLUDES, PV_MACRO, PV_PATTERN, PV_RANDOM, PV_STATEMENTBLOCK, PV_SWITCH, PV_WHILE, pval::statements, pval::str, pval::type, pval::u1, pval::u2, pval::u3, and pval::u4.

Referenced by find_pval_gotos().

01388 {
01389    struct pval *p4;
01390    
01391    if (lev>100) {
01392       ast_log(LOG_ERROR,"find_pval_goto in infinite loop! item_type: %d\n\n", item->type);
01393       return;
01394    }
01395    
01396    switch ( item->type ) {
01397    case PV_MACRO:
01398       /* fields: item->u1.str     == name of macro
01399                  item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
01400                item->u2.arglist->u1.str  == argument
01401                item->u2.arglist->next   == next arg
01402 
01403                item->u3.macro_statements == pval list of statements in macro body.
01404       */
01405          
01406       /* printf("Descending into macro %s at line %d\n", item->u1.str, item->startline); */
01407       find_pval_gotos(item->u3.macro_statements,lev+1); /* if we're just searching for a context, don't bother descending into them */
01408       
01409       break;
01410          
01411    case PV_CONTEXT:
01412       /* fields: item->u1.str     == name of context
01413                  item->u2.statements == pval list of statements in context body
01414                item->u3.abstract == int 1 if an abstract keyword were present
01415       */
01416       break;
01417 
01418    case PV_CASE:
01419       /* fields: item->u1.str     == value of case
01420                  item->u2.statements == pval list of statements under the case
01421       */
01422       /* printf("Descending into Case of %s\n", item->u1.str); */
01423       find_pval_gotos(item->u2.statements,lev+1);
01424       break;
01425          
01426    case PV_PATTERN:
01427       /* fields: item->u1.str     == value of case
01428                  item->u2.statements == pval list of statements under the case
01429       */
01430       /* printf("Descending into Pattern of %s\n", item->u1.str); */
01431       find_pval_gotos(item->u2.statements,lev+1);
01432       break;
01433          
01434    case PV_DEFAULT:
01435       /* fields: 
01436                  item->u2.statements == pval list of statements under the case
01437       */
01438       /* printf("Descending into default\n"); */
01439       find_pval_gotos(item->u2.statements,lev+1);
01440       break;
01441          
01442    case PV_CATCH:
01443       /* fields: item->u1.str     == name of extension to catch
01444                  item->u2.statements == pval list of statements in context body
01445       */
01446       /* printf("Descending into catch of %s\n", item->u1.str); */
01447       find_pval_gotos(item->u2.statements,lev+1);
01448       break;
01449          
01450    case PV_STATEMENTBLOCK:
01451       /* fields: item->u1.list     == pval list of statements in block, one per entry in the list
01452       */
01453       /* printf("Descending into statement block\n"); */
01454       find_pval_gotos(item->u1.list,lev+1);
01455       break;
01456          
01457    case PV_GOTO:
01458       /* fields: item->u1.list     == pval list of PV_WORD target names, up to 3, in order as given by user.
01459                  item->u1.list->u1.str  == where the data on a PV_WORD will always be.
01460       */
01461       check_goto(item);  /* THE WHOLE FUNCTION OF THIS ENTIRE ROUTINE!!!! */
01462       break;
01463          
01464    case PV_INCLUDES:
01465       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
01466       */
01467       for (p4=item->u1.list; p4; p4=p4->next) {
01468          /* for each context pointed to, find it, then find a context/label that matches the
01469             target here! */
01470          char *incl_context = p4->u1.str;
01471          /* find a matching context name */
01472          struct pval *that_context = find_context(incl_context);
01473          if (that_context && that_context->u2.statements) {
01474             /* printf("Descending into include of '%s' at line %d; that_context=%s, that_context type=%d\n", incl_context, item->startline, that_context->u1.str, that_context->type); */
01475             find_pval_gotos(that_context->u2.statements,lev+1); /* keep working up the includes */
01476          }
01477       }
01478       break;
01479       
01480    case PV_FOR:
01481       /* fields: item->u1.for_init     == a string containing the initalizer
01482                  item->u2.for_test     == a string containing the loop test
01483                  item->u3.for_inc      == a string containing the loop increment
01484 
01485                item->u4.for_statements == a pval list of statements in the for ()
01486       */
01487       /* printf("Descending into for at line %d\n", item->startline); */
01488       find_pval_gotos(item->u4.for_statements,lev+1);
01489       break;
01490          
01491    case PV_WHILE:
01492       /* fields: item->u1.str        == the while conditional, as supplied by user
01493 
01494                item->u2.statements == a pval list of statements in the while ()
01495       */
01496       /* printf("Descending into while at line %d\n", item->startline); */
01497       find_pval_gotos(item->u2.statements,lev+1);
01498       break;
01499          
01500    case PV_RANDOM:
01501       /* fields: item->u1.str        == the random number expression, as supplied by user
01502 
01503                item->u2.statements == a pval list of statements in the if ()
01504                item->u3.else_statements == a pval list of statements in the else
01505                                     (could be zero)
01506        fall thru to PV_IF */
01507       
01508    case PV_IFTIME:
01509       /* fields: item->u1.list        == the time values, 4 of them, as PV_WORD structs in a list
01510 
01511                item->u2.statements == a pval list of statements in the if ()
01512                item->u3.else_statements == a pval list of statements in the else
01513                                     (could be zero)
01514       fall thru to PV_IF*/
01515    case PV_IF:
01516       /* fields: item->u1.str        == the if conditional, as supplied by user
01517 
01518                item->u2.statements == a pval list of statements in the if ()
01519                item->u3.else_statements == a pval list of statements in the else
01520                                     (could be zero)
01521       */
01522       /* printf("Descending into random/iftime/if at line %d\n", item->startline); */
01523       find_pval_gotos(item->u2.statements,lev+1);
01524 
01525       if (item->u3.else_statements) {
01526          /* printf("Descending into random/iftime/if's ELSE at line %d\n", item->startline); */
01527          find_pval_gotos(item->u3.else_statements,lev+1);
01528       }
01529       break;
01530          
01531    case PV_SWITCH:
01532       /* fields: item->u1.str        == the switch expression
01533 
01534                item->u2.statements == a pval list of statements in the switch, 
01535                                     (will be case statements, most likely!)
01536       */
01537       /* printf("Descending into switch at line %d\n", item->startline); */
01538       find_pval_gotos(item->u3.else_statements,lev+1);
01539       break;
01540          
01541    case PV_EXTENSION:
01542       /* fields: item->u1.str        == the extension name, label, whatever it's called
01543 
01544                item->u2.statements == a pval list of statements in the extension
01545                item->u3.hints      == a char * hint argument
01546                item->u4.regexten   == an int boolean. non-zero says that regexten was specified
01547       */
01548 
01549       /* printf("Descending into extension %s at line %d\n", item->u1.str, item->startline); */
01550       find_pval_gotos(item->u2.statements,lev+1);
01551       break;
01552 
01553    default:
01554       break;
01555    }
01556 }

static void find_pval_gotos ( pval item,
int  lev 
) [static]

Definition at line 1558 of file pval.c.

References find_pval_goto_item(), and pval::next.

Referenced by check_pval_item(), and find_pval_goto_item().

01559 {
01560    pval *i;
01561    
01562    for (i=item; i; i=i->next) {
01563       /* printf("About to call pval_goto_item, itemcount=%d, itemtype=%d\n", item_count, i->type); */
01564       find_pval_goto_item(i, lev);
01565    }
01566 }

int find_switch_item ( pval item  ) 

Definition at line 3098 of file pval.c.

References contains_switch(), pval::else_statements, pval::for_statements, pval::list, pval::macro_statements, PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTEXT, PV_CONTINUE, PV_DEFAULT, PV_ESWITCHES, PV_EXTENSION, PV_FOR, PV_GLOBALS, PV_GOTO, PV_IF, PV_IFTIME, PV_IGNOREPAT, PV_INCLUDES, PV_LABEL, PV_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::type, pval::u1, pval::u2, pval::u3, and pval::u4.

Referenced by contains_switch().

03099 {
03100    switch ( item->type ) {
03101    case PV_LOCALVARDEC:
03102       /* fields: item->u1.str == string associated with this (word). */
03103       break;
03104       
03105    case PV_WORD:
03106       /* fields: item->u1.str == string associated with this (word). */
03107       break;
03108       
03109    case PV_MACRO:
03110       /* fields: item->u1.str     == name of macro
03111                  item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
03112                item->u2.arglist->u1.str  == argument
03113                item->u2.arglist->next   == next arg
03114 
03115                item->u3.macro_statements == pval list of statements in macro body.
03116       */
03117       /* had better not see this */
03118       if (contains_switch(item->u3.macro_statements))
03119          return 1;
03120       break;
03121          
03122    case PV_CONTEXT:
03123       /* fields: item->u1.str     == name of context
03124                  item->u2.statements == pval list of statements in context body
03125                item->u3.abstract == int 1 if an abstract keyword were present
03126       */
03127       /* had better not see this */
03128       if (contains_switch(item->u2.statements))
03129          return 1;
03130       break;
03131          
03132    case PV_MACRO_CALL:
03133       /* fields: item->u1.str     == name of macro to call
03134                  item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
03135                item->u2.arglist->u1.str  == argument
03136                item->u2.arglist->next   == next arg
03137       */
03138       break;
03139          
03140    case PV_APPLICATION_CALL:
03141       /* fields: item->u1.str     == name of application to call
03142                  item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
03143                item->u2.arglist->u1.str  == argument
03144                item->u2.arglist->next   == next arg
03145       */
03146       break;
03147          
03148    case PV_CASE:
03149       /* fields: item->u1.str     == value of case
03150                  item->u2.statements == pval list of statements under the case
03151       */
03152       /* had better not see this */
03153       if (contains_switch(item->u2.statements))
03154          return 1;
03155       break;
03156          
03157    case PV_PATTERN:
03158       /* fields: item->u1.str     == value of case
03159                  item->u2.statements == pval list of statements under the case
03160       */
03161       /* had better not see this */
03162       if (contains_switch(item->u2.statements))
03163          return 1;
03164       break;
03165          
03166    case PV_DEFAULT:
03167       /* fields: 
03168                  item->u2.statements == pval list of statements under the case
03169       */
03170       /* had better not see this */
03171       if (contains_switch(item->u2.statements))
03172          return 1;
03173       break;
03174          
03175    case PV_CATCH:
03176       /* fields: item->u1.str     == name of extension to catch
03177                  item->u2.statements == pval list of statements in context body
03178       */
03179       /* had better not see this */
03180       if (contains_switch(item->u2.statements))
03181          return 1;
03182       break;
03183          
03184    case PV_SWITCHES:
03185       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
03186       */
03187       break;
03188          
03189    case PV_ESWITCHES:
03190       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
03191       */
03192       break;
03193          
03194    case PV_INCLUDES:
03195       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
03196                  item->u2.arglist  == pval list of 4 PV_WORD elements for time values
03197       */
03198       break;
03199          
03200    case PV_STATEMENTBLOCK:
03201       /* fields: item->u1.list     == pval list of statements in block, one per entry in the list
03202       */
03203       if (contains_switch(item->u1.list) )
03204          return 1;
03205       break;
03206          
03207    case PV_VARDEC:
03208       /* fields: item->u1.str     == variable name
03209                  item->u2.val     == variable value to assign
03210       */
03211       break;
03212          
03213    case PV_GOTO:
03214       /* fields: item->u1.list     == pval list of PV_WORD target names, up to 3, in order as given by user.
03215                  item->u1.list->u1.str  == where the data on a PV_WORD will always be.
03216       */
03217       break;
03218          
03219    case PV_LABEL:
03220       /* fields: item->u1.str     == label name
03221       */
03222       break;
03223          
03224    case PV_FOR:
03225       /* fields: item->u1.for_init     == a string containing the initalizer
03226                  item->u2.for_test     == a string containing the loop test
03227                  item->u3.for_inc      == a string containing the loop increment
03228 
03229                item->u4.for_statements == a pval list of statements in the for ()
03230       */
03231       if (contains_switch(item->u4.for_statements))
03232          return 1;
03233       break;
03234          
03235    case PV_WHILE:
03236       /* fields: item->u1.str        == the while conditional, as supplied by user
03237 
03238                item->u2.statements == a pval list of statements in the while ()
03239       */
03240       if (contains_switch(item->u2.statements))
03241          return 1;
03242       break;
03243          
03244    case PV_BREAK:
03245       /* fields: none
03246       */
03247       break;
03248          
03249    case PV_RETURN:
03250       /* fields: none
03251       */
03252       break;
03253          
03254    case PV_CONTINUE:
03255       /* fields: none
03256       */
03257       break;
03258          
03259    case PV_IFTIME:
03260       /* fields: item->u1.list        == there are 4 linked PV_WORDs here.
03261 
03262                item->u2.statements == a pval list of statements in the if ()
03263                item->u3.else_statements == a pval list of statements in the else
03264                                     (could be zero)
03265       */
03266       if (contains_switch(item->u2.statements))
03267          return 1;
03268       if ( item->u3.else_statements ) {
03269          if (contains_switch(item->u3.else_statements))
03270             return 1;
03271       }
03272       break;
03273          
03274    case PV_RANDOM:
03275       /* fields: item->u1.str        == the random number expression, as supplied by user
03276 
03277                item->u2.statements == a pval list of statements in the if ()
03278                item->u3.else_statements == a pval list of statements in the else
03279                                     (could be zero)
03280       */
03281       if (contains_switch(item->u2.statements))
03282          return 1;
03283       if ( item->u3.else_statements ) {
03284          if (contains_switch(item->u3.else_statements))
03285             return 1;
03286       }
03287       break;
03288          
03289    case PV_IF:
03290       /* fields: item->u1.str        == the if conditional, as supplied by user
03291 
03292                item->u2.statements == a pval list of statements in the if ()
03293                item->u3.else_statements == a pval list of statements in the else
03294                                     (could be zero)
03295       */
03296       if (contains_switch(item->u2.statements))
03297          return 1;
03298       if ( item->u3.else_statements ) {
03299          if (contains_switch(item->u3.else_statements))
03300             return 1;
03301       }
03302       break;
03303          
03304    case PV_SWITCH:
03305       /* fields: item->u1.str        == the switch expression
03306 
03307                item->u2.statements == a pval list of statements in the switch, 
03308                                     (will be case statements, most likely!)
03309       */
03310       return 1; /* JACKPOT */
03311       break;
03312          
03313    case PV_EXTENSION:
03314       /* fields: item->u1.str        == the extension name, label, whatever it's called
03315 
03316                item->u2.statements == a pval list of statements in the extension
03317                item->u3.hints      == a char * hint argument
03318                item->u4.regexten   == an int boolean. non-zero says that regexten was specified
03319       */
03320       if (contains_switch(item->u2.statements))
03321          return 1;
03322       break;
03323          
03324    case PV_IGNOREPAT:
03325       /* fields: item->u1.str        == the ignorepat data
03326       */
03327       break;
03328          
03329    case PV_GLOBALS:
03330       /* fields: item->u1.statements     == pval list of statements, usually vardecs
03331       */
03332       break;
03333    }
03334    return 0;
03335 }

static void fix_gotos_in_extensions ( struct ael_extension exten  )  [static]

Definition at line 4394 of file pval.c.

References buf1, exten, ael_priority::next, ael_extension::next_exten, ael_extension::plist, PV_GOTO, and strdup.

04395 {
04396    struct ael_extension *e;
04397    for(e=exten;e;e=e->next_exten) {
04398 
04399       struct ael_priority *p;
04400       for(p=e->plist;p;p=p->next) {
04401          
04402          if( p->origin && p->origin->type == PV_GOTO && p->origin->u3.goto_target_in_case ) {
04403             
04404             /* fix the extension of the goto target to the actual extension in the post-compiled dialplan */
04405 
04406             pval *target = p->origin->u2.goto_target;
04407             struct ael_extension *z = target->u3.compiled_label;
04408             pval *pv2 = p->origin;
04409             char buf1[500];
04410             char *apparg_save = p->appargs;
04411             
04412             p->appargs = 0;
04413             if (!pv2->u1.list->next) /* just one  -- it won't hurt to repeat the extension */ {
04414                snprintf(buf1,sizeof(buf1),"%s,%s", z->name, pv2->u1.list->u1.str);
04415                p->appargs = strdup(buf1);
04416                
04417             } else if (pv2->u1.list->next && !pv2->u1.list->next->next) /* two */ {
04418                snprintf(buf1,sizeof(buf1),"%s,%s", z->name, pv2->u1.list->next->u1.str);
04419                p->appargs = strdup(buf1);
04420             } else if (pv2->u1.list->next && pv2->u1.list->next->next) {
04421                snprintf(buf1,sizeof(buf1),"%s,%s,%s", pv2->u1.list->u1.str, 
04422                       z->name,
04423                       pv2->u1.list->next->next->u1.str);
04424                p->appargs = strdup(buf1);
04425             }
04426             else
04427                printf("WHAT? The goto doesn't fall into one of three cases for GOTO????\n");
04428             
04429             if( apparg_save ) {
04430                free(apparg_save);
04431             }
04432          }
04433       }
04434    }
04435 }

static void gen_match_to_pattern ( char *  pattern,
char *  result 
) [static]

Definition at line 3069 of file pval.c.

Referenced by gen_prios().

03070 {
03071    /* the result will be a string that will be matched by pattern */
03072    char *p=pattern, *t=result;
03073    while (*p) {
03074       if (*p == 'x' || *p == 'n' || *p == 'z' || *p == 'X' || *p == 'N' || *p == 'Z')
03075          *t++ = '9';
03076       else if (*p == '[') {
03077          char *z = p+1;
03078          while (*z != ']')
03079             z++;
03080          if (*(z+1)== ']')
03081             z++;
03082          *t++=*(p+1); /* use the first char in the set */
03083          p = z;
03084       } else {
03085          *t++ = *p;
03086       }
03087       p++;
03088    }
03089    *t++ = 0; /* cap it off */
03090 }

static int gen_prios ( struct ael_extension exten,
char *  label,
pval statement,
struct ael_extension mother_exten,
struct ast_context this_context 
) [static]

Definition at line 3349 of file pval.c.

References AEL_APPCALL, AEL_CONTROL1, AEL_FOR_CONTROL, AEL_IF_CONTROL, AEL_IFTIME_CONTROL, AEL_LABEL, AEL_RETURN, ael_priority::app, ael_priority::appargs, pval::arglist, ast_compat_app_set, buf1, buf2, BUF_SIZE, ael_extension::checked_switch, pval::compiled_label, contains_switch(), ael_extension::context, control_statement_count, pval::else_statements, ael_priority::exten, exten, first, pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, free, gen_match_to_pattern(), get_goto_target(), ael_priority::goto_false, pval::goto_target, pval::goto_target_in_case, ael_priority::goto_true, ael_extension::has_switch, ael_extension::is_switch, label_inside_case(), linkexten(), linkprio(), pval::list, ael_extension::loop_break, ael_extension::loop_continue, malloc, ael_extension::name, new_exten(), new_prio(), pval::next, ael_priority::origin, PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTINUE, PV_DEFAULT, PV_FOR, PV_GOTO, PV_IF, PV_IFTIME, PV_LABEL, PV_LOCALVARDEC, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_VARDEC, PV_WHILE, remove_spaces_before_equals(), ael_extension::return_needed, pval::statements, pval::str, strdup, pval::type, ael_priority::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.

03350 {
03351    pval *p,*p2,*p3;
03352    struct ael_priority *pr;
03353    struct ael_priority *for_init, *for_test, *for_inc, *for_loop, *for_end;
03354    struct ael_priority *while_test, *while_loop, *while_end;
03355    struct ael_priority *switch_set, *switch_test, *switch_end, *fall_thru, *switch_empty;
03356    struct ael_priority *if_test, *if_end, *if_skip, *if_false;
03357 #ifdef OLD_RAND_ACTION
03358    struct ael_priority *rand_test, *rand_end, *rand_skip;
03359 #endif
03360    char *buf1;
03361    char *buf2;
03362    char *new_label;
03363    char *strp, *strp2;
03364    int default_exists;
03365    int local_control_statement_count;
03366    int first;
03367    struct ael_priority *loop_break_save;
03368    struct ael_priority *loop_continue_save;
03369    struct ael_extension *switch_case,*switch_null;
03370 
03371    if (!(buf1 = malloc(BUF_SIZE))) {
03372       return -1;
03373    }
03374    if (!(buf2 = malloc(BUF_SIZE))) {
03375       return -1;
03376    }
03377    if (!(new_label = malloc(BUF_SIZE))) {
03378       return -1;
03379    }
03380    
03381    if ((mother_exten && !mother_exten->checked_switch) || (exten && !exten->checked_switch)) {
03382       if (contains_switch(statement)) { /* only run contains_switch if you haven't checked before */
03383          if (mother_exten) {
03384             if (!mother_exten->has_switch) {
03385                for (first = 1; first >= 0; first--) {
03386                   switch_set = new_prio();
03387                   switch_set->type = AEL_APPCALL;
03388                   if (!ast_compat_app_set) {
03389                      switch_set->app = strdup("MSet");
03390                   } else {
03391                      switch_set->app = strdup("Set");
03392                   }
03393                   /* Are we likely inside a gosub subroutine? */
03394                   if (!strcmp(mother_exten->name, "~~s~~") && first) {
03395                      /* If we're not actually within a gosub, this will fail, but the
03396                       * second time through, it will get set.  If we are within gosub,
03397                       * the second time through is redundant, but acceptable. */
03398                      switch_set->appargs = strdup("LOCAL(~~EXTEN~~)=${EXTEN}");
03399                   } else {
03400                      switch_set->appargs = strdup("~~EXTEN~~=${EXTEN}");
03401                      first = 0;
03402                   }
03403                   linkprio(exten, switch_set, mother_exten);
03404                   mother_exten->has_switch = 1;
03405                   mother_exten->checked_switch = 1;
03406                   if (exten) {
03407                      exten->has_switch = 1;
03408                      exten->checked_switch = 1;
03409                   }
03410                }
03411             }
03412          } else if (exten) {
03413             if (!exten->has_switch) {
03414                for (first = 1; first >= 0; first--) {
03415                   switch_set = new_prio();
03416                   switch_set->type = AEL_APPCALL;
03417                   if (!ast_compat_app_set) {
03418                      switch_set->app = strdup("MSet");
03419                   } else {
03420                      switch_set->app = strdup("Set");
03421                   }
03422                   /* Are we likely inside a gosub subroutine? */
03423                   if (!strcmp(exten->name, "~~s~~")) {
03424                      /* If we're not actually within a gosub, this will fail, but the
03425                       * second time through, it will get set.  If we are within gosub,
03426                       * the second time through is redundant, but acceptable. */
03427                      switch_set->appargs = strdup("LOCAL(~~EXTEN~~)=${EXTEN}");
03428                   } else {
03429                      switch_set->appargs = strdup("~~EXTEN~~=${EXTEN}");
03430                      first = 0;
03431                   }
03432                   linkprio(exten, switch_set, mother_exten);
03433                   exten->has_switch = 1;
03434                   exten->checked_switch = 1;
03435                   if (mother_exten) {
03436                      mother_exten->has_switch = 1;
03437                      mother_exten->checked_switch = 1;
03438                   }
03439                }
03440             }
03441          }
03442       } else {
03443          if (mother_exten) {
03444             mother_exten->checked_switch = 1;
03445          }
03446          if (exten) {
03447             exten->checked_switch = 1;
03448          }
03449       }
03450    }
03451    for (p=statement; p; p=p->next) {
03452       switch (p->type) {
03453       case PV_VARDEC:
03454          pr = new_prio();
03455          pr->type = AEL_APPCALL;
03456          snprintf(buf1, BUF_SIZE, "%s=$[%s]", p->u1.str, p->u2.val);
03457          if (!ast_compat_app_set) {
03458             pr->app = strdup("MSet");
03459          } else {
03460             pr->app = strdup("Set");
03461          }
03462          remove_spaces_before_equals(buf1);
03463          pr->appargs = strdup(buf1);
03464          pr->origin = p;
03465          linkprio(exten, pr, mother_exten);
03466          break;
03467 
03468       case PV_LOCALVARDEC:
03469          pr = new_prio();
03470          pr->type = AEL_APPCALL;
03471          snprintf(buf1, BUF_SIZE, "LOCAL(%s)=$[%s]", p->u1.str, p->u2.val);
03472          if (!ast_compat_app_set) {
03473             pr->app = strdup("MSet");
03474          } else {
03475             pr->app = strdup("Set");
03476          }
03477          remove_spaces_before_equals(buf1);
03478          pr->appargs = strdup(buf1);
03479          pr->origin = p;
03480          linkprio(exten, pr, mother_exten);
03481          break;
03482          
03483       case PV_GOTO:
03484          pr = new_prio();
03485          pr->type = AEL_APPCALL;
03486          p->u2.goto_target = get_goto_target(p);
03487          if( p->u2.goto_target ) {
03488             p->u3.goto_target_in_case = label_inside_case(p->u2.goto_target);
03489          }
03490          
03491          if (!p->u1.list->next) /* just one */ {
03492             pr->app = strdup("Goto");
03493             if (!mother_exten)
03494                pr->appargs = strdup(p->u1.list->u1.str);
03495             else {  /* for the case of simple within-extension gotos in case/pattern/default statement blocks: */ 
03496                snprintf(buf1, BUF_SIZE, "%s,%s", mother_exten->name, p->u1.list->u1.str);
03497                pr->appargs = strdup(buf1);
03498             }
03499             
03500          } else if (p->u1.list->next && !p->u1.list->next->next) /* two */ {
03501             snprintf(buf1, BUF_SIZE, "%s,%s", p->u1.list->u1.str, p->u1.list->next->u1.str);
03502             pr->app = strdup("Goto");
03503             pr->appargs = strdup(buf1);
03504          } else if (p->u1.list->next && p->u1.list->next->next) {
03505             snprintf(buf1, BUF_SIZE, "%s,%s,%s", p->u1.list->u1.str, 
03506                   p->u1.list->next->u1.str,
03507                   p->u1.list->next->next->u1.str);
03508             pr->app = strdup("Goto");
03509             pr->appargs = strdup(buf1);
03510          }
03511          pr->origin = p;
03512          linkprio(exten, pr, mother_exten);
03513          break;
03514 
03515       case PV_LABEL:
03516          pr = new_prio();
03517          pr->type = AEL_LABEL;
03518          pr->origin = p;
03519          p->u3.compiled_label = exten;
03520          linkprio(exten, pr, mother_exten);
03521          break;
03522 
03523       case PV_FOR:
03524          control_statement_count++;
03525          loop_break_save = exten->loop_break; /* save them, then restore before leaving */
03526          loop_continue_save = exten->loop_continue;
03527          snprintf(new_label, BUF_SIZE, "for_%s_%d", label, control_statement_count);
03528          for_init = new_prio();
03529          for_inc = new_prio();
03530          for_test = new_prio();
03531          for_loop = new_prio();
03532          for_end = new_prio();
03533          for_init->type = AEL_APPCALL;
03534          for_inc->type = AEL_APPCALL;
03535          for_test->type = AEL_FOR_CONTROL;
03536          for_test->goto_false = for_end;
03537          for_loop->type = AEL_CONTROL1; /* simple goto */
03538          for_end->type = AEL_APPCALL;
03539          if (!ast_compat_app_set) {
03540             for_init->app = strdup("MSet");
03541          } else {
03542             for_init->app = strdup("Set");
03543          }
03544          
03545          strcpy(buf2,p->u1.for_init);
03546          remove_spaces_before_equals(buf2);
03547          strp = strchr(buf2, '=');
03548          if (strp) {
03549             strp2 = strchr(p->u1.for_init, '=');
03550             *(strp+1) = 0;
03551             strcat(buf2,"$[");
03552             strncat(buf2,strp2+1, BUF_SIZE-strlen(strp2+1)-2);
03553             strcat(buf2,"]");
03554             for_init->appargs = strdup(buf2);
03555          } else {
03556             strp2 = p->u1.for_init;
03557             while (*strp2 && isspace(*strp2))
03558                strp2++;
03559             if (*strp2 == '&') { /* itsa macro call */
03560                char *strp3 = strp2+1;
03561                while (*strp3 && isspace(*strp3))
03562                   strp3++;
03563                strcpy(buf2, strp3);
03564                strp3 = strchr(buf2,'(');
03565                if (strp3) {
03566                   *strp3 = '|';
03567                }
03568                while ((strp3=strchr(buf2,','))) {
03569                   *strp3 = '|';
03570                }
03571                strp3 = strrchr(buf2, ')');
03572                if (strp3)
03573                   *strp3 = 0; /* remove the closing paren */
03574 
03575                for_init->appargs = strdup(buf2);
03576                free(for_init->app);
03577                for_init->app = strdup("Macro");
03578             } else {  /* must be a regular app call */
03579                char *strp3;
03580                strcpy(buf2, strp2);
03581                strp3 = strchr(buf2,'(');
03582                if (strp3) {
03583                   *strp3 = 0;
03584                   free(for_init->app);
03585                   for_init->app = strdup(buf2);
03586                   for_init->appargs = strdup(strp3+1);
03587                   strp3 = strrchr(for_init->appargs, ')');
03588                   if (strp3)
03589                      *strp3 = 0; /* remove the closing paren */
03590                }
03591             }
03592          }
03593 
03594          strcpy(buf2,p->u3.for_inc);
03595          remove_spaces_before_equals(buf2);
03596          strp = strchr(buf2, '=');
03597          if (strp) {  /* there's an = in this part; that means an assignment. set it up */
03598             strp2 = strchr(p->u3.for_inc, '=');
03599             *(strp+1) = 0;
03600             strcat(buf2,"$[");
03601             strncat(buf2,strp2+1, BUF_SIZE-strlen(strp2+1)-2);
03602             strcat(buf2,"]");
03603             for_inc->appargs = strdup(buf2);
03604             if (!ast_compat_app_set) {
03605                for_inc->app = strdup("MSet");
03606             } else {
03607                for_inc->app = strdup("Set");
03608             }
03609          } else {
03610             strp2 = p->u3.for_inc;
03611             while (*strp2 && isspace(*strp2))
03612                strp2++;
03613             if (*strp2 == '&') { /* itsa macro call  */
03614                char *strp3 = strp2+1;
03615                while (*strp3 && isspace(*strp3))
03616                   strp3++;
03617                strcpy(buf2, strp3);
03618                strp3 = strchr(buf2,'(');
03619                if (strp3) {
03620                   *strp3 = ',';
03621                }
03622                strp3 = strrchr(buf2, ')');
03623                if (strp3)
03624                   *strp3 = 0; /* remove the closing paren */
03625 
03626                for_inc->appargs = strdup(buf2);
03627 
03628                for_inc->app = strdup("Macro");
03629             } else {  /* must be a regular app call */
03630                char *strp3;
03631                strcpy(buf2, strp2);
03632                strp3 = strchr(buf2,'(');
03633                if (strp3) {
03634                   *strp3 = 0;
03635                   for_inc->app = strdup(buf2);
03636                   for_inc->appargs = strdup(strp3+1);
03637                   strp3 = strrchr(for_inc->appargs, ')');
03638                   if (strp3)
03639                      *strp3 = 0; /* remove the closing paren */
03640                }
03641             }
03642          }
03643          snprintf(buf1, BUF_SIZE, "$[%s]",p->u2.for_test);
03644          for_test->app = 0;
03645          for_test->appargs = strdup(buf1);
03646          for_loop->goto_true = for_test;
03647          snprintf(buf1, BUF_SIZE, "Finish for_%s_%d", label, control_statement_count);
03648          for_end->app = strdup("NoOp");
03649          for_end->appargs = strdup(buf1);
03650          /* link & load! */
03651          linkprio(exten, for_init, mother_exten);
03652          linkprio(exten, for_test, mother_exten);
03653          
03654          /* now, put the body of the for loop here */
03655          exten->loop_break = for_end;
03656          exten->loop_continue = for_inc;
03657          
03658          if (gen_prios(exten, new_label, p->u4.for_statements, mother_exten, this_context)) { /* this will link in all the statements here */
03659             return -1;
03660          }
03661          
03662          linkprio(exten, for_inc, mother_exten);
03663          linkprio(exten, for_loop, mother_exten);
03664          linkprio(exten, for_end, mother_exten);
03665          
03666          
03667          exten->loop_break = loop_break_save;
03668          exten->loop_continue = loop_continue_save;
03669          for_loop->origin = p;
03670          break;
03671 
03672       case PV_WHILE:
03673          control_statement_count++;
03674          loop_break_save = exten->loop_break; /* save them, then restore before leaving */
03675          loop_continue_save = exten->loop_continue;
03676          snprintf(new_label, BUF_SIZE, "while_%s_%d", label, control_statement_count);
03677          while_test = new_prio();
03678          while_loop = new_prio();
03679          while_end = new_prio();
03680          while_test->type = AEL_FOR_CONTROL;
03681          while_test->goto_false = while_end;
03682          while_loop->type = AEL_CONTROL1; /* simple goto */
03683          while_end->type = AEL_APPCALL;
03684          snprintf(buf1, BUF_SIZE, "$[%s]",p->u1.str);
03685          while_test->app = 0;
03686          while_test->appargs = strdup(buf1);
03687          while_loop->goto_true = while_test;
03688          snprintf(buf1, BUF_SIZE, "Finish while_%s_%d", label, control_statement_count);
03689          while_end->app = strdup("NoOp");
03690          while_end->appargs = strdup(buf1);
03691 
03692          linkprio(exten, while_test, mother_exten);
03693          
03694          /* now, put the body of the for loop here */
03695          exten->loop_break = while_end;
03696          exten->loop_continue = while_test;
03697          
03698          if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the while body statements here */
03699             return -1;
03700          }
03701 
03702          linkprio(exten, while_loop, mother_exten);
03703          linkprio(exten, while_end, mother_exten);
03704          
03705          
03706          exten->loop_break = loop_break_save;
03707          exten->loop_continue = loop_continue_save;
03708          while_loop->origin = p;
03709          break;
03710 
03711       case PV_SWITCH:
03712          control_statement_count++;
03713          local_control_statement_count = control_statement_count;
03714          loop_break_save = exten->loop_break; /* save them, then restore before leaving */
03715          loop_continue_save = exten->loop_continue;
03716          snprintf(new_label, BUF_SIZE, "sw_%s_%d", label, control_statement_count);
03717          switch_test = new_prio();
03718          switch_end = new_prio();
03719          switch_test->type = AEL_APPCALL;
03720          switch_end->type = AEL_APPCALL;
03721          snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", control_statement_count, p->u1.str);
03722          switch_test->app = strdup("Goto");
03723          switch_test->appargs = strdup(buf1);
03724          snprintf(buf1, BUF_SIZE, "Finish switch_%s_%d", label, control_statement_count);
03725          switch_end->app = strdup("NoOp");
03726          switch_end->appargs = strdup(buf1);
03727          switch_end->origin = p;
03728          switch_end->exten = exten;
03729 
03730          linkprio(exten, switch_test, mother_exten);
03731          linkprio(exten, switch_end, mother_exten);
03732          
03733          exten->loop_break = switch_end;
03734          exten->loop_continue = 0;
03735          default_exists = 0;
03736          
03737          for (p2=p->u2.statements; p2; p2=p2->next) {
03738             /* now, for each case/default put the body of the for loop here */
03739             if (p2->type == PV_CASE) {
03740                /* ok, generate a extension and link it in */
03741                switch_case = new_exten();
03742                if (mother_exten && mother_exten->checked_switch) {
03743                   switch_case->has_switch = mother_exten->has_switch;
03744                   switch_case->checked_switch = mother_exten->checked_switch;
03745                }
03746                if (exten && exten->checked_switch) {
03747                   switch_case->has_switch = exten->has_switch;
03748                   switch_case->checked_switch = exten->checked_switch;
03749                }
03750                switch_case->context = this_context;
03751                switch_case->is_switch = 1;
03752                /* the break/continue locations are inherited from parent */
03753                switch_case->loop_break = exten->loop_break;
03754                switch_case->loop_continue = exten->loop_continue;
03755                
03756                linkexten(exten,switch_case);
03757                snprintf(buf1, BUF_SIZE, "sw_%d_%s", local_control_statement_count, p2->u1.str);
03758                switch_case->name = strdup(buf1);
03759                snprintf(new_label, BUF_SIZE, "sw_%s_%s_%d", label, p2->u1.str, local_control_statement_count);
03760                
03761                if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the case body statements here */
03762                   return -1;
03763                }
03764 
03765                /* here is where we write code to "fall thru" to the next case... if there is one... */
03766                for (p3=p2->u2.statements; p3; p3=p3->next) {
03767                   if (!p3->next)
03768                      break;
03769                }
03770                /* p3 now points the last statement... */
03771                if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN) ) {
03772                   /* is there a following CASE/PATTERN/DEFAULT? */
03773                   if (p2->next && p2->next->type == PV_CASE) {
03774                      fall_thru = new_prio();
03775                      fall_thru->type = AEL_APPCALL;
03776                      fall_thru->app = strdup("Goto");
03777                      snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, p2->next->u1.str);
03778                      fall_thru->appargs = strdup(buf1);
03779                      linkprio(switch_case, fall_thru, mother_exten);
03780                   } else if (p2->next && p2->next->type == PV_PATTERN) {
03781                      fall_thru = new_prio();
03782                      fall_thru->type = AEL_APPCALL;
03783                      fall_thru->app = strdup("Goto");
03784                      gen_match_to_pattern(p2->next->u1.str, buf2);
03785                      snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, buf2);
03786                      fall_thru->appargs = strdup(buf1);
03787                      linkprio(switch_case, fall_thru, mother_exten);
03788                   } else if (p2->next && p2->next->type == PV_DEFAULT) {
03789                      fall_thru = new_prio();
03790                      fall_thru->type = AEL_APPCALL;
03791                      fall_thru->app = strdup("Goto");
03792                      snprintf(buf1, BUF_SIZE, "sw_%d_.,10", local_control_statement_count);
03793                      fall_thru->appargs = strdup(buf1);
03794                      linkprio(switch_case, fall_thru, mother_exten);
03795                   } else if (!p2->next) {
03796                      fall_thru = new_prio();
03797                      fall_thru->type = AEL_CONTROL1;
03798                      fall_thru->goto_true = switch_end;
03799                      fall_thru->app = strdup("Goto");
03800                      linkprio(switch_case, fall_thru, mother_exten);
03801                   }
03802                }
03803                if (switch_case->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */
03804                   char buf[2000];
03805                   struct ael_priority *np2 = new_prio();
03806                   np2->type = AEL_APPCALL;
03807                   np2->app = strdup("NoOp");
03808                   snprintf(buf, BUF_SIZE, "End of Extension %s", switch_case->name);
03809                   np2->appargs = strdup(buf);
03810                   linkprio(switch_case, np2, mother_exten);
03811                   switch_case-> return_target = np2;
03812                }
03813             } else if (p2->type == PV_PATTERN) {
03814                /* ok, generate a extension and link it in */
03815                switch_case = new_exten();
03816                if (mother_exten && mother_exten->checked_switch) {
03817                   switch_case->has_switch = mother_exten->has_switch;
03818                   switch_case->checked_switch = mother_exten->checked_switch;
03819                }
03820                if (exten && exten->checked_switch) {
03821                   switch_case->has_switch = exten->has_switch;
03822                   switch_case->checked_switch = exten->checked_switch;
03823                }
03824                switch_case->context = this_context;
03825                switch_case->is_switch = 1;
03826                /* the break/continue locations are inherited from parent */
03827                switch_case->loop_break = exten->loop_break;
03828                switch_case->loop_continue = exten->loop_continue;
03829 
03830                linkexten(exten,switch_case);
03831                snprintf(buf1, BUF_SIZE, "_sw_%d_%s", local_control_statement_count, p2->u1.str);
03832                switch_case->name = strdup(buf1);
03833                snprintf(new_label, BUF_SIZE, "sw_%s_%s_%d", label, p2->u1.str, local_control_statement_count);
03834 
03835                if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the while body statements here */
03836                   return -1;
03837                }
03838                /* here is where we write code to "fall thru" to the next case... if there is one... */
03839                for (p3=p2->u2.statements; p3; p3=p3->next) {
03840                   if (!p3->next)
03841                      break;
03842                }
03843                /* p3 now points the last statement... */
03844                if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) {
03845                   /* is there a following CASE/PATTERN/DEFAULT? */
03846                   if (p2->next && p2->next->type == PV_CASE) {
03847                      fall_thru = new_prio();
03848                      fall_thru->type = AEL_APPCALL;
03849                      fall_thru->app = strdup("Goto");
03850                      snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, p2->next->u1.str);
03851                      fall_thru->appargs = strdup(buf1);
03852                      linkprio(switch_case, fall_thru, mother_exten);
03853                   } else if (p2->next && p2->next->type == PV_PATTERN) {
03854                      fall_thru = new_prio();
03855                      fall_thru->type = AEL_APPCALL;
03856                      fall_thru->app = strdup("Goto");
03857                      gen_match_to_pattern(p2->next->u1.str, buf2);
03858                      snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, buf2);
03859                      fall_thru->appargs = strdup(buf1);
03860                      linkprio(switch_case, fall_thru, mother_exten);
03861                   } else if (p2->next && p2->next->type == PV_DEFAULT) {
03862                      fall_thru = new_prio();
03863                      fall_thru->type = AEL_APPCALL;
03864                      fall_thru->app = strdup("Goto");
03865                      snprintf(buf1, BUF_SIZE, "sw_%d_.,10", local_control_statement_count);
03866                      fall_thru->appargs = strdup(buf1);
03867                      linkprio(switch_case, fall_thru, mother_exten);
03868                   } else if (!p2->next) {
03869                      fall_thru = new_prio();
03870                      fall_thru->type = AEL_CONTROL1;
03871                      fall_thru->goto_true = switch_end;
03872                      fall_thru->app = strdup("Goto");
03873                      linkprio(switch_case, fall_thru, mother_exten);
03874                   }
03875                }
03876                if (switch_case->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */
03877                   char buf[2000];
03878                   struct ael_priority *np2 = new_prio();
03879                   np2->type = AEL_APPCALL;
03880                   np2->app = strdup("NoOp");
03881                   snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name);
03882                   np2->appargs = strdup(buf);
03883                   linkprio(switch_case, np2, mother_exten);
03884                   switch_case-> return_target = np2;
03885                }
03886             } else if (p2->type == PV_DEFAULT) {
03887                /* ok, generate a extension and link it in */
03888                switch_case = new_exten();
03889                if (mother_exten && mother_exten->checked_switch) {
03890                   switch_case->has_switch = mother_exten->has_switch;
03891                   switch_case->checked_switch = mother_exten->checked_switch;
03892                }
03893                if (exten && exten->checked_switch) {
03894                   switch_case->has_switch = exten->has_switch;
03895                   switch_case->checked_switch = exten->checked_switch;
03896                }
03897                switch_case->context = this_context;
03898                switch_case->is_switch = 1;
03899                
03900                /* new: the default case intros a pattern with ., which covers ALMOST everything.
03901                   but it doesn't cover a NULL pattern. So, we'll define a null extension to match
03902                   that goto's the default extension. */
03903 
03904                default_exists++;
03905                switch_null = new_exten();
03906                if (mother_exten && mother_exten->checked_switch) {
03907                   switch_null->has_switch = mother_exten->has_switch;
03908                   switch_null->checked_switch = mother_exten->checked_switch;
03909                }
03910                if (exten && exten->checked_switch) {
03911                   switch_null->has_switch = exten->has_switch;
03912                   switch_null->checked_switch = exten->checked_switch;
03913                }
03914                switch_null->context = this_context;
03915                switch_null->is_switch = 1;
03916                switch_empty = new_prio();
03917                snprintf(buf1, BUF_SIZE, "sw_%d_.,10", local_control_statement_count);
03918                switch_empty->app = strdup("Goto");
03919                switch_empty->appargs = strdup(buf1);
03920                linkprio(switch_null, switch_empty, mother_exten);
03921                snprintf(buf1, BUF_SIZE, "sw_%d_", local_control_statement_count);
03922                switch_null->name = strdup(buf1);
03923                switch_null->loop_break = exten->loop_break;
03924                switch_null->loop_continue = exten->loop_continue;
03925                linkexten(exten,switch_null);
03926 
03927                /* the break/continue locations are inherited from parent */
03928                switch_case->loop_break = exten->loop_break;
03929                switch_case->loop_continue = exten->loop_continue;
03930                linkexten(exten,switch_case);
03931                snprintf(buf1, BUF_SIZE, "_sw_%d_.", local_control_statement_count);
03932                switch_case->name = strdup(buf1);
03933                
03934                snprintf(new_label, BUF_SIZE, "sw_%s_default_%d", label, local_control_statement_count);
03935                
03936                if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the default:  body statements here */
03937                   return -1;
03938                }
03939                
03940                /* here is where we write code to "fall thru" to the next case... if there is one... */
03941                for (p3=p2->u2.statements; p3; p3=p3->next) {
03942                   if (!p3->next)
03943                      break;
03944                }
03945                /* p3 now points the last statement... */
03946                if (!p3 || (p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) {
03947                   /* is there a following CASE/PATTERN/DEFAULT? */
03948                   if (p2->next && p2->next->type == PV_CASE) {
03949                      fall_thru = new_prio();
03950                      fall_thru->type = AEL_APPCALL;
03951                      fall_thru->app = strdup("Goto");
03952                      snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, p2->next->u1.str);
03953                      fall_thru->appargs = strdup(buf1);
03954                      linkprio(switch_case, fall_thru, mother_exten);
03955                   } else if (p2->next && p2->next->type == PV_PATTERN) {
03956                      fall_thru = new_prio();
03957                      fall_thru->type = AEL_APPCALL;
03958                      fall_thru->app = strdup("Goto");
03959                      gen_match_to_pattern(p2->next->u1.str, buf2);
03960                      snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, buf2);
03961                      fall_thru->appargs = strdup(buf1);
03962                      linkprio(switch_case, fall_thru, mother_exten);
03963                   } else if (p2->next && p2->next->type == PV_DEFAULT) {
03964                      fall_thru = new_prio();
03965                      fall_thru->type = AEL_APPCALL;
03966                      fall_thru->app = strdup("Goto");
03967                      snprintf(buf1, BUF_SIZE, "sw_%d_.,10", local_control_statement_count);
03968                      fall_thru->appargs = strdup(buf1);
03969                      linkprio(switch_case, fall_thru, mother_exten);
03970                   } else if (!p2->next) {
03971                      fall_thru = new_prio();
03972                      fall_thru->type = AEL_CONTROL1;
03973                      fall_thru->goto_true = switch_end;
03974                      fall_thru->app = strdup("Goto");
03975                      linkprio(switch_case, fall_thru, mother_exten);
03976                   }
03977                }
03978                if (switch_case->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */
03979                   char buf[2000];
03980                   struct ael_priority *np2 = new_prio();
03981                   np2->type = AEL_APPCALL;
03982                   np2->app = strdup("NoOp");
03983                   snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name);
03984                   np2->appargs = strdup(buf);
03985                   linkprio(switch_case, np2, mother_exten);
03986                   switch_case-> return_target = np2;
03987                }
03988             } else {
03989                /* what could it be??? */
03990             }
03991          }
03992          
03993          exten->loop_break = loop_break_save;
03994          exten->loop_continue = loop_continue_save;
03995          switch_test->origin = p;
03996          switch_end->origin = p;
03997          break;
03998 
03999       case PV_MACRO_CALL:
04000          pr = new_prio();
04001          pr->type = AEL_APPCALL;
04002          snprintf(buf1, BUF_SIZE, "%s,~~s~~,1", p->u1.str);
04003          first = 1;
04004          for (p2 = p->u2.arglist; p2; p2 = p2->next) {
04005             if (first)
04006             {
04007                strcat(buf1,"(");
04008                first = 0;
04009             }
04010             else
04011                strcat(buf1,",");
04012             strcat(buf1,p2->u1.str);
04013          }
04014          if (!first)
04015             strcat(buf1,")");
04016 
04017          pr->app = strdup("Gosub");
04018          pr->appargs = strdup(buf1);
04019          pr->origin = p;
04020          linkprio(exten, pr, mother_exten);
04021          break;
04022 
04023       case PV_APPLICATION_CALL:
04024          pr = new_prio();
04025          pr->type = AEL_APPCALL;
04026          buf1[0] = 0;
04027          for (p2 = p->u2.arglist; p2; p2 = p2->next) {
04028             if (p2 != p->u2.arglist )
04029                strcat(buf1,",");
04030             strcat(buf1,p2->u1.str);
04031          }
04032          pr->app = strdup(p->u1.str);
04033          pr->appargs = strdup(buf1);
04034          pr->origin = p;
04035          linkprio(exten, pr, mother_exten);
04036          break;
04037 
04038       case PV_BREAK:
04039          pr = new_prio();
04040          pr->type = AEL_CONTROL1; /* simple goto */
04041          pr->goto_true = exten->loop_break;
04042          pr->origin = p;
04043          linkprio(exten, pr, mother_exten);
04044          break;
04045 
04046       case PV_RETURN: /* hmmmm */
04047          pr = new_prio();
04048          pr->type = AEL_RETURN; /* simple Return */
04049          /* exten->return_needed++; */
04050          pr->app = strdup("Return");
04051          pr->appargs = strdup("");
04052          pr->origin = p;
04053          linkprio(exten, pr, mother_exten);
04054          break;
04055 
04056       case PV_CONTINUE:
04057          pr = new_prio();
04058          pr->type = AEL_CONTROL1; /* simple goto */
04059          pr->goto_true = exten->loop_continue;
04060          pr->origin = p;
04061          linkprio(exten, pr, mother_exten);
04062          break;
04063 
04064       case PV_IFTIME:
04065          control_statement_count++;
04066          snprintf(new_label, BUF_SIZE, "iftime_%s_%d", label, control_statement_count);
04067          
04068          if_test = new_prio();
04069          if_test->type = AEL_IFTIME_CONTROL;
04070          snprintf(buf1, BUF_SIZE, "%s,%s,%s,%s",
04071                 p->u1.list->u1.str, 
04072                 p->u1.list->next->u1.str, 
04073                 p->u1.list->next->next->u1.str, 
04074                 p->u1.list->next->next->next->u1.str);
04075          if_test->app = 0;
04076          if_test->appargs = strdup(buf1);
04077          if_test->origin = p;
04078 
04079          if_end = new_prio();
04080          if_end->type = AEL_APPCALL;
04081          snprintf(buf1, BUF_SIZE, "Finish iftime_%s_%d", label, control_statement_count);
04082          if_end->app = strdup("NoOp");
04083          if_end->appargs = strdup(buf1);
04084 
04085          if (p->u3.else_statements) {
04086             if_skip = new_prio();
04087             if_skip->type = AEL_CONTROL1; /* simple goto */
04088             if_skip->goto_true = if_end;
04089             if_skip->origin  = p;
04090 
04091          } else {
04092             if_skip = 0;
04093 
04094             if_test->goto_false = if_end;
04095          }
04096 
04097          if_false = new_prio();
04098          if_false->type = AEL_CONTROL1;
04099          if (p->u3.else_statements) {
04100             if_false->goto_true = if_skip; /* +1 */
04101          } else {
04102             if_false->goto_true = if_end;
04103          }
04104          
04105          /* link & load! */
04106          linkprio(exten, if_test, mother_exten);
04107          linkprio(exten, if_false, mother_exten);
04108          
04109          /* now, put the body of the if here */
04110          
04111          if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the statements here */
04112             return -1;
04113          }
04114          
04115          if (p->u3.else_statements) {
04116             linkprio(exten, if_skip, mother_exten);
04117             if (gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context)) { /* this will link in all the statements here */
04118                return -1;
04119             }
04120          }
04121          
04122          linkprio(exten, if_end, mother_exten);
04123          
04124          break;
04125 
04126       case PV_RANDOM:
04127       case PV_IF:
04128          control_statement_count++;
04129          snprintf(new_label, BUF_SIZE, "if_%s_%d", label, control_statement_count);
04130          
04131          if_test = new_prio();
04132          if_end = new_prio();
04133          if_test->type = AEL_IF_CONTROL;
04134          if_end->type = AEL_APPCALL;
04135          if ( p->type == PV_RANDOM )
04136             snprintf(buf1, BUF_SIZE, "$[${RAND(0,99)} < (%s)]", p->u1.str);
04137          else
04138             snprintf(buf1, BUF_SIZE, "$[%s]", p->u1.str);
04139          if_test->app = 0;
04140          if_test->appargs = strdup(buf1);
04141          snprintf(buf1, BUF_SIZE, "Finish if_%s_%d", label, control_statement_count);
04142          if_end->app = strdup("NoOp");
04143          if_end->appargs = strdup(buf1);
04144          if_test->origin = p;
04145          
04146          if (p->u3.else_statements) {
04147             if_skip = new_prio();
04148             if_skip->type = AEL_CONTROL1; /* simple goto */
04149             if_skip->goto_true = if_end;
04150             if_test->goto_false = if_skip;;
04151          } else {
04152             if_skip = 0;
04153             if_test->goto_false = if_end;;
04154          }
04155          
04156          /* link & load! */
04157          linkprio(exten, if_test, mother_exten);
04158          
04159          /* now, put the body of the if here */
04160          
04161          if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the statements here */
04162             return -1;
04163          }
04164          
04165          if (p->u3.else_statements) {
04166             linkprio(exten, if_skip, mother_exten);
04167             if (gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context)) { /* this will link in all the statements here */
04168                return -1;
04169             }
04170          }
04171          
04172          linkprio(exten, if_end, mother_exten);
04173          
04174          break;
04175 
04176       case PV_STATEMENTBLOCK:
04177          if (gen_prios(exten, label, p->u1.list, mother_exten, this_context)) { /* recurse into the block */
04178             return -1;
04179          }
04180          break;
04181 
04182       case PV_CATCH:
04183          control_statement_count++;
04184          /* generate an extension with name of catch, put all catch stats
04185             into this exten! */
04186          switch_case = new_exten();
04187          if (mother_exten && mother_exten->checked_switch) {
04188             switch_case->has_switch = mother_exten->has_switch;
04189             switch_case->checked_switch = mother_exten->checked_switch;
04190          }
04191          if (exten && exten->checked_switch) {
04192             switch_case->has_switch = exten->has_switch;
04193             switch_case->checked_switch = exten->checked_switch;
04194          }
04195          
04196          switch_case->context = this_context;
04197          linkexten(exten,switch_case);
04198          switch_case->name = strdup(p->u1.str);
04199          snprintf(new_label, BUF_SIZE, "catch_%s_%d",p->u1.str, control_statement_count);
04200          
04201          if (gen_prios(switch_case, new_label, p->u2.statements, mother_exten,this_context)) { /* this will link in all the catch body statements here */
04202             return -1;
04203          }
04204          if (switch_case->return_needed) { /* returns now generate a Return() app call, no longer a goto to the end of the exten */
04205             char buf[2000];
04206             struct ael_priority *np2 = new_prio();
04207             np2->type = AEL_APPCALL;
04208             np2->app = strdup("NoOp");
04209             snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name);
04210             np2->appargs = strdup(buf);
04211             linkprio(switch_case, np2, mother_exten);
04212             switch_case-> return_target = np2;
04213          }
04214 
04215          break;
04216       default:
04217          break;
04218       }
04219    }
04220    free(buf1);
04221    free(buf2);
04222    free(new_label);
04223    return 0;
04224 }

static pval * get_contxt ( pval p  )  [static]

Definition at line 4384 of file pval.c.

References pval::dad, PV_CONTEXT, PV_MACRO, and pval::type.

Referenced by check_goto(), and get_goto_target().

04385 {
04386    while( p && p->type != PV_CONTEXT && p->type != PV_MACRO ) {
04387       
04388       p = p->dad;
04389    }
04390    
04391    return p;
04392 }

static pval * get_extension_or_contxt ( pval p  )  [static]

Definition at line 4374 of file pval.c.

References pval::dad, PV_CONTEXT, PV_EXTENSION, PV_MACRO, and pval::type.

Referenced by check_goto(), and get_goto_target().

04375 {
04376    while( p && p->type != PV_EXTENSION && p->type != PV_CONTEXT && p->type != PV_MACRO ) {
04377       
04378       p = p->dad;
04379    }
04380    
04381    return p;
04382 }

static pval * get_goto_target ( pval item  )  [static]

Definition at line 1161 of file pval.c.

References find_context(), find_label_in_current_context(), find_label_in_current_db(), find_label_in_current_extension(), first, get_contxt(), get_extension_or_contxt(), pval::list, pval::next, PV_INCLUDES, pval::statements, pval::str, pval::type, pval::u1, and pval::u2.

Referenced by gen_prios().

01162 {
01163    /* just one item-- the label should be in the current extension */
01164    pval *curr_ext = get_extension_or_contxt(item); /* containing exten, or macro */
01165    pval *curr_cont;
01166    
01167    if (!item->u1.list) {
01168       return NULL;
01169    }
01170 
01171    if (!item->u1.list->next && !strstr((item->u1.list)->u1.str,"${")) {
01172       struct pval *x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), curr_ext);
01173          return x;
01174    }
01175 
01176    curr_cont = get_contxt(item);
01177 
01178    /* TWO items */
01179    if (item->u1.list->next && !item->u1.list->next->next) {
01180       if (!strstr((item->u1.list)->u1.str,"${") 
01181          && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ {
01182          struct pval *x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, curr_cont);
01183             return x;
01184       }
01185    }
01186    
01187    /* All 3 items! */
01188    if (item->u1.list->next && item->u1.list->next->next) {
01189       /* all three */
01190       pval *first = item->u1.list;
01191       pval *second = item->u1.list->next;
01192       pval *third = item->u1.list->next->next;
01193       
01194       if (!strstr((item->u1.list)->u1.str,"${") 
01195          && !strstr(item->u1.list->next->u1.str,"${")
01196          && !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ {
01197          struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str);
01198          if (!x) {
01199 
01200             struct pval *p3;
01201             struct pval *that_context = find_context(item->u1.list->u1.str);
01202             
01203             /* the target of the goto could be in an included context!! Fancy that!! */
01204             /* look for includes in the current context */
01205             if (that_context) {
01206                for (p3=that_context->u2.statements; p3; p3=p3->next) {
01207                   if (p3->type == PV_INCLUDES) {
01208                      struct pval *p4;
01209                      for (p4=p3->u1.list; p4; p4=p4->next) {
01210                         /* for each context pointed to, find it, then find a context/label that matches the
01211                            target here! */
01212                         char *incl_context = p4->u1.str;
01213                         /* find a matching context name */
01214                         struct pval *that_other_context = find_context(incl_context);
01215                         if (that_other_context) {
01216                            struct pval *x3;
01217                            x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context);
01218                            if (x3) {
01219                               return x3;
01220                            }
01221                         }
01222                      }
01223                   }
01224                }
01225             }
01226          }
01227          return x;
01228       }
01229    }
01230    return NULL;
01231 }

static struct pval* in_context ( pval item  )  [static]

Definition at line 1098 of file pval.c.

References pval::dad, PV_CONTEXT, PV_MACRO, and pval::type.

Referenced by check_goto().

01099 {
01100    struct pval *curr;
01101    curr = item;   
01102    while( curr ) {
01103       if( curr->type == PV_MACRO || curr->type == PV_CONTEXT ) {
01104          return curr;
01105       }
01106       curr = curr->dad;
01107    }
01108    return 0;
01109 }

static struct pval* in_macro ( pval item  )  [static]

Definition at line 1085 of file pval.c.

References pval::dad, PV_MACRO, and pval::type.

Referenced by check_goto().

01086 {
01087    struct pval *curr;
01088    curr = item;   
01089    while( curr ) {
01090       if( curr->type == PV_MACRO  ) {
01091          return curr;
01092       }
01093       curr = curr->dad;
01094    }
01095    return 0;
01096 }

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 label_inside_case ( pval label  )  [static]

Definition at line 3026 of file pval.c.

References pval::dad, PV_CASE, PV_CONTEXT, PV_DEFAULT, PV_MACRO, PV_PATTERN, and pval::type.

Referenced by gen_prios().

03027 {
03028    pval *p = label;
03029    
03030    while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ {
03031       if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN ) {
03032          return 1;
03033       }
03034 
03035       p = p->dad;
03036    }
03037    return 0;
03038 }

static void linkexten ( struct ael_extension exten,
struct ael_extension add 
) [static]

Definition at line 3040 of file pval.c.

References exten, and ael_extension::next_exten.

Referenced by gen_prios().

03041 {
03042    add->next_exten = exten->next_exten; /* this will reverse the order. Big deal. */
03043    exten->next_exten = add;
03044 }

void linkprio ( struct ael_extension exten,
struct ael_priority prio,
struct ael_extension mother_exten 
)

Definition at line 2944 of file pval.c.

References ael_priority::appargs, ael_priority::exten, exten, free, ael_extension::has_switch, and malloc.

Referenced by gen_prios().

02945 {
02946    char *p1, *p2;
02947    
02948    if (!exten->plist) {
02949       exten->plist = prio;
02950       exten->plist_last = prio;
02951    } else {
02952       exten->plist_last->next = prio;
02953       exten->plist_last = prio;
02954    }
02955    if( !prio->exten )
02956       prio->exten = exten; /* don't override the switch value */
02957    /* The following code will cause all priorities within an extension 
02958       to have ${EXTEN} or ${EXTEN: replaced with ~~EXTEN~~, which is
02959       set just before the first switch in an exten. The switches
02960       will muck up the original ${EXTEN} value, so we save it away
02961       and the user accesses this copy instead. */
02962    if (prio->appargs && ((mother_exten && mother_exten->has_switch) || exten->has_switch) ) {
02963       while ((p1 = strstr(prio->appargs, "${EXTEN}"))) {
02964          p2 = malloc(strlen(prio->appargs)+5);
02965          *p1 = 0;
02966          strcpy(p2, prio->appargs);
02967          strcat(p2, "${~~EXTEN~~}");
02968          if (*(p1+8))
02969             strcat(p2, p1+8);
02970          free(prio->appargs);
02971          prio->appargs = p2;
02972       }
02973       while ((p1 = strstr(prio->appargs, "${EXTEN:"))) {
02974          p2 = malloc(strlen(prio->appargs)+5);
02975          *p1 = 0;
02976          strcpy(p2, prio->appargs);
02977          strcat(p2, "${~~EXTEN~~:");
02978          if (*(p1+8))
02979             strcat(p2, p1+8);
02980          free(prio->appargs);
02981          prio->appargs = p2;
02982       }
02983    }
02984 }

pval* linku1 ( pval head,
pval tail 
)

Definition at line 5927 of file pval.c.

References pval::next, pval::prev, and pval::u1_last.

05928 {
05929    if (!head)
05930       return tail;
05931    if (tail) {
05932       if (!head->next) {
05933          head->next = tail;
05934       } else {
05935          head->u1_last->next = tail;
05936       }
05937       head->u1_last = tail;
05938       tail->prev = head; /* the dad link only points to containers */
05939    }
05940    return head;
05941 }

int localized_pbx_load_module ( void   ) 

struct pval * match_pval ( pval item  ) 

Definition at line 1819 of file pval.c.

References match_pval_item(), and pval::next.

Referenced by find_context(), find_first_label_in_current_context(), find_label_in_current_context(), find_label_in_current_db(), find_label_in_current_extension(), find_macro(), and match_pval_item().

01820 {
01821    pval *i;
01822 
01823    for (i=item; i; i=i->next) {
01824       pval *x;
01825       /* printf("   -- match pval: item %d\n", i->type); */
01826       
01827       if ((x = match_pval_item(i))) {
01828          /* printf("match_pval: returning x=%x\n", (int)x); */
01829          return x; /* cut the search short */
01830       }
01831    }
01832    return 0;
01833 }

static struct pval* match_pval_item ( pval item  )  [static]

Definition at line 1571 of file pval.c.

References pval::else_statements, extension_matches(), pval::for_statements, last_matched_label, pval::list, pval::macro_statements, match_pval(), pval::next, PV_CASE, PV_CATCH, PV_CONTEXT, PV_DEFAULT, PV_EXTENSION, PV_FOR, PV_IF, PV_IFTIME, PV_LABEL, PV_MACRO, PV_PATTERN, PV_RANDOM, PV_STATEMENTBLOCK, PV_SWITCH, PV_WHILE, pval::statements, pval::str, pval::type, pval::u1, pval::u2, pval::u3, and pval::u4.

Referenced by match_pval().

01572 {
01573    pval *x;
01574    
01575    switch ( item->type ) {
01576    case PV_MACRO:
01577       /* fields: item->u1.str     == name of macro
01578                  item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
01579                item->u2.arglist->u1.str  == argument
01580                item->u2.arglist->next   == next arg
01581 
01582                item->u3.macro_statements == pval list of statements in macro body.
01583       */
01584       /* printf("    matching in MACRO %s, match_context=%s; retoncontmtch=%d; \n", item->u1.str, match_context, return_on_context_match); */
01585       if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) {
01586          
01587          /* printf("MACRO: match context is: %s\n", match_context); */
01588          
01589          if (return_on_context_match && !strcmp(item->u1.str, match_context)) /* if we're just searching for a context, don't bother descending into them */ {
01590             /* printf("Returning on matching macro %s\n", match_context); */
01591             return item;
01592          }
01593          
01594          
01595          if (!return_on_context_match) {
01596             /* printf("Descending into matching macro %s/%s\n", match_context, item->u1.str); */
01597             if ((x=match_pval(item->u3.macro_statements)))  {
01598                /* printf("Responded with pval match %x\n", x); */
01599                return x;
01600             }
01601          }
01602       } else {
01603          /* printf("Skipping context/macro %s\n", item->u1.str); */
01604       }
01605       
01606       break;
01607          
01608    case PV_CONTEXT:
01609       /* fields: item->u1.str     == name of context
01610                  item->u2.statements == pval list of statements in context body
01611                item->u3.abstract == int 1 if an abstract keyword were present
01612       */
01613       /* printf("    matching in CONTEXT\n"); */
01614       if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) {
01615          if (return_on_context_match && !strcmp(item->u1.str, match_context)) {
01616             /* printf("Returning on matching context %s\n", match_context); */
01617             /* printf("non-CONTEXT: Responded with pval match %x\n", x); */
01618             return item;
01619          }
01620          
01621          if (!return_on_context_match ) {
01622             /* printf("Descending into matching context %s\n", match_context); */
01623             if ((x=match_pval(item->u2.statements))) /* if we're just searching for a context, don't bother descending into them */ {
01624                /* printf("CONTEXT: Responded with pval match %x\n", x); */
01625                return x;
01626             }
01627          }
01628       } else {
01629          /* printf("Skipping context/macro %s\n", item->u1.str); */
01630       }
01631       break;
01632 
01633    case PV_CASE:
01634       /* fields: item->u1.str     == value of case
01635                  item->u2.statements == pval list of statements under the case
01636       */
01637       /* printf("    matching in CASE\n"); */
01638       if ((x=match_pval(item->u2.statements))) {
01639          /* printf("CASE: Responded with pval match %x\n", x); */
01640          return x;
01641       }
01642       break;
01643          
01644    case PV_PATTERN:
01645       /* fields: item->u1.str     == value of case
01646                  item->u2.statements == pval list of statements under the case
01647       */
01648       /* printf("    matching in PATTERN\n"); */
01649       if ((x=match_pval(item->u2.statements))) {
01650          /* printf("PATTERN: Responded with pval match %x\n", x); */
01651          return x;
01652       }
01653       break;
01654          
01655    case PV_DEFAULT:
01656       /* fields: 
01657                  item->u2.statements == pval list of statements under the case
01658       */
01659       /* printf("    matching in DEFAULT\n"); */
01660       if ((x=match_pval(item->u2.statements))) {
01661          /* printf("DEFAULT: Responded with pval match %x\n", x); */
01662          return x;
01663       }
01664       break;
01665          
01666    case PV_CATCH:
01667       /* fields: item->u1.str     == name of extension to catch
01668                  item->u2.statements == pval list of statements in context body
01669       */
01670       /* printf("    matching in CATCH\n"); */
01671       if ((x=match_pval(item->u2.statements))) {
01672          /* printf("CATCH: Responded with pval match %x\n", x); */
01673          return x;
01674       }
01675       break;
01676          
01677    case PV_STATEMENTBLOCK:
01678       /* fields: item->u1.list     == pval list of statements in block, one per entry in the list
01679       */
01680       /* printf("    matching in STATEMENTBLOCK\n"); */
01681       if ((x=match_pval(item->u1.list))) {
01682          /* printf("STATEMENTBLOCK: Responded with pval match %x\n", x); */
01683          return x;
01684       }
01685       break;
01686          
01687    case PV_LABEL:
01688       /* fields: item->u1.str     == label name
01689       */
01690       /* printf("PV_LABEL %s (cont=%s, exten=%s\n", 
01691          item->u1.str, current_context->u1.str, (current_extension?current_extension->u1.str:"<macro>"));*/
01692       
01693       if (count_labels) {
01694          if (!strcmp(match_label, item->u1.str)) {
01695             label_count++;
01696             last_matched_label = item;
01697          }
01698          
01699       } else {
01700          if (!strcmp(match_label, item->u1.str)) {
01701             /* printf("LABEL: Responded with pval match %x\n", x); */
01702             return item;
01703          }
01704       }
01705       break;
01706          
01707    case PV_FOR:
01708       /* fields: item->u1.for_init     == a string containing the initalizer
01709                  item->u2.for_test     == a string containing the loop test
01710                  item->u3.for_inc      == a string containing the loop increment
01711 
01712                item->u4.for_statements == a pval list of statements in the for ()
01713       */
01714       /* printf("    matching in FOR\n"); */
01715       if ((x=match_pval(item->u4.for_statements))) {
01716          /* printf("FOR: Responded with pval match %x\n", x);*/
01717          return x;
01718       }
01719       break;
01720          
01721    case PV_WHILE:
01722       /* fields: item->u1.str        == the while conditional, as supplied by user
01723 
01724                item->u2.statements == a pval list of statements in the while ()
01725       */
01726       /* printf("    matching in WHILE\n"); */
01727       if ((x=match_pval(item->u2.statements))) {
01728          /* printf("WHILE: Responded with pval match %x\n", x); */
01729          return x;
01730       }
01731       break;
01732          
01733    case PV_RANDOM:
01734       /* fields: item->u1.str        == the random number expression, as supplied by user
01735 
01736                item->u2.statements == a pval list of statements in the if ()
01737                item->u3.else_statements == a pval list of statements in the else
01738                                     (could be zero)
01739        fall thru to PV_IF */
01740       
01741    case PV_IFTIME:
01742       /* fields: item->u1.list        == the time values, 4 of them, as PV_WORD structs in a list
01743 
01744                item->u2.statements == a pval list of statements in the if ()
01745                item->u3.else_statements == a pval list of statements in the else
01746                                     (could be zero)
01747       fall thru to PV_IF*/
01748    case PV_IF:
01749       /* fields: item->u1.str        == the if conditional, as supplied by user
01750 
01751                item->u2.statements == a pval list of statements in the if ()
01752                item->u3.else_statements == a pval list of statements in the else
01753                                     (could be zero)
01754       */
01755       /* printf("    matching in IF/IFTIME/RANDOM\n"); */
01756       if ((x=match_pval(item->u2.statements))) {
01757          return x;
01758       }
01759       if (item->u3.else_statements) {
01760          if ((x=match_pval(item->u3.else_statements))) {
01761             /* printf("IF/IFTIME/RANDOM: Responded with pval match %x\n", x); */
01762             return x;
01763          }
01764       }
01765       break;
01766          
01767    case PV_SWITCH:
01768       /* fields: item->u1.str        == the switch expression
01769 
01770                item->u2.statements == a pval list of statements in the switch, 
01771                                     (will be case statements, most likely!)
01772       */
01773       /* printf("    matching in SWITCH\n"); */
01774       if ((x=match_pval(item->u2.statements))) {
01775          /* printf("SWITCH: Responded with pval match %x\n", x); */
01776          return x;
01777       }
01778       break;
01779          
01780    case PV_EXTENSION:
01781       /* fields: item->u1.str        == the extension name, label, whatever it's called
01782 
01783                item->u2.statements == a pval list of statements in the extension
01784                item->u3.hints      == a char * hint argument
01785                item->u4.regexten   == an int boolean. non-zero says that regexten was specified
01786       */
01787       /* printf("    matching in EXTENSION\n"); */
01788       if (!strcmp(match_exten,"*") || extension_matches(item, match_exten, item->u1.str) ) {
01789          /* printf("Descending into matching exten %s => %s\n", match_exten, item->u1.str); */
01790          if (strcmp(match_label,"1") == 0) {
01791             if (item->u2.statements) {
01792                struct pval *p5 = item->u2.statements;
01793                while (p5 && p5->type == PV_LABEL)  /* find the first non-label statement in this context. If it exists, there's a "1" */
01794                   p5 = p5->next;
01795                if (p5)
01796                   return p5;
01797                else
01798                   return 0;
01799             }
01800             else
01801                return 0;
01802          }
01803 
01804          if ((x=match_pval(item->u2.statements))) {
01805             /* printf("EXTENSION: Responded with pval match %x\n", x); */
01806             return x;
01807          }
01808       } else {
01809          /* printf("Skipping exten %s\n", item->u1.str); */
01810       }
01811       break;
01812    default:
01813       /* printf("    matching in default = %d\n", item->type); */
01814       break;
01815    }
01816    return 0;
01817 }

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 void print_pval ( FILE *  fin,
pval item,
int  depth 
) [static]

Definition at line 118 of file pval.c.

References pval::arglist, pval::next, PV_MACRO, PV_WORD, pval::str, pval::type, pval::u1, and pval::u2.

Referenced by print_pval_list().

00119 {
00120    int i;
00121    pval *lp;
00122    
00123    for (i=0; i<depth; i++) {
00124       fprintf(fin, "\t"); /* depth == indentation */
00125    }
00126    
00127    switch ( item->type ) {
00128    case PV_WORD:
00129       fprintf(fin,"%s;\n", item->u1.str); /* usually, words are encapsulated in something else */
00130       break;
00131       
00132    case PV_MACRO:
00133       fprintf(fin,"macro %s(", item->u1.str);
00134       for (lp=item->u2.arglist; lp; lp=lp->next) {
00135          if (lp != item->u2.arglist )
00136             fprintf(fin,", ");
00137          fprintf(fin,"%s", lp->u1.str);
00138       }
00139       fprintf(fin,") {\n");
00140       print_pval_list(fin,item->u3.macro_statements,depth+1);
00141       for (i=0; i<depth; i++) {
00142          fprintf(fin,"\t"); /* depth == indentation */
00143       }
00144       fprintf(fin,"};\n\n");
00145       break;
00146          
00147    case PV_CONTEXT:
00148       if ( item->u3.abstract )
00149          fprintf(fin,"abstract context %s {\n", item->u1.str);
00150       else
00151          fprintf(fin,"context %s {\n", item->u1.str);
00152       print_pval_list(fin,item->u2.statements,depth+1);
00153       for (i=0; i<depth; i++) {
00154          fprintf(fin,"\t"); /* depth == indentation */
00155       }
00156       fprintf(fin,"};\n\n");
00157       break;
00158          
00159    case PV_MACRO_CALL:
00160       fprintf(fin,"&%s(", item->u1.str);
00161       for (lp=item->u2.arglist; lp; lp=lp->next) {
00162          if ( lp != item->u2.arglist )
00163             fprintf(fin,", ");
00164          fprintf(fin,"%s", lp->u1.str);
00165       }
00166       fprintf(fin,");\n");
00167       break;
00168          
00169    case PV_APPLICATION_CALL:
00170       fprintf(fin,"%s(", item->u1.str);
00171       for (lp=item->u2.arglist; lp; lp=lp->next) {
00172          if ( lp != item->u2.arglist )
00173             fprintf(fin,",");
00174          fprintf(fin,"%s", lp->u1.str);
00175       }
00176       fprintf(fin,");\n");
00177       break;
00178          
00179    case PV_CASE:
00180       fprintf(fin,"case %s:\n", item->u1.str);
00181       print_pval_list(fin,item->u2.statements, depth+1);
00182       break;
00183          
00184    case PV_PATTERN:
00185       fprintf(fin,"pattern %s:\n", item->u1.str);
00186       print_pval_list(fin,item->u2.statements, depth+1);
00187       break;
00188          
00189    case PV_DEFAULT:
00190       fprintf(fin,"default:\n");
00191       print_pval_list(fin,item->u2.statements, depth+1);
00192       break;
00193          
00194    case PV_CATCH:
00195       fprintf(fin,"catch %s {\n", item->u1.str);
00196       print_pval_list(fin,item->u2.statements, depth+1);
00197       for (i=0; i<depth; i++) {
00198          fprintf(fin,"\t"); /* depth == indentation */
00199       }
00200       fprintf(fin,"};\n");
00201       break;
00202          
00203    case PV_SWITCHES:
00204       fprintf(fin,"switches {\n");
00205       print_pval_list(fin,item->u1.list,depth+1);
00206       for (i=0; i<depth; i++) {
00207          fprintf(fin,"\t"); /* depth == indentation */
00208       }
00209       fprintf(fin,"};\n");
00210       break;
00211          
00212    case PV_ESWITCHES:
00213       fprintf(fin,"eswitches {\n");
00214       print_pval_list(fin,item->u1.list,depth+1);
00215       for (i=0; i<depth; i++) {
00216          fprintf(fin,"\t"); /* depth == indentation */
00217       }
00218       fprintf(fin,"};\n");
00219       break;
00220          
00221    case PV_INCLUDES:
00222       fprintf(fin,"includes {\n");
00223       for (lp=item->u1.list; lp; lp=lp->next) {
00224          for (i=0; i<depth+1; i++) {
00225             fprintf(fin,"\t"); /* depth == indentation */
00226          }
00227          fprintf(fin,"%s", lp->u1.str); /* usually, words are encapsulated in something else */
00228          if (lp->u2.arglist)
00229             fprintf(fin,"|%s|%s|%s|%s", 
00230                   lp->u2.arglist->u1.str,
00231                   lp->u2.arglist->next->u1.str,
00232                   lp->u2.arglist->next->next->u1.str,
00233                   lp->u2.arglist->next->next->next->u1.str
00234                );
00235          fprintf(fin,";\n"); /* usually, words are encapsulated in something else */
00236       }
00237       
00238       for (i=0; i<depth; i++) {
00239          fprintf(fin,"\t"); /* depth == indentation */
00240       }
00241       fprintf(fin,"};\n");
00242       break;
00243          
00244    case PV_STATEMENTBLOCK:
00245       fprintf(fin,"{\n");
00246       print_pval_list(fin,item->u1.list, depth+1);
00247       for (i=0; i<depth; i++) {
00248          fprintf(fin,"\t"); /* depth == indentation */
00249       }
00250       fprintf(fin,"}\n");
00251       break;
00252          
00253    case PV_VARDEC:
00254       fprintf(fin,"%s=%s;\n", item->u1.str, item->u2.val);
00255       break;
00256          
00257    case PV_LOCALVARDEC:
00258       fprintf(fin,"local %s=%s;\n", item->u1.str, item->u2.val);
00259       break;
00260          
00261    case PV_GOTO:
00262       fprintf(fin,"goto %s", item->u1.list->u1.str);
00263       if ( item->u1.list->next )
00264          fprintf(fin,",%s", item->u1.list->next->u1.str);
00265       if ( item->u1.list->next && item->u1.list->next->next )
00266          fprintf(fin,",%s", item->u1.list->next->next->u1.str);
00267       fprintf(fin,"\n");
00268       break;
00269          
00270    case PV_LABEL:
00271       fprintf(fin,"%s:\n", item->u1.str);
00272       break;
00273          
00274    case PV_FOR:
00275       fprintf(fin,"for (%s; %s; %s)\n", item->u1.for_init, item->u2.for_test, item->u3.for_inc);
00276       print_pval_list(fin,item->u4.for_statements,depth+1);
00277       break;
00278          
00279    case PV_WHILE:
00280       fprintf(fin,"while (%s)\n", item->u1.str);
00281       print_pval_list(fin,item->u2.statements,depth+1);
00282       break;
00283          
00284    case PV_BREAK:
00285       fprintf(fin,"break;\n");
00286       break;
00287          
00288    case PV_RETURN:
00289       fprintf(fin,"return;\n");
00290       break;
00291          
00292    case PV_CONTINUE:
00293       fprintf(fin,"continue;\n");
00294       break;
00295          
00296    case PV_RANDOM:
00297    case PV_IFTIME:
00298    case PV_IF:
00299       if ( item->type == PV_IFTIME ) {
00300          
00301          fprintf(fin,"ifTime ( %s|%s|%s|%s )\n", 
00302                item->u1.list->u1.str, 
00303                item->u1.list->next->u1.str, 
00304                item->u1.list->next->next->u1.str, 
00305                item->u1.list->next->next->next->u1.str
00306                );
00307       } else if ( item->type == PV_RANDOM ) {
00308          fprintf(fin,"random ( %s )\n", item->u1.str );
00309       } else
00310          fprintf(fin,"if ( %s )\n", item->u1.str);
00311       if ( item->u2.statements && item->u2.statements->next ) {
00312          for (i=0; i<depth; i++) {
00313             fprintf(fin,"\t"); /* depth == indentation */
00314          }
00315          fprintf(fin,"{\n");
00316          print_pval_list(fin,item->u2.statements,depth+1);
00317          for (i=0; i<depth; i++) {
00318             fprintf(fin,"\t"); /* depth == indentation */
00319          }
00320          if ( item->u3.else_statements )
00321             fprintf(fin,"}\n");
00322          else
00323             fprintf(fin,"};\n");
00324       } else if (item->u2.statements ) {
00325          print_pval_list(fin,item->u2.statements,depth+1);
00326       } else {
00327          if (item->u3.else_statements )
00328             fprintf(fin, " {} ");
00329          else
00330             fprintf(fin, " {}; ");
00331       }
00332       if ( item->u3.else_statements ) {
00333          for (i=0; i<depth; i++) {
00334             fprintf(fin,"\t"); /* depth == indentation */
00335          }
00336          fprintf(fin,"else\n");
00337          print_pval_list(fin,item->u3.else_statements, depth);
00338       }
00339       break;
00340          
00341    case PV_SWITCH:
00342       fprintf(fin,"switch( %s ) {\n", item->u1.str);
00343       print_pval_list(fin,item->u2.statements,depth+1);
00344       for (i=0; i<depth; i++) {
00345          fprintf(fin,"\t"); /* depth == indentation */
00346       }
00347       fprintf(fin,"}\n");
00348       break;
00349          
00350    case PV_EXTENSION:
00351       if ( item->u4.regexten )
00352          fprintf(fin, "regexten ");
00353       if ( item->u3.hints )
00354          fprintf(fin,"hints(%s) ", item->u3.hints);
00355       
00356       fprintf(fin,"%s => ", item->u1.str);
00357       print_pval_list(fin,item->u2.statements,depth+1);
00358       fprintf(fin,"\n");
00359       break;
00360          
00361    case PV_IGNOREPAT:
00362       fprintf(fin,"ignorepat => %s;\n", item->u1.str);
00363       break;
00364          
00365    case PV_GLOBALS:
00366       fprintf(fin,"globals {\n");
00367       print_pval_list(fin,item->u1.statements,depth+1);
00368       for (i=0; i<depth; i++) {
00369          fprintf(fin,"\t"); /* depth == indentation */
00370       }
00371       fprintf(fin,"}\n");
00372       break;
00373    }
00374 }

static void print_pval_list ( FILE *  fin,
pval item,
int  depth 
) [static]

Definition at line 376 of file pval.c.

References pval::next, and print_pval().

Referenced by ael2_print().

00377 {
00378    pval *i;
00379    
00380    for (i=item; i; i=i->next) {
00381       print_pval(fin, i, depth);
00382    }
00383 }

void pvalAppCallAddArg ( pval p,
pval arg 
)

Definition at line 5305 of file pval.c.

References pval::arglist, linku1(), PV_APPLICATION_CALL, pvalCheckType(), and pval::u2.

05306 {
05307    if (!pvalCheckType(p, "pvalAppCallAddArg", PV_APPLICATION_CALL))
05308       return;
05309    if (!p->u2.arglist)
05310       p->u2.arglist = arg;
05311    else
05312       linku1(p->u2.arglist, arg);
05313 }

char* pvalAppCallGetAppName ( pval p  ) 

Definition at line 5291 of file pval.c.

References PV_APPLICATION_CALL, pvalCheckType(), pval::str, and pval::u1.

05292 {
05293    if (!pvalCheckType(p, "pvalAppCallGetAppName", PV_APPLICATION_CALL))
05294       return 0;
05295    return p->u1.str;
05296 }

void pvalAppCallSetAppName ( pval p,
char *  name 
)

Definition at line 5284 of file pval.c.

References PV_APPLICATION_CALL, pvalCheckType(), pval::str, and pval::u1.

05285 {
05286    if (!pvalCheckType(p, "pvalAppCallSetAppName", PV_APPLICATION_CALL))
05287       return;
05288    p->u1.str = name;
05289 }

void pvalAppCallSetArglist ( pval p,
pval arglist 
)

Definition at line 5298 of file pval.c.

References pval::arglist, PV_APPLICATION_CALL, pvalCheckType(), and pval::u2.

05299 {
05300    if (!pvalCheckType(p, "pvalAppCallSetArglist", PV_APPLICATION_CALL))
05301       return;
05302    p->u2.arglist = arglist;
05303 }

pval* pvalAppCallWalkArgs ( pval p,
pval **  args 
)

Definition at line 5315 of file pval.c.

References pval::arglist, args, PV_APPLICATION_CALL, pvalCheckType(), and pval::u2.

05316 {
05317    if (!pvalCheckType(p, "pvalAppCallWalkArgs", PV_APPLICATION_CALL))
05318       return 0;
05319    if (!(*args))
05320       *args = p->u2.arglist;
05321    else {
05322       *args = (*args)->next;
05323    }
05324    return *args;
05325 }

void pvalCasePatDefAddStatement ( pval p,
pval statement 
)

Definition at line 5340 of file pval.c.

References pval::arglist, linku1(), pval::statements, and pval::u2.

05341 {
05342    if (!p->u2.arglist)
05343       p->u2.statements = statement;
05344    else
05345       linku1(p->u2.statements, statement);
05346 }

pval* pvalCasePatDefWalkStatements ( pval p,
pval **  statement 
)

Definition at line 5348 of file pval.c.

References pval::next, pval::statements, and pval::u2.

05349 {
05350    if (!(*statement))
05351       *statement = p->u2.statements;
05352    else {
05353       *statement = (*statement)->next;
05354    }
05355    return *statement;
05356 }

char* pvalCasePatGetVal ( pval p  ) 

Definition at line 5335 of file pval.c.

References pval::str, and pval::u1.

05336 {
05337    return p->u1.str;
05338 }

void pvalCasePatSetVal ( pval p,
char *  val 
)

Definition at line 5328 of file pval.c.

References PV_APPLICATION_CALL, pvalCheckType(), pval::str, and pval::u1.

05329 {
05330    if (!pvalCheckType(p, "pvalAppCallWalkArgs", PV_APPLICATION_CALL))
05331       return;
05332    p->u1.str = val;
05333 }

char* pvalCatchGetExtName ( pval p  ) 

Definition at line 5366 of file pval.c.

References PV_CATCH, pvalCheckType(), pval::str, and pval::u1.

05367 {
05368    if (!pvalCheckType(p, "pvalCatchGetExtName", PV_CATCH))
05369       return 0;
05370    return p->u1.str;
05371 }

pval* pvalCatchGetStatement ( pval p  ) 

Definition at line 5380 of file pval.c.

References PV_CATCH, pvalCheckType(), pval::statements, and pval::u2.

05381 {
05382    if (!pvalCheckType(p, "pvalCatchGetStatement", PV_CATCH))
05383       return 0;
05384    return p->u2.statements;
05385 }

void pvalCatchSetExtName ( pval p,
char *  name 
)

Definition at line 5359 of file pval.c.

References PV_CATCH, pvalCheckType(), pval::str, and pval::u1.

05360 {
05361    if (!pvalCheckType(p, "pvalCatchSetExtName", PV_CATCH))
05362       return;
05363    p->u1.str = name;
05364 }

void pvalCatchSetStatement ( pval p,
pval statement 
)

Definition at line 5373 of file pval.c.

References PV_CATCH, pvalCheckType(), pval::statements, and pval::u2.

05374 {
05375    if (!pvalCheckType(p, "pvalCatchSetStatement", PV_CATCH))
05376       return;
05377    p->u2.statements = statement;
05378 }

int pvalCheckType ( pval p,
char *  funcname,
pvaltype  type 
)

Definition at line 5071 of file pval.c.

References ast_log(), LOG_ERROR, and pval::type.

Referenced by pvalAppCallAddArg(), pvalAppCallGetAppName(), pvalAppCallSetAppName(), pvalAppCallSetArglist(), pvalAppCallWalkArgs(), pvalCasePatSetVal(), pvalCatchGetExtName(), pvalCatchGetStatement(), pvalCatchSetExtName(), pvalCatchSetStatement(), pvalContextAddStatement(), pvalContextGetAbstract(), pvalContextGetName(), pvalContextSetAbstract(), pvalContextSetName(), pvalContextUnsetAbstract(), pvalContextWalkStatements(), pvalESwitchesAddSwitch(), pvalESwitchesWalkNames(), pvalExtenGetHints(), pvalExtenGetName(), pvalExtenGetRegexten(), pvalExtenGetStatement(), pvalExtenSetHints(), pvalExtenSetName(), pvalExtenSetRegexten(), pvalExtenSetStatement(), pvalExtenUnSetRegexten(), pvalForGetInc(), pvalForGetInit(), pvalForGetStatement(), pvalForGetTest(), pvalForSetInc(), pvalForSetInit(), pvalForSetStatement(), pvalForSetTest(), pvalGlobalsWalkStatements(), pvalGotoGetTarget(), pvalGotoSetTarget(), pvalIfGetCondition(), pvalIfSetCondition(), pvalIfTimeGetCondition(), pvalIfTimeSetCondition(), pvalIgnorePatGetPattern(), pvalIgnorePatSetPattern(), pvalIncludeGetTimeConstraints(), pvalIncludesAddInclude(), pvalIncludesAddIncludeWithTimeConstraints(), pvalIncludesWalk(), pvalLabelGetName(), pvalLabelSetName(), pvalMacroAddArg(), pvalMacroAddStatement(), pvalMacroCallAddArg(), pvalMacroCallGetMacroName(), pvalMacroCallSetArglist(), pvalMacroCallSetMacroName(), pvalMacroCallWalkArgs(), pvalMacroGetName(), pvalMacroSetArglist(), pvalMacroSetName(), pvalMacroWalkArgs(), pvalMacroWalkStatements(), pvalRandomGetCondition(), pvalRandomSetCondition(), pvalStatementBlockAddStatement(), pvalStatementBlockWalkStatements(), pvalSwitchAddCase(), pvalSwitchesAddSwitch(), pvalSwitchesWalkNames(), pvalSwitchGetTestexpr(), pvalSwitchSetTestexpr(), pvalSwitchWalkCases(), pvalVarDecGetValue(), pvalVarDecGetVarname(), pvalVarDecSetValue(), pvalVarDecSetVarname(), pvalWordGetString(), and pvalWordSetString().

05072 {
05073    if (p->type != type)
05074    {
05075       ast_log(LOG_ERROR, "Func: %s the pval passed is not appropriate for this function!\n", funcname);
05076       return 0;
05077    }
05078    return 1;
05079 }

pval* pvalConditionalGetElseStatement ( pval p  ) 

Definition at line 5756 of file pval.c.

References pval::else_statements, and pval::u3.

05757 {
05758    return p->u3.else_statements;
05759 }

pval* pvalConditionalGetThenStatement ( pval p  ) 

Definition at line 5751 of file pval.c.

References pval::statements, and pval::u2.

05752 {
05753    return p->u2.statements;
05754 }

void pvalConditionalSetElseStatement ( pval p,
pval statement 
)

Definition at line 5746 of file pval.c.

References pval::else_statements, and pval::u3.

05747 {
05748    p->u3.else_statements = statement;
05749 }

void pvalConditionalSetThenStatement ( pval p,
pval statement 
)

Definition at line 5741 of file pval.c.

References pval::statements, and pval::u2.

05742 {
05743    p->u2.statements = statement;
05744 }

void pvalContextAddStatement ( pval p,
pval statement 
)

Definition at line 5217 of file pval.c.

References linku1(), PV_CONTEXT, pvalCheckType(), pval::statements, and pval::u2.

05218 {
05219    if (!pvalCheckType(p, "pvalContextAddStatement", PV_CONTEXT))
05220       return;
05221    if (!p->u2.statements)
05222       p->u2.statements = statement;
05223    else
05224       linku1(p->u2.statements, statement);
05225 }

int pvalContextGetAbstract ( pval p  ) 

Definition at line 5208 of file pval.c.

References pval::abstract, PV_CONTEXT, pvalCheckType(), and pval::u3.

05209 {
05210    if (!pvalCheckType(p, "pvalContextGetAbstract", PV_CONTEXT))
05211       return 0;
05212    return p->u3.abstract;
05213 }

char* pvalContextGetName ( pval p  ) 

Definition at line 5187 of file pval.c.

References PV_CONTEXT, pvalCheckType(), pval::str, and pval::u1.

05188 {
05189    if (!pvalCheckType(p, "pvalContextGetName", PV_CONTEXT))
05190       return 0;
05191    return p->u1.str;
05192 }

void pvalContextSetAbstract ( pval p  ) 

Definition at line 5194 of file pval.c.

References pval::abstract, PV_CONTEXT, pvalCheckType(), and pval::u3.

05195 {
05196    if (!pvalCheckType(p, "pvalContextSetAbstract", PV_CONTEXT))
05197       return;
05198    p->u3.abstract = 1;
05199 }

void pvalContextSetName ( pval p,
char *  name 
)

Definition at line 5180 of file pval.c.

References PV_CONTEXT, pvalCheckType(), pval::str, and pval::u1.

05181 {
05182    if (!pvalCheckType(p, "pvalContextSetName", PV_CONTEXT))
05183       return;
05184    p->u1.str = name;
05185 }

void pvalContextUnsetAbstract ( pval p  ) 

Definition at line 5201 of file pval.c.

References pval::abstract, PV_CONTEXT, pvalCheckType(), and pval::u3.

05202 {
05203    if (!pvalCheckType(p, "pvalContextUnsetAbstract", PV_CONTEXT))
05204       return;
05205    p->u3.abstract = 0;
05206 }

pval* pvalContextWalkStatements ( pval p,
pval **  statements 
)

Definition at line 5227 of file pval.c.

References pval::next, PV_CONTEXT, pvalCheckType(), pval::statements, and pval::u2.

05228 {
05229    if (!pvalCheckType(p, "pvalContextWalkStatements", PV_CONTEXT))
05230       return 0;
05231    if (!(*statements))
05232       *statements = p->u2.statements;
05233    else {
05234       *statements = (*statements)->next;
05235    }
05236    return *statements;
05237 }

pval* pvalCreateNode ( pvaltype  type  ) 

Definition at line 5082 of file pval.c.

References calloc, and pval::type.

Referenced by pvalESwitchesAddSwitch(), pvalGotoSetTarget(), pvalIfTimeSetCondition(), pvalIncludesAddInclude(), pvalIncludesAddIncludeWithTimeConstraints(), and pvalSwitchesAddSwitch().

05083 {
05084    pval *p = calloc(1,sizeof(pval)); /* why, oh why, don't I use ast_calloc? Way, way, way too messy if I do! */
05085    p->type = type;                   /* remember, this can be used externally or internally to asterisk */
05086    return p;
05087 }

void pvalESwitchesAddSwitch ( pval p,
char *  name 
)

Definition at line 5410 of file pval.c.

References linku1(), pval::list, PV_ESWITCHES, PV_WORD, pvalCheckType(), pvalCreateNode(), pval::str, and pval::u1.

05411 {
05412    pval *s;
05413    if (!pvalCheckType(p, "pvalESwitchesAddSwitch", PV_ESWITCHES))
05414       return;
05415    s = pvalCreateNode(PV_WORD);
05416    s->u1.str = name;
05417    p->u1.list = linku1(p->u1.list, s);
05418 }

char* pvalESwitchesWalkNames ( pval p,
pval **  next_item 
)

Definition at line 5420 of file pval.c.

References pval::list, next_item(), PV_ESWITCHES, pvalCheckType(), and pval::u1.

05421 {
05422    if (!pvalCheckType(p, "pvalESwitchesWalkNames", PV_ESWITCHES))
05423       return 0;
05424    if (!(*next_item))
05425       *next_item = p->u1.list;
05426    else {
05427       *next_item = (*next_item)->next;
05428    }
05429    return (*next_item)->u1.str;
05430 }

char* pvalExtenGetHints ( pval p  ) 

Definition at line 5842 of file pval.c.

References pval::hints, PV_EXTENSION, pvalCheckType(), and pval::u3.

05843 {
05844    if (!pvalCheckType(p, "pvalExtenGetHints", PV_EXTENSION))
05845       return 0;
05846    return p->u3.hints;
05847 }

char* pvalExtenGetName ( pval p  ) 

Definition at line 5807 of file pval.c.

References PV_EXTENSION, pvalCheckType(), pval::str, and pval::u1.

05808 {
05809    if (!pvalCheckType(p, "pvalExtenGetName", PV_EXTENSION))
05810       return 0;
05811    return p->u1.str;
05812 }

int pvalExtenGetRegexten ( pval p  ) 

Definition at line 5828 of file pval.c.

References PV_EXTENSION, pvalCheckType(), pval::regexten, and pval::u4.

05829 {
05830    if (!pvalCheckType(p, "pvalExtenGetRegexten", PV_EXTENSION))
05831       return 0;
05832    return p->u4.regexten;
05833 }

pval* pvalExtenGetStatement ( pval p  ) 

Definition at line 5856 of file pval.c.

References PV_EXTENSION, pvalCheckType(), pval::statements, and pval::u2.

05857 {
05858    if (!pvalCheckType(p, "pvalExtenGetStatement", PV_EXTENSION))
05859       return 0;
05860    return p->u2.statements;
05861 }

void pvalExtenSetHints ( pval p,
char *  hints 
)

Definition at line 5835 of file pval.c.

References pval::hints, PV_EXTENSION, pvalCheckType(), and pval::u3.

05836 {
05837    if (!pvalCheckType(p, "pvalExtenSetHints", PV_EXTENSION))
05838       return;
05839    p->u3.hints = hints;
05840 }

void pvalExtenSetName ( pval p,
char *  name 
)

Definition at line 5800 of file pval.c.

References PV_EXTENSION, pvalCheckType(), pval::str, and pval::u1.

05801 {
05802    if (!pvalCheckType(p, "pvalExtenSetName", PV_EXTENSION))
05803       return;
05804    p->u1.str = name;
05805 }

void pvalExtenSetRegexten ( pval p  ) 

Definition at line 5814 of file pval.c.

References PV_EXTENSION, pvalCheckType(), pval::regexten, and pval::u4.

05815 {
05816    if (!pvalCheckType(p, "pvalExtenSetRegexten", PV_EXTENSION))
05817       return;
05818    p->u4.regexten = 1;
05819 }

void pvalExtenSetStatement ( pval p,
pval statement 
)

Definition at line 5849 of file pval.c.

References PV_EXTENSION, pvalCheckType(), pval::statements, and pval::u2.

05850 {
05851    if (!pvalCheckType(p, "pvalExtenSetStatement", PV_EXTENSION))
05852       return;
05853    p->u2.statements = statement;
05854 }

void pvalExtenUnSetRegexten ( pval p  ) 

Definition at line 5821 of file pval.c.

References PV_EXTENSION, pvalCheckType(), pval::regexten, and pval::u4.

05822 {
05823    if (!pvalCheckType(p, "pvalExtenUnSetRegexten", PV_EXTENSION))
05824       return;
05825    p->u4.regexten = 0;
05826 }

char* pvalForGetInc ( pval p  ) 

Definition at line 5668 of file pval.c.

References pval::for_inc, PV_FOR, pvalCheckType(), and pval::u3.

05669 {
05670    if (!pvalCheckType(p, "pvalForGetInc", PV_FOR))
05671       return 0;
05672    return p->u3.for_inc;
05673 }

char* pvalForGetInit ( pval p  ) 

Definition at line 5654 of file pval.c.

References pval::for_init, PV_FOR, pvalCheckType(), and pval::u1.

05655 {
05656    if (!pvalCheckType(p, "pvalForGetInit", PV_FOR))
05657       return 0;
05658    return p->u1.for_init;
05659 }

pval* pvalForGetStatement ( pval p  ) 

Definition at line 5675 of file pval.c.

References pval::for_statements, PV_FOR, pvalCheckType(), and pval::u4.

05676 {
05677    if (!pvalCheckType(p, "pvalForGetStatement", PV_FOR))
05678       return 0;
05679    return p->u4.for_statements;
05680 }

char* pvalForGetTest ( pval p  ) 

Definition at line 5661 of file pval.c.

References pval::for_test, PV_FOR, pvalCheckType(), and pval::u2.

05662 {
05663    if (!pvalCheckType(p, "pvalForGetTest", PV_FOR))
05664       return 0;
05665    return p->u2.for_test;
05666 }

void pvalForSetInc ( pval p,
char *  inc 
)

Definition at line 5640 of file pval.c.

References pval::for_inc, PV_FOR, pvalCheckType(), and pval::u3.

05641 {
05642    if (!pvalCheckType(p, "pvalForSetInc", PV_FOR))
05643       return;
05644    p->u3.for_inc = inc;
05645 }

void pvalForSetInit ( pval p,
char *  init 
)

Definition at line 5626 of file pval.c.

References pval::for_init, PV_FOR, pvalCheckType(), and pval::u1.

05627 {
05628    if (!pvalCheckType(p, "pvalForSetInit", PV_FOR))
05629       return;
05630    p->u1.for_init = init;
05631 }

void pvalForSetStatement ( pval p,
pval statement 
)

Definition at line 5647 of file pval.c.

References pval::for_statements, PV_FOR, pvalCheckType(), and pval::u4.

05648 {
05649    if (!pvalCheckType(p, "pvalForSetStatement", PV_FOR))
05650       return;
05651    p->u4.for_statements = statement;
05652 }

void pvalForSetTest ( pval p,
char *  test 
)

Definition at line 5633 of file pval.c.

References pval::for_test, PV_FOR, pvalCheckType(), and pval::u2.

05634 {
05635    if (!pvalCheckType(p, "pvalForSetTest", PV_FOR))
05636       return;
05637    p->u2.for_test = test;
05638 }

void pvalGlobalsAddStatement ( pval p,
pval statement 
)

Definition at line 5879 of file pval.c.

References ast_log(), linku1(), LOG_ERROR, PV_GLOBALS, pval::statements, pval::type, and pval::u1.

05880 {
05881    if (p->type != PV_GLOBALS) {
05882       ast_log(LOG_ERROR, "pvalGlobalsAddStatement called where first arg is not a Globals!\n");
05883    } else {
05884       if (!p->u1.statements) {
05885          p->u1.statements = statement;
05886       } else {
05887          p->u1.statements = linku1(p->u1.statements,statement);
05888       }
05889    }
05890 }

pval* pvalGlobalsWalkStatements ( pval p,
pval **  next_statement 
)

Definition at line 5892 of file pval.c.

References pval::next, PV_GLOBALS, and pvalCheckType().

05893 {
05894    if (!pvalCheckType(p, "pvalGlobalsWalkStatements", PV_GLOBALS))
05895       return 0;
05896    if (!*next_statement) {
05897       *next_statement = p;
05898       return p;
05899    } else {
05900       *next_statement = (*next_statement)->next;
05901       return (*next_statement)->next;
05902    }
05903 }

void pvalGotoGetTarget ( pval p,
char **  context,
char **  exten,
char **  label 
)

Definition at line 5584 of file pval.c.

References pval::list, pval::next, PV_GOTO, pvalCheckType(), pval::str, and pval::u1.

05585 {
05586    if (!pvalCheckType(p, "pvalGotoGetTarget", PV_GOTO))
05587       return;
05588    if (p->u1.list && p->u1.list->next && p->u1.list->next->next) {
05589       *context = p->u1.list->u1.str;
05590       *exten = p->u1.list->next->u1.str;
05591       *label = p->u1.list->next->next->u1.str;
05592       
05593    } else if (p->u1.list && p->u1.list->next ) {
05594       *exten = p->u1.list->u1.str;
05595       *label = p->u1.list->next->u1.str;
05596       *context = 0;
05597 
05598    } else if (p->u1.list) {
05599       *label = p->u1.list->u1.str;
05600       *context = 0;
05601       *exten = 0;
05602       
05603    } else {
05604       *context = 0;
05605       *exten = 0;
05606       *label = 0;
05607    }
05608 }

void pvalGotoSetTarget ( pval p,
char *  context,
char *  exten,
char *  label 
)

Definition at line 5548 of file pval.c.

References ext, pval::list, pval::next, PV_GOTO, PV_WORD, pvalCheckType(), pvalCreateNode(), pval::str, and pval::u1.

05549 {
05550    pval *con, *ext, *pri;
05551    
05552    if (!pvalCheckType(p, "pvalGotoSetTarget", PV_GOTO))
05553       return;
05554    if (context && strlen(context)) {
05555       con = pvalCreateNode(PV_WORD);
05556       ext = pvalCreateNode(PV_WORD);
05557       pri = pvalCreateNode(PV_WORD);
05558       
05559       con->u1.str = context;
05560       ext->u1.str = exten;
05561       pri->u1.str = label;
05562       
05563       con->next = ext;
05564       ext->next = pri;
05565       p->u1.list = con;
05566    } else if (exten && strlen(exten)) {
05567       ext = pvalCreateNode(PV_WORD);
05568       pri = pvalCreateNode(PV_WORD);
05569       
05570       ext->u1.str = exten;
05571       pri->u1.str = label;
05572       
05573       ext->next = pri;
05574       p->u1.list = ext;
05575    } else {
05576       pri = pvalCreateNode(PV_WORD);
05577       
05578       pri->u1.str = label;
05579       
05580       p->u1.list = pri;
05581    }
05582 }

char* pvalIfGetCondition ( pval p  ) 

Definition at line 5691 of file pval.c.

References PV_IFTIME, pvalCheckType(), pval::str, and pval::u1.

05692 {
05693    if (!pvalCheckType(p, "pvalIfGetCondition", PV_IFTIME))
05694       return 0;
05695    return p->u1.str;
05696 }

void pvalIfSetCondition ( pval p,
char *  expr 
)

Definition at line 5684 of file pval.c.

References PV_IF, pvalCheckType(), pval::str, and pval::u1.

05685 {
05686    if (!pvalCheckType(p, "pvalIfSetCondition", PV_IF))
05687       return;
05688    p->u1.str = expr;
05689 }

void pvalIfTimeGetCondition ( pval p,
char **  hour_range,
char **  dow_range,
char **  dom_range,
char **  month_range 
)

Definition at line 5717 of file pval.c.

References pval::list, pval::next, PV_IFTIME, pvalCheckType(), pval::str, and pval::u1.

05718 {
05719    if (!pvalCheckType(p, "pvalIfTimeGetCondition", PV_IFTIME))
05720       return;
05721    *hour_range = p->u1.list->u1.str;
05722    *dow_range = p->u1.list->next->u1.str;
05723    *dom_range = p->u1.list->next->next->u1.str;
05724    *month_range = p->u1.list->next->next->next->u1.str;
05725 }

void pvalIfTimeSetCondition ( pval p,
char *  hour_range,
char *  dow_range,
char *  dom_range,
char *  mon_range 
)

Definition at line 5698 of file pval.c.

References pval::list, pval::next, PV_IFTIME, PV_WORD, pvalCheckType(), pvalCreateNode(), pvalWordSetString(), and pval::u1.

05698                                                                                                                                  : 24-hour format begin-end|dow range|dom range|month range */
05699 {
05700    pval *hr = pvalCreateNode(PV_WORD);
05701    pval *dow = pvalCreateNode(PV_WORD);
05702    pval *dom = pvalCreateNode(PV_WORD);
05703    pval *mon = pvalCreateNode(PV_WORD);
05704    if (!pvalCheckType(p, "pvalIfTimeSetCondition", PV_IFTIME))
05705       return;
05706    pvalWordSetString(hr, hour_range);
05707    pvalWordSetString(dow, dow_range);
05708    pvalWordSetString(dom, dom_range);
05709    pvalWordSetString(mon, mon_range);
05710    dom->next = mon;
05711    dow->next = dom;
05712    hr->next = dow;
05713    p->u1.list = hr;
05714 }

char* pvalIgnorePatGetPattern ( pval p  ) 

Definition at line 5871 of file pval.c.

References PV_IGNOREPAT, pvalCheckType(), pval::str, and pval::u1.

05872 {
05873    if (!pvalCheckType(p, "pvalIgnorePatGetPattern", PV_IGNOREPAT))
05874       return 0;
05875    return p->u1.str;
05876 }

void pvalIgnorePatSetPattern ( pval p,
char *  pat 
)

Definition at line 5864 of file pval.c.

References PV_IGNOREPAT, pvalCheckType(), pval::str, and pval::u1.

05865 {
05866    if (!pvalCheckType(p, "pvalIgnorePatSetPattern", PV_IGNOREPAT))
05867       return;
05868    p->u1.str = pat;
05869 }

void pvalIncludeGetTimeConstraints ( pval p,
char **  hour_range,
char **  dom_range,
char **  dow_range,
char **  month_range 
)

Definition at line 5471 of file pval.c.

References pval::arglist, pval::next, PV_WORD, pvalCheckType(), pval::str, pval::u1, and pval::u2.

05472 {
05473    if (!pvalCheckType(p, "pvalIncludeGetTimeConstraints", PV_WORD))
05474       return;
05475    if (p->u2.arglist) {
05476       *hour_range = p->u2.arglist->u1.str;
05477       *dom_range = p->u2.arglist->next->u1.str;
05478       *dow_range = p->u2.arglist->next->next->u1.str;
05479       *month_range = p->u2.arglist->next->next->next->u1.str;
05480    } else {
05481       *hour_range = 0;
05482       *dom_range = 0;
05483       *dow_range = 0;
05484       *month_range = 0;
05485    }
05486 }

void pvalIncludesAddInclude ( pval p,
const char *  include 
)

Definition at line 5433 of file pval.c.

References linku1(), pval::list, PV_INCLUDES, PV_WORD, pvalCheckType(), pvalCreateNode(), pval::str, and pval::u1.

05434 {
05435    pval *s;
05436    if (!pvalCheckType(p, "pvalIncludesAddSwitch", PV_INCLUDES))
05437       return;
05438    s = pvalCreateNode(PV_WORD);
05439    s->u1.str = (char *)include;
05440    p->u1.list = linku1(p->u1.list, s);
05441 }

void pvalIncludesAddIncludeWithTimeConstraints ( pval p,
const char *  include,
char *  hour_range,
char *  dom_range,
char *  dow_range,
char *  month_range 
)

Definition at line 5444 of file pval.c.

References pval::arglist, linku1(), pval::list, pval::next, PV_INCLUDES, PV_WORD, pvalCheckType(), pvalCreateNode(), pval::str, pval::u1, and pval::u2.

05445 {
05446    pval *hr = pvalCreateNode(PV_WORD);
05447    pval *dom = pvalCreateNode(PV_WORD);
05448    pval *dow = pvalCreateNode(PV_WORD);
05449    pval *mon = pvalCreateNode(PV_WORD);
05450    pval *s = pvalCreateNode(PV_WORD);
05451    
05452    if (!pvalCheckType(p, "pvalIncludeAddIncludeWithTimeConstraints", PV_INCLUDES))
05453       return;
05454 
05455    s->u1.str = (char *)include;
05456    p->u1.list = linku1(p->u1.list, s);
05457 
05458    hr->u1.str = hour_range;
05459    dom->u1.str = dom_range;
05460    dow->u1.str = dow_range;
05461    mon->u1.str = month_range;
05462 
05463    s->u2.arglist = hr;
05464 
05465    hr->next = dom;
05466    dom->next = dow;
05467    dow->next = mon;
05468    mon->next = 0;
05469 }

char* pvalIncludesWalk ( pval p,
pval **  next_item 
)

Definition at line 5488 of file pval.c.

References pval::list, next_item(), PV_INCLUDES, pvalCheckType(), and pval::u1.

05489 {
05490    if (!pvalCheckType(p, "pvalIncludesWalk", PV_INCLUDES))
05491       return 0;
05492    if (!(*next_item))
05493       *next_item = p->u1.list;
05494    else {
05495       *next_item = (*next_item)->next;
05496    }
05497    return (*next_item)->u1.str;
05498 }

char* pvalLabelGetName ( pval p  ) 

Definition at line 5618 of file pval.c.

References PV_LABEL, pvalCheckType(), pval::str, and pval::u1.

05619 {
05620    if (!pvalCheckType(p, "pvalLabelGetName", PV_LABEL))
05621       return 0;
05622    return p->u1.str;
05623 }

void pvalLabelSetName ( pval p,
char *  name 
)

Definition at line 5611 of file pval.c.

References PV_LABEL, pvalCheckType(), pval::str, and pval::u1.

05612 {
05613    if (!pvalCheckType(p, "pvalLabelSetName", PV_LABEL))
05614       return;
05615    p->u1.str = name;
05616 }

void pvalMacroAddArg ( pval p,
pval arg 
)

Definition at line 5131 of file pval.c.

References pval::arglist, linku1(), PV_MACRO, pvalCheckType(), and pval::u2.

05132 {
05133    if (!pvalCheckType(p, "pvalMacroAddArg", PV_MACRO))
05134       return;
05135    if (!p->u2.arglist)
05136       p->u2.arglist = arg;
05137    else
05138       linku1(p->u2.arglist, arg);
05139 
05140 }

void pvalMacroAddStatement ( pval p,
pval statement 
)

Definition at line 5154 of file pval.c.

References linku1(), pval::macro_statements, PV_MACRO, pvalCheckType(), and pval::u3.

05155 {
05156    if (!pvalCheckType(p, "pvalMacroAddStatement", PV_MACRO))
05157       return;
05158    if (!p->u3.macro_statements)
05159       p->u3.macro_statements = statement;
05160    else
05161       linku1(p->u3.macro_statements, statement);
05162 
05163    
05164 }

void pvalMacroCallAddArg ( pval p,
pval arg 
)

Definition at line 5261 of file pval.c.

References pval::arglist, linku1(), PV_MACRO_CALL, pvalCheckType(), and pval::u2.

05262 {
05263    if (!pvalCheckType(p, "pvalMacroCallGetAddArg", PV_MACRO_CALL))
05264       return;
05265    if (!p->u2.arglist)
05266       p->u2.arglist = arg;
05267    else
05268       linku1(p->u2.arglist, arg);
05269 }

char* pvalMacroCallGetMacroName ( pval p  ) 

Definition at line 5247 of file pval.c.

References PV_MACRO_CALL, pvalCheckType(), pval::str, and pval::u1.

05248 {
05249    if (!pvalCheckType(p, "pvalMacroCallGetMacroName", PV_MACRO_CALL))
05250       return 0;
05251    return p->u1.str;
05252 }

void pvalMacroCallSetArglist ( pval p,
pval arglist 
)

Definition at line 5254 of file pval.c.

References pval::arglist, PV_MACRO_CALL, pvalCheckType(), and pval::u2.

05255 {
05256    if (!pvalCheckType(p, "pvalMacroCallSetArglist", PV_MACRO_CALL))
05257       return;
05258    p->u2.arglist = arglist;
05259 }

void pvalMacroCallSetMacroName ( pval p,
char *  name 
)

Definition at line 5240 of file pval.c.

References PV_MACRO_CALL, pvalCheckType(), pval::str, and pval::u1.

05241 {
05242    if (!pvalCheckType(p, "pvalMacroCallSetMacroName", PV_MACRO_CALL))
05243       return;
05244    p->u1.str = name;
05245 }

pval* pvalMacroCallWalkArgs ( pval p,
pval **  args 
)

Definition at line 5271 of file pval.c.

References pval::arglist, args, PV_MACRO_CALL, pvalCheckType(), and pval::u2.

05272 {
05273    if (!pvalCheckType(p, "pvalMacroCallWalkArgs", PV_MACRO_CALL))
05274       return 0;
05275    if (!(*args))
05276       *args = p->u2.arglist;
05277    else {
05278       *args = (*args)->next;
05279    }
05280    return *args;
05281 }

char* pvalMacroGetName ( pval p  ) 

Definition at line 5117 of file pval.c.

References PV_MACRO, pvalCheckType(), pval::str, and pval::u1.

05118 {
05119    if (!pvalCheckType(p, "pvalMacroGetName", PV_MACRO))
05120       return 0;
05121    return p->u1.str;
05122 }

void pvalMacroSetArglist ( pval p,
pval arglist 
)

Definition at line 5124 of file pval.c.

References pval::arglist, PV_MACRO, pvalCheckType(), and pval::u2.

05125 {
05126    if (!pvalCheckType(p, "pvalMacroSetArglist", PV_MACRO))
05127       return;
05128    p->u2.arglist = arglist;
05129 }

void pvalMacroSetName ( pval p,
char *  name 
)

Definition at line 5110 of file pval.c.

References PV_MACRO, pvalCheckType(), pval::str, and pval::u1.

05111 {
05112    if (!pvalCheckType(p, "pvalMacroSetName", PV_MACRO))
05113       return;
05114    p->u1.str = name;
05115 }

pval* pvalMacroWalkArgs ( pval p,
pval **  arg 
)

Definition at line 5142 of file pval.c.

References pval::arglist, pval::next, PV_MACRO, pvalCheckType(), and pval::u2.

05143 {
05144    if (!pvalCheckType(p, "pvalMacroWalkArgs", PV_MACRO))
05145       return 0;
05146    if (!(*arg))
05147       *arg = p->u2.arglist;
05148    else {
05149       *arg = (*arg)->next;
05150    }
05151    return *arg;
05152 }

pval* pvalMacroWalkStatements ( pval p,
pval **  next_statement 
)

Definition at line 5166 of file pval.c.

References pval::macro_statements, pval::next, PV_MACRO, pvalCheckType(), and pval::u3.

05167 {
05168    if (!pvalCheckType(p, "pvalMacroWalkStatements", PV_MACRO))
05169       return 0;
05170    if (!(*next_statement))
05171       *next_statement = p->u3.macro_statements;
05172    else {
05173       *next_statement = (*next_statement)->next;
05174    }
05175    return *next_statement;
05176 }

pvaltype pvalObjectGetType ( pval p  ) 

Definition at line 5089 of file pval.c.

References pval::type.

05090 {
05091    return p->type;
05092 }

char* pvalRandomGetCondition ( pval p  ) 

Definition at line 5734 of file pval.c.

References PV_RANDOM, pvalCheckType(), pval::str, and pval::u1.

05735 {
05736    if (!pvalCheckType(p, "pvalRandomGetCondition", PV_RANDOM))
05737       return 0;
05738    return p->u1.str;
05739 }

void pvalRandomSetCondition ( pval p,
char *  percent 
)

Definition at line 5727 of file pval.c.

References PV_RANDOM, pvalCheckType(), pval::str, and pval::u1.

05728 {
05729    if (!pvalCheckType(p, "pvalRandomSetCondition", PV_RANDOM))
05730       return;
05731    p->u1.str = percent;
05732 }

void pvalStatementBlockAddStatement ( pval p,
pval statement 
)

Definition at line 5501 of file pval.c.

References linku1(), pval::list, PV_STATEMENTBLOCK, pvalCheckType(), and pval::u1.

05502 {
05503    if (!pvalCheckType(p, "pvalStatementBlockAddStatement", PV_STATEMENTBLOCK))
05504       return;
05505    p->u1.list = linku1(p->u1.list, statement);
05506 }

pval* pvalStatementBlockWalkStatements ( pval p,
pval **  next_statement 
)

Definition at line 5508 of file pval.c.

References pval::list, pval::next, PV_STATEMENTBLOCK, pvalCheckType(), and pval::u1.

05509 {
05510    if (!pvalCheckType(p, "pvalStatementBlockWalkStatements", PV_STATEMENTBLOCK))
05511       return 0;
05512    if (!(*next_statement))
05513       *next_statement = p->u1.list;
05514    else {
05515       *next_statement = (*next_statement)->next;
05516    }
05517    return *next_statement;
05518 }

void pvalSwitchAddCase ( pval p,
pval Case 
)

Definition at line 5775 of file pval.c.

References linku1(), PV_CASE, PV_SWITCH, pvalCheckType(), pval::statements, and pval::u2.

05776 {
05777    if (!pvalCheckType(p, "pvalSwitchAddCase", PV_SWITCH))
05778       return;
05779    if (!pvalCheckType(Case, "pvalSwitchAddCase", PV_CASE))
05780       return;
05781    if (!p->u2.statements)
05782       p->u2.statements = Case;
05783    else
05784       linku1(p->u2.statements, Case);
05785 }

void pvalSwitchesAddSwitch ( pval p,
char *  name 
)

Definition at line 5388 of file pval.c.

References linku1(), pval::list, PV_SWITCHES, PV_WORD, pvalCheckType(), pvalCreateNode(), pval::str, and pval::u1.

05389 {
05390    pval *s;
05391    if (!pvalCheckType(p, "pvalSwitchesAddSwitch", PV_SWITCHES))
05392       return;
05393    s = pvalCreateNode(PV_WORD);
05394    s->u1.str = name;
05395    p->u1.list = linku1(p->u1.list, s);
05396 }

char* pvalSwitchesWalkNames ( pval p,
pval **  next_item 
)

Definition at line 5398 of file pval.c.

References pval::list, next_item(), PV_SWITCHES, pvalCheckType(), and pval::u1.

05399 {
05400    if (!pvalCheckType(p, "pvalSwitchesWalkNames", PV_SWITCHES))
05401       return 0;
05402    if (!(*next_item))
05403       *next_item = p->u1.list;
05404    else {
05405       *next_item = (*next_item)->next;
05406    }
05407    return (*next_item)->u1.str;
05408 }

char* pvalSwitchGetTestexpr ( pval p  ) 

Definition at line 5768 of file pval.c.

References PV_SWITCH, pvalCheckType(), pval::str, and pval::u1.

05769 {
05770    if (!pvalCheckType(p, "pvalSwitchGetTestexpr", PV_SWITCH))
05771       return 0;
05772    return p->u1.str;
05773 }

void pvalSwitchSetTestexpr ( pval p,
char *  expr 
)

Definition at line 5761 of file pval.c.

References PV_SWITCH, pvalCheckType(), pval::str, and pval::u1.

05762 {
05763    if (!pvalCheckType(p, "pvalSwitchSetTestexpr", PV_SWITCH))
05764       return;
05765    p->u1.str = expr;
05766 }

pval* pvalSwitchWalkCases ( pval p,
pval **  next_case 
)

Definition at line 5787 of file pval.c.

References pval::next, PV_SWITCH, pvalCheckType(), pval::statements, and pval::u2.

05788 {
05789    if (!pvalCheckType(p, "pvalSwitchWalkCases", PV_SWITCH))
05790       return 0;
05791    if (!(*next_case))
05792       *next_case = p->u2.statements;
05793    else {
05794       *next_case = (*next_case)->next;
05795    }
05796    return *next_case;
05797 }

void pvalTopLevAddObject ( pval p,
pval contextOrObj 
)

Definition at line 5906 of file pval.c.

References ast_log(), linku1(), and LOG_ERROR.

05907 {
05908    if (p) {
05909       linku1(p,contextOrObj);
05910    } else {
05911       ast_log(LOG_ERROR, "First arg to pvalTopLevel is NULL!\n");
05912    }
05913 }

pval* pvalTopLevWalkObjects ( pval p,
pval **  next_obj 
)

Definition at line 5915 of file pval.c.

References pval::next.

05916 {
05917    if (!*next_obj) {
05918       *next_obj = p;
05919       return p;
05920    } else {
05921       *next_obj = (*next_obj)->next;
05922       return (*next_obj)->next;
05923    }
05924 }

char* pvalVarDecGetValue ( pval p  ) 

Definition at line 5541 of file pval.c.

References PV_VARDEC, pvalCheckType(), pval::u2, and pval::val.

05542 {
05543    if (!pvalCheckType(p, "pvalVarDecGetValue", PV_VARDEC))
05544       return 0;
05545    return p->u2.val;
05546 }

char* pvalVarDecGetVarname ( pval p  ) 

Definition at line 5534 of file pval.c.

References PV_VARDEC, pvalCheckType(), pval::str, and pval::u1.

05535 {
05536    if (!pvalCheckType(p, "pvalVarDecGetVarname", PV_VARDEC))
05537       return 0;
05538    return p->u1.str;
05539 }

void pvalVarDecSetValue ( pval p,
char *  value 
)

Definition at line 5527 of file pval.c.

References PV_VARDEC, pvalCheckType(), pval::u2, and pval::val.

05528 {
05529    if (!pvalCheckType(p, "pvalVarDecSetValue", PV_VARDEC))
05530       return;
05531    p->u2.val = value;
05532 }

void pvalVarDecSetVarname ( pval p,
char *  name 
)

Definition at line 5520 of file pval.c.

References PV_VARDEC, pvalCheckType(), pval::str, and pval::u1.

05521 {
05522    if (!pvalCheckType(p, "pvalVarDecSetVarname", PV_VARDEC))
05523       return;
05524    p->u1.str = name;
05525 }

char* pvalWordGetString ( pval p  ) 

Definition at line 5102 of file pval.c.

References PV_WORD, pvalCheckType(), pval::str, and pval::u1.

05103 {
05104    if (!pvalCheckType(p, "pvalWordGetString", PV_WORD))
05105       return 0;
05106    return p->u1.str;
05107 }

void pvalWordSetString ( pval p,
char *  str 
)

Definition at line 5095 of file pval.c.

References PV_WORD, pvalCheckType(), pval::str, and pval::u1.

Referenced by pvalIfTimeSetCondition().

05096 {
05097    if (!pvalCheckType(p, "pvalWordSetString", PV_WORD))
05098       return;
05099    p->u1.str = str;
05100 }

static void remove_spaces_before_equals ( char *  str  )  [static]

Definition at line 3046 of file pval.c.

Referenced by gen_prios().

03047 {
03048    char *p;
03049    while( str && *str && *str != '=' )
03050    {
03051       if( *str == ' ' || *str == '\n' || *str == '\r' || *str == '\t' )
03052       {
03053          p = str;
03054          while( *p )
03055          {
03056             *p = *(p+1);
03057             p++;
03058          }
03059       }
03060       else
03061          str++;
03062    }
03063 }

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 }

void traverse_pval_item_template ( pval item,
int  depth 
)

Definition at line 403 of file pval.c.

References pval::arglist, pval::else_statements, pval::for_statements, pval::list, pval::macro_statements, pval::next, PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTEXT, PV_CONTINUE, PV_DEFAULT, PV_ESWITCHES, PV_EXTENSION, PV_FOR, PV_GLOBALS, PV_GOTO, PV_IF, PV_IFTIME, PV_IGNOREPAT, PV_INCLUDES, PV_LABEL, PV_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::type, pval::u1, pval::u2, pval::u3, and pval::u4.

Referenced by traverse_pval_template().

00405 {
00406    pval *lp;
00407    
00408    switch ( item->type ) {
00409    case PV_WORD:
00410       /* fields: item->u1.str == string associated with this (word). */
00411       break;
00412       
00413    case PV_MACRO:
00414       /* fields: item->u1.str     == name of macro
00415                  item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
00416                item->u2.arglist->u1.str  == argument
00417                item->u2.arglist->next   == next arg
00418 
00419                item->u3.macro_statements == pval list of statements in macro body.
00420       */
00421       for (lp=item->u2.arglist; lp; lp=lp->next) {
00422       
00423       }
00424       traverse_pval_item_template(item->u3.macro_statements,depth+1);
00425       break;
00426          
00427    case PV_CONTEXT:
00428       /* fields: item->u1.str     == name of context
00429                  item->u2.statements == pval list of statements in context body
00430                item->u3.abstract == int 1 if an abstract keyword were present
00431       */
00432       traverse_pval_item_template(item->u2.statements,depth+1);
00433       break;
00434          
00435    case PV_MACRO_CALL:
00436       /* fields: item->u1.str     == name of macro to call
00437                  item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
00438                item->u2.arglist->u1.str  == argument
00439                item->u2.arglist->next   == next arg
00440       */
00441       for (lp=item->u2.arglist; lp; lp=lp->next) {
00442       }
00443       break;
00444          
00445    case PV_APPLICATION_CALL:
00446       /* fields: item->u1.str     == name of application to call
00447                  item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
00448                item->u2.arglist->u1.str  == argument
00449                item->u2.arglist->next   == next arg
00450       */
00451       for (lp=item->u2.arglist; lp; lp=lp->next) {
00452       }
00453       break;
00454          
00455    case PV_CASE:
00456       /* fields: item->u1.str     == value of case
00457                  item->u2.statements == pval list of statements under the case
00458       */
00459       traverse_pval_item_template(item->u2.statements,depth+1);
00460       break;
00461          
00462    case PV_PATTERN:
00463       /* fields: item->u1.str     == value of case
00464                  item->u2.statements == pval list of statements under the case
00465       */
00466       traverse_pval_item_template(item->u2.statements,depth+1);
00467       break;
00468          
00469    case PV_DEFAULT:
00470       /* fields: 
00471                  item->u2.statements == pval list of statements under the case
00472       */
00473       traverse_pval_item_template(item->u2.statements,depth+1);
00474       break;
00475          
00476    case PV_CATCH:
00477       /* fields: item->u1.str     == name of extension to catch
00478                  item->u2.statements == pval list of statements in context body
00479       */
00480       traverse_pval_item_template(item->u2.statements,depth+1);
00481       break;
00482          
00483    case PV_SWITCHES:
00484       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
00485       */
00486       traverse_pval_item_template(item->u1.list,depth+1);
00487       break;
00488          
00489    case PV_ESWITCHES:
00490       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
00491       */
00492       traverse_pval_item_template(item->u1.list,depth+1);
00493       break;
00494          
00495    case PV_INCLUDES:
00496       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
00497                  item->u2.arglist  == pval list of 4 PV_WORD elements for time values
00498       */
00499       traverse_pval_item_template(item->u1.list,depth+1);
00500       traverse_pval_item_template(item->u2.arglist,depth+1);
00501       break;
00502          
00503    case PV_STATEMENTBLOCK:
00504       /* fields: item->u1.list     == pval list of statements in block, one per entry in the list
00505       */
00506       traverse_pval_item_template(item->u1.list,depth+1);
00507       break;
00508          
00509    case PV_LOCALVARDEC:
00510    case PV_VARDEC:
00511       /* fields: item->u1.str     == variable name
00512                  item->u2.val     == variable value to assign
00513       */
00514       break;
00515          
00516    case PV_GOTO:
00517       /* fields: item->u1.list     == pval list of PV_WORD target names, up to 3, in order as given by user.
00518                  item->u1.list->u1.str  == where the data on a PV_WORD will always be.
00519       */
00520       
00521       if ( item->u1.list->next )
00522          ;
00523       if ( item->u1.list->next && item->u1.list->next->next )
00524          ;
00525       
00526       break;
00527          
00528    case PV_LABEL:
00529       /* fields: item->u1.str     == label name
00530       */
00531       break;
00532          
00533    case PV_FOR:
00534       /* fields: item->u1.for_init     == a string containing the initalizer
00535                  item->u2.for_test     == a string containing the loop test
00536                  item->u3.for_inc      == a string containing the loop increment
00537 
00538                item->u4.for_statements == a pval list of statements in the for ()
00539       */
00540       traverse_pval_item_template(item->u4.for_statements,depth+1);
00541       break;
00542          
00543    case PV_WHILE:
00544       /* fields: item->u1.str        == the while conditional, as supplied by user
00545 
00546                item->u2.statements == a pval list of statements in the while ()
00547       */
00548       traverse_pval_item_template(item->u2.statements,depth+1);
00549       break;
00550          
00551    case PV_BREAK:
00552       /* fields: none
00553       */
00554       break;
00555          
00556    case PV_RETURN:
00557       /* fields: none
00558       */
00559       break;
00560          
00561    case PV_CONTINUE:
00562       /* fields: none
00563       */
00564       break;
00565          
00566    case PV_IFTIME:
00567       /* fields: item->u1.list        == there are 4 linked PV_WORDs here.
00568 
00569                item->u2.statements == a pval list of statements in the if ()
00570                item->u3.else_statements == a pval list of statements in the else
00571                                     (could be zero)
00572       */
00573       traverse_pval_item_template(item->u2.statements,depth+1);
00574       if ( item->u3.else_statements ) {
00575          traverse_pval_item_template(item->u3.else_statements,depth+1);
00576       }
00577       break;
00578          
00579    case PV_RANDOM:
00580       /* fields: item->u1.str        == the random number expression, as supplied by user
00581 
00582                item->u2.statements == a pval list of statements in the if ()
00583                item->u3.else_statements == a pval list of statements in the else
00584                                     (could be zero)
00585       */
00586       traverse_pval_item_template(item->u2.statements,depth+1);
00587       if ( item->u3.else_statements ) {
00588          traverse_pval_item_template(item->u3.else_statements,depth+1);
00589       }
00590       break;
00591          
00592    case PV_IF:
00593       /* fields: item->u1.str        == the if conditional, as supplied by user
00594 
00595                item->u2.statements == a pval list of statements in the if ()
00596                item->u3.else_statements == a pval list of statements in the else
00597                                     (could be zero)
00598       */
00599       traverse_pval_item_template(item->u2.statements,depth+1);
00600       if ( item->u3.else_statements ) {
00601          traverse_pval_item_template(item->u3.else_statements,depth+1);
00602       }
00603       break;
00604          
00605    case PV_SWITCH:
00606       /* fields: item->u1.str        == the switch expression
00607 
00608                item->u2.statements == a pval list of statements in the switch, 
00609                                     (will be case statements, most likely!)
00610       */
00611       traverse_pval_item_template(item->u2.statements,depth+1);
00612       break;
00613          
00614    case PV_EXTENSION:
00615       /* fields: item->u1.str        == the extension name, label, whatever it's called
00616 
00617                item->u2.statements == a pval list of statements in the extension
00618                item->u3.hints      == a char * hint argument
00619                item->u4.regexten   == an int boolean. non-zero says that regexten was specified
00620       */
00621       traverse_pval_item_template(item->u2.statements,depth+1);
00622       break;
00623          
00624    case PV_IGNOREPAT:
00625       /* fields: item->u1.str        == the ignorepat data
00626       */
00627       break;
00628          
00629    case PV_GLOBALS:
00630       /* fields: item->u1.statements     == pval list of statements, usually vardecs
00631       */
00632       traverse_pval_item_template(item->u1.statements,depth+1);
00633       break;
00634    }
00635 }

void traverse_pval_template ( pval item,
int  depth 
)

Definition at line 637 of file pval.c.

References pval::next, and traverse_pval_item_template().

00639 {
00640    pval *i;
00641    
00642    for (i=item; i; i=i->next) {
00643       traverse_pval_item_template(i, depth);
00644    }
00645 }


Variable Documentation

int control_statement_count = 0 [static]

Definition at line 2930 of file pval.c.

Referenced by gen_prios().

int count_labels [static]

Definition at line 83 of file pval.c.

pval* current_context [static]

Definition at line 76 of file pval.c.

Referenced by check_label(), and check_pval_item().

pval* current_db [static]

Definition at line 75 of file pval.c.

Referenced by ael2_semantic_check(), check_abstract_reference(), check_context_names(), find_context(), find_label_in_current_db(), and find_macro().

pval* current_extension [static]

Definition at line 77 of file pval.c.

Referenced by check_label(), and check_pval_item().

char* days[] [static]

Definition at line 894 of file pval.c.

int errs [static]

Definition at line 68 of file pval.c.

Referenced by pbx_load_module().

char expr_output[2096] [static]

Definition at line 62 of file pval.c.

int in_abstract_context [static]

Definition at line 82 of file pval.c.

int label_count [static]

Definition at line 84 of file pval.c.

pval* last_matched_label [static]

Definition at line 86 of file pval.c.

Referenced by match_pval_item().

const char* match_context [static]

Definition at line 79 of file pval.c.

const char* match_exten [static]

Definition at line 80 of file pval.c.

const char* match_label [static]

Definition at line 81 of file pval.c.

char* months[] [static]

Definition at line 992 of file pval.c.

int notes [static]

Definition at line 69 of file pval.c.

char* registrar = "pbx_ael" [static]

Definition at line 73 of file pval.c.

int return_on_context_match [static]

Definition at line 85 of file pval.c.

int warns [static]

Definition at line 68 of file pval.c.


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