Thu Oct 11 06:49:31 2012

Asterisk developer's documentation


pval.c File Reference

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

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

Include dependency graph for pval.c:

Go to the source code of this file.

Defines

#define AST_PBX_MAX_STACK   128
#define BUF_SIZE   2000

Functions

void add_extensions (struct ael_extension *exten)
void ael2_print (char *fname, pval *tree)
void ael2_semantic_check (pval *item, int *arg_errs, int *arg_warns, int *arg_notes)
int ast_compile_ael2 (struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root)
static void attach_exten (struct ael_extension **list, struct ael_extension *newmem)
static void check_abstract_reference (pval *abstract_context)
int check_app_args (pval *appcall, pval *arglist, struct argapp *app)
static int check_break (pval *item)
static void check_context_names (void)
static int check_continue (pval *item)
static void check_day (pval *DAY)
static void check_dow (pval *DOW)
 get_dow: Get day of week
static void check_expr2_input (pval *expr, char *str)
static void check_goto (pval *item)
static void check_includes (pval *includes)
static void check_label (pval *item)
static void check_macro_returns (pval *macro)
static void check_month (pval *MON)
void check_pval (pval *item, struct argapp *apps, int in_globals)
void check_pval_item (pval *item, struct argapp *apps, int in_globals)
void check_switch_expr (pval *item, struct argapp *apps)
static void check_timerange (pval *p)
int contains_switch (pval *item)
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 AST_PBX_MAX_STACK   128

Definition at line 59 of file pval.c.

#define BUF_SIZE   2000

Definition at line 60 of file pval.c.


Function Documentation

void add_extensions ( struct ael_extension exten  ) 

Definition at line 4241 of file pval.c.

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

Referenced by ast_compile_ael2().

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

void ael2_print ( char *  fname,
pval tree 
)

Definition at line 381 of file pval.c.

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

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

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

Definition at line 2882 of file pval.c.

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

Referenced by pbx_load_module().

02883 {
02884    
02885 #ifdef AAL_ARGCHECK
02886    int argapp_errs =0;
02887    char *rfilename;
02888 #endif
02889    struct argapp *apps=0;
02890 
02891    if (!item)
02892       return; /* don't check an empty tree */
02893 #ifdef AAL_ARGCHECK
02894    rfilename = alloca(10 + strlen(ast_config_AST_VAR_DIR));
02895    sprintf(rfilename, "%s/applist", ast_config_AST_VAR_DIR);
02896    
02897    apps = argdesc_parse(rfilename, &argapp_errs); /* giveth */
02898 #endif
02899    current_db = item;
02900    errs = warns = notes = 0;
02901 
02902    check_context_names();
02903    check_pval(item, apps, 0);
02904 
02905 #ifdef AAL_ARGCHECK
02906    argdesc_destroy(apps);  /* taketh away */
02907 #endif
02908    current_db = 0;
02909 
02910    *arg_errs = errs;
02911    *arg_warns = warns;
02912    *arg_notes = notes;
02913 }

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

Definition at line 4427 of file pval.c.

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

Referenced by pbx_load_module().

04428 {
04429    pval *p,*p2;
04430    struct ast_context *context;
04431    char buf[2000];
04432    struct ael_extension *exten;
04433    struct ael_extension *exten_list = 0;
04434 
04435    for (p=root; p; p=p->next ) { /* do the globals first, so they'll be there
04436                             when we try to eval them */
04437       switch (p->type) {
04438       case PV_GLOBALS:
04439          /* just VARDEC elements */
04440          for (p2=p->u1.list; p2; p2=p2->next) {
04441             char buf2[2000];
04442             snprintf(buf2,sizeof(buf2),"%s=%s", p2->u1.str, p2->u2.val);
04443             pbx_builtin_setvar(NULL, buf2);
04444          }
04445          break;
04446       default:
04447          break;
04448       }
04449    }
04450 
04451    for (p=root; p; p=p->next ) {
04452       pval *lp;
04453       int argc;
04454       
04455       switch (p->type) {
04456       case PV_MACRO:
04457          
04458          context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar);
04459          
04460          exten = new_exten();
04461          exten->context = context;
04462          exten->name = strdup("~~s~~");
04463          argc = 1;
04464          for (lp=p->u2.arglist; lp; lp=lp->next) {
04465             /* for each arg, set up a "Set" command */
04466             struct ael_priority *np2 = new_prio();
04467             np2->type = AEL_APPCALL;
04468             if (!ast_compat_app_set) {
04469                np2->app = strdup("MSet");
04470             } else {
04471                np2->app = strdup("Set");
04472             }
04473             snprintf(buf,sizeof(buf),"LOCAL(%s)=${ARG%d}", lp->u1.str, argc++);
04474             remove_spaces_before_equals(buf);
04475             np2->appargs = strdup(buf);
04476             linkprio(exten, np2, NULL);
04477          }
04478          
04479          /* CONTAINS APPCALLS, CATCH, just like extensions... */
04480          if (gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context)) {
04481             return -1;
04482          }
04483          if (exten->return_needed) {  /* most likely, this will go away */
04484             struct ael_priority *np2 = new_prio();
04485             np2->type = AEL_APPCALL;
04486             np2->app = strdup("NoOp");
04487             snprintf(buf,sizeof(buf),"End of Macro %s-%s",p->u1.str, exten->name);
04488             np2->appargs = strdup(buf);
04489             linkprio(exten, np2, NULL);
04490             exten-> return_target = np2;
04491          }
04492          
04493          set_priorities(exten);
04494          attach_exten(&exten_list, exten);
04495          break;
04496          
04497       case PV_GLOBALS:
04498          /* already done */
04499          break;
04500          
04501       case PV_CONTEXT:
04502          context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar);
04503          
04504          /* contexts contain: ignorepat, includes, switches, eswitches, extensions,  */
04505          for (p2=p->u2.statements; p2; p2=p2->next) {
04506             pval *p3;
04507             char *s3;
04508             
04509             switch (p2->type) {
04510             case PV_EXTENSION:
04511                exten = new_exten();
04512                exten->name = strdup(p2->u1.str);
04513                exten->context = context;
04514                
04515                if( (s3=strchr(exten->name, '/') ) != 0 )
04516                {
04517                   *s3 = 0;
04518                   exten->cidmatch = s3+1;
04519                }
04520                
04521                if ( p2->u3.hints )
04522                   exten->hints = strdup(p2->u3.hints);
04523                exten->regexten = p2->u4.regexten;
04524                if (gen_prios(exten, p->u1.str, p2->u2.statements, 0, context)) {
04525                   return -1;
04526                }
04527                if (exten->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */
04528                   struct ael_priority *np2 = new_prio();
04529                   np2->type = AEL_APPCALL;
04530                   np2->app = strdup("NoOp");
04531                   snprintf(buf,sizeof(buf),"End of Extension %s", exten->name);
04532                   np2->appargs = strdup(buf);
04533                   linkprio(exten, np2, NULL);
04534                   exten-> return_target = np2;
04535                }
04536                /* is the last priority in the extension a label? Then add a trailing no-op */
04537                if ( exten->plist_last && exten->plist_last->type == AEL_LABEL ) {
04538                   struct ael_priority *np2 = new_prio();
04539                   np2->type = AEL_APPCALL;
04540                   np2->app = strdup("NoOp");
04541                   snprintf(buf,sizeof(buf),"A NoOp to follow a trailing label %s", exten->plist_last->origin->u1.str);
04542                   np2->appargs = strdup(buf);
04543                   linkprio(exten, np2, NULL);
04544                }
04545 
04546                set_priorities(exten);
04547                attach_exten(&exten_list, exten);
04548                break;
04549                
04550             case PV_IGNOREPAT:
04551                ast_context_add_ignorepat2(context, p2->u1.str, registrar);
04552                break;
04553                
04554             case PV_INCLUDES:
04555                for (p3 = p2->u1.list; p3 ;p3=p3->next) {
04556                   if ( p3->u2.arglist ) {
04557                      snprintf(buf,sizeof(buf), "%s,%s,%s,%s,%s", 
04558                             p3->u1.str,
04559                             p3->u2.arglist->u1.str,
04560                             p3->u2.arglist->next->u1.str,
04561                             p3->u2.arglist->next->next->u1.str,
04562                             p3->u2.arglist->next->next->next->u1.str);
04563                      ast_context_add_include2(context, buf, registrar);
04564                   } else
04565                      ast_context_add_include2(context, p3->u1.str, registrar);
04566                }
04567                break;
04568                
04569             case PV_SWITCHES:
04570                for (p3 = p2->u1.list; p3 ;p3=p3->next) {
04571                   char *c = strchr(p3->u1.str, '/');
04572                   if (c) {
04573                      *c = '\0';
04574                      c++;
04575                   } else
04576                      c = "";
04577 
04578                   ast_context_add_switch2(context, p3->u1.str, c, 0, registrar);
04579                }
04580                break;
04581 
04582             case PV_ESWITCHES:
04583                for (p3 = p2->u1.list; p3 ;p3=p3->next) {
04584                   char *c = strchr(p3->u1.str, '/');
04585                   if (c) {
04586                      *c = '\0';
04587                      c++;
04588                   } else
04589                      c = "";
04590 
04591                   ast_context_add_switch2(context, p3->u1.str, c, 1, registrar);
04592                }
04593                break;
04594             default:
04595                break;
04596             }
04597          }
04598          
04599          break;
04600          
04601       default:
04602          /* huh? what? */
04603          break;
04604          
04605       }
04606    }
04607    /* moved these from being done after a macro or extension were processed,
04608       to after all processing is done, for the sake of fixing gotos to labels inside cases... */
04609    /* I guess this would be considered 2nd pass of compiler now... */
04610    fix_gotos_in_extensions(exten_list); /* find and fix extension ref in gotos to labels that are in case statements */
04611    add_extensions(exten_list);   /* actually makes calls to create priorities in ast_contexts -- feeds dialplan to asterisk */
04612    destroy_extensions(exten_list);  /* all that remains is an empty husk, discard of it as is proper */
04613    
04614    return 0;
04615 }

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

Definition at line 4346 of file pval.c.

References ael_extension::next_exten.

Referenced by ast_compile_ael2().

04347 {
04348    /* travel to the end of the list... */
04349    struct ael_extension *lptr;
04350    if( !*list ) {
04351       *list = newmem;
04352       return;
04353    }
04354    lptr = *list;
04355    
04356    while( lptr->next_exten ) {
04357       lptr = lptr->next_exten;
04358    }
04359    /* lptr should now pointing to the last element in the list; it has a null next_exten pointer */
04360    lptr->next_exten = newmem;
04361 }

static void check_abstract_reference ( pval abstract_context  )  [static]

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

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

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

Definition at line 2127 of file pval.c.

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

Referenced by check_pval_item().

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

static int check_break ( pval item  )  [static]

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

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

static void check_context_names ( void   )  [static]

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

02308 {
02309    pval *i,*j;
02310    for (i=current_db; i; i=i->next) {
02311       if (i->type == PV_CONTEXT || i->type == PV_MACRO) {
02312          for (j=i->next; j; j=j->next) {
02313             if ( j->type == PV_CONTEXT || j->type == PV_MACRO ) {
02314                if ( !strcmp(i->u1.str, j->u1.str) && !(i->u3.abstract&2) && !(j->u3.abstract&2) )
02315                {
02316                   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",
02317                         i->filename, i->startline, i->endline, i->u1.str,  j->filename, j->startline, j->endline);
02318                   warns++;
02319                }
02320             }
02321          }
02322       }
02323    }
02324 }

static int check_continue ( pval item  )  [static]

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

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

static void check_day ( pval DAY  )  [static]

Definition at line 941 of file pval.c.

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

Referenced by check_pval_item().

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

static void check_dow ( pval DOW  )  [static]

get_dow: Get day of week

Definition at line 902 of file pval.c.

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

Referenced by check_pval_item().

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

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

Definition at line 805 of file pval.c.

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

Referenced by check_pval_item().

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

static void check_goto ( pval item  )  [static]

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

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

static void check_includes ( pval includes  )  [static]

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

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

static void check_label ( pval item  )  [static]

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

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

static void check_macro_returns ( pval macro  )  [static]

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

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

static void check_month ( pval MON  )  [static]

Definition at line 1004 of file pval.c.

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

Referenced by check_pval_item().

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

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

Definition at line 2862 of file pval.c.

References check_pval_item(), and pval::next.

Referenced by ael2_semantic_check(), and check_pval_item().

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

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

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

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

void check_switch_expr ( pval item,
struct argapp apps 
)

Definition at line 2181 of file pval.c.

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

Referenced by check_pval_item().

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

static void check_timerange ( pval p  )  [static]

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

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

int contains_switch ( pval item  ) 

Definition at line 3326 of file pval.c.

References find_switch_item(), and pval::next.

Referenced by find_switch_item(), and gen_prios().

03327 {
03328    pval *i;
03329    
03330    for (i=item; i; i=i->next) {
03331       if (find_switch_item(i))
03332          return 1;
03333    }
03334    return 0;
03335 }

void destroy_extensions ( struct ael_extension exten  ) 

Definition at line 2975 of file pval.c.

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

Referenced by ast_compile_ael2().

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

void destroy_pval ( pval item  ) 

Definition at line 4890 of file pval.c.

References destroy_pval_item(), and pval::next.

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

04891 {
04892    pval *i,*nxt;
04893    
04894    for (i=item; i; i=nxt) {
04895       nxt = i->next;
04896       
04897       destroy_pval_item(i);
04898    }
04899 }

void destroy_pval_item ( pval item  ) 

Definition at line 4622 of file pval.c.

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

Referenced by destroy_pval().

04623 {
04624    if (item == NULL) {
04625       ast_log(LOG_WARNING, "null item\n");
04626       return;
04627    }
04628 
04629    if (item->filename)
04630       free(item->filename);
04631    
04632    switch (item->type) {
04633    case PV_WORD:
04634       /* fields: item->u1.str == string associated with this (word). */
04635       if (item->u1.str )
04636          free(item->u1.str);
04637       if ( item->u2.arglist )
04638          destroy_pval(item->u2.arglist);
04639       break;
04640       
04641    case PV_MACRO:
04642       /* fields: item->u1.str     == name of macro
04643                  item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
04644                item->u2.arglist->u1.str  == argument
04645                item->u2.arglist->next   == next arg
04646 
04647                item->u3.macro_statements == pval list of statements in macro body.
04648       */
04649       destroy_pval(item->u2.arglist);
04650       if (item->u1.str )
04651          free(item->u1.str);
04652       destroy_pval(item->u3.macro_statements);
04653       break;
04654          
04655    case PV_CONTEXT:
04656       /* fields: item->u1.str     == name of context
04657                  item->u2.statements == pval list of statements in context body
04658                item->u3.abstract == int 1 if an abstract keyword were present
04659       */
04660       if (item->u1.str)
04661          free(item->u1.str);
04662       destroy_pval(item->u2.statements);
04663       break;
04664          
04665    case PV_MACRO_CALL:
04666       /* fields: item->u1.str     == name of macro to call
04667                  item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
04668                item->u2.arglist->u1.str  == argument
04669                item->u2.arglist->next   == next arg
04670       */
04671       if (item->u1.str)
04672          free(item->u1.str);
04673       destroy_pval(item->u2.arglist);
04674       break;
04675          
04676    case PV_APPLICATION_CALL:
04677       /* fields: item->u1.str     == name of application to call
04678                  item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
04679                item->u2.arglist->u1.str  == argument
04680                item->u2.arglist->next   == next arg
04681       */
04682       if (item->u1.str)
04683          free(item->u1.str);
04684       destroy_pval(item->u2.arglist);
04685       break;
04686          
04687    case PV_CASE:
04688       /* fields: item->u1.str     == value of case
04689                  item->u2.statements == pval list of statements under the case
04690       */
04691       if (item->u1.str)
04692          free(item->u1.str);
04693       destroy_pval(item->u2.statements);
04694       break;
04695          
04696    case PV_PATTERN:
04697       /* fields: item->u1.str     == value of case
04698                  item->u2.statements == pval list of statements under the case
04699       */
04700       if (item->u1.str)
04701          free(item->u1.str);
04702       destroy_pval(item->u2.statements);
04703       break;
04704          
04705    case PV_DEFAULT:
04706       /* fields: 
04707                  item->u2.statements == pval list of statements under the case
04708       */
04709       destroy_pval(item->u2.statements);
04710       break;
04711          
04712    case PV_CATCH:
04713       /* fields: item->u1.str     == name of extension to catch
04714                  item->u2.statements == pval list of statements in context body
04715       */
04716       if (item->u1.str)
04717          free(item->u1.str);
04718       destroy_pval(item->u2.statements);
04719       break;
04720          
04721    case PV_SWITCHES:
04722       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
04723       */
04724       destroy_pval(item->u1.list);
04725       break;
04726          
04727    case PV_ESWITCHES:
04728       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
04729       */
04730       destroy_pval(item->u1.list);
04731       break;
04732          
04733    case PV_INCLUDES:
04734       /* fields: item->u1.list     == pval list of PV_WORD elements, one per entry in the list
04735                  item->u2.arglist  == pval list of 4 PV_WORD elements for time values
04736       */
04737       destroy_pval(item->u1.list);
04738       break;
04739          
04740    case PV_STATEMENTBLOCK:
04741       /* fields: item->u1.list     == pval list of statements in block, one per entry in the list
04742       */
04743       destroy_pval(item->u1.list);
04744       break;
04745          
04746    case PV_LOCALVARDEC:
04747    case PV_VARDEC:
04748       /* fields: item->u1.str     == variable name
04749                  item->u2.val     == variable value to assign
04750       */
04751       if (item->u1.str)
04752          free(item->u1.str);
04753       if (item->u2.val)
04754          free(item->u2.val);
04755       break;
04756          
04757    case PV_GOTO:
04758       /* fields: item->u1.list     == pval list of PV_WORD target names, up to 3, in order as given by user.
04759                  item->u1.list->u1.str  == where the data on a PV_WORD will always be.
04760       */
04761       
04762       destroy_pval(item->u1.list);
04763       break;
04764          
04765    case PV_LABEL:
04766       /* fields: item->u1.str     == label name
04767       */
04768       if (item->u1.str)
04769          free(item->u1.str);
04770       break;
04771          
04772    case PV_FOR:
04773       /* fields: item->u1.for_init     == a string containing the initalizer
04774                  item->u2.for_test     == a string containing the loop test
04775                  item->u3.for_inc      == a string containing the loop increment
04776 
04777                item->u4.for_statements == a pval list of statements in the for ()
04778       */
04779       if (item->u1.for_init)
04780          free(item->u1.for_init);
04781       if (item->u2.for_test)
04782          free(item->u2.for_test);
04783       if (item->u3.for_inc)
04784          free(item->u3.for_inc);
04785       destroy_pval(item->u4.for_statements);
04786       break;
04787          
04788    case PV_WHILE:
04789       /* fields: item->u1.str        == the while conditional, as supplied by user
04790 
04791                item->u2.statements == a pval list of statements in the while ()
04792       */
04793       if (item->u1.str)
04794          free(item->u1.str);
04795       destroy_pval(item->u2.statements);
04796       break;
04797          
04798    case PV_BREAK:
04799       /* fields: none
04800       */
04801       break;
04802          
04803    case PV_RETURN:
04804       /* fields: none
04805       */
04806       break;
04807          
04808    case PV_CONTINUE:
04809       /* fields: none
04810       */
04811       break;
04812          
04813    case PV_IFTIME:
04814       /* fields: item->u1.list        == the 4 time values, in PV_WORD structs, linked list
04815 
04816                item->u2.statements == a pval list of statements in the if ()
04817                item->u3.else_statements == a pval list of statements in the else
04818                                     (could be zero)
04819       */
04820       destroy_pval(item->u1.list);
04821       destroy_pval(item->u2.statements);
04822       if (item->u3.else_statements) {
04823          destroy_pval(item->u3.else_statements);
04824       }
04825       break;
04826          
04827    case PV_RANDOM:
04828       /* fields: item->u1.str        == the random percentage, as supplied by user
04829 
04830                item->u2.statements == a pval list of statements in the true part ()
04831                item->u3.else_statements == a pval list of statements in the else
04832                                     (could be zero)
04833       fall thru to If */
04834    case PV_IF:
04835       /* fields: item->u1.str        == the if conditional, as supplied by user
04836 
04837                item->u2.statements == a pval list of statements in the if ()
04838                item->u3.else_statements == a pval list of statements in the else
04839                                     (could be zero)
04840       */
04841       if (item->u1.str)
04842          free(item->u1.str);
04843       destroy_pval(item->u2.statements);
04844       if (item->u3.else_statements) {
04845          destroy_pval(item->u3.else_statements);
04846       }
04847       break;
04848          
04849    case PV_SWITCH:
04850       /* fields: item->u1.str        == the switch expression
04851 
04852                item->u2.statements == a pval list of statements in the switch, 
04853                                     (will be case statements, most likely!)
04854       */
04855       if (item->u1.str)
04856          free(item->u1.str);
04857       destroy_pval(item->u2.statements);
04858       break;
04859          
04860    case PV_EXTENSION:
04861       /* fields: item->u1.str        == the extension name, label, whatever it's called
04862 
04863                item->u2.statements == a pval list of statements in the extension
04864                item->u3.hints      == a char * hint argument
04865                item->u4.regexten   == an int boolean. non-zero says that regexten was specified
04866       */
04867       if (item->u1.str)
04868          free(item->u1.str);
04869       if (item->u3.hints)
04870          free(item->u3.hints);
04871       destroy_pval(item->u2.statements);
04872       break;
04873          
04874    case PV_IGNOREPAT:
04875       /* fields: item->u1.str        == the ignorepat data
04876       */
04877       if (item->u1.str)
04878          free(item->u1.str);
04879       break;
04880          
04881    case PV_GLOBALS:
04882       /* fields: item->u1.statements     == pval list of statements, usually vardecs
04883       */
04884       destroy_pval(item->u1.statements);
04885       break;
04886    }
04887    free(item);
04888 }

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

Definition at line 693 of file pval.c.

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

Referenced by match_pval_item().

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

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

Definition at line 1950 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(), and get_goto_target().

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 }

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

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

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

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

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

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

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

Definition at line 1926 of file pval.c.

References match_pval().

Referenced by check_goto(), and get_goto_target().

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

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

Definition at line 1915 of file pval.c.

References match_pval().

Referenced by check_goto(), and get_goto_target().

01916 {
01917    /* printf("  --- Got args %s\n", label); */
01918    count_labels = 0;
01919    return_on_context_match = 0;
01920    match_context = "*";
01921    match_exten = "*";
01922    match_label = label;
01923    return match_pval(curr_ext);
01924 }

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

Definition at line 1940 of file pval.c.

References match_pval().

Referenced by check_pval_item().

01941 {
01942    return_on_context_match = 1;
01943    count_labels = 0;
01944    match_context = name;
01945    match_exten = "*";  /* don't really need to set these, shouldn't be reached */
01946    match_label = "*";
01947    return match_pval(current_db);
01948 }

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

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

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

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

Definition at line 1547 of file pval.c.

References find_pval_goto_item(), and pval::next.

Referenced by check_pval_item(), and find_pval_goto_item().

01548 {
01549    pval *i;
01550    
01551    for (i=item; i; i=i->next) {
01552       /* printf("About to call pval_goto_item, itemcount=%d, itemtype=%d\n", item_count, i->type); */
01553       find_pval_goto_item(i, lev);
01554    }
01555 }

int find_switch_item ( pval item  ) 

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

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

static void fix_gotos_in_extensions ( struct ael_extension exten  )  [static]

Definition at line 4383 of file pval.c.

References ael_priority::appargs, buf1, 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().

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

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

Definition at line 3058 of file pval.c.

Referenced by gen_prios().

03059 {
03060    /* the result will be a string that will be matched by pattern */
03061    char *p=pattern, *t=result;
03062    while (*p) {
03063       if (*p == 'x' || *p == 'n' || *p == 'z' || *p == 'X' || *p == 'N' || *p == 'Z')
03064          *t++ = '9';
03065       else if (*p == '[') {
03066          char *z = p+1;
03067          while (*z != ']')
03068             z++;
03069          if (*(z+1)== ']')
03070             z++;
03071          *t++=*(p+1); /* use the first char in the set */
03072          p = z;
03073       } else {
03074          *t++ = *p;
03075       }
03076       p++;
03077    }
03078    *t++ = 0; /* cap it off */
03079 }

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 3338 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, buf1, buf2, 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().

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

static pval * get_contxt ( pval p  )  [static]

Definition at line 4373 of file pval.c.

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

Referenced by check_goto(), and get_goto_target().

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

static pval * get_extension_or_contxt ( pval p  )  [static]

Definition at line 4363 of file pval.c.

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

Referenced by check_goto(), and get_goto_target().

04364 {
04365    while( p && p->type != PV_EXTENSION && p->type != PV_CONTEXT && p->type != PV_MACRO ) {
04366       
04367       p = p->dad;
04368    }
04369    
04370    return p;
04371 }

static pval * get_goto_target ( pval item  )  [static]

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

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

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

Definition at line 1094 of file pval.c.

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

Referenced by check_goto().

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

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

Definition at line 1081 of file pval.c.

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

Referenced by check_goto().

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

int is_empty ( char *  arg  ) 

Definition at line 1978 of file pval.c.

01979 {
01980    if (!arg)
01981       return 1;
01982    if (*arg == 0)
01983       return 1;
01984    while (*arg) {
01985       if (*arg != ' ' && *arg != '\t')
01986          return 0;
01987       arg++;
01988    }
01989    return 1;
01990 }

int is_float ( char *  arg  ) 

Definition at line 1960 of file pval.c.

References s.

01961 {
01962    char *s;
01963    for (s=arg; *s; s++) {
01964       if (*s != '.' && (*s < '0' || *s > '9'))
01965          return 0;
01966    }
01967    return 1;
01968 }

int is_int ( char *  arg  ) 

Definition at line 1969 of file pval.c.

References s.

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

static int label_inside_case ( pval label  )  [static]

Definition at line 3015 of file pval.c.

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

Referenced by gen_prios().

03016 {
03017    pval *p = label;
03018    
03019    while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ {
03020       if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN ) {
03021          return 1;
03022       }
03023 
03024       p = p->dad;
03025    }
03026    return 0;
03027 }

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

Definition at line 3029 of file pval.c.

References ael_extension::next_exten.

Referenced by gen_prios().

03030 {
03031    add->next_exten = exten->next_exten; /* this will reverse the order. Big deal. */
03032    exten->next_exten = add;
03033 }

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

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

02934 {
02935    char *p1, *p2;
02936    
02937    if (!exten->plist) {
02938       exten->plist = prio;
02939       exten->plist_last = prio;
02940    } else {
02941       exten->plist_last->next = prio;
02942       exten->plist_last = prio;
02943    }
02944    if( !prio->exten )
02945       prio->exten = exten; /* don't override the switch value */
02946    /* The following code will cause all priorities within an extension 
02947       to have ${EXTEN} or ${EXTEN: replaced with ~~EXTEN~~, which is
02948       set just before the first switch in an exten. The switches
02949       will muck up the original ${EXTEN} value, so we save it away
02950       and the user accesses this copy instead. */
02951    if (prio->appargs && ((mother_exten && mother_exten->has_switch) || exten->has_switch) ) {
02952       while ((p1 = strstr(prio->appargs, "${EXTEN}"))) {
02953          p2 = malloc(strlen(prio->appargs)+5);
02954          *p1 = 0;
02955          strcpy(p2, prio->appargs);
02956          strcat(p2, "${~~EXTEN~~}");
02957          if (*(p1+8))
02958             strcat(p2, p1+8);
02959          free(prio->appargs);
02960          prio->appargs = p2;
02961       }
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    }
02973 }

pval* linku1 ( pval head,
pval tail 
)

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

05838 {
05839    if (!head)
05840       return tail;
05841    if (tail) {
05842       if (!head->next) {
05843          head->next = tail;
05844       } else {
05845          head->u1_last->next = tail;
05846       }
05847       head->u1_last = tail;
05848       tail->prev = head; /* the dad link only points to containers */
05849    }
05850    return head;
05851 }

int localized_pbx_load_module ( void   ) 

struct pval * match_pval ( pval item  )  [read]

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

01809 {
01810    pval *i;
01811 
01812    for (i=item; i; i=i->next) {
01813       pval *x;
01814       /* printf("   -- match pval: item %d\n", i->type); */
01815       
01816       if ((x = match_pval_item(i))) {
01817          /* printf("match_pval: returning x=%x\n", (int)x); */
01818          return x; /* cut the search short */
01819       }
01820    }
01821    return 0;
01822 }

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

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

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

struct ael_extension* new_exten ( void   )  [read]

Definition at line 2927 of file pval.c.

References calloc.

Referenced by ast_compile_ael2(), and gen_prios().

02928 {
02929    struct ael_extension *x = (struct ael_extension *)calloc(sizeof(struct ael_extension),1);
02930    return x;
02931 }

struct ael_priority* new_prio ( void   )  [read]

Definition at line 2921 of file pval.c.

References calloc.

Referenced by ast_compile_ael2(), and gen_prios().

02922 {
02923    struct ael_priority *x = (struct ael_priority *)calloc(sizeof(struct ael_priority),1);
02924    return x;
02925 }

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

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

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

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

Definition at line 372 of file pval.c.

References pval::next, and print_pval().

Referenced by ael2_print(), and print_pval().

00373 {
00374    pval *i;
00375    
00376    for (i=item; i; i=i->next) {
00377       print_pval(fin, i, depth);
00378    }
00379 }

void pvalAppCallAddArg ( pval p,
pval arg 
)

Definition at line 5215 of file pval.c.

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

05216 {
05217    if (!pvalCheckType(p, "pvalAppCallAddArg", PV_APPLICATION_CALL))
05218       return;
05219    if (!p->u2.arglist)
05220       p->u2.arglist = arg;
05221    else
05222       linku1(p->u2.arglist, arg);
05223 }

char* pvalAppCallGetAppName ( pval p  ) 

Definition at line 5201 of file pval.c.

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

05202 {
05203    if (!pvalCheckType(p, "pvalAppCallGetAppName", PV_APPLICATION_CALL))
05204       return 0;
05205    return p->u1.str;
05206 }

void pvalAppCallSetAppName ( pval p,
char *  name 
)

Definition at line 5194 of file pval.c.

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

05195 {
05196    if (!pvalCheckType(p, "pvalAppCallSetAppName", PV_APPLICATION_CALL))
05197       return;
05198    p->u1.str = name;
05199 }

void pvalAppCallSetArglist ( pval p,
pval arglist 
)

Definition at line 5208 of file pval.c.

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

05209 {
05210    if (!pvalCheckType(p, "pvalAppCallSetArglist", PV_APPLICATION_CALL))
05211       return;
05212    p->u2.arglist = arglist;
05213 }

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

Definition at line 5225 of file pval.c.

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

05226 {
05227    if (!pvalCheckType(p, "pvalAppCallWalkArgs", PV_APPLICATION_CALL))
05228       return 0;
05229    if (!(*args))
05230       *args = p->u2.arglist;
05231    else {
05232       *args = (*args)->next;
05233    }
05234    return *args;
05235 }

void pvalCasePatDefAddStatement ( pval p,
pval statement 
)

Definition at line 5250 of file pval.c.

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

05251 {
05252    if (!p->u2.arglist)
05253       p->u2.statements = statement;
05254    else
05255       linku1(p->u2.statements, statement);
05256 }

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

Definition at line 5258 of file pval.c.

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

05259 {
05260    if (!(*statement))
05261       *statement = p->u2.statements;
05262    else {
05263       *statement = (*statement)->next;
05264    }
05265    return *statement;
05266 }

char* pvalCasePatGetVal ( pval p  ) 

Definition at line 5245 of file pval.c.

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

05246 {
05247    return p->u1.str;
05248 }

void pvalCasePatSetVal ( pval p,
char *  val 
)

Definition at line 5238 of file pval.c.

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

05239 {
05240    if (!pvalCheckType(p, "pvalAppCallWalkArgs", PV_APPLICATION_CALL))
05241       return;
05242    p->u1.str = val;
05243 }

char* pvalCatchGetExtName ( pval p  ) 

Definition at line 5276 of file pval.c.

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

05277 {
05278    if (!pvalCheckType(p, "pvalCatchGetExtName", PV_CATCH))
05279       return 0;
05280    return p->u1.str;
05281 }

pval* pvalCatchGetStatement ( pval p  ) 

Definition at line 5290 of file pval.c.

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

05291 {
05292    if (!pvalCheckType(p, "pvalCatchGetStatement", PV_CATCH))
05293       return 0;
05294    return p->u2.statements;
05295 }

void pvalCatchSetExtName ( pval p,
char *  name 
)

Definition at line 5269 of file pval.c.

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

05270 {
05271    if (!pvalCheckType(p, "pvalCatchSetExtName", PV_CATCH))
05272       return;
05273    p->u1.str = name;
05274 }

void pvalCatchSetStatement ( pval p,
pval statement 
)

Definition at line 5283 of file pval.c.

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

05284 {
05285    if (!pvalCheckType(p, "pvalCatchSetStatement", PV_CATCH))
05286       return;
05287    p->u2.statements = statement;
05288 }

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

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

04982 {
04983    if (p->type != type)
04984    {
04985       ast_log(LOG_ERROR, "Func: %s the pval passed is not appropriate for this function!\n", funcname);
04986       return 0;
04987    }
04988    return 1;
04989 }

pval* pvalConditionalGetElseStatement ( pval p  ) 

Definition at line 5666 of file pval.c.

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

05667 {
05668    return p->u3.else_statements;
05669 }

pval* pvalConditionalGetThenStatement ( pval p  ) 

Definition at line 5661 of file pval.c.

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

05662 {
05663    return p->u2.statements;
05664 }

void pvalConditionalSetElseStatement ( pval p,
pval statement 
)

Definition at line 5656 of file pval.c.

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

05657 {
05658    p->u3.else_statements = statement;
05659 }

void pvalConditionalSetThenStatement ( pval p,
pval statement 
)

Definition at line 5651 of file pval.c.

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

05652 {
05653    p->u2.statements = statement;
05654 }

void pvalContextAddStatement ( pval p,
pval statement 
)

Definition at line 5127 of file pval.c.

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

05128 {
05129    if (!pvalCheckType(p, "pvalContextAddStatement", PV_CONTEXT))
05130       return;
05131    if (!p->u2.statements)
05132       p->u2.statements = statement;
05133    else
05134       linku1(p->u2.statements, statement);
05135 }

int pvalContextGetAbstract ( pval p  ) 

Definition at line 5118 of file pval.c.

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

05119 {
05120    if (!pvalCheckType(p, "pvalContextGetAbstract", PV_CONTEXT))
05121       return 0;
05122    return p->u3.abstract;
05123 }

char* pvalContextGetName ( pval p  ) 

Definition at line 5097 of file pval.c.

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

05098 {
05099    if (!pvalCheckType(p, "pvalContextGetName", PV_CONTEXT))
05100       return 0;
05101    return p->u1.str;
05102 }

void pvalContextSetAbstract ( pval p  ) 

Definition at line 5104 of file pval.c.

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

05105 {
05106    if (!pvalCheckType(p, "pvalContextSetAbstract", PV_CONTEXT))
05107       return;
05108    p->u3.abstract = 1;
05109 }

void pvalContextSetName ( pval p,
char *  name 
)

Definition at line 5090 of file pval.c.

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

05091 {
05092    if (!pvalCheckType(p, "pvalContextSetName", PV_CONTEXT))
05093       return;
05094    p->u1.str = name;
05095 }

void pvalContextUnsetAbstract ( pval p  ) 

Definition at line 5111 of file pval.c.

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

05112 {
05113    if (!pvalCheckType(p, "pvalContextUnsetAbstract", PV_CONTEXT))
05114       return;
05115    p->u3.abstract = 0;
05116 }

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

Definition at line 5137 of file pval.c.

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

05138 {
05139    if (!pvalCheckType(p, "pvalContextWalkStatements", PV_CONTEXT))
05140       return 0;
05141    if (!(*statements))
05142       *statements = p->u2.statements;
05143    else {
05144       *statements = (*statements)->next;
05145    }
05146    return *statements;
05147 }

pval* pvalCreateNode ( pvaltype  type  ) 

Definition at line 4992 of file pval.c.

References calloc, and pval::type.

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

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

void pvalESwitchesAddSwitch ( pval p,
char *  name 
)

Definition at line 5320 of file pval.c.

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

05321 {
05322    pval *s;
05323    if (!pvalCheckType(p, "pvalESwitchesAddSwitch", PV_ESWITCHES))
05324       return;
05325    s = pvalCreateNode(PV_WORD);
05326    s->u1.str = name;
05327    p->u1.list = linku1(p->u1.list, s);
05328 }

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

Definition at line 5330 of file pval.c.

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

05331 {
05332    if (!pvalCheckType(p, "pvalESwitchesWalkNames", PV_ESWITCHES))
05333       return 0;
05334    if (!(*next_item))
05335       *next_item = p->u1.list;
05336    else {
05337       *next_item = (*next_item)->next;
05338    }
05339    return (*next_item)->u1.str;
05340 }

char* pvalExtenGetHints ( pval p  ) 

Definition at line 5752 of file pval.c.

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

05753 {
05754    if (!pvalCheckType(p, "pvalExtenGetHints", PV_EXTENSION))
05755       return 0;
05756    return p->u3.hints;
05757 }

char* pvalExtenGetName ( pval p  ) 

Definition at line 5717 of file pval.c.

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

05718 {
05719    if (!pvalCheckType(p, "pvalExtenGetName", PV_EXTENSION))
05720       return 0;
05721    return p->u1.str;
05722 }

int pvalExtenGetRegexten ( pval p  ) 

Definition at line 5738 of file pval.c.

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

05739 {
05740    if (!pvalCheckType(p, "pvalExtenGetRegexten", PV_EXTENSION))
05741       return 0;
05742    return p->u4.regexten;
05743 }

pval* pvalExtenGetStatement ( pval p  ) 

Definition at line 5766 of file pval.c.

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

05767 {
05768    if (!pvalCheckType(p, "pvalExtenGetStatement", PV_EXTENSION))
05769       return 0;
05770    return p->u2.statements;
05771 }

void pvalExtenSetHints ( pval p,
char *  hints 
)

Definition at line 5745 of file pval.c.

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

05746 {
05747    if (!pvalCheckType(p, "pvalExtenSetHints", PV_EXTENSION))
05748       return;
05749    p->u3.hints = hints;
05750 }

void pvalExtenSetName ( pval p,
char *  name 
)

Definition at line 5710 of file pval.c.

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

05711 {
05712    if (!pvalCheckType(p, "pvalExtenSetName", PV_EXTENSION))
05713       return;
05714    p->u1.str = name;
05715 }

void pvalExtenSetRegexten ( pval p  ) 

Definition at line 5724 of file pval.c.

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

05725 {
05726    if (!pvalCheckType(p, "pvalExtenSetRegexten", PV_EXTENSION))
05727       return;
05728    p->u4.regexten = 1;
05729 }

void pvalExtenSetStatement ( pval p,
pval statement 
)

Definition at line 5759 of file pval.c.

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

05760 {
05761    if (!pvalCheckType(p, "pvalExtenSetStatement", PV_EXTENSION))
05762       return;
05763    p->u2.statements = statement;
05764 }

void pvalExtenUnSetRegexten ( pval p  ) 

Definition at line 5731 of file pval.c.

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

05732 {
05733    if (!pvalCheckType(p, "pvalExtenUnSetRegexten", PV_EXTENSION))
05734       return;
05735    p->u4.regexten = 0;
05736 }

char* pvalForGetInc ( pval p  ) 

Definition at line 5578 of file pval.c.

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

05579 {
05580    if (!pvalCheckType(p, "pvalForGetInc", PV_FOR))
05581       return 0;
05582    return p->u3.for_inc;
05583 }

char* pvalForGetInit ( pval p  ) 

Definition at line 5564 of file pval.c.

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

05565 {
05566    if (!pvalCheckType(p, "pvalForGetInit", PV_FOR))
05567       return 0;
05568    return p->u1.for_init;
05569 }

pval* pvalForGetStatement ( pval p  ) 

Definition at line 5585 of file pval.c.

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

05586 {
05587    if (!pvalCheckType(p, "pvalForGetStatement", PV_FOR))
05588       return 0;
05589    return p->u4.for_statements;
05590 }

char* pvalForGetTest ( pval p  ) 

Definition at line 5571 of file pval.c.

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

05572 {
05573    if (!pvalCheckType(p, "pvalForGetTest", PV_FOR))
05574       return 0;
05575    return p->u2.for_test;
05576 }

void pvalForSetInc ( pval p,
char *  inc 
)

Definition at line 5550 of file pval.c.

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

05551 {
05552    if (!pvalCheckType(p, "pvalForSetInc", PV_FOR))
05553       return;
05554    p->u3.for_inc = inc;
05555 }

void pvalForSetInit ( pval p,
char *  init 
)

Definition at line 5536 of file pval.c.

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

05537 {
05538    if (!pvalCheckType(p, "pvalForSetInit", PV_FOR))
05539       return;
05540    p->u1.for_init = init;
05541 }

void pvalForSetStatement ( pval p,
pval statement 
)

Definition at line 5557 of file pval.c.

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

05558 {
05559    if (!pvalCheckType(p, "pvalForSetStatement", PV_FOR))
05560       return;
05561    p->u4.for_statements = statement;
05562 }

void pvalForSetTest ( pval p,
char *  test 
)

Definition at line 5543 of file pval.c.

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

05544 {
05545    if (!pvalCheckType(p, "pvalForSetTest", PV_FOR))
05546       return;
05547    p->u2.for_test = test;
05548 }

void pvalGlobalsAddStatement ( pval p,
pval statement 
)

Definition at line 5789 of file pval.c.

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

05790 {
05791    if (p->type != PV_GLOBALS) {
05792       ast_log(LOG_ERROR, "pvalGlobalsAddStatement called where first arg is not a Globals!\n");
05793    } else {
05794       if (!p->u1.statements) {
05795          p->u1.statements = statement;
05796       } else {
05797          p->u1.statements = linku1(p->u1.statements,statement);
05798       }
05799    }
05800 }

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

Definition at line 5802 of file pval.c.

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

05803 {
05804    if (!pvalCheckType(p, "pvalGlobalsWalkStatements", PV_GLOBALS))
05805       return 0;
05806    if (!next_statement) {
05807       *next_statement = p;
05808       return p;
05809    } else {
05810       *next_statement = (*next_statement)->next;
05811       return (*next_statement)->next;
05812    }
05813 }

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

Definition at line 5494 of file pval.c.

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

05495 {
05496    if (!pvalCheckType(p, "pvalGotoGetTarget", PV_GOTO))
05497       return;
05498    if (p->u1.list && p->u1.list->next && p->u1.list->next->next) {
05499       *context = p->u1.list->u1.str;
05500       *exten = p->u1.list->next->u1.str;
05501       *label = p->u1.list->next->next->u1.str;
05502       
05503    } else if (p->u1.list && p->u1.list->next ) {
05504       *exten = p->u1.list->u1.str;
05505       *label = p->u1.list->next->u1.str;
05506       *context = 0;
05507 
05508    } else if (p->u1.list) {
05509       *label = p->u1.list->u1.str;
05510       *context = 0;
05511       *exten = 0;
05512       
05513    } else {
05514       *context = 0;
05515       *exten = 0;
05516       *label = 0;
05517    }
05518 }

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

Definition at line 5458 of file pval.c.

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

05459 {
05460    pval *con, *ext, *pri;
05461    
05462    if (!pvalCheckType(p, "pvalGotoSetTarget", PV_GOTO))
05463       return;
05464    if (context && strlen(context)) {
05465       con = pvalCreateNode(PV_WORD);
05466       ext = pvalCreateNode(PV_WORD);
05467       pri = pvalCreateNode(PV_WORD);
05468       
05469       con->u1.str = context;
05470       ext->u1.str = exten;
05471       pri->u1.str = label;
05472       
05473       con->next = ext;
05474       ext->next = pri;
05475       p->u1.list = con;
05476    } else if (exten && strlen(exten)) {
05477       ext = pvalCreateNode(PV_WORD);
05478       pri = pvalCreateNode(PV_WORD);
05479       
05480       ext->u1.str = exten;
05481       pri->u1.str = label;
05482       
05483       ext->next = pri;
05484       p->u1.list = ext;
05485    } else {
05486       pri = pvalCreateNode(PV_WORD);
05487       
05488       pri->u1.str = label;
05489       
05490       p->u1.list = pri;
05491    }
05492 }

char* pvalIfGetCondition ( pval p  ) 

Definition at line 5601 of file pval.c.

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

05602 {
05603    if (!pvalCheckType(p, "pvalIfGetCondition", PV_IFTIME))
05604       return 0;
05605    return p->u1.str;
05606 }

void pvalIfSetCondition ( pval p,
char *  expr 
)

Definition at line 5594 of file pval.c.

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

05595 {
05596    if (!pvalCheckType(p, "pvalIfSetCondition", PV_IF))
05597       return;
05598    p->u1.str = expr;
05599 }

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

Definition at line 5627 of file pval.c.

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

05628 {
05629    if (!pvalCheckType(p, "pvalIfTimeGetCondition", PV_IFTIME))
05630       return;
05631    *hour_range = p->u1.list->u1.str;
05632    *dow_range = p->u1.list->next->u1.str;
05633    *dom_range = p->u1.list->next->next->u1.str;
05634    *month_range = p->u1.list->next->next->next->u1.str;
05635 }

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

Definition at line 5608 of file pval.c.

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

05608                                                                                                                                  : 24-hour format begin-end|dow range|dom range|month range */
05609 {
05610    pval *hr = pvalCreateNode(PV_WORD);
05611    pval *dow = pvalCreateNode(PV_WORD);
05612    pval *dom = pvalCreateNode(PV_WORD);
05613    pval *mon = pvalCreateNode(PV_WORD);
05614    if (!pvalCheckType(p, "pvalIfTimeSetCondition", PV_IFTIME))
05615       return;
05616    pvalWordSetString(hr, hour_range);
05617    pvalWordSetString(dow, dow_range);
05618    pvalWordSetString(dom, dom_range);
05619    pvalWordSetString(mon, mon_range);
05620    dom->next = mon;
05621    dow->next = dom;
05622    hr->next = dow;
05623    p->u1.list = hr;
05624 }

char* pvalIgnorePatGetPattern ( pval p  ) 

Definition at line 5781 of file pval.c.

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

05782 {
05783    if (!pvalCheckType(p, "pvalIgnorePatGetPattern", PV_IGNOREPAT))
05784       return 0;
05785    return p->u1.str;
05786 }

void pvalIgnorePatSetPattern ( pval p,
char *  pat 
)

Definition at line 5774 of file pval.c.

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

05775 {
05776    if (!pvalCheckType(p, "pvalIgnorePatSetPattern", PV_IGNOREPAT))
05777       return;
05778    p->u1.str = pat;
05779 }

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

Definition at line 5381 of file pval.c.

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

05382 {
05383    if (!pvalCheckType(p, "pvalIncludeGetTimeConstraints", PV_WORD))
05384       return;
05385    if (p->u2.arglist) {
05386       *hour_range = p->u2.arglist->u1.str;
05387       *dom_range = p->u2.arglist->next->u1.str;
05388       *dow_range = p->u2.arglist->next->next->u1.str;
05389       *month_range = p->u2.arglist->next->next->next->u1.str;
05390    } else {
05391       *hour_range = 0;
05392       *dom_range = 0;
05393       *dow_range = 0;
05394       *month_range = 0;
05395    }
05396 }

void pvalIncludesAddInclude ( pval p,
const char *  include 
)

Definition at line 5343 of file pval.c.

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

05344 {
05345    pval *s;
05346    if (!pvalCheckType(p, "pvalIncludesAddSwitch", PV_INCLUDES))
05347       return;
05348    s = pvalCreateNode(PV_WORD);
05349    s->u1.str = (char *)include;
05350    p->u1.list = linku1(p->u1.list, s);
05351 }

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

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

05355 {
05356    pval *hr = pvalCreateNode(PV_WORD);
05357    pval *dom = pvalCreateNode(PV_WORD);
05358    pval *dow = pvalCreateNode(PV_WORD);
05359    pval *mon = pvalCreateNode(PV_WORD);
05360    pval *s = pvalCreateNode(PV_WORD);
05361    
05362    if (!pvalCheckType(p, "pvalIncludeAddIncludeWithTimeConstraints", PV_INCLUDES))
05363       return;
05364 
05365    s->u1.str = (char *)include;
05366    p->u1.list = linku1(p->u1.list, s);
05367 
05368    hr->u1.str = hour_range;
05369    dom->u1.str = dom_range;
05370    dow->u1.str = dow_range;
05371    mon->u1.str = month_range;
05372 
05373    s->u2.arglist = hr;
05374 
05375    hr->next = dom;
05376    dom->next = dow;
05377    dow->next = mon;
05378    mon->next = 0;
05379 }

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

Definition at line 5398 of file pval.c.

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

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

char* pvalLabelGetName ( pval p  ) 

Definition at line 5528 of file pval.c.

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

05529 {
05530    if (!pvalCheckType(p, "pvalLabelGetName", PV_LABEL))
05531       return 0;
05532    return p->u1.str;
05533 }

void pvalLabelSetName ( pval p,
char *  name 
)

Definition at line 5521 of file pval.c.

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

05522 {
05523    if (!pvalCheckType(p, "pvalLabelSetName", PV_LABEL))
05524       return;
05525    p->u1.str = name;
05526 }

void pvalMacroAddArg ( pval p,
pval arg 
)

Definition at line 5041 of file pval.c.

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

05042 {
05043    if (!pvalCheckType(p, "pvalMacroAddArg", PV_MACRO))
05044       return;
05045    if (!p->u2.arglist)
05046       p->u2.arglist = arg;
05047    else
05048       linku1(p->u2.arglist, arg);
05049 
05050 }

void pvalMacroAddStatement ( pval p,
pval statement 
)

Definition at line 5064 of file pval.c.

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

05065 {
05066    if (!pvalCheckType(p, "pvalMacroAddStatement", PV_MACRO))
05067       return;
05068    if (!p->u3.macro_statements)
05069       p->u3.macro_statements = statement;
05070    else
05071       linku1(p->u3.macro_statements, statement);
05072 
05073    
05074 }

void pvalMacroCallAddArg ( pval p,
pval arg 
)

Definition at line 5171 of file pval.c.

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

05172 {
05173    if (!pvalCheckType(p, "pvalMacroCallGetAddArg", PV_MACRO_CALL))
05174       return;
05175    if (!p->u2.arglist)
05176       p->u2.arglist = arg;
05177    else
05178       linku1(p->u2.arglist, arg);
05179 }

char* pvalMacroCallGetMacroName ( pval p  ) 

Definition at line 5157 of file pval.c.

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

05158 {
05159    if (!pvalCheckType(p, "pvalMacroCallGetMacroName", PV_MACRO_CALL))
05160       return 0;
05161    return p->u1.str;
05162 }

void pvalMacroCallSetArglist ( pval p,
pval arglist 
)

Definition at line 5164 of file pval.c.

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

05165 {
05166    if (!pvalCheckType(p, "pvalMacroCallSetArglist", PV_MACRO_CALL))
05167       return;
05168    p->u2.arglist = arglist;
05169 }

void pvalMacroCallSetMacroName ( pval p,
char *  name 
)

Definition at line 5150 of file pval.c.

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

05151 {
05152    if (!pvalCheckType(p, "pvalMacroCallSetMacroName", PV_MACRO_CALL))
05153       return;
05154    p->u1.str = name;
05155 }

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

Definition at line 5181 of file pval.c.

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

05182 {
05183    if (!pvalCheckType(p, "pvalMacroCallWalkArgs", PV_MACRO_CALL))
05184       return 0;
05185    if (!(*args))
05186       *args = p->u2.arglist;
05187    else {
05188       *args = (*args)->next;
05189    }
05190    return *args;
05191 }

char* pvalMacroGetName ( pval p  ) 

Definition at line 5027 of file pval.c.

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

05028 {
05029    if (!pvalCheckType(p, "pvalMacroGetName", PV_MACRO))
05030       return 0;
05031    return p->u1.str;
05032 }

void pvalMacroSetArglist ( pval p,
pval arglist 
)

Definition at line 5034 of file pval.c.

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

05035 {
05036    if (!pvalCheckType(p, "pvalMacroSetArglist", PV_MACRO))
05037       return;
05038    p->u2.arglist = arglist;
05039 }

void pvalMacroSetName ( pval p,
char *  name 
)

Definition at line 5020 of file pval.c.

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

05021 {
05022    if (!pvalCheckType(p, "pvalMacroSetName", PV_MACRO))
05023       return;
05024    p->u1.str = name;
05025 }

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

Definition at line 5052 of file pval.c.

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

05053 {
05054    if (!pvalCheckType(p, "pvalMacroWalkArgs", PV_MACRO))
05055       return 0;
05056    if (!(*arg))
05057       *arg = p->u2.arglist;
05058    else {
05059       *arg = (*arg)->next;
05060    }
05061    return *arg;
05062 }

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

Definition at line 5076 of file pval.c.

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

05077 {
05078    if (!pvalCheckType(p, "pvalMacroWalkStatements", PV_MACRO))
05079       return 0;
05080    if (!(*next_statement))
05081       *next_statement = p->u3.macro_statements;
05082    else {
05083       *next_statement = (*next_statement)->next;
05084    }
05085    return *next_statement;
05086 }

pvaltype pvalObjectGetType ( pval p  ) 

Definition at line 4999 of file pval.c.

References pval::type.

05000 {
05001    return p->type;
05002 }

char* pvalRandomGetCondition ( pval p  ) 

Definition at line 5644 of file pval.c.

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

05645 {
05646    if (!pvalCheckType(p, "pvalRandomGetCondition", PV_RANDOM))
05647       return 0;
05648    return p->u1.str;
05649 }

void pvalRandomSetCondition ( pval p,
char *  percent 
)

Definition at line 5637 of file pval.c.

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

05638 {
05639    if (!pvalCheckType(p, "pvalRandomSetCondition", PV_RANDOM))
05640       return;
05641    p->u1.str = percent;
05642 }

void pvalStatementBlockAddStatement ( pval p,
pval statement 
)

Definition at line 5411 of file pval.c.

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

05412 {
05413    if (!pvalCheckType(p, "pvalStatementBlockAddStatement", PV_STATEMENTBLOCK))
05414       return;
05415    p->u1.list = linku1(p->u1.list, statement);
05416 }

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

Definition at line 5418 of file pval.c.

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

05419 {
05420    if (!pvalCheckType(p, "pvalStatementBlockWalkStatements", PV_STATEMENTBLOCK))
05421       return 0;
05422    if (!(*next_statement))
05423       *next_statement = p->u1.list;
05424    else {
05425       *next_statement = (*next_statement)->next;
05426    }
05427    return *next_statement;
05428 }

void pvalSwitchAddCase ( pval p,
pval Case 
)

Definition at line 5685 of file pval.c.

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

05686 {
05687    if (!pvalCheckType(p, "pvalSwitchAddCase", PV_SWITCH))
05688       return;
05689    if (!pvalCheckType(Case, "pvalSwitchAddCase", PV_CASE))
05690       return;
05691    if (!p->u2.statements)
05692       p->u2.statements = Case;
05693    else
05694       linku1(p->u2.statements, Case);
05695 }

void pvalSwitchesAddSwitch ( pval p,
char *  name 
)

Definition at line 5298 of file pval.c.

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

05299 {
05300    pval *s;
05301    if (!pvalCheckType(p, "pvalSwitchesAddSwitch", PV_SWITCHES))
05302       return;
05303    s = pvalCreateNode(PV_WORD);
05304    s->u1.str = name;
05305    p->u1.list = linku1(p->u1.list, s);
05306 }

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

Definition at line 5308 of file pval.c.

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

05309 {
05310    if (!pvalCheckType(p, "pvalSwitchesWalkNames", PV_SWITCHES))
05311       return 0;
05312    if (!(*next_item))
05313       *next_item = p->u1.list;
05314    else {
05315       *next_item = (*next_item)->next;
05316    }
05317    return (*next_item)->u1.str;
05318 }

char* pvalSwitchGetTestexpr ( pval p  ) 

Definition at line 5678 of file pval.c.

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

05679 {
05680    if (!pvalCheckType(p, "pvalSwitchGetTestexpr", PV_SWITCH))
05681       return 0;
05682    return p->u1.str;
05683 }

void pvalSwitchSetTestexpr ( pval p,
char *  expr 
)

Definition at line 5671 of file pval.c.

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

05672 {
05673    if (!pvalCheckType(p, "pvalSwitchSetTestexpr", PV_SWITCH))
05674       return;
05675    p->u1.str = expr;
05676 }

pval* pvalSwitchWalkCases ( pval p,