Wed Aug 7 17:16:09 2019

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 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)
struct 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)
struct 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)
struct pvalmatch_pval (pval *item)
static struct pvalmatch_pval_item (pval *item)
struct ael_extensionnew_exten (void)
struct 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

struct 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 BUF_SIZE   2000

Definition at line 63 of file pval.c.


Function Documentation

void add_extensions ( struct ael_extension exten  ) 

Definition at line 4251 of file pval.c.

References AEL_APPCALL, AEL_CONTROL1, AEL_FOR_CONTROL, AEL_IF_CONTROL, AEL_IFTIME_CONTROL, AEL_LABEL, AEL_RAND_CONTROL, AEL_RETURN, ael_priority::app, ael_priority::appargs, ast_add_extension2(), ast_free_ptr(), ast_log(), AST_MAX_EXTENSION, ael_extension::cidmatch, ael_extension::context, pval::else_statements, ael_priority::exten, ael_priority::goto_false, ael_priority::goto_true, ael_extension::hints, last, LOG_WARNING, ael_extension::name, ael_priority::next, ael_extension::next_exten, ael_priority::origin, pbx_substitute_variables_helper(), ael_extension::plist, PRIORITY_HINT, ael_priority::priority_num, PV_IFTIME, PV_SWITCH, pval::str, strdup, pval::type, ael_priority::type, pval::u1, and pval::u3.

Referenced by ast_compile_ael2().

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

void ael2_print ( char *  fname,
pval tree 
)

Definition at line 384 of file pval.c.

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

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

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

Definition at line 2892 of file pval.c.

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

Referenced by pbx_load_module().

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

int ast_compile_ael2 ( struct ast_context **  local_contexts,
struct ast_hashtab local_table,
struct pval root 
)

Definition at line 4451 of file pval.c.

References add_extensions(), AEL_APPCALL, AEL_LABEL, ael_priority::app, ael_priority::appargs, pval::arglist, ARRAY_LEN, ast_compat_app_set, ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_find_or_create(), ast_custom_function_find(), ast_get_context_name(), attach_exten(), ael_extension::cidmatch, ael_extension::context, context, context_used(), destroy_extensions(), exten, fix_gotos_in_extensions(), gen_prios(), ael_extension::hints, pval::hints, linkprio(), pval::list, pval::macro_statements, ael_extension::name, new_exten(), new_prio(), pval::next, ael_extension::next_exten, ael_priority::origin, pbx_builtin_setvar(), ael_extension::plist_last, ael_priority::priority_num, PV_CONTEXT, PV_ESWITCHES, PV_EXTENSION, PV_GLOBALS, PV_IGNOREPAT, PV_INCLUDES, PV_MACRO, PV_SWITCHES, pval::regexten, ael_extension::regexten, remove_spaces_before_equals(), ael_extension::return_needed, set_priorities(), pval::statements, pval::str, strdup, ael_priority::type, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.

Referenced by pbx_load_module().

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

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

Definition at line 4356 of file pval.c.

References ael_extension::next_exten.

Referenced by ast_compile_ael2().

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

static void check_abstract_reference ( pval abstract_context  )  [static]

Definition at line 2336 of file pval.c.

References ast_log(), pval::endline, pval::filename, pval::list, LOG_WARNING, pval::next, PV_CONTEXT, PV_INCLUDES, pval::startline, pval::str, pval::type, pval::u1, and pval::u2.

Referenced by check_pval_item().

02337 {
02338    pval *i,*j;
02339    /* find some context includes that reference this context */
02340    
02341 
02342    /* otherwise, print out a warning */
02343    for (i=current_db; i; i=i->next) {
02344       if (i->type == PV_CONTEXT) {
02345          for (j=i->u2. statements; j; j=j->next) {
02346             if ( j->type == PV_INCLUDES ) {
02347                struct pval *p4;
02348                for (p4=j->u1.list; p4; p4=p4->next) {
02349                   /* for each context pointed to, find it, then find a context/label that matches the
02350                      target here! */
02351                   if ( !strcmp(p4->u1.str, abstract_context->u1.str) )
02352                      return; /* found a match! */
02353                }
02354             }
02355          }
02356       }
02357    }
02358    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",
02359          abstract_context->filename, abstract_context->startline, abstract_context->endline, abstract_context->u1.str);
02360    warns++;
02361 }

int check_app_args ( pval appcall,
pval arglist,
struct argapp app 
)

Definition at line 2137 of file pval.c.

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

Referenced by check_pval_item().

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

static int check_break ( pval item  )  [static]

Definition at line 1045 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().

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

static void check_context_names ( void   )  [static]

Definition at line 2317 of file pval.c.

References pval::abstract, ast_log(), 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().

02318 {
02319    pval *i,*j;
02320    for (i=current_db; i; i=i->next) {
02321       if (i->type == PV_CONTEXT || i->type == PV_MACRO) {
02322          for (j=i->next; j; j=j->next) {
02323             if ( j->type == PV_CONTEXT || j->type == PV_MACRO ) {
02324                if ( !strcmp(i->u1.str, j->u1.str) && !(i->u3.abstract&2) && !(j->u3.abstract&2) )
02325                {
02326                   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",
02327                         i->filename, i->startline, i->endline, i->u1.str,  j->filename, j->startline, j->endline);
02328                   warns++;
02329                }
02330             }
02331          }
02332       }
02333    }
02334 }

static int check_continue ( pval item  )  [static]

Definition at line 1065 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().

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

static void check_day ( pval DAY  )  [static]

Definition at line 944 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().

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

static void check_dow ( pval DOW  )  [static]

get_dow: Get day of week

Definition at line 905 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().

00906 {
00907    char *dow;
00908    char *c;
00909    /* The following line is coincidence, really! */
00910    int s, e;
00911    
00912    dow = ast_strdupa(DOW->u1.str);
00913 
00914    /* Check for all days */
00915    if (ast_strlen_zero(dow) || !strcmp(dow, "*"))
00916       return;
00917    /* Get start and ending days */
00918    c = strchr(dow, '-');
00919    if (c) {
00920       *c = '\0';
00921       c++;
00922    } else
00923       c = NULL;
00924    /* Find the start */
00925    s = 0;
00926    while ((s < 7) && strcasecmp(dow, days[s])) s++;
00927    if (s >= 7) {
00928       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",
00929             DOW->filename, DOW->startline, DOW->endline, dow);
00930       warns++;
00931    }
00932    if (c) {
00933       e = 0;
00934       while ((e < 7) && strcasecmp(c, days[e])) e++;
00935       if (e >= 7) {
00936          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",
00937                DOW->filename, DOW->startline, DOW->endline, c);
00938          warns++;
00939       }
00940    } else
00941       e = s;
00942 }

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

Definition at line 808 of file pval.c.

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

Referenced by check_pval_item().

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

static void check_goto ( pval item  )  [static]

Definition at line 1232 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().

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

static void check_includes ( pval includes  )  [static]

Definition at line 818 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().

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

static void check_label ( pval item  )  [static]

Definition at line 1113 of file pval.c.

References ast_log(), 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().

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

static void check_macro_returns ( pval macro  )  [static]

Definition at line 652 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().

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

static void check_month ( pval MON  )  [static]

Definition at line 1007 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().

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

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

Definition at line 2872 of file pval.c.

References check_pval_item(), and pval::next.

Referenced by ael2_semantic_check(), and check_pval_item().

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

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

Definition at line 2364 of file pval.c.

References pval::abstract, pval::arglist, ast_expr(), ast_expr_clear_extra_error_info(), ast_expr_register_extra_error_info(), ast_log(), check_abstract_reference(), check_app_args(), check_break(), check_continue(), check_day(), check_dow(), check_expr2_input(), check_goto(), check_includes(), check_label(), check_macro_returns(), check_month(), check_pval(), check_switch_expr(), check_timerange(), E_MATCH, pval::else_statements, pval::endcol, pval::endline, pval::filename, find_context(), find_macro(), find_pval_gotos(), pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, free, pval::list, localized_pbx_load_module(), LOG_ERROR, LOG_WARNING, pval::macro_statements, argapp::next, pval::next, pbx_find_extension(), PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTEXT, PV_CONTINUE, PV_DEFAULT, PV_ESWITCHES, PV_EXTENSION, PV_FOR, PV_GLOBALS, PV_GOTO, PV_IF, PV_IFTIME, PV_IGNOREPAT, PV_INCLUDES, PV_LABEL, PV_LOCALVARDEC, PV_MACRO, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_SWITCHES, PV_VARDEC, PV_WHILE, PV_WORD, pbx_find_info::stacklen, pval::startcol, pval::startline, pval::statements, pbx_find_info::status, STATUS_SUCCESS, pval::str, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.

Referenced by check_pval().

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

void check_switch_expr ( pval item,
struct argapp apps 
)

Definition at line 2191 of file pval.c.

References ast_log(), ast_strdupa, calloc, pval::endcol, pval::endline, pval::filename, LOG_WARNING, pval::next, argapp::next, PV_APPLICATION_CALL, PV_CASE, PV_DEFAULT, PV_PATTERN, PV_STATEMENTBLOCK, pval::startcol, pval::startline, pval::statements, pval::str, strdup, pval::type, pval::u1, and pval::u2.

Referenced by check_pval_item().

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

static void check_timerange ( pval p  )  [static]

Definition at line 837 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().

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

int contains_switch ( pval item  ) 

Definition at line 3336 of file pval.c.

References find_switch_item(), and pval::next.

Referenced by find_switch_item(), and gen_prios().

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

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

Definition at line 4436 of file pval.c.

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

Referenced by ast_compile_ael2().

04437 {
04438    struct ael_extension *exten;
04439    /* Check the simple elements first */
04440    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)) {
04441       return 1;
04442    }
04443    for (exten = exten_list; exten; exten = exten->next_exten) {
04444       if (exten->context == context) {
04445          return 1;
04446       }
04447    }
04448    return 0;
04449 }

void destroy_extensions ( struct ael_extension exten  ) 

Definition at line 2985 of file pval.c.

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

Referenced by ast_compile_ael2().

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

void destroy_pval ( pval item  ) 

Definition at line 4979 of file pval.c.

References destroy_pval_item(), and pval::next.

Referenced by destroy_pval_item(), pbx_load_module(), yydestruct(), and yyparse().

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

void destroy_pval_item ( pval item  ) 

Definition at line 4711 of file pval.c.

References pval::arglist, ast_log(), destroy_pval(), pval::else_statements, pval::filename, pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, free, pval::hints, pval::list, LOG_WARNING, pval::macro_statements, PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTEXT, PV_CONTINUE, PV_DEFAULT, PV_ESWITCHES, PV_EXTENSION, PV_FOR, PV_GLOBALS, PV_GOTO, PV_IF, PV_IFTIME, PV_IGNOREPAT, PV_INCLUDES, PV_LABEL, PV_LOCALVARDEC, PV_MACRO, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_SWITCHES, PV_VARDEC, PV_WHILE, PV_WORD, pval::statements, pval::str, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.

Referenced by destroy_pval().

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

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

Definition at line 696 of file pval.c.

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

Referenced by match_pval_item().

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

struct pval* find_context ( char *  name  )  [read]

Definition at line 1960 of file pval.c.

References match_pval().

Referenced by ast_add_extension_nolock(), check_goto(), check_includes(), check_pval_item(), find_first_label_in_current_context(), find_label_in_current_context(), find_pval_goto_item(), get_goto_target(), and pbx_find_extension().

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

struct pval * find_first_label_in_current_context ( char *  label,
pval curr_cont 
) [static, read]

Definition at line 1846 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().

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

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

Definition at line 1886 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().

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

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

Definition at line 1936 of file pval.c.

References match_pval().

Referenced by check_goto(), and get_goto_target().

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

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

Definition at line 1925 of file pval.c.

References match_pval().

Referenced by check_goto(), and get_goto_target().

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

struct pval* find_macro ( char *  name  )  [read]

Definition at line 1950 of file pval.c.

References match_pval().

Referenced by check_pval_item().

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

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

Definition at line 1386 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().

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

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

Definition at line 1557 of file pval.c.

References find_pval_goto_item(), and pval::next.

Referenced by check_pval_item(), and find_pval_goto_item().

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

int find_switch_item ( pval item  ) 

Definition at line 3097 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().

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

static void fix_gotos_in_extensions ( struct ael_extension exten  )  [static]

Definition at line 4393 of file pval.c.

References ael_priority::appargs, pval::compiled_label, free, pval::goto_target, pval::goto_target_in_case, pval::list, ael_extension::name, pval::next, ael_priority::next, ael_extension::next_exten, ael_priority::origin, ael_extension::plist, PV_GOTO, pval::str, strdup, pval::type, pval::u1, pval::u2, and pval::u3.

Referenced by ast_compile_ael2().

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

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

Definition at line 3068 of file pval.c.

Referenced by gen_prios().

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

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 3348 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, BUF_SIZE, ael_extension::checked_switch, pval::compiled_label, contains_switch(), ael_extension::context, pval::else_statements, ael_priority::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.

Referenced by ast_compile_ael2().

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

static pval * get_contxt ( pval p  )  [static]

Definition at line 4383 of file pval.c.

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

Referenced by check_goto(), and get_goto_target().

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

static pval * get_extension_or_contxt ( pval p  )  [static]

Definition at line 4373 of file pval.c.

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

Referenced by check_goto(), and get_goto_target().

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

static pval * get_goto_target ( pval item  )  [static]

Definition at line 1160 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().

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

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

Definition at line 1097 of file pval.c.

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

Referenced by check_goto().

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

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

Definition at line 1084 of file pval.c.

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

Referenced by check_goto().

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

int is_empty ( char *  arg  ) 

Definition at line 1988 of file pval.c.

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

int is_float ( char *  arg  ) 

Definition at line 1970 of file pval.c.

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

int is_int ( char *  arg  ) 

Definition at line 1979 of file pval.c.

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

static int label_inside_case ( pval label  )  [static]

Definition at line 3025 of file pval.c.

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

Referenced by gen_prios().

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

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

Definition at line 3039 of file pval.c.

References ael_extension::next_exten.

Referenced by gen_prios().

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

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

Definition at line 2943 of file pval.c.

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

Referenced by ast_compile_ael2(), and gen_prios().

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

pval* linku1 ( pval head,
pval tail 
)

Definition at line 5926 of file pval.c.

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

Referenced by pvalAppCallAddArg(), pvalCasePatDefAddStatement(), pvalContextAddStatement(), pvalESwitchesAddSwitch(), pvalGlobalsAddStatement(), pvalIncludesAddInclude(), pvalIncludesAddIncludeWithTimeConstraints(), pvalMacroAddArg(), pvalMacroAddStatement(), pvalMacroCallAddArg(), pvalStatementBlockAddStatement(), pvalSwitchAddCase(), pvalSwitchesAddSwitch(), pvalTopLevAddObject(), and yyparse().

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

int localized_pbx_load_module ( void   ) 
struct pval * match_pval ( pval item  )  [read]

Definition at line 1818 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().

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

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

Definition at line 1570 of file pval.c.

References pval::else_statements, extension_matches(), pval::for_statements, 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().

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

struct ael_extension* new_exten ( void   )  [read]

Definition at line 2937 of file pval.c.

References calloc.

Referenced by ast_compile_ael2(), and gen_prios().

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

struct ael_priority* new_prio ( void   )  [read]

Definition at line 2931 of file pval.c.

References calloc.

Referenced by ast_compile_ael2(), and gen_prios().

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

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

Definition at line 117 of file pval.c.

References pval::abstract, pval::arglist, pval::else_statements, pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, pval::hints, pval::list, pval::macro_statements, pval::next, print_pval_list(), 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::regexten, pval::statements, pval::str, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.

Referenced by print_pval_list().

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

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

Definition at line 375 of file pval.c.

References pval::next, and print_pval().

Referenced by ael2_print(), and print_pval().

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

void pvalAppCallAddArg ( pval p,
pval arg 
)

Definition at line 5304 of file pval.c.

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

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

char* pvalAppCallGetAppName ( pval p  ) 

Definition at line 5290 of file pval.c.

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

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

void pvalAppCallSetAppName ( pval p,
char *  name 
)

Definition at line 5283 of file pval.c.

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

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

void pvalAppCallSetArglist ( pval p,
pval arglist 
)

Definition at line 5297 of file pval.c.

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

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

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

Definition at line 5314 of file pval.c.

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

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

void pvalCasePatDefAddStatement ( pval p,
pval statement 
)

Definition at line 5339 of file pval.c.

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

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

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

Definition at line 5347 of file pval.c.

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

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

char* pvalCasePatGetVal ( pval p  ) 

Definition at line 5334 of file pval.c.

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

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

void pvalCasePatSetVal ( pval p,
char *  val 
)

Definition at line 5327 of file pval.c.

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

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

char* pvalCatchGetExtName ( pval p  ) 

Definition at line 5365 of file pval.c.

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

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

pval* pvalCatchGetStatement ( pval p  ) 

Definition at line 5379 of file pval.c.

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

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

void pvalCatchSetExtName ( pval p,
char *  name 
)

Definition at line 5358 of file pval.c.

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

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

void pvalCatchSetStatement ( pval p,
pval statement 
)

Definition at line 5372 of file pval.c.

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

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

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

Definition at line 5070 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().

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

pval* pvalConditionalGetElseStatement ( pval p  ) 

Definition at line 5755 of file pval.c.

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

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

pval* pvalConditionalGetThenStatement ( pval p  ) 

Definition at line 5750 of file pval.c.

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

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

void pvalConditionalSetElseStatement ( pval p,
pval statement 
)

Definition at line 5745 of file pval.c.

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

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

void pvalConditionalSetThenStatement ( pval p,
pval statement 
)

Definition at line 5740 of file pval.c.

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

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

void pvalContextAddStatement ( pval p,
pval statement 
)

Definition at line 5216 of file pval.c.

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

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

int pvalContextGetAbstract ( pval p  ) 

Definition at line 5207 of file pval.c.

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

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

char* pvalContextGetName ( pval p  ) 

Definition at line 5186 of file pval.c.

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

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

void pvalContextSetAbstract ( pval p  ) 

Definition at line 5193 of file pval.c.

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

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

void pvalContextSetName ( pval p,
char *  name 
)

Definition at line 5179 of file pval.c.

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

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

void pvalContextUnsetAbstract ( pval p  ) 

Definition at line 5200 of file pval.c.

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

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

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

Definition at line 5226 of file pval.c.

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

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

pval* pvalCreateNode ( pvaltype  type  ) 

Definition at line 5081 of file pval.c.

References calloc, and pval::type.

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

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

void pvalESwitchesAddSwitch ( pval p,
char *  name 
)

Definition at line 5409 of file pval.c.

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

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

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

Definition at line 5419 of file pval.c.

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

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

char* pvalExtenGetHints ( pval p  ) 

Definition at line 5841 of file pval.c.

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

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

char* pvalExtenGetName ( pval p  ) 

Definition at line 5806 of file pval.c.

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

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

int pvalExtenGetRegexten ( pval p  ) 

Definition at line 5827 of file pval.c.

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

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

pval* pvalExtenGetStatement ( pval p  ) 

Definition at line 5855 of file pval.c.

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

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

void pvalExtenSetHints ( pval p,
char *  hints 
)

Definition at line 5834 of file pval.c.

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

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

void pvalExtenSetName ( pval p,
char *  name 
)

Definition at line 5799 of file pval.c.

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

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

void pvalExtenSetRegexten ( pval p  ) 

Definition at line 5813 of file pval.c.

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

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

void pvalExtenSetStatement ( pval p,
pval statement 
)

Definition at line 5848 of file pval.c.

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

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

void pvalExtenUnSetRegexten ( pval p  ) 

Definition at line 5820 of file pval.c.

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

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

char* pvalForGetInc ( pval p  ) 

Definition at line 5667 of file pval.c.

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

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

char* pvalForGetInit ( pval p  ) 

Definition at line 5653 of file pval.c.

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

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

pval* pvalForGetStatement ( pval p  ) 

Definition at line 5674 of file pval.c.

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

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

char* pvalForGetTest ( pval p  ) 

Definition at line 5660 of file pval.c.

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

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

void pvalForSetInc ( pval p,
char *  inc 
)

Definition at line 5639 of file pval.c.

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

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

void pvalForSetInit ( pval p,
char *  init 
)

Definition at line 5625 of file pval.c.

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

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

void pvalForSetStatement ( pval p,
pval statement 
)

Definition at line 5646 of file pval.c.

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

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

void pvalForSetTest ( pval p,
char *  test 
)

Definition at line 5632 of file pval.c.

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

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

void pvalGlobalsAddStatement ( pval p,
pval statement 
)

Definition at line 5878 of file pval.c.

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

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

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

Definition at line 5891 of file pval.c.

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

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

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

Definition at line 5583 of file pval.c.

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

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

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

Definition at line 5547 of file pval.c.

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

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

char* pvalIfGetCondition ( pval p  ) 

Definition at line 5690 of file pval.c.

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

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

void pvalIfSetCondition ( pval p,
char *  expr 
)

Definition at line 5683 of file pval.c.

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

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

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

Definition at line 5716 of file pval.c.

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

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

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

Definition at line 5697 of file pval.c.

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

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

char* pvalIgnorePatGetPattern ( pval p  ) 

Definition at line 5870 of file pval.c.

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

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

void pvalIgnorePatSetPattern ( pval p,
char *  pat 
)

Definition at line 5863 of file pval.c.

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

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

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

Definition at line 5470 of file pval.c.

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

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

void pvalIncludesAddInclude ( pval p,
const char *  include 
)

Definition at line 5432 of file pval.c.

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

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

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

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

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

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

Definition at line 5487 of file pval.c.

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

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

char* pvalLabelGetName ( pval p  ) 

Definition at line 5617 of file pval.c.

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

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

void pvalLabelSetName ( pval p,
char *  name 
)

Definition at line 5610 of file pval.c.

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

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

void pvalMacroAddArg ( pval p,
pval arg 
)

Definition at line 5130 of file pval.c.

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

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

void pvalMacroAddStatement ( pval p,
pval statement 
)

Definition at line 5153 of file pval.c.

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

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

void pvalMacroCallAddArg ( pval p,
pval arg 
)

Definition at line 5260 of file pval.c.

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

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

char* pvalMacroCallGetMacroName ( pval p  ) 

Definition at line 5246 of file pval.c.

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

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

void pvalMacroCallSetArglist ( pval p,
pval arglist 
)

Definition at line 5253 of file pval.c.

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

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

void pvalMacroCallSetMacroName ( pval p,
char *  name 
)

Definition at line 5239 of file pval.c.

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

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

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

Definition at line 5270 of file pval.c.

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

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

char* pvalMacroGetName ( pval p  ) 

Definition at line 5116 of file pval.c.

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

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

void pvalMacroSetArglist ( pval p,
pval arglist 
)

Definition at line 5123 of file pval.c.

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

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

void pvalMacroSetName ( pval p,
char *  name 
)

Definition at line 5109 of file pval.c.

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

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

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

Definition at line 5141 of file pval.c.

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

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

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

Definition at line 5165 of file pval.c.

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

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

pvaltype pvalObjectGetType ( pval p  ) 

Definition at line 5088 of file pval.c.

References pval::type.

05089 {
05090    return p->type;
05091 }

char* pvalRandomGetCondition ( pval p  ) 

Definition at line 5733 of file pval.c.

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

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

void pvalRandomSetCondition ( pval p,
char *  percent 
)

Definition at line 5726 of file pval.c.

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

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

void pvalStatementBlockAddStatement ( pval p,
pval statement 
)

Definition at line 5500 of file pval.c.

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

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

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

Definition at line 5507 of file pval.c.

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

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

void pvalSwitchAddCase ( pval p,
pval Case 
)

Definition at line 5774 of file pval.c.

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

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

void pvalSwitchesAddSwitch ( pval p,
char *  name 
)

Definition at line 5387 of file pval.c.

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

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

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

Definition at line 5397 of file pval.c.

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

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

char* pvalSwitchGetTestexpr ( pval p  ) 

Definition at line 5767 of file pval.c.

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

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

void pvalSwitchSetTestexpr ( pval p,
char *  expr 
)

Definition at line 5760 of file pval.c.

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

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

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

Definition at line 5786 of file pval.c.

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

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

void pvalTopLevAddObject ( pval p,
pval contextOrObj 
)

Definition at line 5905 of file pval.c.

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

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

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

Definition at line 5914 of file pval.c.

References pval::next.

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

char* pvalVarDecGetValue ( pval p  ) 

Definition at line 5540 of file pval.c.

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

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

char* pvalVarDecGetVarname ( pval p  ) 

Definition at line 5533 of file pval.c.

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

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

void pvalVarDecSetValue ( pval p,
char *  value 
)

Definition at line 5526 of file pval.c.

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

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

void pvalVarDecSetVarname ( pval p,
char *  name 
)

Definition at line 5519 of file pval.c.

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

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

char* pvalWordGetString ( pval p  ) 

Definition at line 5101 of file pval.c.

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

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

void pvalWordSetString ( pval p,
char *  str 
)

Definition at line 5094 of file pval.c.

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

Referenced by pvalIfTimeSetCondition().

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

static void remove_spaces_before_equals ( char *  str  )  [static]

Definition at line 3045 of file pval.c.

Referenced by ast_compile_ael2(), and gen_prios().

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

void set_priorities ( struct ael_extension exten  ) 

Definition at line 4225 of file pval.c.

References ael_extension::is_switch, ael_priority::next, ael_extension::next_exten, ael_priority::origin, ael_extension::plist, ael_priority::priority_num, PV_LABEL, ael_extension::regexten, and pval::type.

Referenced by ast_compile_ael2().

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

void traverse_pval_item_template ( pval item,
int  depth 
)

Definition at line 402 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().

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

void traverse_pval_template ( pval item,
int  depth 
)

Definition at line 636 of file pval.c.

References pval::next, and traverse_pval_item_template().

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


Variable Documentation

int control_statement_count = 0 [static]

Definition at line 2929 of file pval.c.

int count_labels [static]

Definition at line 82 of file pval.c.

pval* current_context [static]

Definition at line 75 of file pval.c.

pval* current_db [static]

Definition at line 74 of file pval.c.

Definition at line 76 of file pval.c.

char* days[] [static]

Definition at line 893 of file pval.c.

int errs [static]

Definition at line 67 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 81 of file pval.c.

int label_count [static]

Definition at line 83 of file pval.c.

Definition at line 85 of file pval.c.

const char* match_context [static]

Definition at line 78 of file pval.c.

const char* match_exten [static]

Definition at line 79 of file pval.c.

const char* match_label [static]

Definition at line 80 of file pval.c.

char* months[] [static]

Definition at line 991 of file pval.c.

int notes [static]

Definition at line 68 of file pval.c.

char* registrar = "pbx_ael" [static]

Definition at line 72 of file pval.c.

Definition at line 84 of file pval.c.

int warns [static]

Definition at line 67 of file pval.c.


Generated on 7 Aug 2019 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1