Asterisk - The Open Source Telephony Project GIT-master-7e7a603
Macros | Functions | Variables
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.

Macros

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

Variables

static int control_statement_count
 
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.

Macro Definition Documentation

◆ ASTMM_LIBC

#define ASTMM_LIBC   ASTMM_REDIRECT

Definition at line 30 of file pval.c.

◆ BUF_SIZE

#define BUF_SIZE   2000

Definition at line 61 of file pval.c.

Function Documentation

◆ add_extensions()

void add_extensions ( struct ael_extension exten)

Definition at line 4213 of file pval.c.

4214{
4215 struct ael_priority *pr;
4216 char *label=0;
4217 char realext[AST_MAX_EXTENSION];
4218 if (!exten) {
4219 ast_log(LOG_WARNING, "This file is Empty!\n" );
4220 return;
4221 }
4222 do {
4223 struct ael_priority *last = 0;
4224
4225 pbx_substitute_variables_helper(NULL, exten->name, realext, sizeof(realext) - 1);
4226 if (exten->hints) {
4227 if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, PRIORITY_HINT, NULL, exten->cidmatch,
4229 ast_log(LOG_WARNING, "Unable to add step at priority 'hint' of extension '%s'\n",
4230 exten->name);
4231 }
4232 }
4233
4234 for (pr=exten->plist; pr; pr=pr->next) {
4235 char app[2000];
4236 char appargs[2000];
4237
4238 /* before we can add the extension, we need to prep the app/appargs;
4239 the CONTROL types need to be done after the priority numbers are calculated.
4240 */
4241 if (pr->type == AEL_LABEL) /* don't try to put labels in the dialplan! */ {
4242 last = pr;
4243 continue;
4244 }
4245
4246 if (pr->app)
4247 strcpy(app, pr->app);
4248 else
4249 app[0] = 0;
4250 if (pr->appargs )
4251 strcpy(appargs, pr->appargs);
4252 else
4253 appargs[0] = 0;
4254 switch( pr->type ) {
4255 case AEL_APPCALL:
4256 /* easy case. Everything is all set up */
4257 break;
4258
4259 case AEL_CONTROL1: /* FOR loop, WHILE loop, BREAK, CONTINUE, IF, IFTIME */
4260 /* simple, unconditional goto. */
4261 strcpy(app,"Goto");
4262 if (pr->goto_true->origin && pr->goto_true->origin->type == PV_SWITCH ) {
4263 snprintf(appargs,sizeof(appargs),"%s,%d", pr->goto_true->exten->name, pr->goto_true->priority_num);
4264 } else if (pr->goto_true->origin && pr->goto_true->origin->type == PV_IFTIME && pr->goto_true->origin->u3.else_statements ) {
4265 snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num+1);
4266 } else
4267 snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num);
4268 break;
4269
4270 case AEL_FOR_CONTROL: /* WHILE loop test, FOR loop test */
4271 strcpy(app,"GotoIf");
4272 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num);
4273 break;
4274
4275 case AEL_IF_CONTROL:
4276 strcpy(app,"GotoIf");
4277 if (pr->origin->u3.else_statements )
4278 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num+1);
4279 else
4280 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num);
4281 break;
4282
4283 case AEL_RAND_CONTROL:
4284 strcpy(app,"Random");
4285 snprintf(appargs,sizeof(appargs),"%s:%d", pr->appargs, pr->goto_true->priority_num+1);
4286 break;
4287
4288 case AEL_IFTIME_CONTROL:
4289 strcpy(app,"GotoIfTime");
4290 snprintf(appargs,sizeof(appargs),"%s?%d", pr->appargs, pr->priority_num+2);
4291 break;
4292
4293 case AEL_RETURN:
4294 strcpy(app,"Return");
4295 appargs[0] = 0;
4296 break;
4297
4298 default:
4299 break;
4300 }
4301 if (last && last->type == AEL_LABEL ) {
4302 label = last->origin->u1.str;
4303 }
4304 else
4305 label = 0;
4306
4307 if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, pr->priority_num, (label?label:NULL), exten->cidmatch,
4309 ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num,
4310 exten->name);
4311 }
4312 last = pr;
4313 }
4315 } while ( exten );
4316}
@ AEL_FOR_CONTROL
Definition: ael_structs.h:84
@ AEL_RAND_CONTROL
Definition: ael_structs.h:84
@ AEL_RETURN
Definition: ael_structs.h:84
@ AEL_IF_CONTROL
Definition: ael_structs.h:84
@ AEL_IFTIME_CONTROL
Definition: ael_structs.h:84
@ AEL_CONTROL1
Definition: ael_structs.h:84
@ AEL_LABEL
Definition: ael_structs.h:84
@ AEL_APPCALL
Definition: ael_structs.h:84
static const char app[]
Definition: app_adsiprog.c:56
struct sla_ringing_trunk * last
Definition: app_sla.c:332
#define strdup(a)
Definition: astmm.h:163
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
#define ast_log
Definition: astobj2.c:42
#define AST_MAX_EXTENSION
Definition: channel.h:134
#define LOG_WARNING
int ast_add_extension2(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line)
Add an extension to an extension context, this time with an ast_context *.
Definition: pbx.c:7257
#define PRIORITY_HINT
Definition: pbx.h:54
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211
static char * registrar
Definition: pval.c:70
@ PV_SWITCH
Definition: pval.h:32
@ PV_IFTIME
Definition: pval.h:30
#define NULL
Definition: resample.c:96
struct ael_priority * plist
Definition: ael_structs.h:115
struct ast_context * context
Definition: ael_structs.h:113
char * cidmatch
Definition: ael_structs.h:106
struct ael_extension * next_exten
Definition: ael_structs.h:117
struct ael_priority * goto_false
Definition: ael_structs.h:99
struct ael_priority * goto_true
Definition: ael_structs.h:98
struct pval * origin
Definition: ael_structs.h:95
char * appargs
Definition: ael_structs.h:93
char * app
Definition: ael_structs.h:92
ael_priority_type type
Definition: ael_structs.h:90
struct ael_priority * next
Definition: ael_structs.h:100
int priority_num
Definition: ael_structs.h:89
struct ael_extension * exten
Definition: ael_structs.h:96
struct pval * else_statements
Definition: pval.h:78
union pval::@248 u3
pvaltype type
Definition: pval.h:50

References AEL_APPCALL, AEL_CONTROL1, AEL_FOR_CONTROL, AEL_IF_CONTROL, AEL_IFTIME_CONTROL, AEL_LABEL, AEL_RAND_CONTROL, AEL_RETURN, app, ael_priority::app, ael_priority::appargs, ast_add_extension2(), ast_free_ptr(), ast_log, AST_MAX_EXTENSION, 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, NULL, ael_priority::origin, pbx_substitute_variables_helper(), ael_extension::plist, PRIORITY_HINT, ael_priority::priority_num, PV_IFTIME, PV_SWITCH, registrar, strdup, ael_priority::type, pval::type, and pval::u3.

Referenced by ast_compile_ael2().

◆ ael2_print()

void ael2_print ( char *  fname,
pval tree 
)

Definition at line 382 of file pval.c.

383{
384 FILE *fin = fopen(fname,"w");
385 if ( !fin ) {
386 ast_log(LOG_ERROR, "Couldn't open %s for writing.\n", fname);
387 return;
388 }
389 print_pval_list(fin, tree, 0);
390 fclose(fin);
391}
#define LOG_ERROR
static void print_pval_list(FILE *fin, pval *item, int depth)
Definition: pval.c:373

References ast_log, LOG_ERROR, and print_pval_list().

◆ ael2_semantic_check()

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

Definition at line 2885 of file pval.c.

2886{
2887
2888#ifdef AAL_ARGCHECK
2889 int argapp_errs =0;
2890 char *rfilename;
2891#endif
2892 struct argapp *apps=0;
2893
2894 if (!item)
2895 return; /* don't check an empty tree */
2896#ifdef AAL_ARGCHECK
2897 rfilename = ast_alloca(10 + strlen(ast_config_AST_VAR_DIR));
2898 sprintf(rfilename, "%s/applist", ast_config_AST_VAR_DIR);
2899
2900 apps = argdesc_parse(rfilename, &argapp_errs); /* giveth */
2901#endif
2902 current_db = item;
2903 errs = warns = notes = 0;
2904
2906 check_pval(item, apps, 0);
2907
2908#ifdef AAL_ARGCHECK
2909 argdesc_destroy(apps); /* taketh away */
2910#endif
2911 current_db = 0;
2912
2913 *arg_errs = errs;
2914 *arg_warns = warns;
2915 *arg_notes = notes;
2916}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
const char * ast_config_AST_VAR_DIR
Definition: options.c:157
static pval * current_db
Definition: pval.c:72
static int notes
Definition: pval.c:66
static int warns
Definition: pval.c:65
static int errs
Definition: pval.c:65
void check_pval(pval *item, struct argapp *apps, int in_globals)
Definition: pval.c:2865
static void check_context_names(void)
Definition: pval.c:2310
Registered applications container.
Definition: pbx_app.c:67
Definition: pval.h:111
static struct aco_type item
Definition: test_config.c:1463

References ast_alloca, ast_config_AST_VAR_DIR, check_context_names(), check_pval(), current_db, errs, item, notes, and warns.

Referenced by pbx_load_module().

◆ ast_compile_ael2()

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

Definition at line 4413 of file pval.c.

4414{
4415 pval *p,*p2;
4416 struct ast_context *context;
4417 char buf[2000];
4418 struct ael_extension *exten;
4419 struct ael_extension *exten_list = 0;
4420
4421 /* Reset the counter so that we get consistent labels between reloads */
4423
4424 for (p=root; p; p=p->next ) { /* do the globals first, so they'll be there
4425 when we try to eval them */
4426 switch (p->type) {
4427 case PV_GLOBALS:
4428 /* just VARDEC elements */
4429 for (p2=p->u1.list; p2; p2=p2->next) {
4430 char buf2[2000];
4431 snprintf(buf2,sizeof(buf2),"%s=%s", p2->u1.str, p2->u2.val);
4433 }
4434 break;
4435 default:
4436 break;
4437 }
4438 }
4439
4440 for (p=root; p; p=p->next ) {
4441 pval *lp;
4442 int argc;
4443
4444 switch (p->type) {
4445 case PV_MACRO:
4446
4448
4449 exten = new_exten();
4450 exten->context = context;
4451 exten->name = strdup("~~s~~");
4452 argc = 1;
4453 for (lp=p->u2.arglist; lp; lp=lp->next) {
4454 /* for each arg, set up a "Set" command */
4455 struct ael_priority *np2 = new_prio();
4456 np2->type = AEL_APPCALL;
4457 np2->app = strdup("MSet");
4458 snprintf(buf,sizeof(buf),"LOCAL(%s)=${ARG%d}", lp->u1.str, argc++);
4460 np2->appargs = strdup(buf);
4461 linkprio(exten, np2, NULL);
4462 }
4463
4464 /* CONTAINS APPCALLS, CATCH, just like extensions... */
4465 if (gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context)) {
4466 return -1;
4467 }
4468 if (exten->return_needed) { /* most likely, this will go away */
4469 struct ael_priority *np2 = new_prio();
4470 np2->type = AEL_APPCALL;
4471 np2->app = strdup("NoOp");
4472 snprintf(buf,sizeof(buf),"End of Macro %s-%s",p->u1.str, exten->name);
4473 np2->appargs = strdup(buf);
4474 linkprio(exten, np2, NULL);
4475 exten-> return_target = np2;
4476 }
4477
4479 attach_exten(&exten_list, exten);
4480 break;
4481
4482 case PV_GLOBALS:
4483 /* already done */
4484 break;
4485
4486 case PV_CONTEXT:
4488
4489 /* contexts contain: ignorepat, includes, switches, eswitches, extensions, */
4490 for (p2=p->u2.statements; p2; p2=p2->next) {
4491 pval *p3;
4492 char *s3;
4493
4494 switch (p2->type) {
4495 case PV_EXTENSION:
4496 exten = new_exten();
4497 exten->name = strdup(p2->u1.str);
4499
4500 if( (s3=strchr(exten->name, '/') ) != 0 )
4501 {
4502 *s3 = 0;
4503 exten->cidmatch = s3+1;
4504 }
4505
4506 if ( p2->u3.hints )
4507 exten->hints = strdup(p2->u3.hints);
4508 exten->regexten = p2->u4.regexten;
4509 if (gen_prios(exten, p->u1.str, p2->u2.statements, 0, context)) {
4510 return -1;
4511 }
4512 if (exten->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */
4513 struct ael_priority *np2 = new_prio();
4514 np2->type = AEL_APPCALL;
4515 np2->app = strdup("NoOp");
4516 snprintf(buf,sizeof(buf),"End of Extension %s", exten->name);
4517 np2->appargs = strdup(buf);
4518 linkprio(exten, np2, NULL);
4519 exten-> return_target = np2;
4520 }
4521 /* is the last priority in the extension a label? Then add a trailing no-op */
4522 if ( exten->plist_last && exten->plist_last->type == AEL_LABEL ) {
4523 struct ael_priority *np2 = new_prio();
4524 np2->type = AEL_APPCALL;
4525 np2->app = strdup("NoOp");
4526 snprintf(buf,sizeof(buf),"A NoOp to follow a trailing label %s", exten->plist_last->origin->u1.str);
4527 np2->appargs = strdup(buf);
4528 linkprio(exten, np2, NULL);
4529 }
4530
4532 attach_exten(&exten_list, exten);
4533 break;
4534
4535 case PV_IGNOREPAT:
4537 break;
4538
4539 case PV_INCLUDES:
4540 for (p3 = p2->u1.list; p3 ;p3=p3->next) {
4541 if ( p3->u2.arglist ) {
4542 snprintf(buf,sizeof(buf), "%s,%s,%s,%s,%s",
4543 p3->u1.str,
4544 p3->u2.arglist->u1.str,
4545 p3->u2.arglist->next->u1.str,
4546 p3->u2.arglist->next->next->u1.str,
4547 p3->u2.arglist->next->next->next->u1.str);
4549 } else
4551 }
4552 break;
4553
4554 case PV_SWITCHES:
4555 for (p3 = p2->u1.list; p3 ;p3=p3->next) {
4556 char *c = strchr(p3->u1.str, '/');
4557 if (c) {
4558 *c = '\0';
4559 c++;
4560 } else
4561 c = "";
4562
4564 }
4565 break;
4566
4567 case PV_ESWITCHES:
4568 for (p3 = p2->u1.list; p3 ;p3=p3->next) {
4569 char *c = strchr(p3->u1.str, '/');
4570 if (c) {
4571 *c = '\0';
4572 c++;
4573 } else
4574 c = "";
4575
4577 }
4578 break;
4579 default:
4580 break;
4581 }
4582 }
4583
4584 break;
4585
4586 default:
4587 /* huh? what? */
4588 break;
4589
4590 }
4591 }
4592
4593 /* Create default "h" bubble context */
4594 if (ast_custom_function_find("DIALPLAN_EXISTS") && ast_custom_function_find("STACK_PEEK")) {
4595 int i;
4596 const char *h_context = "ael-builtin-h-bubble";
4597 struct ael_priority *np;
4598 struct {
4599 int priority;
4600 const char *app;
4601 const char *arg;
4602 } steps[] = {
4603 /* Start high, to avoid conflict with existing h extensions */
4604 { 1, "Goto", "9991" },
4605 /* Save the context, because after the StackPop, it disappears */
4606 { 9991, "Set", "~~parentcxt~~=${STACK_PEEK(1,c,1)}" },
4607 /* If we're not in a Gosub frame, exit */
4608 { 9992, "GotoIf", "$[\"${~~parentcxt~~}\"=\"\"]?9996" },
4609 /* Check for an "h" extension in that context */
4610 { 9993, "GotoIf", "${DIALPLAN_EXISTS(${~~parentcxt~~},h,1)}?9994:9996" },
4611 /* Pop off the stack frame to prevent an infinite loop */
4612 { 9994, "StackPop", "" },
4613 /* Finally, go there. */
4614 { 9995, "Goto", "${~~parentcxt~~},h,1" },
4615 /* Just an empty priority for jumping out early */
4616 { 9996, "NoOp", "" }
4617 };
4619 if (context_used(exten_list, context)) {
4620 int found = 0;
4621 while (!found) {
4622 /* Pick a new context name that is not used. */
4623 char h_context_template[] = "/tmp/ael-builtin-h-bubble-XXXXXX";
4624 int fd = mkstemp(h_context_template);
4625 unlink(h_context_template);
4626 close(fd);
4628 found = !context_used(exten_list, context);
4629 }
4630 h_context = ast_get_context_name(context);
4631 }
4632 exten = new_exten();
4633 exten->context = context;
4634 exten->name = strdup("h");
4635
4636 for (i = 0; i < ARRAY_LEN(steps); i++) {
4637 np = new_prio();
4638 np->type = AEL_APPCALL;
4639 np->priority_num = steps[i].priority;
4640 np->app = strdup(steps[i].app);
4641 np->appargs = strdup(steps[i].arg);
4642 linkprio(exten, np, NULL);
4643 }
4644 attach_exten(&exten_list, exten);
4645
4646 /* Include the default "h" bubble context in each macro context */
4647 for (exten = exten_list; exten; exten = exten->next_exten) {
4648 /* All macros contain a "~~s~~" extension, and it's the first created. If
4649 * we perchance get a non-macro context, it's no big deal; the logic is
4650 * designed to exit out smoothly if not called from within a Gosub. */
4651 if (!strcmp(exten->name, "~~s~~")) {
4652 ast_context_add_include2(exten->context, h_context, registrar);
4653 }
4654 }
4655 }
4656
4657 /* moved these from being done after a macro or extension were processed,
4658 to after all processing is done, for the sake of fixing gotos to labels inside cases... */
4659 /* I guess this would be considered 2nd pass of compiler now... */
4660 fix_gotos_in_extensions(exten_list); /* find and fix extension ref in gotos to labels that are in case statements */
4661 add_extensions(exten_list); /* actually makes calls to create priorities in ast_contexts -- feeds dialplan to asterisk */
4662 destroy_extensions(exten_list); /* all that remains is an empty husk, discard of it as is proper */
4663
4664 return 0;
4665}
static int priority
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct ast_threadstorage buf2
int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
Parse and set a single channel variable, where the name and value are separated with an '=' character...
int ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
Add a context include.
Definition: ael_main.c:359
int ast_context_add_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
Definition: ael_main.c:348
struct ast_custom_function * ast_custom_function_find(const char *name)
Definition: ael_main.c:173
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6149
const char * ast_get_context_name(struct ast_context *con)
Definition: ael_main.c:421
int ast_context_add_switch2(struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar)
Adds a switch (first param is a ast_context)
Definition: ael_main.c:370
static struct ast_context * local_contexts
Definition: pbx_config.c:113
static struct ast_hashtab * local_table
Definition: pbx_config.c:114
static void attach_exten(struct ael_extension **list, struct ael_extension *newmem)
Definition: pval.c:4318
struct ael_priority * new_prio(void)
Definition: pval.c:2924
static int context_used(struct ael_extension *exten_list, struct ast_context *context)
Definition: pval.c:4398
static void remove_spaces_before_equals(char *str)
Definition: pval.c:3038
void set_priorities(struct ael_extension *exten)
Definition: pval.c:4187
struct ael_extension * new_exten(void)
Definition: pval.c:2930
static int gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *this_context)
Definition: pval.c:3341
void destroy_extensions(struct ael_extension *exten)
Definition: pval.c:2978
void linkprio(struct ael_extension *exten, struct ael_priority *prio, struct ael_extension *mother_exten)
Definition: pval.c:2936
void add_extensions(struct ael_extension *exten)
Definition: pval.c:4213
static int control_statement_count
Definition: pval.c:2922
static void fix_gotos_in_extensions(struct ael_extension *exten)
Definition: pval.c:4355
@ PV_GLOBALS
Definition: pval.h:35
@ PV_CONTEXT
Definition: pval.h:10
@ PV_INCLUDES
Definition: pval.h:19
@ PV_MACRO
Definition: pval.h:9
@ PV_SWITCHES
Definition: pval.h:17
@ PV_IGNOREPAT
Definition: pval.h:34
@ PV_ESWITCHES
Definition: pval.h:18
@ PV_EXTENSION
Definition: pval.h:33
struct ael_priority * plist_last
Definition: ael_structs.h:116
ast_context: An extension context
Definition: pbx.c:284
Definition: pval.h:49
struct pval * arglist
Definition: pval.h:68
char * val
Definition: pval.h:70
struct pval * next
Definition: pval.h:93
char * hints
Definition: pval.h:81
struct pval * statements
Definition: pval.h:61
struct pval * macro_statements
Definition: pval.h:79
union pval::@246 u1
char * str
Definition: pval.h:59
union pval::@247 u2
union pval::@249 u4
int regexten
Definition: pval.h:90
struct pval * list
Definition: pval.h:60
static struct test_val c
#define ARRAY_LEN(a)
Definition: utils.h:666

References add_extensions(), AEL_APPCALL, AEL_LABEL, app, ael_priority::app, ael_priority::appargs, pval::arglist, ARRAY_LEN, ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_find_or_create(), ast_custom_function_find(), ast_get_context_name(), attach_exten(), buf, buf2, c, ael_extension::cidmatch, voicemailpwcheck::context, ael_extension::context, context_used(), control_statement_count, destroy_extensions(), ael_priority::exten, fix_gotos_in_extensions(), gen_prios(), ael_extension::hints, pval::hints, linkprio(), pval::list, local_contexts, local_table, pval::macro_statements, ael_extension::name, new_exten(), new_prio(), pval::next, ael_extension::next_exten, NULL, ael_priority::origin, pbx_builtin_setvar(), ael_extension::plist_last, priority, ael_priority::priority_num, PV_CONTEXT, PV_ESWITCHES, PV_EXTENSION, PV_GLOBALS, PV_IGNOREPAT, PV_INCLUDES, PV_MACRO, PV_SWITCHES, ael_extension::regexten, pval::regexten, registrar, 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().

◆ attach_exten()

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

Definition at line 4318 of file pval.c.

4319{
4320 /* travel to the end of the list... */
4321 struct ael_extension *lptr;
4322 if( !*list ) {
4323 *list = newmem;
4324 return;
4325 }
4326 lptr = *list;
4327
4328 while( lptr->next_exten ) {
4329 lptr = lptr->next_exten;
4330 }
4331 /* lptr should now pointing to the last element in the list; it has a null next_exten pointer */
4332 lptr->next_exten = newmem;
4333}

References ael_extension::next_exten.

Referenced by ast_compile_ael2().

◆ check_abstract_reference()

static void check_abstract_reference ( pval abstract_context)
static

Definition at line 2329 of file pval.c.

2330{
2331 pval *i,*j;
2332 /* find some context includes that reference this context */
2333
2334
2335 /* otherwise, print out a warning */
2336 for (i=current_db; i; i=i->next) {
2337 if (i->type == PV_CONTEXT) {
2338 for (j=i->u2. statements; j; j=j->next) {
2339 if ( j->type == PV_INCLUDES ) {
2340 struct pval *p4;
2341 for (p4=j->u1.list; p4; p4=p4->next) {
2342 /* for each context pointed to, find it, then find a context/label that matches the
2343 target here! */
2344 if ( !strcmp(p4->u1.str, abstract_context->u1.str) )
2345 return; /* found a match! */
2346 }
2347 }
2348 }
2349 }
2350 }
2351 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",
2352 abstract_context->filename, abstract_context->startline, abstract_context->endline, abstract_context->u1.str);
2353 warns++;
2354}
int endline
Definition: pval.h:52
char * filename
Definition: pval.h:55
int startline
Definition: pval.h:51

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

Referenced by check_pval_item().

◆ check_app_args()

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

Definition at line 2130 of file pval.c.

2131{
2132#ifdef AAL_ARGCHECK
2133 struct argdesc *ad = app->args;
2134 pval *pa;
2135 int z;
2136
2137 for (pa = arglist; pa; pa=pa->next) {
2138 if (!ad) {
2139 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Extra argument %s not in application call to %s !\n",
2140 arglist->filename, arglist->startline, arglist->endline, pa->u1.str, app->name);
2141 warns++;
2142 return 1;
2143 } else {
2144 /* find the first entry in the ad list that will match */
2145 do {
2146 if ( ad->dtype == ARGD_VARARG ) /* once we hit the VARARG, all bets are off. Discontinue the comparisons */
2147 break;
2148
2149 z= option_matches( ad, pa, app);
2150 if (!z) {
2151 if ( !arglist )
2152 arglist=appcall;
2153
2154 if (ad->type == ARGD_REQUIRED) {
2155 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n",
2156 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name);
2157 warns++;
2158 return 1;
2159 }
2160 } else if (z && ad->dtype == ARGD_OPTIONSET) {
2161 option_matches_j( ad, pa, app);
2162 }
2163 ad = ad->next;
2164 } while (ad && !z);
2165 }
2166 }
2167 /* any app nodes left, that are not optional? */
2168 for ( ; ad; ad=ad->next) {
2169 if (ad->type == ARGD_REQUIRED && ad->dtype != ARGD_VARARG) {
2170 if ( !arglist )
2171 arglist=appcall;
2172 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n",
2173 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name);
2174 warns++;
2175 return 1;
2176 }
2177 }
2178 return 0;
2179#else
2180 return 0;
2181#endif
2182}

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

Referenced by check_pval_item().

◆ check_break()

static int check_break ( pval item)
static

Definition at line 1038 of file pval.c.

1039{
1040 pval *p = item;
1041
1042 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ {
1043 /* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make
1044 no sense */
1045 if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN
1046 || p->type == PV_WHILE || p->type == PV_FOR ) {
1047 return 1;
1048 }
1049 p = p->dad;
1050 }
1051 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'break' not in switch, for, or while statement!\n",
1052 item->filename, item->startline, item->endline);
1053 errs++;
1054
1055 return 0;
1056}
@ PV_DEFAULT
Definition: pval.h:15
@ PV_CASE
Definition: pval.h:13
@ PV_PATTERN
Definition: pval.h:14
@ PV_FOR
Definition: pval.h:24
@ PV_WHILE
Definition: pval.h:25
struct pval * dad
Definition: pval.h:96

References ast_log, pval::dad, errs, item, LOG_ERROR, PV_CASE, PV_CONTEXT, PV_DEFAULT, PV_FOR, PV_MACRO, PV_PATTERN, PV_WHILE, and pval::type.

Referenced by check_pval_item().

◆ check_context_names()

static void check_context_names ( void  )
static

Definition at line 2310 of file pval.c.

2311{
2312 pval *i,*j;
2313 for (i=current_db; i; i=i->next) {
2314 if (i->type == PV_CONTEXT || i->type == PV_MACRO) {
2315 for (j=i->next; j; j=j->next) {
2316 if ( j->type == PV_CONTEXT || j->type == PV_MACRO ) {
2317 if ( !strcmp(i->u1.str, j->u1.str) && !(i->u3.abstract&2) && !(j->u3.abstract&2) )
2318 {
2319 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",
2320 i->filename, i->startline, i->endline, i->u1.str, j->filename, j->startline, j->endline);
2321 warns++;
2322 }
2323 }
2324 }
2325 }
2326 }
2327}
int abstract
Definition: pval.h:80

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

Referenced by ael2_semantic_check().

◆ check_continue()

static int check_continue ( pval item)
static

Definition at line 1058 of file pval.c.

1059{
1060 pval *p = item;
1061
1062 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ {
1063 /* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make
1064 no sense */
1065 if( p->type == PV_WHILE || p->type == PV_FOR ) {
1066 return 1;
1067 }
1068 p = p->dad;
1069 }
1070 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'continue' not in 'for' or 'while' statement!\n",
1071 item->filename, item->startline, item->endline);
1072 errs++;
1073
1074 return 0;
1075}

References ast_log, pval::dad, errs, item, LOG_ERROR, PV_CONTEXT, PV_FOR, PV_MACRO, PV_WHILE, and pval::type.

Referenced by check_pval_item().

◆ check_day()

static void check_day ( pval DAY)
static

Definition at line 937 of file pval.c.

938{
939 char *day;
940 char *c;
941 /* The following line is coincidence, really! */
942 int s, e;
943
944 day = ast_strdupa(DAY->u1.str);
945
946 /* Check for all days */
947 if (ast_strlen_zero(day) || !strcmp(day, "*")) {
948 return;
949 }
950 /* Get start and ending days */
951 c = strchr(day, '-');
952 if (c) {
953 *c = '\0';
954 c++;
955 }
956 /* Find the start */
957 if (sscanf(day, "%2d", &s) != 1) {
958 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start day of month (%s) must be a number!\n",
959 DAY->filename, DAY->startline, DAY->endline, day);
960 warns++;
961 }
962 else if ((s < 1) || (s > 31)) {
963 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",
964 DAY->filename, DAY->startline, DAY->endline, day);
965 warns++;
966 }
967 s--;
968 if (c) {
969 if (sscanf(c, "%2d", &e) != 1) {
970 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end day of month (%s) must be a number!\n",
971 DAY->filename, DAY->startline, DAY->endline, c);
972 warns++;
973 }
974 else if ((e < 1) || (e > 31)) {
975 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",
976 DAY->filename, DAY->startline, DAY->endline, day);
977 warns++;
978 }
979 e--;
980 } else
981 e = s;
982}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define DAY
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65

References ast_log, ast_strdupa, ast_strlen_zero(), c, DAY, LOG_WARNING, and warns.

Referenced by check_pval_item().

◆ check_dow()

static void check_dow ( pval DOW)
static

get_dow: Get day of week

Definition at line 898 of file pval.c.

899{
900 char *dow;
901 char *c;
902 /* The following line is coincidence, really! */
903 int s, e;
904
905 dow = ast_strdupa(DOW->u1.str);
906
907 /* Check for all days */
908 if (ast_strlen_zero(dow) || !strcmp(dow, "*"))
909 return;
910 /* Get start and ending days */
911 c = strchr(dow, '-');
912 if (c) {
913 *c = '\0';
914 c++;
915 } else
916 c = NULL;
917 /* Find the start */
918 s = 0;
919 while ((s < 7) && strcasecmp(dow, days[s])) s++;
920 if (s >= 7) {
921 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",
922 DOW->filename, DOW->startline, DOW->endline, dow);
923 warns++;
924 }
925 if (c) {
926 e = 0;
927 while ((e < 7) && strcasecmp(c, days[e])) e++;
928 if (e >= 7) {
929 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",
930 DOW->filename, DOW->startline, DOW->endline, c);
931 warns++;
932 }
933 } else
934 e = s;
935}
static char * days[]
Definition: pval.c:886

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

Referenced by check_pval_item().

◆ check_expr2_input()

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

Definition at line 801 of file pval.c.

802{
803 int spaces = strspn(str,"\t \n");
804 if ( !strncmp(str+spaces,"$[",2) ) {
805 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The expression '%s' is redundantly wrapped in '$[ ]'. \n",
806 expr->filename, expr->startline, expr->endline, str);
807 warns++;
808 }
809}
const char * str
Definition: app_jack.c:147

References ast_log, pval::endline, pval::filename, LOG_WARNING, pval::startline, str, and warns.

Referenced by check_pval_item().

◆ check_goto()

static void check_goto ( pval item)
static

Definition at line 1225 of file pval.c.

1226{
1227 if (!item->u1.list) {
1228 return;
1229 }
1230
1231 /* check for the target of the goto-- does it exist? */
1232 if ( !(item->u1.list)->next && !(item->u1.list)->u1.str ) {
1233 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: empty label reference found!\n",
1234 item->filename, item->startline, item->endline);
1235 errs++;
1236 }
1237
1238 /* just one item-- the label should be in the current extension */
1239 if (!item->u1.list->next && !strstr(item->u1.list->u1.str,"${")) {
1240 struct pval *z = get_extension_or_contxt(item);
1241 struct pval *x = 0;
1242 if (z)
1243 x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), z); /* if in macro, use current context instead */
1244 /* printf("Called find_label_in_current_extension with arg %s; current_extension is %x: %d\n",
1245 (char*)((item->u1.list)->u1.str), current_extension?current_extension:current_context, current_extension?current_extension->type:current_context->type); */
1246 if (!x) {
1247 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s exists in the current extension!\n",
1248 item->filename, item->startline, item->endline, item->u1.list->u1.str);
1249 errs++;
1250 }
1251 else
1252 return;
1253 }
1254
1255 /* TWO items */
1256 if (item->u1.list->next && !item->u1.list->next->next) {
1257 /* two items */
1258 /* printf("Calling find_label_in_current_context with args %s, %s\n",
1259 (char*)((item->u1.list)->u1.str), (char *)item->u1.list->next->u1.str); */
1260 if (!strstr((item->u1.list)->u1.str,"${")
1261 && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ {
1262 struct pval *z = get_contxt(item);
1263 struct pval *x = 0;
1264
1265 if (z)
1266 x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, z);
1267
1268 if (!x) {
1269 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",
1270 item->filename, item->startline, item->endline, item->u1.list->u1.str, item->u1.list->next->u1.str );
1271 errs++;
1272 }
1273 else
1274 return;
1275 }
1276 }
1277
1278 /* All 3 items! */
1279 if (item->u1.list->next && item->u1.list->next->next) {
1280 /* all three */
1281 pval *first = item->u1.list;
1282 pval *second = item->u1.list->next;
1283 pval *third = item->u1.list->next->next;
1284
1285 /* printf("Calling find_label_in_current_db with args %s, %s, %s\n",
1286 (char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); */
1287 if (!strstr((item->u1.list)->u1.str,"${")
1288 && !strstr(item->u1.list->next->u1.str,"${")
1289 && !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ {
1290 struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str);
1291 if (!x) {
1292 struct pval *p3;
1293 struct pval *found = 0;
1294 struct pval *that_context = find_context(item->u1.list->u1.str);
1295
1296 /* the target of the goto could be in an included context!! Fancy that!! */
1297 /* look for includes in the current context */
1298 if (that_context) {
1299 for (p3=that_context->u2.statements; p3; p3=p3->next) {
1300 if (p3->type == PV_INCLUDES) {
1301 struct pval *p4;
1302 for (p4=p3->u1.list; p4; p4=p4->next) {
1303 /* for each context pointed to, find it, then find a context/label that matches the
1304 target here! */
1305 char *incl_context = p4->u1.str;
1306 /* find a matching context name */
1307 struct pval *that_other_context = find_context(incl_context);
1308 if (that_other_context) {
1309 struct pval *x3;
1310 x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context);
1311 if (x3) {
1312 found = x3;
1313 break;
1314 }
1315 }
1316 }
1317 }
1318 }
1319 if (!found) {
1320 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s|%s exists in the context %s or its inclusions!\n",
1321 item->filename, item->startline, item->endline, item->u1.list->next->u1.str, item->u1.list->next->next->u1.str, item->u1.list->u1.str );
1322 errs++;
1323 } else {
1324 struct pval *mac = in_macro(item); /* is this goto inside a macro? */
1325 if( mac ) { /* yes! */
1326 struct pval *targ = in_context(found);
1327 if( mac != targ )
1328 {
1329 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",
1330 item->filename, item->startline, item->endline);
1331 warns++;
1332 }
1333 }
1334 }
1335 } else {
1336 /* here is where code would go to check for target existence in extensions.conf files */
1337#ifdef STANDALONE
1338 struct pbx_find_info pfiq = {.stacklen = 0 };
1339 extern int localized_pbx_load_module(void);
1340 /* if this is a standalone, we will need to make sure the
1341 localized load of extensions.conf is done */
1342 if (!extensions_dot_conf_loaded) {
1344 extensions_dot_conf_loaded++;
1345 }
1346
1347 pbx_find_extension(NULL, NULL, &pfiq, first->u1.str, second->u1.str, atoi(third->u1.str),
1348 atoi(third->u1.str) ? NULL : third->u1.str, NULL,
1349 atoi(third->u1.str) ? E_MATCH : E_FINDLABEL);
1350
1351 if (pfiq.status != STATUS_SUCCESS) {
1352 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",
1353 item->filename, item->startline, item->endline, first->u1.str, second->u1.str, third->u1.str);
1354 warns++;
1355 }
1356#else
1357 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: goto: Couldn't find goto target %s|%s|%s in the AEL code!\n",
1358 item->filename, item->startline, item->endline, first->u1.str, second->u1.str, third->u1.str);
1359 warns++;
1360#endif
1361 }
1362 } else {
1363 struct pval *mac = in_macro(item); /* is this goto inside a macro? */
1364 if( mac ) { /* yes! */
1365 struct pval *targ = in_context(x);
1366 if( mac != targ )
1367 {
1368 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",
1369 item->filename, item->startline, item->endline);
1370 warns++;
1371 }
1372 }
1373 }
1374 }
1375 }
1376}
struct sla_ringing_trunk * first
Definition: app_sla.c:332
@ E_MATCH
Definition: extconf.h:217
@ E_FINDLABEL
Definition: extconf.h:220
#define STATUS_SUCCESS
Definition: extconf.h:248
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: ael_main.c:152
static struct pval * find_label_in_current_context(char *exten, char *label, pval *curr_cont)
Definition: pval.c:1879
static pval * get_contxt(pval *p)
Definition: pval.c:4345
static struct pval * in_macro(pval *item)
Definition: pval.c:1077
static struct pval * find_label_in_current_extension(const char *label, pval *curr_ext)
Definition: pval.c:1918
static pval * get_extension_or_contxt(pval *p)
Definition: pval.c:4335
struct pval * find_context(char *name)
Definition: pval.c:1953
static struct pval * in_context(pval *item)
Definition: pval.c:1090
int localized_pbx_load_module(void)
Definition: extconf.c:5644
static struct pval * find_label_in_current_db(const char *context, const char *exten, const char *label)
Definition: pval.c:1929
int stacklen
Definition: extconf.h:237

References ast_log, E_FINDLABEL, E_MATCH, errs, 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(), item, pval::list, localized_pbx_load_module(), LOG_ERROR, LOG_WARNING, pval::next, NULL, pbx_find_extension(), PV_INCLUDES, pbx_find_info::stacklen, pval::statements, pbx_find_info::status, STATUS_SUCCESS, pval::str, pval::type, pval::u1, pval::u2, and warns.

Referenced by check_pval_item(), and find_pval_goto_item().

◆ check_includes()

static void check_includes ( pval includes)
static

Definition at line 811 of file pval.c.

812{
813 struct pval *p4;
814 for (p4=includes->u1.list; p4; p4=p4->next) {
815 /* for each context pointed to, find it, then find a context/label that matches the
816 target here! */
817 char *incl_context = p4->u1.str;
818 /* find a matching context name */
819 struct pval *that_other_context = find_context(incl_context);
820 if (!that_other_context && strcmp(incl_context, "parkedcalls") != 0) {
821 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The included context '%s' cannot be found.\n\
822 (You may ignore this warning if '%s' exists in extensions.conf, or is created by another module. I cannot check for those.)\n",
823 includes->filename, includes->startline, includes->endline, incl_context, incl_context);
824 warns++;
825 }
826 }
827}

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

Referenced by check_pval_item().

◆ check_label()

static void check_label ( pval item)
static

Definition at line 1106 of file pval.c.

1107{
1108 struct pval *curr;
1109 struct pval *x;
1110 int alright = 0;
1111
1112 /* A label outside an extension just plain does not make sense! */
1113
1114 curr = item;
1115
1116 while( curr ) {
1117 if( curr->type == PV_MACRO || curr->type == PV_EXTENSION ) {
1118 alright = 1;
1119 break;
1120 }
1121 curr = curr->dad;
1122 }
1123 if( !alright )
1124 {
1125 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: Label %s is not within an extension or macro!\n",
1126 item->filename, item->startline, item->endline, item->u1.str);
1127 errs++;
1128 }
1129
1130
1131 /* basically, ensure that a label is not repeated in a context. Period.
1132 The method: well, for each label, find the first label in the context
1133 with the same name. If it's not the current label, then throw an error. */
1134
1135
1136 /* printf("==== check_label: ====\n"); */
1137 if( !current_extension )
1138 curr = current_context;
1139 else
1140 curr = current_extension;
1141
1142 x = find_first_label_in_current_context((char *)item->u1.str, curr);
1143 /* 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); */
1144 if( x && x != item )
1145 {
1146 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: Duplicate label %s! Previously defined at file %s, line %d.\n",
1147 item->filename, item->startline, item->endline, item->u1.str, x->filename, x->startline);
1148 errs++;
1149 }
1150 /* printf("<<<<< check_label: ====\n"); */
1151}
static pval * current_context
Definition: pval.c:73
static pval * current_extension
Definition: pval.c:74
static struct pval * find_first_label_in_current_context(char *label, pval *curr_cont)
Definition: pval.c:1839

References ast_log, current_context, current_extension, pval::dad, errs, pval::filename, find_first_label_in_current_context(), item, LOG_ERROR, PV_EXTENSION, PV_MACRO, pval::startline, and pval::type.

Referenced by check_pval_item().

◆ check_macro_returns()

static void check_macro_returns ( pval macro)
static

Definition at line 650 of file pval.c.

651{
652 pval *i;
653 if (!macro->u3.macro_statements)
654 {
655 pval *z = calloc(1, sizeof(struct pval));
656 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The macro %s is empty! I will insert a return.\n",
657 macro->filename, macro->startline, macro->endline, macro->u1.str);
658
659 z->type = PV_RETURN;
660 z->startline = macro->startline;
661 z->endline = macro->endline;
662 z->startcol = macro->startcol;
663 z->endcol = macro->endcol;
664 z->filename = strdup(macro->filename);
665
666 macro->u3.macro_statements = z;
667 return;
668 }
669 for (i=macro->u3.macro_statements; i; i=i->next) {
670 /* if the last statement in the list is not return, then insert a return there */
671 if (i->next == NULL) {
672 if (i->type != PV_RETURN) {
673 pval *z = calloc(1, sizeof(struct pval));
674 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The macro %s does not end with a return; I will insert one.\n",
675 macro->filename, macro->startline, macro->endline, macro->u1.str);
676
677 z->type = PV_RETURN;
678 z->startline = macro->startline;
679 z->endline = macro->endline;
680 z->startcol = macro->startcol;
681 z->endcol = macro->endcol;
682 z->filename = strdup(macro->filename);
683
684 i->next = z;
685 return;
686 }
687 }
688 }
689 return;
690}
#define calloc(a, b)
Definition: astmm.h:155
@ PV_RETURN
Definition: pval.h:27
int startcol
Definition: pval.h:53
int endcol
Definition: pval.h:54

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

Referenced by check_pval_item().

◆ check_month()

static void check_month ( pval MON)
static

Definition at line 1000 of file pval.c.

1001{
1002 char *mon;
1003 char *c;
1004 /* The following line is coincidence, really! */
1005 int s, e;
1006
1007 mon = ast_strdupa(MON->u1.str);
1008
1009 /* Check for all days */
1010 if (ast_strlen_zero(mon) || !strcmp(mon, "*"))
1011 return ;
1012 /* Get start and ending days */
1013 c = strchr(mon, '-');
1014 if (c) {
1015 *c = '\0';
1016 c++;
1017 }
1018 /* Find the start */
1019 s = 0;
1020 while ((s < 12) && strcasecmp(mon, months[s])) s++;
1021 if (s >= 12) {
1022 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n",
1023 MON->filename, MON->startline, MON->endline, mon);
1024 warns++;
1025 }
1026 if (c) {
1027 e = 0;
1028 while ((e < 12) && strcasecmp(mon, months[e])) e++;
1029 if (e >= 12) {
1030 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n",
1031 MON->filename, MON->startline, MON->endline, c);
1032 warns++;
1033 }
1034 } else
1035 e = s;
1036}
static char * months[]
Definition: pval.c:984

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

Referenced by check_pval_item().

◆ check_pval()

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

Definition at line 2865 of file pval.c.

2866{
2867 pval *i;
2868
2869 /* checks to do:
2870 1. Do goto's point to actual labels?
2871 2. Do macro calls reference a macro?
2872 3. Does the number of macro args match the definition?
2873 4. Is a macro call missing its & at the front?
2874 5. Application calls-- we could check syntax for existing applications,
2875 but I need some sort of universal description bnf for a general
2876 sort of method for checking arguments, in number, maybe even type, at least.
2877 Don't want to hand code checks for hundreds of applications.
2878 */
2879
2880 for (i=item; i; i=i->next) {
2881 check_pval_item(i,apps,in_globals);
2882 }
2883}
void check_pval_item(pval *item, struct argapp *apps, int in_globals)
Definition: pval.c:2357

References check_pval_item(), item, and pval::next.

Referenced by ael2_semantic_check(), and check_pval_item().

◆ check_pval_item()

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

Definition at line 2357 of file pval.c.

2358{
2359 pval *lp;
2360#ifdef AAL_ARGCHECK
2361 struct argapp *app, *found;
2362#endif
2363 struct pval *macro_def;
2364 struct pval *app_def;
2365
2366 char errmsg[4096];
2367 char *strp;
2368
2369 switch (item->type) {
2370 case PV_WORD:
2371 /* fields: item->u1.str == string associated with this (word).
2372 item->u2.arglist == pval list of 4 PV_WORD elements for time values (only in PV_INCLUDES) */
2373 break;
2374
2375 case PV_MACRO:
2376 /* fields: item->u1.str == name of macro
2377 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
2378 item->u2.arglist->u1.str == argument
2379 item->u2.arglist->next == next arg
2380
2381 item->u3.macro_statements == pval list of statements in macro body.
2382 */
2386
2388
2389 for (lp=item->u2.arglist; lp; lp=lp->next) {
2390
2391 }
2392 check_pval(item->u3.macro_statements, apps,in_globals);
2393 break;
2394
2395 case PV_CONTEXT:
2396 /* fields: item->u1.str == name of context
2397 item->u2.statements == pval list of statements in context body
2398 item->u3.abstract == int 1 if an abstract keyword were present
2399 */
2402 if ( item->u3.abstract ) {
2405 } else
2407 check_pval(item->u2.statements, apps,in_globals);
2408 break;
2409
2410 case PV_MACRO_CALL:
2411 /* fields: item->u1.str == name of macro to call
2412 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
2413 item->u2.arglist->u1.str == argument
2414 item->u2.arglist->next == next arg
2415 */
2416#ifdef STANDALONE
2417 /* if this is a standalone, we will need to make sure the
2418 localized load of extensions.conf is done */
2419 if (!extensions_dot_conf_loaded) {
2421 extensions_dot_conf_loaded++;
2422 }
2423#endif
2424 macro_def = find_macro(item->u1.str);
2425 if (!macro_def) {
2426#ifdef STANDALONE
2427 struct pbx_find_info pfiq = {.stacklen = 0 };
2428 struct pbx_find_info pfiq2 = {.stacklen = 0 };
2429
2430 /* look for the macro in the extensions.conf world */
2431 pbx_find_extension(NULL, NULL, &pfiq, item->u1.str, "s", 1, NULL, NULL, E_MATCH);
2432
2433 if (pfiq.status != STATUS_SUCCESS) {
2434 char namebuf2[256];
2435 snprintf(namebuf2, 256, "macro-%s", item->u1.str);
2436
2437 /* look for the macro in the extensions.conf world */
2438 pbx_find_extension(NULL, NULL, &pfiq2, namebuf2, "s", 1, NULL, NULL, E_MATCH);
2439
2440 if (pfiq2.status == STATUS_SUCCESS) {
2441 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",
2442 item->filename, item->startline, item->endline, item->u1.str, item->u1.str);
2443 warns++;
2444 } else {
2445 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to non-existent %s! (Not even in the extensions.conf stuff!)\n",
2446 item->filename, item->startline, item->endline, item->u1.str);
2447 warns++;
2448 }
2449 }
2450#else
2451 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to %s cannot be found in the AEL code!\n",
2452 item->filename, item->startline, item->endline, item->u1.str);
2453 warns++;
2454
2455#endif
2456#ifdef THIS_IS_1DOT4
2457 char namebuf2[256];
2458 snprintf(namebuf2, 256, "macro-%s", item->u1.str);
2459
2460 /* look for the macro in the extensions.conf world */
2461 pbx_find_extension(NULL, NULL, &pfiq, namebuf2, "s", 1, NULL, NULL, E_MATCH);
2462
2463 if (pfiq.status != STATUS_SUCCESS) {
2464 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",
2465 item->filename, item->startline, item->endline, item->u1.str);
2466 warns++;
2467 }
2468
2469#endif
2470
2471 } else if (macro_def->type != PV_MACRO) {
2472 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: macro call to %s references a context, not a macro!\n",
2473 item->filename, item->startline, item->endline, item->u1.str);
2474 errs++;
2475 } else {
2476 /* macro_def is a MACRO, so do the args match in number? */
2477 int hereargs = 0;
2478 int thereargs = 0;
2479
2480 for (lp=item->u2.arglist; lp; lp=lp->next) {
2481 hereargs++;
2482 }
2483 for (lp=macro_def->u2.arglist; lp; lp=lp->next) {
2484 thereargs++;
2485 }
2486 if (hereargs != thereargs ) {
2487 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",
2488 item->filename, item->startline, item->endline, item->u1.str, hereargs, thereargs);
2489 errs++;
2490 }
2491 }
2492 break;
2493
2495 /* fields: item->u1.str == name of application to call
2496 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
2497 item->u2.arglist->u1.str == argument
2498 item->u2.arglist->next == next arg
2499 */
2500 /* Need to check to see if the application is available! */
2501 app_def = find_context(item->u1.str);
2502 if (app_def && app_def->type == PV_MACRO) {
2503 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: application call to %s references an existing macro, but had no & preceding it!\n",
2504 item->filename, item->startline, item->endline, item->u1.str);
2505 errs++;
2506 }
2507 if (strcasecmp(item->u1.str,"GotoIf") == 0
2508 || strcasecmp(item->u1.str,"GotoIfTime") == 0
2509 || strcasecmp(item->u1.str,"while") == 0
2510 || strcasecmp(item->u1.str,"endwhile") == 0
2511 || strcasecmp(item->u1.str,"random") == 0
2512 || strcasecmp(item->u1.str,"gosub") == 0
2513 || strcasecmp(item->u1.str,"gosubif") == 0
2514 || strcasecmp(item->u1.str,"continuewhile") == 0
2515 || strcasecmp(item->u1.str,"endwhile") == 0
2516 || strcasecmp(item->u1.str,"execif") == 0
2517 || strcasecmp(item->u1.str,"execiftime") == 0
2518 || strcasecmp(item->u1.str,"exitwhile") == 0
2519 || strcasecmp(item->u1.str,"goto") == 0
2520 || strcasecmp(item->u1.str,"macro") == 0
2521 || strcasecmp(item->u1.str,"macroexclusive") == 0
2522 || strcasecmp(item->u1.str,"macroif") == 0
2523 || strcasecmp(item->u1.str,"stackpop") == 0
2524 || strcasecmp(item->u1.str,"execIf") == 0 ) {
2525 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",
2526 item->filename, item->startline, item->endline, item->u1.str);
2527 warns++;
2528 }
2529 if (strcasecmp(item->u1.str,"macroexit") == 0) {
2530 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: I am converting the MacroExit call here to a return statement.\n",
2531 item->filename, item->startline, item->endline);
2532 item->type = PV_RETURN;
2533 free(item->u1.str);
2534 item->u1.str = 0;
2535 }
2536
2537#ifdef AAL_ARGCHECK
2538 found = 0;
2539 for (app=apps; app; app=app->next) {
2540 if (strcasecmp(app->name, item->u1.str) == 0) {
2541 found =app;
2542 break;
2543 }
2544 }
2545 if (!found) {
2546 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: application call to %s not listed in applist database!\n",
2547 item->filename, item->startline, item->endline, item->u1.str);
2548 warns++;
2549 } else
2550 check_app_args(item, item->u2.arglist, app);
2551#endif
2552 break;
2553
2554 case PV_CASE:
2555 /* fields: item->u1.str == value of case
2556 item->u2.statements == pval list of statements under the case
2557 */
2558 /* Make sure sequence of statements under case is terminated with goto, return, or break */
2559 /* find the last statement */
2560 check_pval(item->u2.statements, apps,in_globals);
2561 break;
2562
2563 case PV_PATTERN:
2564 /* fields: item->u1.str == value of case
2565 item->u2.statements == pval list of statements under the case
2566 */
2567 /* Make sure sequence of statements under case is terminated with goto, return, or break */
2568 /* find the last statement */
2569
2570 check_pval(item->u2.statements, apps,in_globals);
2571 break;
2572
2573 case PV_DEFAULT:
2574 /* fields:
2575 item->u2.statements == pval list of statements under the case
2576 */
2577
2578 check_pval(item->u2.statements, apps,in_globals);
2579 break;
2580
2581 case PV_CATCH:
2582 /* fields: item->u1.str == name of extension to catch
2583 item->u2.statements == pval list of statements in context body
2584 */
2585 check_pval(item->u2.statements, apps,in_globals);
2586 break;
2587
2588 case PV_SWITCHES:
2589 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
2590 */
2591 check_pval(item->u1.list, apps,in_globals);
2592 break;
2593
2594 case PV_ESWITCHES:
2595 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
2596 */
2597 check_pval(item->u1.list, apps,in_globals);
2598 break;
2599
2600 case PV_INCLUDES:
2601 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
2602 */
2603 check_pval(item->u1.list, apps,in_globals);
2605 for (lp=item->u1.list; lp; lp=lp->next){
2606 char *incl_context = lp->u1.str;
2607 struct pval *that_context = find_context(incl_context);
2608
2609 if ( lp->u2.arglist ) {
2611 check_dow(lp->u2.arglist->next);
2612 check_day(lp->u2.arglist->next->next);
2614 }
2615
2616 if (that_context) {
2617 find_pval_gotos(that_context->u2.statements,0);
2618
2619 }
2620 }
2621 break;
2622
2623 case PV_STATEMENTBLOCK:
2624 /* fields: item->u1.list == pval list of statements in block, one per entry in the list
2625 */
2626 check_pval(item->u1.list, apps,in_globals);
2627 break;
2628
2629 case PV_VARDEC:
2630 /* fields: item->u1.str == variable name
2631 item->u2.val == variable value to assign
2632 */
2633 /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */
2634 if( !in_globals ) { /* don't check stuff inside the globals context; no wrapping in $[ ] there... */
2635 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);
2637 ast_expr(item->u2.val, expr_output, sizeof(expr_output),NULL);
2639 if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) {
2640 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
2641 item->filename, item->startline, item->endline, item->u2.val);
2642 warns++;
2643 }
2644 check_expr2_input(item,item->u2.val);
2645 }
2646 break;
2647
2648 case PV_LOCALVARDEC:
2649 /* fields: item->u1.str == variable name
2650 item->u2.val == variable value to assign
2651 */
2652 /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */
2653 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);
2655 ast_expr(item->u2.val, expr_output, sizeof(expr_output),NULL);
2657 if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) {
2658 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
2659 item->filename, item->startline, item->endline, item->u2.val);
2660 warns++;
2661 }
2662 check_expr2_input(item,item->u2.val);
2663 break;
2664
2665 case PV_GOTO:
2666 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user.
2667 item->u1.list->u1.str == where the data on a PV_WORD will always be.
2668 */
2669 /* don't check goto's in abstract contexts */
2670 if ( in_abstract_context )
2671 break;
2672
2674 break;
2675
2676 case PV_LABEL:
2677 /* fields: item->u1.str == label name
2678 */
2679 if ( strspn(item->u1.str, "0123456789") == strlen(item->u1.str) ) {
2680 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: label '%s' is numeric, this is bad practice!\n",
2681 item->filename, item->startline, item->endline, item->u1.str);
2682 warns++;
2683 }
2684
2686 break;
2687
2688 case PV_FOR:
2689 /* fields: item->u1.for_init == a string containing the initializer
2690 item->u2.for_test == a string containing the loop test
2691 item->u3.for_inc == a string containing the loop increment
2692
2693 item->u4.for_statements == a pval list of statements in the for ()
2694 */
2695 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);
2697
2698 strp = strchr(item->u1.for_init, '=');
2699 if (strp) {
2700 ast_expr(strp+1, expr_output, sizeof(expr_output),NULL);
2701 }
2702 ast_expr(item->u2.for_test, expr_output, sizeof(expr_output),NULL);
2703 strp = strchr(item->u3.for_inc, '=');
2704 if (strp) {
2705 ast_expr(strp+1, expr_output, sizeof(expr_output),NULL);
2706 }
2707 if ( strpbrk(item->u2.for_test,"~!-+<>=*/&^") && !strstr(item->u2.for_test,"${") ) {
2708 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
2709 item->filename, item->startline, item->endline, item->u2.for_test);
2710 warns++;
2711 }
2712 if ( strpbrk(item->u3.for_inc,"~!-+<>=*/&^") && !strstr(item->u3.for_inc,"${") ) {
2713 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
2714 item->filename, item->startline, item->endline, item->u3.for_inc);
2715 warns++;
2716 }
2717 check_expr2_input(item,item->u2.for_test);
2718 check_expr2_input(item,item->u3.for_inc);
2719
2721 check_pval(item->u4.for_statements, apps,in_globals);
2722 break;
2723
2724 case PV_WHILE:
2725 /* fields: item->u1.str == the while conditional, as supplied by user
2726
2727 item->u2.statements == a pval list of statements in the while ()
2728 */
2729 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);
2731 ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL);
2733 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) {
2734 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
2735 item->filename, item->startline, item->endline, item->u1.str);
2736 warns++;
2737 }
2738 check_expr2_input(item,item->u1.str);
2739 check_pval(item->u2.statements, apps,in_globals);
2740 break;
2741
2742 case PV_BREAK:
2743 /* fields: none
2744 */
2746 break;
2747
2748 case PV_RETURN:
2749 /* fields: none
2750 */
2751 break;
2752
2753 case PV_CONTINUE:
2754 /* fields: none
2755 */
2757 break;
2758
2759 case PV_RANDOM:
2760 /* fields: item->u1.str == the random number expression, as supplied by user
2761
2762 item->u2.statements == a pval list of statements in the if ()
2763 item->u3.else_statements == a pval list of statements in the else
2764 (could be zero)
2765 */
2766 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);
2768 ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL);
2770 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) {
2771 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: random expression '%s' has operators, but no variables. Interesting...\n",
2772 item->filename, item->startline, item->endline, item->u1.str);
2773 warns++;
2774 }
2775 check_expr2_input(item,item->u1.str);
2776 check_pval(item->u2.statements, apps,in_globals);
2777 if (item->u3.else_statements) {
2778 check_pval(item->u3.else_statements, apps,in_globals);
2779 }
2780 break;
2781
2782 case PV_IFTIME:
2783 /* fields: item->u1.list == the if time values, 4 of them, each in PV_WORD, linked list
2784
2785 item->u2.statements == a pval list of statements in the if ()
2786 item->u3.else_statements == a pval list of statements in the else
2787 (could be zero)
2788 */
2789 if ( item->u2.arglist ) {
2790 check_timerange(item->u1.list);
2791 check_dow(item->u1.list->next);
2792 check_day(item->u1.list->next->next);
2793 check_month(item->u1.list->next->next->next);
2794 }
2795
2796 check_pval(item->u2.statements, apps,in_globals);
2797 if (item->u3.else_statements) {
2798 check_pval(item->u3.else_statements, apps,in_globals);
2799 }
2800 break;
2801
2802 case PV_IF:
2803 /* fields: item->u1.str == the if conditional, as supplied by user
2804
2805 item->u2.statements == a pval list of statements in the if ()
2806 item->u3.else_statements == a pval list of statements in the else
2807 (could be zero)
2808 */
2809 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);
2811 ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL);
2813 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) {
2814 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression '%s' has operators, but no variables. Interesting...\n",
2815 item->filename, item->startline, item->endline, item->u1.str);
2816 warns++;
2817 }
2818 check_expr2_input(item,item->u1.str);
2819 check_pval(item->u2.statements, apps,in_globals);
2820 if (item->u3.else_statements) {
2821 check_pval(item->u3.else_statements, apps,in_globals);
2822 }
2823 break;
2824
2825 case PV_SWITCH:
2826 /* fields: item->u1.str == the switch expression
2827
2828 item->u2.statements == a pval list of statements in the switch,
2829 (will be case statements, most likely!)
2830 */
2831 /* we can check the switch expression, see if it matches any of the app variables...
2832 if it does, then, are all the possible cases accounted for? */
2834 check_pval(item->u2.statements, apps,in_globals);
2835 break;
2836
2837 case PV_EXTENSION:
2838 /* fields: item->u1.str == the extension name, label, whatever it's called
2839
2840 item->u2.statements == a pval list of statements in the extension
2841 item->u3.hints == a char * hint argument
2842 item->u4.regexten == an int boolean. non-zero says that regexten was specified
2843 */
2845
2846 check_pval(item->u2.statements, apps,in_globals);
2847 break;
2848
2849 case PV_IGNOREPAT:
2850 /* fields: item->u1.str == the ignorepat data
2851 */
2852 break;
2853
2854 case PV_GLOBALS:
2855 /* fields: item->u1.statements == pval list of statements, usually vardecs
2856 */
2858 check_pval(item->u1.statements, apps, 1);
2859 break;
2860 default:
2861 break;
2862 }
2863}
int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan)
Evaluate the given expression.
Definition: ast_expr2f.c:2391
void free()
static int check_continue(pval *item)
Definition: pval.c:1058
void check_switch_expr(pval *item, struct argapp *apps)
Definition: pval.c:2184
static void check_macro_returns(pval *macro)
Definition: pval.c:650
static void check_day(pval *DAY)
Definition: pval.c:937
struct pval * find_macro(char *name)
Definition: pval.c:1943
static void check_label(pval *item)
Definition: pval.c:1106
static void find_pval_gotos(pval *item, int lev)
Definition: pval.c:1550
int check_app_args(pval *appcall, pval *arglist, struct argapp *app)
Definition: pval.c:2130
static void check_dow(pval *DOW)
get_dow: Get day of week
Definition: pval.c:898
static void check_goto(pval *item)
Definition: pval.c:1225
static void check_abstract_reference(pval *abstract_context)
Definition: pval.c:2329
static void check_timerange(pval *p)
Definition: pval.c:830
static void check_includes(pval *includes)
Definition: pval.c:811
static void check_month(pval *MON)
Definition: pval.c:1000
static int in_abstract_context
Definition: pval.c:79
static void check_expr2_input(pval *expr, char *str)
Definition: pval.c:801
static int check_break(pval *item)
Definition: pval.c:1038
static char expr_output[2096]
Definition: pval.c:60
void ast_expr_clear_extra_error_info(void)
Definition: ast_expr2f.c:2469
@ PV_CATCH
Definition: pval.h:16
@ PV_WORD
Definition: pval.h:8
@ PV_LOCALVARDEC
Definition: pval.h:36
@ PV_CONTINUE
Definition: pval.h:28
@ PV_BREAK
Definition: pval.h:26
@ PV_APPLICATION_CALL
Definition: pval.h:12
@ PV_IF
Definition: pval.h:29
@ PV_VARDEC
Definition: pval.h:21
@ PV_MACRO_CALL
Definition: pval.h:11
@ PV_GOTO
Definition: pval.h:22
@ PV_LABEL
Definition: pval.h:23
@ PV_RANDOM
Definition: pval.h:31
@ PV_STATEMENTBLOCK
Definition: pval.h:20
void ast_expr_register_extra_error_info(char *errmsg)
Definition: ast_expr2f.c:2463
enum aco_type_t type

References app, pval::arglist, ast_expr(), ast_expr_clear_extra_error_info(), ast_expr_register_extra_error_info(), ast_log, check_abstract_reference(), check_app_args(), check_break(), check_continue(), check_day(), check_dow(), check_expr2_input(), check_goto(), check_includes(), check_label(), check_macro_returns(), check_month(), check_pval(), check_switch_expr(), check_timerange(), current_context, current_extension, E_MATCH, errs, expr_output, find_context(), find_macro(), find_pval_gotos(), free(), in_abstract_context, item, localized_pbx_load_module(), LOG_ERROR, LOG_WARNING, pval::next, NULL, 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::statements, pbx_find_info::status, STATUS_SUCCESS, pval::str, aco_type::type, pval::type, pval::u1, pval::u2, and warns.

Referenced by check_pval().

◆ check_switch_expr()

void check_switch_expr ( pval item,
struct argapp apps 
)

Definition at line 2184 of file pval.c.

2185{
2186#ifdef AAL_ARGCHECK
2187 /* get and clean the variable name */
2188 char *buff1, *p;
2189 struct argapp *a,*a2;
2190 struct appsetvar *v,*v2;
2191 struct argchoice *c;
2192 pval *t;
2193
2194 p = item->u1.str;
2195 while (p && *p && (*p == ' ' || *p == '\t' || *p == '$' || *p == '{' ) )
2196 p++;
2197
2198 buff1 = ast_strdupa(p);
2199
2200 while (strlen(buff1) > 0 && ( buff1[strlen(buff1)-1] == '}' || buff1[strlen(buff1)-1] == ' ' || buff1[strlen(buff1)-1] == '\t'))
2201 buff1[strlen(buff1)-1] = 0;
2202 /* buff1 now contains the variable name */
2203 v = 0;
2204 for (a=apps; a; a=a->next) {
2205 for (v=a->setvars;v;v=v->next) {
2206 if (strcmp(v->name,buff1) == 0) {
2207 break;
2208 }
2209 }
2210 if ( v )
2211 break;
2212 }
2213 if (v && v->vals) {
2214 /* we have a match, to a variable that has a set of determined values */
2215 int def= 0;
2216 int pat = 0;
2217 int f1 = 0;
2218
2219 /* first of all, does this switch have a default case ? */
2220 for (t=item->u2.statements; t; t=t->next) {
2221 if (t->type == PV_DEFAULT) {
2222 def =1;
2223 break;
2224 }
2225 if (t->type == PV_PATTERN) {
2226 pat++;
2227 }
2228 }
2229 if (def || pat) /* nothing to check. All cases accounted for! */
2230 return;
2231 for (c=v->vals; c; c=c->next) {
2232 f1 = 0;
2233 for (t=item->u2.statements; t; t=t->next) {
2234 if (t->type == PV_CASE || t->type == PV_PATTERN) {
2235 if (!strcmp(t->u1.str,c->name)) {
2236 f1 = 1;
2237 break;
2238 }
2239 }
2240 }
2241 if (!f1) {
2242 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: switch with expression(%s) does not handle the case of %s !\n",
2243 item->filename, item->startline, item->endline, item->u1.str, c->name);
2244 warns++;
2245 }
2246 }
2247 /* next, is there an app call in the current exten, that would set this var? */
2248 f1 = 0;
2250 if ( t && t->type == PV_STATEMENTBLOCK )
2251 t = t->u1.statements;
2252 for (; t && t != item; t=t->next) {
2253 if (t->type == PV_APPLICATION_CALL) {
2254 /* find the application that matches the u1.str */
2255 for (a2=apps; a2; a2=a2->next) {
2256 if (strcasecmp(a2->name, t->u1.str)==0) {
2257 for (v2=a2->setvars; v2; v2=v2->next) {
2258 if (strcmp(v2->name, buff1) == 0) {
2259 /* found an app that sets the var */
2260 f1 = 1;
2261 break;
2262 }
2263 }
2264 }
2265 if (f1)
2266 break;
2267 }
2268 }
2269 if (f1)
2270 break;
2271 }
2272
2273 /* see if it sets the var */
2274 if (!f1) {
2275 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",
2276 item->filename, item->startline, item->endline, item->u1.str);
2277 warns++;
2278 }
2279 }
2280#else
2281 pval *t,*tl=0,*p2;
2282 int def= 0;
2283
2284 /* first of all, does this switch have a default case ? */
2285 for (t=item->u2.statements; t; t=t->next) {
2286 if (t->type == PV_DEFAULT) {
2287 def =1;
2288 break;
2289 }
2290 tl = t;
2291 }
2292 if (def) /* nothing to check. All cases accounted for! */
2293 return;
2294 /* if no default, warn and insert a default case at the end */
2295 p2 = tl->next = calloc(1, sizeof(struct pval));
2296
2297 p2->type = PV_DEFAULT;
2298 p2->startline = tl->startline;
2299 p2->endline = tl->endline;
2300 p2->startcol = tl->startcol;
2301 p2->endcol = tl->endcol;
2302 p2->filename = strdup(tl->filename);
2303 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: A default case was automatically added to the switch.\n",
2304 p2->filename, p2->startline, p2->endline);
2305 warns++;
2306
2307#endif
2308}
struct argapp * next
Definition: pval.h:112
struct test_val * next
const char * name
static struct test_val a

References a, ast_log, ast_strdupa, c, calloc, current_extension, pval::endcol, pval::endline, pval::filename, item, LOG_WARNING, test_val::name, pval::next, argapp::next, test_val::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, pval::u2, and warns.

Referenced by check_pval_item().

◆ check_timerange()

static void check_timerange ( pval p)
static

Definition at line 830 of file pval.c.

831{
832 char *times;
833 char *e;
834 int s1, s2;
835 int e1, e2;
836
837 times = ast_strdupa(p->u1.str);
838
839 /* Star is all times */
840 if (ast_strlen_zero(times) || !strcmp(times, "*")) {
841 return;
842 }
843 /* Otherwise expect a range */
844 e = strchr(times, '-');
845 if (!e) {
846 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",
847 p->filename, p->startline, p->endline, times);
848 warns++;
849 return;
850 }
851 *e = '\0';
852 e++;
853 while (*e && !isdigit(*e))
854 e++;
855 if (!*e) {
856 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The time range format (%s) is missing the end time!\n",
857 p->filename, p->startline, p->endline, p->u1.str);
858 warns++;
859 }
860 if (sscanf(times, "%2d:%2d", &s1, &s2) != 2) {
861 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) isn't quite right!\n",
862 p->filename, p->startline, p->endline, times);
863 warns++;
864 }
865 if (sscanf(e, "%2d:%2d", &e1, &e2) != 2) {
866 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) isn't quite right!\n",
867 p->filename, p->startline, p->endline, times);
868 warns++;
869 }
870
871 s1 = s1 * 30 + s2/2;
872 if ((s1 < 0) || (s1 >= 24*30)) {
873 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) is out of range!\n",
874 p->filename, p->startline, p->endline, times);
875 warns++;
876 }
877 e1 = e1 * 30 + e2/2;
878 if ((e1 < 0) || (e1 >= 24*30)) {
879 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) is out of range!\n",
880 p->filename, p->startline, p->endline, e);
881 warns++;
882 }
883 return;
884}

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

Referenced by check_pval_item().

◆ contains_switch()

int contains_switch ( pval item)

Definition at line 3329 of file pval.c.

3330{
3331 pval *i;
3332
3333 for (i=item; i; i=i->next) {
3334 if (find_switch_item(i))
3335 return 1;
3336 }
3337 return 0;
3338}
int find_switch_item(pval *item)
Definition: pval.c:3090

References find_switch_item(), item, and pval::next.

Referenced by find_switch_item(), and gen_prios().

◆ context_used()

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

Definition at line 4398 of file pval.c.

4399{
4400 struct ael_extension *exten;
4401 /* Check the simple elements first */
4403 return 1;
4404 }
4405 for (exten = exten_list; exten; exten = exten->next_exten) {
4406 if (exten->context == context) {
4407 return 1;
4408 }
4409 }
4410 return 0;
4411}
int ast_context_ignorepats_count(const struct ast_context *con)
Definition: pbx.c:8722
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
Definition: ael_main.c:427
int ast_context_switches_count(const struct ast_context *con)
Definition: pbx.c:8634
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8679

References ast_context_ignorepats_count(), ast_context_includes_count(), ast_context_switches_count(), ast_walk_context_extensions(), voicemailpwcheck::context, ael_extension::context, ael_extension::next_exten, and NULL.

Referenced by ast_compile_ael2().

◆ destroy_extensions()

void destroy_extensions ( struct ael_extension exten)

Definition at line 2978 of file pval.c.

2979{
2980 struct ael_extension *ne, *nen;
2981 for (ne=exten; ne; ne=nen) {
2982 struct ael_priority *pe, *pen;
2983
2984 if (ne->name)
2985 free(ne->name);
2986
2987 /* cidmatch fields are allocated with name, and freed when
2988 the name field is freed. Don't do a free for this field,
2989 unless you LIKE to see a crash! */
2990
2991 if (ne->hints)
2992 free(ne->hints);
2993
2994 for (pe=ne->plist; pe; pe=pen) {
2995 pen = pe->next;
2996 if (pe->app)
2997 free(pe->app);
2998 pe->app = 0;
2999 if (pe->appargs)
3000 free(pe->appargs);
3001 pe->appargs = 0;
3002 pe->origin = 0;
3003 pe->goto_true = 0;
3004 pe->goto_false = 0;
3005 free(pe);
3006 }
3007 nen = ne->next_exten;
3008 ne->next_exten = 0;
3009 ne->plist =0;
3010 ne->plist_last = 0;
3011 ne->next_exten = 0;
3012 ne->loop_break = 0;
3013 ne->loop_continue = 0;
3014 free(ne);
3015 }
3016}
struct ael_priority * loop_break
Definition: ael_structs.h:119
struct ael_priority * loop_continue
Definition: ael_structs.h:120

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

◆ destroy_pval()

void destroy_pval ( pval item)

Definition at line 4940 of file pval.c.

4941{
4942 pval *i,*nxt;
4943
4944 for (i=item; i; i=nxt) {
4945 nxt = i->next;
4946
4948 }
4949}
void destroy_pval_item(pval *item)
Definition: pval.c:4672

References destroy_pval_item(), item, and pval::next.

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

◆ destroy_pval_item()

void destroy_pval_item ( pval item)

Definition at line 4672 of file pval.c.

4673{
4674 if (item == NULL) {
4675 ast_log(LOG_WARNING, "null item\n");
4676 return;
4677 }
4678
4679 if (item->filename)
4680 free(item->filename);
4681
4682 switch (item->type) {
4683 case PV_WORD:
4684 /* fields: item->u1.str == string associated with this (word). */
4685 if (item->u1.str )
4686 free(item->u1.str);
4687 if ( item->u2.arglist )
4688 destroy_pval(item->u2.arglist);
4689 break;
4690
4691 case PV_MACRO:
4692 /* fields: item->u1.str == name of macro
4693 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
4694 item->u2.arglist->u1.str == argument
4695 item->u2.arglist->next == next arg
4696
4697 item->u3.macro_statements == pval list of statements in macro body.
4698 */
4699 destroy_pval(item->u2.arglist);
4700 if (item->u1.str )
4701 free(item->u1.str);
4702 destroy_pval(item->u3.macro_statements);
4703 break;
4704
4705 case PV_CONTEXT:
4706 /* fields: item->u1.str == name of context
4707 item->u2.statements == pval list of statements in context body
4708 item->u3.abstract == int 1 if an abstract keyword were present
4709 */
4710 if (item->u1.str)
4711 free(item->u1.str);
4712 destroy_pval(item->u2.statements);
4713 break;
4714
4715 case PV_MACRO_CALL:
4716 /* fields: item->u1.str == name of macro to call
4717 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
4718 item->u2.arglist->u1.str == argument
4719 item->u2.arglist->next == next arg
4720 */
4721 if (item->u1.str)
4722 free(item->u1.str);
4723 destroy_pval(item->u2.arglist);
4724 break;
4725
4727 /* fields: item->u1.str == name of application to call
4728 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
4729 item->u2.arglist->u1.str == argument
4730 item->u2.arglist->next == next arg
4731 */
4732 if (item->u1.str)
4733 free(item->u1.str);
4734 destroy_pval(item->u2.arglist);
4735 break;
4736
4737 case PV_CASE:
4738 /* fields: item->u1.str == value of case
4739 item->u2.statements == pval list of statements under the case
4740 */
4741 if (item->u1.str)
4742 free(item->u1.str);
4743 destroy_pval(item->u2.statements);
4744 break;
4745
4746 case PV_PATTERN:
4747 /* fields: item->u1.str == value of case
4748 item->u2.statements == pval list of statements under the case
4749 */
4750 if (item->u1.str)
4751 free(item->u1.str);
4752 destroy_pval(item->u2.statements);
4753 break;
4754
4755 case PV_DEFAULT:
4756 /* fields:
4757 item->u2.statements == pval list of statements under the case
4758 */
4759 destroy_pval(item->u2.statements);
4760 break;
4761
4762 case PV_CATCH:
4763 /* fields: item->u1.str == name of extension to catch
4764 item->u2.statements == pval list of statements in context body
4765 */
4766 if (item->u1.str)
4767 free(item->u1.str);
4768 destroy_pval(item->u2.statements);
4769 break;
4770
4771 case PV_SWITCHES:
4772 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
4773 */
4774 destroy_pval(item->u1.list);
4775 break;
4776
4777 case PV_ESWITCHES:
4778 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
4779 */
4780 destroy_pval(item->u1.list);
4781 break;
4782
4783 case PV_INCLUDES:
4784 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
4785 item->u2.arglist == pval list of 4 PV_WORD elements for time values
4786 */
4787 destroy_pval(item->u1.list);
4788 break;
4789
4790 case PV_STATEMENTBLOCK:
4791 /* fields: item->u1.list == pval list of statements in block, one per entry in the list
4792 */
4793 destroy_pval(item->u1.list);
4794 break;
4795
4796 case PV_LOCALVARDEC:
4797 case PV_VARDEC:
4798 /* fields: item->u1.str == variable name
4799 item->u2.val == variable value to assign
4800 */
4801 if (item->u1.str)
4802 free(item->u1.str);
4803 if (item->u2.val)
4804 free(item->u2.val);
4805 break;
4806
4807 case PV_GOTO:
4808 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user.
4809 item->u1.list->u1.str == where the data on a PV_WORD will always be.
4810 */
4811
4812 destroy_pval(item->u1.list);
4813 break;
4814
4815 case PV_LABEL:
4816 /* fields: item->u1.str == label name
4817 */
4818 if (item->u1.str)
4819 free(item->u1.str);
4820 break;
4821
4822 case PV_FOR:
4823 /* fields: item->u1.for_init == a string containing the initializer
4824 item->u2.for_test == a string containing the loop test
4825 item->u3.for_inc == a string containing the loop increment
4826
4827 item->u4.for_statements == a pval list of statements in the for ()
4828 */
4829 if (item->u1.for_init)
4830 free(item->u1.for_init);
4831 if (item->u2.for_test)
4832 free(item->u2.for_test);
4833 if (item->u3.for_inc)
4834 free(item->u3.for_inc);
4835 destroy_pval(item->u4.for_statements);
4836 break;
4837
4838 case PV_WHILE:
4839 /* fields: item->u1.str == the while conditional, as supplied by user
4840
4841 item->u2.statements == a pval list of statements in the while ()
4842 */
4843 if (item->u1.str)
4844 free(item->u1.str);
4845 destroy_pval(item->u2.statements);
4846 break;
4847
4848 case PV_BREAK:
4849 /* fields: none
4850 */
4851 break;
4852
4853 case PV_RETURN:
4854 /* fields: none
4855 */
4856 break;
4857
4858 case PV_CONTINUE:
4859 /* fields: none
4860 */
4861 break;
4862
4863 case PV_IFTIME:
4864 /* fields: item->u1.list == the 4 time values, in PV_WORD structs, linked list
4865
4866 item->u2.statements == a pval list of statements in the if ()
4867 item->u3.else_statements == a pval list of statements in the else
4868 (could be zero)
4869 */
4870 destroy_pval(item->u1.list);
4871 destroy_pval(item->u2.statements);
4872 if (item->u3.else_statements) {
4873 destroy_pval(item->u3.else_statements);
4874 }
4875 break;
4876
4877 case PV_RANDOM:
4878 /* fields: item->u1.str == the random percentage, as supplied by user
4879
4880 item->u2.statements == a pval list of statements in the true part ()
4881 item->u3.else_statements == a pval list of statements in the else
4882 (could be zero)
4883 fall thru to If */
4884 case PV_IF:
4885 /* fields: item->u1.str == the if conditional, as supplied by user
4886
4887 item->u2.statements == a pval list of statements in the if ()
4888 item->u3.else_statements == a pval list of statements in the else
4889 (could be zero)
4890 */
4891 if (item->u1.str)
4892 free(item->u1.str);
4893 destroy_pval(item->u2.statements);
4894 if (item->u3.else_statements) {
4895 destroy_pval(item->u3.else_statements);
4896 }
4897 break;
4898
4899 case PV_SWITCH:
4900 /* fields: item->u1.str == the switch expression
4901
4902 item->u2.statements == a pval list of statements in the switch,
4903 (will be case statements, most likely!)
4904 */
4905 if (item->u1.str)
4906 free(item->u1.str);
4907 destroy_pval(item->u2.statements);
4908 break;
4909
4910 case PV_EXTENSION:
4911 /* fields: item->u1.str == the extension name, label, whatever it's called
4912
4913 item->u2.statements == a pval list of statements in the extension
4914 item->u3.hints == a char * hint argument
4915 item->u4.regexten == an int boolean. non-zero says that regexten was specified
4916 */
4917 if (item->u1.str)
4918 free(item->u1.str);
4919 if (item->u3.hints)
4920 free(item->u3.hints);
4921 destroy_pval(item->u2.statements);
4922 break;
4923
4924 case PV_IGNOREPAT:
4925 /* fields: item->u1.str == the ignorepat data
4926 */
4927 if (item->u1.str)
4928 free(item->u1.str);
4929 break;
4930
4931 case PV_GLOBALS:
4932 /* fields: item->u1.statements == pval list of statements, usually vardecs
4933 */
4934 destroy_pval(item->u1.statements);
4935 break;
4936 }
4937 free(item);
4938}
void destroy_pval(pval *item)
Definition: pval.c:4940

References ast_log, destroy_pval(), free(), item, LOG_WARNING, NULL, 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, and aco_type::type.

Referenced by destroy_pval().

◆ extension_matches()

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

Definition at line 694 of file pval.c.

695{
696 int err1;
697 regex_t preg;
698
699 /* simple case, they match exactly, the pattern and exten name */
700 if (strcmp(pattern,exten) == 0)
701 return 1;
702
703 if (pattern[0] == '_') {
704 char reg1[2000];
705 const char *p;
706 char *r = reg1;
707
708 if ( strlen(pattern)*5 >= 2000 ) /* safety valve */ {
709 ast_log(LOG_ERROR,"Error: The pattern %s is way too big. Pattern matching cancelled.\n",
710 pattern);
711 return 0;
712 }
713 /* form a regular expression from the pattern, and then match it against exten */
714 *r++ = '^'; /* what if the extension is a pattern ?? */
715 *r++ = '_'; /* what if the extension is a pattern ?? */
716 *r++ = '?';
717 for (p=pattern+1; *p; p++) {
718 switch ( *p ) {
719 case 'X':
720 *r++ = '[';
721 *r++ = '0';
722 *r++ = '-';
723 *r++ = '9';
724 *r++ = 'X';
725 *r++ = ']';
726 break;
727
728 case 'Z':
729 *r++ = '[';
730 *r++ = '1';
731 *r++ = '-';
732 *r++ = '9';
733 *r++ = 'Z';
734 *r++ = ']';
735 break;
736
737 case 'N':
738 *r++ = '[';
739 *r++ = '2';
740 *r++ = '-';
741 *r++ = '9';
742 *r++ = 'N';
743 *r++ = ']';
744 break;
745
746 case '[':
747 while ( *p && *p != ']' ) {
748 *r++ = *p++;
749 }
750 *r++ = ']';
751 if ( *p != ']') {
752 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The extension pattern '%s' is missing a closing bracket \n",
753 here->filename, here->startline, here->endline, pattern);
754 }
755 break;
756
757 case '.':
758 case '!':
759 *r++ = '.';
760 *r++ = '*';
761 break;
762 case '*': /* regex metacharacter */
763 case '+': /* regex metacharacter */
764 *r++ = '\\';
765 /* fall through */
766 default:
767 *r++ = *p;
768 break;
769
770 }
771 }
772 *r++ = '$'; /* what if the extension is a pattern ?? */
773 *r++ = *p++; /* put in the closing null */
774 err1 = regcomp(&preg, reg1, REG_NOSUB|REG_EXTENDED);
775 if ( err1 ) {
776 char errmess[500];
777 regerror(err1,&preg,errmess,sizeof(errmess));
778 regfree(&preg);
779 ast_log(LOG_WARNING, "Regcomp of %s failed, error code %d\n",
780 reg1, err1);
781 return 0;
782 }
783 err1 = regexec(&preg, exten, 0, 0, 0);
784 regfree(&preg);
785
786 if ( err1 ) {
787 /* ast_log(LOG_NOTICE,"*****************************[%d]Extension %s did not match %s(%s)\n",
788 err1,exten, pattern, reg1); */
789 return 0; /* no match */
790 } else {
791 /* ast_log(LOG_NOTICE,"*****************************Extension %s matched %s\n",
792 exten, pattern); */
793 return 1;
794 }
795 }
796
797 return 0;
798}

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

Referenced by match_pval_item().

◆ find_context()

struct pval * find_context ( char *  name)

Definition at line 1953 of file pval.c.

1954{
1956 count_labels = 0;
1958 match_exten = "*"; /* don't really need to set these, shouldn't be reached */
1959 match_label = "*";
1960 return match_pval(current_db);
1961}
static const char name[]
Definition: format_mp3.c:68
static const char * match_context
Definition: pval.c:76
struct pval * match_pval(pval *item)
Definition: pval.c:1811
static int count_labels
Definition: pval.c:80
static int return_on_context_match
Definition: pval.c:82
static const char * match_label
Definition: pval.c:78
static const char * match_exten
Definition: pval.c:77

References count_labels, current_db, match_context, match_exten, match_label, match_pval(), name, and return_on_context_match.

Referenced by 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().

◆ find_first_label_in_current_context()

struct pval * find_first_label_in_current_context ( char *  label,
pval curr_cont 
)
static

Definition at line 1839 of file pval.c.

1840{
1841 /* printf(" --- Got args %s, %s\n", exten, label); */
1842 struct pval *ret;
1843 struct pval *p3;
1844
1845 count_labels = 0;
1847 match_context = "*";
1848 match_exten = "*";
1849 match_label = label;
1850
1851 ret = match_pval(curr_cont);
1852 if (ret)
1853 return ret;
1854
1855 /* the target of the goto could be in an included context!! Fancy that!! */
1856 /* look for includes in the current context */
1857 for (p3=curr_cont->u2.statements; p3; p3=p3->next) {
1858 if (p3->type == PV_INCLUDES) {
1859 struct pval *p4;
1860 for (p4=p3->u1.list; p4; p4=p4->next) {
1861 /* for each context pointed to, find it, then find a context/label that matches the
1862 target here! */
1863 char *incl_context = p4->u1.str;
1864 /* find a matching context name */
1865 struct pval *that_context = find_context(incl_context);
1866 if (that_context) {
1867 struct pval *x3;
1868 x3 = find_first_label_in_current_context(label, that_context);
1869 if (x3) {
1870 return x3;
1871 }
1872 }
1873 }
1874 }
1875 }
1876 return 0;
1877}

References count_labels, find_context(), find_first_label_in_current_context(), pval::list, match_context, match_exten, match_label, match_pval(), pval::next, PV_INCLUDES, return_on_context_match, pval::statements, pval::str, pval::type, pval::u1, and pval::u2.

Referenced by check_label(), and find_first_label_in_current_context().

◆ find_label_in_current_context()

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

Definition at line 1879 of file pval.c.

1880{
1881 /* printf(" --- Got args %s, %s\n", exten, label); */
1882 struct pval *ret;
1883 struct pval *p3;
1884
1885 count_labels = 0;
1887 match_context = "*";
1888 match_exten = exten;
1889 match_label = label;
1890 ret = match_pval(curr_cont->u2.statements);
1891 if (ret)
1892 return ret;
1893
1894 /* the target of the goto could be in an included context!! Fancy that!! */
1895 /* look for includes in the current context */
1896 for (p3=curr_cont->u2.statements; p3; p3=p3->next) {
1897 if (p3->type == PV_INCLUDES) {
1898 struct pval *p4;
1899 for (p4=p3->u1.list; p4; p4=p4->next) {
1900 /* for each context pointed to, find it, then find a context/label that matches the
1901 target here! */
1902 char *incl_context = p4->u1.str;
1903 /* find a matching context name */
1904 struct pval *that_context = find_context(incl_context);
1905 if (that_context) {
1906 struct pval *x3;
1907 x3 = find_label_in_current_context(exten, label, that_context);
1908 if (x3) {
1909 return x3;
1910 }
1911 }
1912 }
1913 }
1914 }
1915 return 0;
1916}

References count_labels, find_context(), find_label_in_current_context(), pval::list, match_context, match_exten, match_label, match_pval(), pval::next, PV_INCLUDES, return_on_context_match, pval::statements, pval::str, pval::type, pval::u1, and pval::u2.

Referenced by check_goto(), find_label_in_current_context(), and get_goto_target().

◆ find_label_in_current_db()

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

Definition at line 1929 of file pval.c.

1930{
1931 /* printf(" --- Got args %s, %s, %s\n", context, exten, label); */
1932 count_labels = 0;
1934
1936 match_exten = exten;
1937 match_label = label;
1938
1939 return match_pval(current_db);
1940}

References voicemailpwcheck::context, count_labels, current_db, match_context, match_exten, match_label, match_pval(), and return_on_context_match.

Referenced by check_goto(), and get_goto_target().

◆ find_label_in_current_extension()

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

Definition at line 1918 of file pval.c.

1919{
1920 /* printf(" --- Got args %s\n", label); */
1921 count_labels = 0;
1923 match_context = "*";
1924 match_exten = "*";
1925 match_label = label;
1926 return match_pval(curr_ext);
1927}

References count_labels, match_context, match_exten, match_label, match_pval(), and return_on_context_match.

Referenced by check_goto(), and get_goto_target().

◆ find_macro()

struct pval * find_macro ( char *  name)

Definition at line 1943 of file pval.c.

1944{
1946 count_labels = 0;
1948 match_exten = "*"; /* don't really need to set these, shouldn't be reached */
1949 match_label = "*";
1950 return match_pval(current_db);
1951}

References count_labels, current_db, match_context, match_exten, match_label, match_pval(), name, and return_on_context_match.

Referenced by check_pval_item().

◆ find_pval_goto_item()

static void find_pval_goto_item ( pval item,
int  lev 
)
static

Definition at line 1379 of file pval.c.

1380{
1381 struct pval *p4;
1382
1383 if (lev>100) {
1384 ast_log(LOG_ERROR,"find_pval_goto in infinite loop! item_type: %u\n\n", item->type);
1385 return;
1386 }
1387
1388 switch ( item->type ) {
1389 case PV_MACRO:
1390 /* fields: item->u1.str == name of macro
1391 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
1392 item->u2.arglist->u1.str == argument
1393 item->u2.arglist->next == next arg
1394
1395 item->u3.macro_statements == pval list of statements in macro body.
1396 */
1397
1398 /* printf("Descending into macro %s at line %d\n", item->u1.str, item->startline); */
1399 find_pval_gotos(item->u3.macro_statements,lev+1); /* if we're just searching for a context, don't bother descending into them */
1400
1401 break;
1402
1403 case PV_CONTEXT:
1404 /* fields: item->u1.str == name of context
1405 item->u2.statements == pval list of statements in context body
1406 item->u3.abstract == int 1 if an abstract keyword were present
1407 */
1408 break;
1409
1410 case PV_CASE:
1411 /* fields: item->u1.str == value of case
1412 item->u2.statements == pval list of statements under the case
1413 */
1414 /* printf("Descending into Case of %s\n", item->u1.str); */
1415 find_pval_gotos(item->u2.statements,lev+1);
1416 break;
1417
1418 case PV_PATTERN:
1419 /* fields: item->u1.str == value of case
1420 item->u2.statements == pval list of statements under the case
1421 */
1422 /* printf("Descending into Pattern of %s\n", item->u1.str); */
1423 find_pval_gotos(item->u2.statements,lev+1);
1424 break;
1425
1426 case PV_DEFAULT:
1427 /* fields:
1428 item->u2.statements == pval list of statements under the case
1429 */
1430 /* printf("Descending into default\n"); */
1431 find_pval_gotos(item->u2.statements,lev+1);
1432 break;
1433
1434 case PV_CATCH:
1435 /* fields: item->u1.str == name of extension to catch
1436 item->u2.statements == pval list of statements in context body
1437 */
1438 /* printf("Descending into catch of %s\n", item->u1.str); */
1439 find_pval_gotos(item->u2.statements,lev+1);
1440 break;
1441
1442 case PV_STATEMENTBLOCK:
1443 /* fields: item->u1.list == pval list of statements in block, one per entry in the list
1444 */
1445 /* printf("Descending into statement block\n"); */
1446 find_pval_gotos(item->u1.list,lev+1);
1447 break;
1448
1449 case PV_GOTO:
1450 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user.
1451 item->u1.list->u1.str == where the data on a PV_WORD will always be.
1452 */
1453 check_goto(item); /* THE WHOLE FUNCTION OF THIS ENTIRE ROUTINE!!!! */
1454 break;
1455
1456 case PV_INCLUDES:
1457 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
1458 */
1459 for (p4=item->u1.list; p4; p4=p4->next) {
1460 /* for each context pointed to, find it, then find a context/label that matches the
1461 target here! */
1462 char *incl_context = p4->u1.str;
1463 /* find a matching context name */
1464 struct pval *that_context = find_context(incl_context);
1465 if (that_context && that_context->u2.statements) {
1466 /* 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); */
1467 find_pval_gotos(that_context->u2.statements,lev+1); /* keep working up the includes */
1468 }
1469 }
1470 break;
1471
1472 case PV_FOR:
1473 /* fields: item->u1.for_init == a string containing the initializer
1474 item->u2.for_test == a string containing the loop test
1475 item->u3.for_inc == a string containing the loop increment
1476
1477 item->u4.for_statements == a pval list of statements in the for ()
1478 */
1479 /* printf("Descending into for at line %d\n", item->startline); */
1480 find_pval_gotos(item->u4.for_statements,lev+1);
1481 break;
1482
1483 case PV_WHILE:
1484 /* fields: item->u1.str == the while conditional, as supplied by user
1485
1486 item->u2.statements == a pval list of statements in the while ()
1487 */
1488 /* printf("Descending into while at line %d\n", item->startline); */
1489 find_pval_gotos(item->u2.statements,lev+1);
1490 break;
1491
1492 case PV_RANDOM:
1493 /* fields: item->u1.str == the random number expression, as supplied by user
1494
1495 item->u2.statements == a pval list of statements in the if ()
1496 item->u3.else_statements == a pval list of statements in the else
1497 (could be zero)
1498 fall thru to PV_IF */
1499
1500 case PV_IFTIME:
1501 /* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list
1502
1503 item->u2.statements == a pval list of statements in the if ()
1504 item->u3.else_statements == a pval list of statements in the else
1505 (could be zero)
1506 fall thru to PV_IF*/
1507 case PV_IF:
1508 /* fields: item->u1.str == the if conditional, as supplied by user
1509
1510 item->u2.statements == a pval list of statements in the if ()
1511 item->u3.else_statements == a pval list of statements in the else
1512 (could be zero)
1513 */
1514 /* printf("Descending into random/iftime/if at line %d\n", item->startline); */
1515 find_pval_gotos(item->u2.statements,lev+1);
1516
1517 if (item->u3.else_statements) {
1518 /* printf("Descending into random/iftime/if's ELSE at line %d\n", item->startline); */
1519 find_pval_gotos(item->u3.else_statements,lev+1);
1520 }
1521 break;
1522
1523 case PV_SWITCH:
1524 /* fields: item->u1.str == the switch expression
1525
1526 item->u2.statements == a pval list of statements in the switch,
1527 (will be case statements, most likely!)
1528 */
1529 /* printf("Descending into switch at line %d\n", item->startline); */
1530 find_pval_gotos(item->u3.else_statements,lev+1);
1531 break;
1532
1533 case PV_EXTENSION:
1534 /* fields: item->u1.str == the extension name, label, whatever it's called
1535
1536 item->u2.statements == a pval list of statements in the extension
1537 item->u3.hints == a char * hint argument
1538 item->u4.regexten == an int boolean. non-zero says that regexten was specified
1539 */
1540
1541 /* printf("Descending into extension %s at line %d\n", item->u1.str, item->startline); */
1542 find_pval_gotos(item->u2.statements,lev+1);
1543 break;
1544
1545 default:
1546 break;
1547 }
1548}

References ast_log, check_goto(), find_context(), find_pval_gotos(), item, LOG_ERROR, 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, aco_type::type, pval::u1, and pval::u2.

Referenced by find_pval_gotos().

◆ find_pval_gotos()

static void find_pval_gotos ( pval item,
int  lev 
)
static

Definition at line 1550 of file pval.c.

1551{
1552 pval *i;
1553
1554 for (i=item; i; i=i->next) {
1555 /* printf("About to call pval_goto_item, itemcount=%d, itemtype=%d\n", item_count, i->type); */
1556 find_pval_goto_item(i, lev);
1557 }
1558}
static void find_pval_goto_item(pval *item, int lev)
Definition: pval.c:1379

References find_pval_goto_item(), item, and pval::next.

Referenced by check_pval_item(), and find_pval_goto_item().

◆ find_switch_item()

int find_switch_item ( pval item)

Definition at line 3090 of file pval.c.

3091{
3092 switch ( item->type ) {
3093 case PV_LOCALVARDEC:
3094 /* fields: item->u1.str == string associated with this (word). */
3095 break;
3096
3097 case PV_WORD:
3098 /* fields: item->u1.str == string associated with this (word). */
3099 break;
3100
3101 case PV_MACRO:
3102 /* fields: item->u1.str == name of macro
3103 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
3104 item->u2.arglist->u1.str == argument
3105 item->u2.arglist->next == next arg
3106
3107 item->u3.macro_statements == pval list of statements in macro body.
3108 */
3109 /* had better not see this */
3110 if (contains_switch(item->u3.macro_statements))
3111 return 1;
3112 break;
3113
3114 case PV_CONTEXT:
3115 /* fields: item->u1.str == name of context
3116 item->u2.statements == pval list of statements in context body
3117 item->u3.abstract == int 1 if an abstract keyword were present
3118 */
3119 /* had better not see this */
3120 if (contains_switch(item->u2.statements))
3121 return 1;
3122 break;
3123
3124 case PV_MACRO_CALL:
3125 /* fields: item->u1.str == name of macro to call
3126 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
3127 item->u2.arglist->u1.str == argument
3128 item->u2.arglist->next == next arg
3129 */
3130 break;
3131
3133 /* fields: item->u1.str == name of application to call
3134 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
3135 item->u2.arglist->u1.str == argument
3136 item->u2.arglist->next == next arg
3137 */
3138 break;
3139
3140 case PV_CASE:
3141 /* fields: item->u1.str == value of case
3142 item->u2.statements == pval list of statements under the case
3143 */
3144 /* had better not see this */
3145 if (contains_switch(item->u2.statements))
3146 return 1;
3147 break;
3148
3149 case PV_PATTERN:
3150 /* fields: item->u1.str == value of case
3151 item->u2.statements == pval list of statements under the case
3152 */
3153 /* had better not see this */
3154 if (contains_switch(item->u2.statements))
3155 return 1;
3156 break;
3157
3158 case PV_DEFAULT:
3159 /* fields:
3160 item->u2.statements == pval list of statements under the case
3161 */
3162 /* had better not see this */
3163 if (contains_switch(item->u2.statements))
3164 return 1;
3165 break;
3166
3167 case PV_CATCH:
3168 /* fields: item->u1.str == name of extension to catch
3169 item->u2.statements == pval list of statements in context body
3170 */
3171 /* had better not see this */
3172 if (contains_switch(item->u2.statements))
3173 return 1;
3174 break;
3175
3176 case PV_SWITCHES:
3177 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
3178 */
3179 break;
3180
3181 case PV_ESWITCHES:
3182 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
3183 */
3184 break;
3185
3186 case PV_INCLUDES:
3187 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
3188 item->u2.arglist == pval list of 4 PV_WORD elements for time values
3189 */
3190 break;
3191
3192 case PV_STATEMENTBLOCK:
3193 /* fields: item->u1.list == pval list of statements in block, one per entry in the list
3194 */
3195 if (contains_switch(item->u1.list) )
3196 return 1;
3197 break;
3198
3199 case PV_VARDEC:
3200 /* fields: item->u1.str == variable name
3201 item->u2.val == variable value to assign
3202 */
3203 break;
3204
3205 case PV_GOTO:
3206 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user.
3207 item->u1.list->u1.str == where the data on a PV_WORD will always be.
3208 */
3209 break;
3210
3211 case PV_LABEL:
3212 /* fields: item->u1.str == label name
3213 */
3214 break;
3215
3216 case PV_FOR:
3217 /* fields: item->u1.for_init == a string containing the initializer
3218 item->u2.for_test == a string containing the loop test
3219 item->u3.for_inc == a string containing the loop increment
3220
3221 item->u4.for_statements == a pval list of statements in the for ()
3222 */
3223 if (contains_switch(item->u4.for_statements))
3224 return 1;
3225 break;
3226
3227 case PV_WHILE:
3228 /* fields: item->u1.str == the while conditional, as supplied by user
3229
3230 item->u2.statements == a pval list of statements in the while ()
3231 */
3232 if (contains_switch(item->u2.statements))
3233 return 1;
3234 break;
3235
3236 case PV_BREAK:
3237 /* fields: none
3238 */
3239 break;
3240
3241 case PV_RETURN:
3242 /* fields: none
3243 */
3244 break;
3245
3246 case PV_CONTINUE:
3247 /* fields: none
3248 */
3249 break;
3250
3251 case PV_IFTIME:
3252 /* fields: item->u1.list == there are 4 linked PV_WORDs here.
3253
3254 item->u2.statements == a pval list of statements in the if ()
3255 item->u3.else_statements == a pval list of statements in the else
3256 (could be zero)
3257 */
3258 if (contains_switch(item->u2.statements))
3259 return 1;
3260 if ( item->u3.else_statements ) {
3261 if (contains_switch(item->u3.else_statements))
3262 return 1;
3263 }
3264 break;
3265
3266 case PV_RANDOM:
3267 /* fields: item->u1.str == the random number expression, as supplied by user
3268
3269 item->u2.statements == a pval list of statements in the if ()
3270 item->u3.else_statements == a pval list of statements in the else
3271 (could be zero)
3272 */
3273 if (contains_switch(item->u2.statements))
3274 return 1;
3275 if ( item->u3.else_statements ) {
3276 if (contains_switch(item->u3.else_statements))
3277 return 1;
3278 }
3279 break;
3280
3281 case PV_IF:
3282 /* fields: item->u1.str == the if conditional, as supplied by user
3283
3284 item->u2.statements == a pval list of statements in the if ()
3285 item->u3.else_statements == a pval list of statements in the else
3286 (could be zero)
3287 */
3288 if (contains_switch(item->u2.statements))
3289 return 1;
3290 if ( item->u3.else_statements ) {
3291 if (contains_switch(item->u3.else_statements))
3292 return 1;
3293 }
3294 break;
3295
3296 case PV_SWITCH:
3297 /* fields: item->u1.str == the switch expression
3298
3299 item->u2.statements == a pval list of statements in the switch,
3300 (will be case statements, most likely!)
3301 */
3302 return 1; /* JACKPOT */
3303 break;
3304
3305 case PV_EXTENSION:
3306 /* fields: item->u1.str == the extension name, label, whatever it's called
3307
3308 item->u2.statements == a pval list of statements in the extension
3309 item->u3.hints == a char * hint argument
3310 item->u4.regexten == an int boolean. non-zero says that regexten was specified
3311 */
3312 if (contains_switch(item->u2.statements))
3313 return 1;
3314 break;
3315
3316 case PV_IGNOREPAT:
3317 /* fields: item->u1.str == the ignorepat data
3318 */
3319 break;
3320
3321 case PV_GLOBALS:
3322 /* fields: item->u1.statements == pval list of statements, usually vardecs
3323 */
3324 break;
3325 }
3326 return 0;
3327}
int contains_switch(pval *item)
Definition: pval.c:3329

References contains_switch(), item, 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, and aco_type::type.

Referenced by contains_switch().

◆ fix_gotos_in_extensions()

static void fix_gotos_in_extensions ( struct ael_extension exten)
static

Definition at line 4355 of file pval.c.

4356{
4357 struct ael_extension *e;
4358 for(e=exten;e;e=e->next_exten) {
4359
4360 struct ael_priority *p;
4361 for(p=e->plist;p;p=p->next) {
4362
4363 if( p->origin && p->origin->type == PV_GOTO && p->origin->u3.goto_target_in_case ) {
4364
4365 /* fix the extension of the goto target to the actual extension in the post-compiled dialplan */
4366
4367 pval *target = p->origin->u2.goto_target;
4368 struct ael_extension *z = target->u3.compiled_label;
4369 pval *pv2 = p->origin;
4370 char buf1[500];
4371 char *apparg_save = p->appargs;
4372
4373 p->appargs = 0;
4374 if (!pv2->u1.list->next) /* just one -- it won't hurt to repeat the extension */ {
4375 snprintf(buf1,sizeof(buf1),"%s,%s", z->name, pv2->u1.list->u1.str);
4376 p->appargs = strdup(buf1);
4377
4378 } else if (pv2->u1.list->next && !pv2->u1.list->next->next) /* two */ {
4379 snprintf(buf1,sizeof(buf1),"%s,%s", z->name, pv2->u1.list->next->u1.str);
4380 p->appargs = strdup(buf1);
4381 } else if (pv2->u1.list->next && pv2->u1.list->next->next) {
4382 snprintf(buf1,sizeof(buf1),"%s,%s,%s", pv2->u1.list->u1.str,
4383 z->name,
4384 pv2->u1.list->next->next->u1.str);
4385 p->appargs = strdup(buf1);
4386 }
4387 else
4388 printf("WHAT? The goto doesn't fall into one of three cases for GOTO????\n");
4389
4390 if( apparg_save ) {
4391 free(apparg_save);
4392 }
4393 }
4394 }
4395 }
4396}
static struct ast_threadstorage buf1
int goto_target_in_case
Definition: pval.h:82
struct pval * goto_target
Definition: pval.h:72
struct ael_extension * compiled_label
Definition: pval.h:83

References ael_priority::appargs, buf1, pval::compiled_label, free(), pval::goto_target, pval::goto_target_in_case, pval::list, ael_extension::name, ael_priority::next, pval::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().

◆ gen_match_to_pattern()

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

Definition at line 3061 of file pval.c.

3062{
3063 /* the result will be a string that will be matched by pattern */
3064 char *p=pattern, *t=result;
3065 while (*p) {
3066 if (*p == 'x' || *p == 'n' || *p == 'z' || *p == 'X' || *p == 'N' || *p == 'Z')
3067 *t++ = '9';
3068 else if (*p == '[') {
3069 char *z = p+1;
3070 while (*z != ']')
3071 z++;
3072 if (*(z+1)== ']')
3073 z++;
3074 *t++=*(p+1); /* use the first char in the set */
3075 p = z;
3076 } else {
3077 *t++ = *p;
3078 }
3079 p++;
3080 }
3081 *t++ = 0; /* cap it off */
3082}
static PGresult * result
Definition: cel_pgsql.c:84

References result.

Referenced by gen_prios().

◆ gen_prios()

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

3342{
3343 pval *p,*p2,*p3;
3344 struct ael_priority *pr;
3345 struct ael_priority *for_init, *for_test, *for_inc, *for_loop, *for_end;
3346 struct ael_priority *while_test, *while_loop, *while_end;
3347 struct ael_priority *switch_set, *switch_test, *switch_end, *fall_thru, *switch_empty;
3348 struct ael_priority *if_test, *if_end, *if_skip, *if_false;
3349#ifdef OLD_RAND_ACTION
3350 struct ael_priority *rand_test, *rand_end, *rand_skip;
3351#endif
3352 RAII_VAR(char *, buf1, NULL, free);
3353 RAII_VAR(char *, buf2, NULL, free);
3354 RAII_VAR(char *, new_label, NULL, free);
3355 char *strp, *strp2;
3356 int default_exists;
3357 int local_control_statement_count;
3358 int first;
3359 struct ael_priority *loop_break_save;
3360 struct ael_priority *loop_continue_save;
3361 struct ael_extension *switch_case,*switch_null;
3362
3363 if (!(buf1 = malloc(BUF_SIZE))) {
3364 return -1;
3365 }
3366 if (!(buf2 = malloc(BUF_SIZE))) {
3367 return -1;
3368 }
3369 if (!(new_label = malloc(BUF_SIZE))) {
3370 return -1;
3371 }
3372
3373 if ((mother_exten && !mother_exten->checked_switch) || (exten && !exten->checked_switch)) {
3374 if (contains_switch(statement)) { /* only run contains_switch if you haven't checked before */
3375 if (mother_exten) {
3376 if (!mother_exten->has_switch) {
3377 for (first = 1; first >= 0; first--) {
3378 switch_set = new_prio();
3379 switch_set->type = AEL_APPCALL;
3380 switch_set->app = strdup("MSet");
3381 /* Are we likely inside a gosub subroutine? */
3382 if (!strcmp(mother_exten->name, "~~s~~") && first) {
3383 /* If we're not actually within a gosub, this will fail, but the
3384 * second time through, it will get set. If we are within gosub,
3385 * the second time through is redundant, but acceptable. */
3386 switch_set->appargs = strdup("LOCAL(~~EXTEN~~)=${EXTEN}");
3387 } else {
3388 switch_set->appargs = strdup("~~EXTEN~~=${EXTEN}");
3389 first = 0;
3390 }
3391 linkprio(exten, switch_set, mother_exten);
3392 mother_exten->has_switch = 1;
3393 mother_exten->checked_switch = 1;
3394 if (exten) {
3395 exten->has_switch = 1;
3396 exten->checked_switch = 1;
3397 }
3398 }
3399 }
3400 } else if (exten) {
3401 if (!exten->has_switch) {
3402 for (first = 1; first >= 0; first--) {
3403 switch_set = new_prio();
3404 switch_set->type = AEL_APPCALL;
3405 switch_set->app = strdup("MSet");
3406 /* Are we likely inside a gosub subroutine? */
3407 if (!strcmp(exten->name, "~~s~~")) {
3408 /* If we're not actually within a gosub, this will fail, but the
3409 * second time through, it will get set. If we are within gosub,
3410 * the second time through is redundant, but acceptable. */
3411 switch_set->appargs = strdup("LOCAL(~~EXTEN~~)=${EXTEN}");
3412 } else {
3413 switch_set->appargs = strdup("~~EXTEN~~=${EXTEN}");
3414 first = 0;
3415 }
3416 linkprio(exten, switch_set, mother_exten);
3417 exten->has_switch = 1;
3418 exten->checked_switch = 1;
3419 if (mother_exten) {
3420 mother_exten->has_switch = 1;
3421 mother_exten->checked_switch = 1;
3422 }
3423 }
3424 }
3425 }
3426 } else {
3427 if (mother_exten) {
3428 mother_exten->checked_switch = 1;
3429 }
3430 if (exten) {
3431 exten->checked_switch = 1;
3432 }
3433 }
3434 }
3435 for (p=statement; p; p=p->next) {
3436 switch (p->type) {
3437 case PV_VARDEC:
3438 pr = new_prio();
3439 pr->type = AEL_APPCALL;
3440 snprintf(buf1, BUF_SIZE, "%s=$[%s]", p->u1.str, p->u2.val);
3441 pr->app = strdup("MSet");
3443 pr->appargs = strdup(buf1);
3444 pr->origin = p;
3445 linkprio(exten, pr, mother_exten);
3446 break;
3447
3448 case PV_LOCALVARDEC:
3449 pr = new_prio();
3450 pr->type = AEL_APPCALL;
3451 snprintf(buf1, BUF_SIZE, "LOCAL(%s)=$[%s]", p->u1.str, p->u2.val);
3452 pr->app = strdup("MSet");
3454 pr->appargs = strdup(buf1);
3455 pr->origin = p;
3456 linkprio(exten, pr, mother_exten);
3457 break;
3458
3459 case PV_GOTO:
3460 pr = new_prio();
3461 pr->type = AEL_APPCALL;
3463 if( p->u2.goto_target ) {
3465 }
3466
3467 if (!p->u1.list->next) /* just one */ {
3468 pr->app = strdup("Goto");
3469 if (!mother_exten)
3470 pr->appargs = strdup(p->u1.list->u1.str);
3471 else { /* for the case of simple within-extension gotos in case/pattern/default statement blocks: */
3472 snprintf(buf1, BUF_SIZE, "%s,%s", mother_exten->name, p->u1.list->u1.str);
3473 pr->appargs = strdup(buf1);
3474 }
3475
3476 } else if (p->u1.list->next && !p->u1.list->next->next) /* two */ {
3477 snprintf(buf1, BUF_SIZE, "%s,%s", p->u1.list->u1.str, p->u1.list->next->u1.str);
3478 pr->app = strdup("Goto");
3479 pr->appargs = strdup(buf1);
3480 } else if (p->u1.list->next && p->u1.list->next->next) {
3481 snprintf(buf1, BUF_SIZE, "%s,%s,%s", p->u1.list->u1.str,
3482 p->u1.list->next->u1.str,
3483 p->u1.list->next->next->u1.str);
3484 pr->app = strdup("Goto");
3485 pr->appargs = strdup(buf1);
3486 }
3487 pr->origin = p;
3488 linkprio(exten, pr, mother_exten);
3489 break;
3490
3491 case PV_LABEL:
3492 pr = new_prio();
3493 pr->type = AEL_LABEL;
3494 pr->origin = p;
3495 p->u3.compiled_label = exten;
3496 linkprio(exten, pr, mother_exten);
3497 break;
3498
3499 case PV_FOR:
3501 loop_break_save = exten->loop_break; /* save them, then restore before leaving */
3502 loop_continue_save = exten->loop_continue;
3503 snprintf(new_label, BUF_SIZE, "for_%s_%d", label, control_statement_count);
3504 for_init = new_prio();
3505 for_inc = new_prio();
3506 for_test = new_prio();
3507 for_loop = new_prio();
3508 for_end = new_prio();
3509 for_init->type = AEL_APPCALL;
3510 for_inc->type = AEL_APPCALL;
3511 for_test->type = AEL_FOR_CONTROL;
3512 for_test->goto_false = for_end;
3513 for_loop->type = AEL_CONTROL1; /* simple goto */
3514 for_end->type = AEL_APPCALL;
3515 for_init->app = strdup("MSet");
3516
3517 strcpy(buf2,p->u1.for_init);
3519 strp = strchr(buf2, '=');
3520 if (strp) {
3521 strp2 = strchr(p->u1.for_init, '=');
3522 *(strp+1) = 0;
3523 strcat(buf2,"$[");
3524 strncat(buf2,strp2+1, BUF_SIZE-strlen(strp2+1)-2);
3525 strcat(buf2,"]");
3526 for_init->appargs = strdup(buf2);
3527 } else {
3528 strp2 = p->u1.for_init;
3529 while (*strp2 && isspace(*strp2))
3530 strp2++;
3531 if (*strp2 == '&') { /* itsa macro call */
3532 char *strp3 = strp2+1;
3533 while (*strp3 && isspace(*strp3))
3534 strp3++;
3535 strcpy(buf2, strp3);
3536 strp3 = strchr(buf2,'(');
3537 if (strp3) {
3538 *strp3 = ',';
3539 }
3540 strp3 = strrchr(buf2, ')');
3541 if (strp3)
3542 *strp3 = 0; /* remove the closing paren */
3543 for_init->appargs = strdup(buf2);
3544 free(for_init->app);
3545 for_init->app = strdup("Gosub");
3546 } else { /* must be a regular app call */
3547 char *strp3;
3548 strcpy(buf2, strp2);
3549 strp3 = strchr(buf2,'(');
3550 if (strp3) {
3551 *strp3 = 0;
3552 free(for_init->app);
3553 for_init->app = strdup(buf2);
3554 for_init->appargs = strdup(strp3+1);
3555 strp3 = strrchr(for_init->appargs, ')');
3556 if (strp3)
3557 *strp3 = 0; /* remove the closing paren */
3558 }
3559 }
3560 }
3561
3562 strcpy(buf2,p->u3.for_inc);
3564 strp = strchr(buf2, '=');
3565 if (strp) { /* there's an = in this part; that means an assignment. set it up */
3566 strp2 = strchr(p->u3.for_inc, '=');
3567 *(strp+1) = 0;
3568 strcat(buf2,"$[");
3569 strncat(buf2,strp2+1, BUF_SIZE-strlen(strp2+1)-2);
3570 strcat(buf2,"]");
3571 for_inc->appargs = strdup(buf2);
3572 for_inc->app = strdup("MSet");
3573 } else {
3574 strp2 = p->u3.for_inc;
3575 while (*strp2 && isspace(*strp2))
3576 strp2++;
3577 if (*strp2 == '&') { /* itsa macro call */
3578 char *strp3 = strp2+1;
3579 while (*strp3 && isspace(*strp3))
3580 strp3++;
3581 strcpy(buf2, strp3);
3582 strp3 = strchr(buf2,'(');
3583 if (strp3) {
3584 *strp3 = ',';
3585 }
3586 strp3 = strrchr(buf2, ')');
3587 if (strp3)
3588 *strp3 = 0; /* remove the closing paren */
3589
3590 for_inc->appargs = strdup(buf2);
3591
3592 for_inc->app = strdup("Gosub");
3593 } else { /* must be a regular app call */
3594 char *strp3;
3595 strcpy(buf2, strp2);
3596 strp3 = strchr(buf2,'(');
3597 if (strp3) {
3598 *strp3 = 0;
3599 for_inc->app = strdup(buf2);
3600 for_inc->appargs = strdup(strp3+1);
3601 strp3 = strrchr(for_inc->appargs, ')');
3602 if (strp3)
3603 *strp3 = 0; /* remove the closing paren */
3604 }
3605 }
3606 }
3607 snprintf(buf1, BUF_SIZE, "$[%s]",p->u2.for_test);
3608 for_test->app = 0;
3609 for_test->appargs = strdup(buf1);
3610 for_loop->goto_true = for_test;
3611 snprintf(buf1, BUF_SIZE, "Finish for_%s_%d", label, control_statement_count);
3612 for_end->app = strdup("NoOp");
3613 for_end->appargs = strdup(buf1);
3614 /* link & load! */
3615 linkprio(exten, for_init, mother_exten);
3616 linkprio(exten, for_test, mother_exten);
3617
3618 /* now, put the body of the for loop here */
3619 exten->loop_break = for_end;
3620 exten->loop_continue = for_inc;
3621
3622 if (gen_prios(exten, new_label, p->u4.for_statements, mother_exten, this_context)) { /* this will link in all the statements here */
3623 return -1;
3624 }
3625
3626 linkprio(exten, for_inc, mother_exten);
3627 linkprio(exten, for_loop, mother_exten);
3628 linkprio(exten, for_end, mother_exten);
3629
3630
3631 exten->loop_break = loop_break_save;
3632 exten->loop_continue = loop_continue_save;
3633 for_loop->origin = p;
3634 break;
3635
3636 case PV_WHILE:
3638 loop_break_save = exten->loop_break; /* save them, then restore before leaving */
3639 loop_continue_save = exten->loop_continue;
3640 snprintf(new_label, BUF_SIZE, "while_%s_%d", label, control_statement_count);
3641 while_test = new_prio();
3642 while_loop = new_prio();
3643 while_end = new_prio();
3644 while_test->type = AEL_FOR_CONTROL;
3645 while_test->goto_false = while_end;
3646 while_loop->type = AEL_CONTROL1; /* simple goto */
3647 while_end->type = AEL_APPCALL;
3648 snprintf(buf1, BUF_SIZE, "$[%s]",p->u1.str);
3649 while_test->app = 0;
3650 while_test->appargs = strdup(buf1);
3651 while_loop->goto_true = while_test;
3652 snprintf(buf1, BUF_SIZE, "Finish while_%s_%d", label, control_statement_count);
3653 while_end->app = strdup("NoOp");
3654 while_end->appargs = strdup(buf1);
3655
3656 linkprio(exten, while_test, mother_exten);
3657
3658 /* now, put the body of the for loop here */
3659 exten->loop_break = while_end;
3660 exten->loop_continue = while_test;
3661
3662 if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the while body statements here */
3663 return -1;
3664 }
3665
3666 linkprio(exten, while_loop, mother_exten);
3667 linkprio(exten, while_end, mother_exten);
3668
3669
3670 exten->loop_break = loop_break_save;
3671 exten->loop_continue = loop_continue_save;
3672 while_loop->origin = p;
3673 break;
3674
3675 case PV_SWITCH:
3677 local_control_statement_count = control_statement_count;
3678 loop_break_save = exten->loop_break; /* save them, then restore before leaving */
3679 loop_continue_save = exten->loop_continue;
3680 snprintf(new_label, BUF_SIZE, "sw_%s_%d", label, control_statement_count);
3681 switch_test = new_prio();
3682 switch_end = new_prio();
3683 switch_test->type = AEL_APPCALL;
3684 switch_end->type = AEL_APPCALL;
3685 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", control_statement_count, p->u1.str);
3686 switch_test->app = strdup("Goto");
3687 switch_test->appargs = strdup(buf1);
3688 snprintf(buf1, BUF_SIZE, "Finish switch_%s_%d", label, control_statement_count);
3689 switch_end->app = strdup("NoOp");
3690 switch_end->appargs = strdup(buf1);
3691 switch_end->origin = p;
3692 switch_end->exten = exten;
3693
3694 linkprio(exten, switch_test, mother_exten);
3695 linkprio(exten, switch_end, mother_exten);
3696
3697 exten->loop_break = switch_end;
3698 exten->loop_continue = 0;
3699 default_exists = 0;
3700
3701 for (p2=p->u2.statements; p2; p2=p2->next) {
3702 /* now, for each case/default put the body of the for loop here */
3703 if (p2->type == PV_CASE) {
3704 /* ok, generate a extension and link it in */
3705 switch_case = new_exten();
3706 if (mother_exten && mother_exten->checked_switch) {
3707 switch_case->has_switch = mother_exten->has_switch;
3708 switch_case->checked_switch = mother_exten->checked_switch;
3709 }
3710 if (exten && exten->checked_switch) {
3711 switch_case->has_switch = exten->has_switch;
3712 switch_case->checked_switch = exten->checked_switch;
3713 }
3714 switch_case->context = this_context;
3715 switch_case->is_switch = 1;
3716 /* the break/continue locations are inherited from parent */
3717 switch_case->loop_break = exten->loop_break;
3718 switch_case->loop_continue = exten->loop_continue;
3719
3720 linkexten(exten,switch_case);
3721 snprintf(buf1, BUF_SIZE, "sw_%d_%s", local_control_statement_count, p2->u1.str);
3722 switch_case->name = strdup(buf1);
3723 snprintf(new_label, BUF_SIZE, "sw_%s_%s_%d", label, p2->u1.str, local_control_statement_count);
3724
3725 if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the case body statements here */
3726 return -1;
3727 }
3728
3729 /* here is where we write code to "fall thru" to the next case... if there is one... */
3730 for (p3=p2->u2.statements; p3; p3=p3->next) {
3731 if (!p3->next)
3732 break;
3733 }
3734 /* p3 now points the last statement... */
3735 if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN) ) {
3736 /* is there a following CASE/PATTERN/DEFAULT? */
3737 if (p2->next && p2->next->type == PV_CASE) {
3738 fall_thru = new_prio();
3739 fall_thru->type = AEL_APPCALL;
3740 fall_thru->app = strdup("Goto");
3741 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, p2->next->u1.str);
3742 fall_thru->appargs = strdup(buf1);
3743 linkprio(switch_case, fall_thru, mother_exten);
3744 } else if (p2->next && p2->next->type == PV_PATTERN) {
3745 fall_thru = new_prio();
3746 fall_thru->type = AEL_APPCALL;
3747 fall_thru->app = strdup("Goto");
3749 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, buf2);
3750 fall_thru->appargs = strdup(buf1);
3751 linkprio(switch_case, fall_thru, mother_exten);
3752 } else if (p2->next && p2->next->type == PV_DEFAULT) {
3753 fall_thru = new_prio();
3754 fall_thru->type = AEL_APPCALL;
3755 fall_thru->app = strdup("Goto");
3756 snprintf(buf1, BUF_SIZE, "sw_%d_.,10", local_control_statement_count);
3757 fall_thru->appargs = strdup(buf1);
3758 linkprio(switch_case, fall_thru, mother_exten);
3759 } else if (!p2->next) {
3760 fall_thru = new_prio();
3761 fall_thru->type = AEL_CONTROL1;
3762 fall_thru->goto_true = switch_end;
3763 fall_thru->app = strdup("Goto");
3764 linkprio(switch_case, fall_thru, mother_exten);
3765 }
3766 }
3767 if (switch_case->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */
3768 char buf[2000];
3769 struct ael_priority *np2 = new_prio();
3770 np2->type = AEL_APPCALL;
3771 np2->app = strdup("NoOp");
3772 snprintf(buf, BUF_SIZE, "End of Extension %s", switch_case->name);
3773 np2->appargs = strdup(buf);
3774 linkprio(switch_case, np2, mother_exten);
3775 switch_case-> return_target = np2;
3776 }
3777 } else if (p2->type == PV_PATTERN) {
3778 /* ok, generate a extension and link it in */
3779 switch_case = new_exten();
3780 if (mother_exten && mother_exten->checked_switch) {
3781 switch_case->has_switch = mother_exten->has_switch;
3782 switch_case->checked_switch = mother_exten->checked_switch;
3783 }
3784 if (exten && exten->checked_switch) {
3785 switch_case->has_switch = exten->has_switch;
3786 switch_case->checked_switch = exten->checked_switch;
3787 }
3788 switch_case->context = this_context;
3789 switch_case->is_switch = 1;
3790 /* the break/continue locations are inherited from parent */
3791 switch_case->loop_break = exten->loop_break;
3792 switch_case->loop_continue = exten->loop_continue;
3793
3794 linkexten(exten,switch_case);
3795 snprintf(buf1, BUF_SIZE, "_sw_%d_%s", local_control_statement_count, p2->u1.str);
3796 switch_case->name = strdup(buf1);
3797 snprintf(new_label, BUF_SIZE, "sw_%s_%s_%d", label, p2->u1.str, local_control_statement_count);
3798
3799 if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the while body statements here */
3800 return -1;
3801 }
3802 /* here is where we write code to "fall thru" to the next case... if there is one... */
3803 for (p3=p2->u2.statements; p3; p3=p3->next) {
3804 if (!p3->next)
3805 break;
3806 }
3807 /* p3 now points the last statement... */
3808 if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) {
3809 /* is there a following CASE/PATTERN/DEFAULT? */
3810 if (p2->next && p2->next->type == PV_CASE) {
3811 fall_thru = new_prio();
3812 fall_thru->type = AEL_APPCALL;
3813 fall_thru->app = strdup("Goto");
3814 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, p2->next->u1.str);
3815 fall_thru->appargs = strdup(buf1);
3816 linkprio(switch_case, fall_thru, mother_exten);
3817 } else if (p2->next && p2->next->type == PV_PATTERN) {
3818 fall_thru = new_prio();
3819 fall_thru->type = AEL_APPCALL;
3820 fall_thru->app = strdup("Goto");
3822 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, buf2);
3823 fall_thru->appargs = strdup(buf1);
3824 linkprio(switch_case, fall_thru, mother_exten);
3825 } else if (p2->next && p2->next->type == PV_DEFAULT) {
3826 fall_thru = new_prio();
3827 fall_thru->type = AEL_APPCALL;
3828 fall_thru->app = strdup("Goto");
3829 snprintf(buf1, BUF_SIZE, "sw_%d_.,10", local_control_statement_count);
3830 fall_thru->appargs = strdup(buf1);
3831 linkprio(switch_case, fall_thru, mother_exten);
3832 } else if (!p2->next) {
3833 fall_thru = new_prio();
3834 fall_thru->type = AEL_CONTROL1;
3835 fall_thru->goto_true = switch_end;
3836 fall_thru->app = strdup("Goto");
3837 linkprio(switch_case, fall_thru, mother_exten);
3838 }
3839 }
3840 if (switch_case->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */
3841 char buf[2000];
3842 struct ael_priority *np2 = new_prio();
3843 np2->type = AEL_APPCALL;
3844 np2->app = strdup("NoOp");
3845 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name);
3846 np2->appargs = strdup(buf);
3847 linkprio(switch_case, np2, mother_exten);
3848 switch_case-> return_target = np2;
3849 }
3850 } else if (p2->type == PV_DEFAULT) {
3851 /* ok, generate a extension and link it in */
3852 switch_case = new_exten();
3853 if (mother_exten && mother_exten->checked_switch) {
3854 switch_case->has_switch = mother_exten->has_switch;
3855 switch_case->checked_switch = mother_exten->checked_switch;
3856 }
3857 if (exten && exten->checked_switch) {
3858 switch_case->has_switch = exten->has_switch;
3859 switch_case->checked_switch = exten->checked_switch;
3860 }
3861 switch_case->context = this_context;
3862 switch_case->is_switch = 1;
3863
3864 /* new: the default case intros a pattern with ., which covers ALMOST everything.
3865 but it doesn't cover a NULL pattern. So, we'll define a null extension to match
3866 that goto's the default extension. */
3867
3868 default_exists++;
3869 switch_null = new_exten();
3870 if (mother_exten && mother_exten->checked_switch) {
3871 switch_null->has_switch = mother_exten->has_switch;
3872 switch_null->checked_switch = mother_exten->checked_switch;
3873 }
3874 if (exten && exten->checked_switch) {
3875 switch_null->has_switch = exten->has_switch;
3876 switch_null->checked_switch = exten->checked_switch;
3877 }
3878 switch_null->context = this_context;
3879 switch_null->is_switch = 1;
3880 switch_empty = new_prio();
3881 snprintf(buf1, BUF_SIZE, "sw_%d_.,10", local_control_statement_count);
3882 switch_empty->app = strdup("Goto");
3883 switch_empty->appargs = strdup(buf1);
3884 linkprio(switch_null, switch_empty, mother_exten);
3885 snprintf(buf1, BUF_SIZE, "sw_%d_", local_control_statement_count);
3886 switch_null->name = strdup(buf1);
3887 switch_null->loop_break = exten->loop_break;
3888 switch_null->loop_continue = exten->loop_continue;
3889 linkexten(exten,switch_null);
3890
3891 /* the break/continue locations are inherited from parent */
3892 switch_case->loop_break = exten->loop_break;
3893 switch_case->loop_continue = exten->loop_continue;
3894 linkexten(exten,switch_case);
3895 snprintf(buf1, BUF_SIZE, "_sw_%d_.", local_control_statement_count);
3896 switch_case->name = strdup(buf1);
3897
3898 snprintf(new_label, BUF_SIZE, "sw_%s_default_%d", label, local_control_statement_count);
3899
3900 if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the default: body statements here */
3901 return -1;
3902 }
3903
3904 /* here is where we write code to "fall thru" to the next case... if there is one... */
3905 for (p3=p2->u2.statements; p3; p3=p3->next) {
3906 if (!p3->next)
3907 break;
3908 }
3909 /* p3 now points the last statement... */
3910 if (!p3 || (p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) {
3911 /* is there a following CASE/PATTERN/DEFAULT? */
3912 if (p2->next && p2->next->type == PV_CASE) {
3913 fall_thru = new_prio();
3914 fall_thru->type = AEL_APPCALL;
3915 fall_thru->app = strdup("Goto");
3916 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, p2->next->u1.str);
3917 fall_thru->appargs = strdup(buf1);
3918 linkprio(switch_case, fall_thru, mother_exten);
3919 } else if (p2->next && p2->next->type == PV_PATTERN) {
3920 fall_thru = new_prio();
3921 fall_thru->type = AEL_APPCALL;
3922 fall_thru->app = strdup("Goto");
3924 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, buf2);
3925 fall_thru->appargs = strdup(buf1);
3926 linkprio(switch_case, fall_thru, mother_exten);
3927 } else if (p2->next && p2->next->type == PV_DEFAULT) {
3928 fall_thru = new_prio();
3929 fall_thru->type = AEL_APPCALL;
3930 fall_thru->app = strdup("Goto");
3931 snprintf(buf1, BUF_SIZE, "sw_%d_.,10", local_control_statement_count);
3932 fall_thru->appargs = strdup(buf1);
3933 linkprio(switch_case, fall_thru, mother_exten);
3934 } else if (!p2->next) {
3935 fall_thru = new_prio();
3936 fall_thru->type = AEL_CONTROL1;
3937 fall_thru->goto_true = switch_end;
3938 fall_thru->app = strdup("Goto");
3939 linkprio(switch_case, fall_thru, mother_exten);
3940 }
3941 }
3942 if (switch_case->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */
3943 char buf[2000];
3944 struct ael_priority *np2 = new_prio();
3945 np2->type = AEL_APPCALL;
3946 np2->app = strdup("NoOp");
3947 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name);
3948 np2->appargs = strdup(buf);
3949 linkprio(switch_case, np2, mother_exten);
3950 switch_case-> return_target = np2;
3951 }
3952 } else {
3953 /* what could it be??? */
3954 }
3955 }
3956
3957 exten->loop_break = loop_break_save;
3958 exten->loop_continue = loop_continue_save;
3959 switch_test->origin = p;
3960 switch_end->origin = p;
3961 break;
3962
3963 case PV_MACRO_CALL:
3964 pr = new_prio();
3965 pr->type = AEL_APPCALL;
3966 snprintf(buf1, BUF_SIZE, "%s,~~s~~,1", p->u1.str);
3967 first = 1;
3968 for (p2 = p->u2.arglist; p2; p2 = p2->next) {
3969 if (first)
3970 {
3971 strcat(buf1,"(");
3972 first = 0;
3973 }
3974 else
3975 strcat(buf1,",");
3976 strcat(buf1,p2->u1.str);
3977 }
3978 if (!first)
3979 strcat(buf1,")");
3980
3981 pr->app = strdup("Gosub");
3982 pr->appargs = strdup(buf1);
3983 pr->origin = p;
3984 linkprio(exten, pr, mother_exten);
3985 break;
3986
3988 pr = new_prio();
3989 pr->type = AEL_APPCALL;
3990 buf1[0] = 0;
3991 for (p2 = p->u2.arglist; p2; p2 = p2->next) {
3992 if (p2 != p->u2.arglist )
3993 strcat(buf1,",");
3994 strcat(buf1,p2->u1.str);
3995 }
3996 pr->app = strdup(p->u1.str);
3997 pr->appargs = strdup(buf1);
3998 pr->origin = p;
3999 linkprio(exten, pr, mother_exten);
4000 break;
4001
4002 case PV_BREAK:
4003 pr = new_prio();
4004 pr->type = AEL_CONTROL1; /* simple goto */
4005 pr->goto_true = exten->loop_break;
4006 pr->origin = p;
4007 linkprio(exten, pr, mother_exten);
4008 break;
4009
4010 case PV_RETURN: /* hmmmm */
4011 pr = new_prio();
4012 pr->type = AEL_RETURN; /* simple Return */
4013 /* exten->return_needed++; */
4014 pr->app = strdup("Return");
4015 pr->appargs = strdup("");
4016 pr->origin = p;
4017 linkprio(exten, pr, mother_exten);
4018 break;
4019
4020 case PV_CONTINUE:
4021 pr = new_prio();
4022 pr->type = AEL_CONTROL1; /* simple goto */
4024 pr->origin = p;
4025 linkprio(exten, pr, mother_exten);
4026 break;
4027
4028 case PV_IFTIME:
4030 snprintf(new_label, BUF_SIZE, "iftime_%s_%d", label, control_statement_count);
4031
4032 if_test = new_prio();
4033 if_test->type = AEL_IFTIME_CONTROL;
4034 snprintf(buf1, BUF_SIZE, "%s,%s,%s,%s",
4035 p->u1.list->u1.str,
4036 p->u1.list->next->u1.str,
4037 p->u1.list->next->next->u1.str,
4038 p->u1.list->next->next->next->u1.str);
4039 if_test->app = 0;
4040 if_test->appargs = strdup(buf1);
4041 if_test->origin = p;
4042
4043 if_end = new_prio();
4044 if_end->type = AEL_APPCALL;
4045 snprintf(buf1, BUF_SIZE, "Finish iftime_%s_%d", label, control_statement_count);
4046 if_end->app = strdup("NoOp");
4047 if_end->appargs = strdup(buf1);
4048
4049 if (p->u3.else_statements) {
4050 if_skip = new_prio();
4051 if_skip->type = AEL_CONTROL1; /* simple goto */
4052 if_skip->goto_true = if_end;
4053 if_skip->origin = p;
4054
4055 } else {
4056 if_skip = 0;
4057
4058 if_test->goto_false = if_end;
4059 }
4060
4061 if_false = new_prio();
4062 if_false->type = AEL_CONTROL1;
4063 if (p->u3.else_statements) {
4064 if_false->goto_true = if_skip; /* +1 */
4065 } else {
4066 if_false->goto_true = if_end;
4067 }
4068
4069 /* link & load! */
4070 linkprio(exten, if_test, mother_exten);
4071 linkprio(exten, if_false, mother_exten);
4072
4073 /* now, put the body of the if here */
4074
4075 if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the statements here */
4076 return -1;
4077 }
4078
4079 if (p->u3.else_statements) {
4080 linkprio(exten, if_skip, mother_exten);
4081 if (gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context)) { /* this will link in all the statements here */
4082 return -1;
4083 }
4084 }
4085
4086 linkprio(exten, if_end, mother_exten);
4087
4088 break;
4089
4090 case PV_RANDOM:
4091 case PV_IF:
4093 snprintf(new_label, BUF_SIZE, "if_%s_%d", label, control_statement_count);
4094
4095 if_test = new_prio();
4096 if_end = new_prio();
4097 if_test->type = AEL_IF_CONTROL;
4098 if_end->type = AEL_APPCALL;
4099 if ( p->type == PV_RANDOM )
4100 snprintf(buf1, BUF_SIZE, "$[${RAND(0,99)} < (%s)]", p->u1.str);
4101 else
4102 snprintf(buf1, BUF_SIZE, "$[%s]", p->u1.str);
4103 if_test->app = 0;
4104 if_test->appargs = strdup(buf1);
4105 snprintf(buf1, BUF_SIZE, "Finish if_%s_%d", label, control_statement_count);
4106 if_end->app = strdup("NoOp");
4107 if_end->appargs = strdup(buf1);
4108 if_test->origin = p;
4109
4110 if (p->u3.else_statements) {
4111 if_skip = new_prio();
4112 if_skip->type = AEL_CONTROL1; /* simple goto */
4113 if_skip->goto_true = if_end;
4114 if_test->goto_false = if_skip;;
4115 } else {
4116 if_skip = 0;
4117 if_test->goto_false = if_end;;
4118 }
4119
4120 /* link & load! */
4121 linkprio(exten, if_test, mother_exten);
4122
4123 /* now, put the body of the if here */
4124
4125 if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the statements here */
4126 return -1;
4127 }
4128
4129 if (p->u3.else_statements) {
4130 linkprio(exten, if_skip, mother_exten);
4131 if (gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context)) { /* this will link in all the statements here */
4132 return -1;
4133 }
4134 }
4135
4136 linkprio(exten, if_end, mother_exten);
4137
4138 break;
4139
4140 case PV_STATEMENTBLOCK:
4141 if (gen_prios(exten, label, p->u1.list, mother_exten, this_context)) { /* recurse into the block */
4142 return -1;
4143 }
4144 break;
4145
4146 case PV_CATCH:
4148 /* generate an extension with name of catch, put all catch stats
4149 into this exten! */
4150 switch_case = new_exten();
4151 if (mother_exten && mother_exten->checked_switch) {
4152 switch_case->has_switch = mother_exten->has_switch;
4153 switch_case->checked_switch = mother_exten->checked_switch;
4154 }
4155 if (exten && exten->checked_switch) {
4156 switch_case->has_switch = exten->has_switch;
4157 switch_case->checked_switch = exten->checked_switch;
4158 }
4159
4160 switch_case->context = this_context;
4161 linkexten(exten,switch_case);
4162 switch_case->name = strdup(p->u1.str);
4163 snprintf(new_label, BUF_SIZE, "catch_%s_%d",p->u1.str, control_statement_count);
4164
4165 if (gen_prios(switch_case, new_label, p->u2.statements, mother_exten,this_context)) { /* this will link in all the catch body statements here */
4166 return -1;
4167 }
4168 if (switch_case->return_needed) { /* returns now generate a Return() app call, no longer a goto to the end of the exten */
4169 char buf[2000];
4170 struct ael_priority *np2 = new_prio();
4171 np2->type = AEL_APPCALL;
4172 np2->app = strdup("NoOp");
4173 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name);
4174 np2->appargs = strdup(buf);
4175 linkprio(switch_case, np2, mother_exten);
4176 switch_case-> return_target = np2;
4177 }
4178
4179 break;
4180 default:
4181 break;
4182 }
4183 }
4184 return 0;
4185}
char * malloc()
static void gen_match_to_pattern(char *pattern, char *result)
Definition: pval.c:3061
static int label_inside_case(pval *label)
Definition: pval.c:3018
#define BUF_SIZE
Definition: pval.c:61
static void linkexten(struct ael_extension *exten, struct ael_extension *add)
Definition: pval.c:3032
static pval * get_goto_target(pval *item)
Definition: pval.c:1153
char * for_init
Definition: pval.h:62
struct pval * for_statements
Definition: pval.h:89
char * for_inc
Definition: pval.h:77
char * for_test
Definition: pval.h:71
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

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, buf, buf1, buf2, BUF_SIZE, ael_extension::checked_switch, pval::compiled_label, contains_switch(), ael_extension::context, control_statement_count, pval::else_statements, ael_priority::exten, first, pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, free(), gen_match_to_pattern(), gen_prios(), 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, NULL, 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, RAII_VAR, remove_spaces_before_equals(), ael_extension::return_needed, pval::statements, pval::str, strdup, ael_priority::type, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.

Referenced by ast_compile_ael2(), and gen_prios().

◆ get_contxt()

static pval * get_contxt ( pval p)
static

Definition at line 4345 of file pval.c.

4346{
4347 while( p && p->type != PV_CONTEXT && p->type != PV_MACRO ) {
4348
4349 p = p->dad;
4350 }
4351
4352 return p;
4353}

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

Referenced by check_goto(), and get_goto_target().

◆ get_extension_or_contxt()

static pval * get_extension_or_contxt ( pval p)
static

Definition at line 4335 of file pval.c.

4336{
4337 while( p && p->type != PV_EXTENSION && p->type != PV_CONTEXT && p->type != PV_MACRO ) {
4338
4339 p = p->dad;
4340 }
4341
4342 return p;
4343}

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

Referenced by check_goto(), and get_goto_target().

◆ get_goto_target()

static pval * get_goto_target ( pval item)
static

Definition at line 1153 of file pval.c.

1154{
1155 /* just one item-- the label should be in the current extension */
1156 pval *curr_ext = get_extension_or_contxt(item); /* containing exten, or macro */
1157 pval *curr_cont;
1158
1159 if (!item->u1.list) {
1160 return NULL;
1161 }
1162
1163 if (!item->u1.list->next && !strstr((item->u1.list)->u1.str,"${")) {
1164 struct pval *x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), curr_ext);
1165 return x;
1166 }
1167
1168 curr_cont = get_contxt(item);
1169
1170 /* TWO items */
1171 if (item->u1.list->next && !item->u1.list->next->next) {
1172 if (!strstr((item->u1.list)->u1.str,"${")
1173 && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ {
1174 struct pval *x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, curr_cont);
1175 return x;
1176 }
1177 }
1178
1179 /* All 3 items! */
1180 if (item->u1.list->next && item->u1.list->next->next) {
1181 /* all three */
1182 pval *first = item->u1.list;
1183 pval *second = item->u1.list->next;
1184 pval *third = item->u1.list->next->next;
1185
1186 if (!strstr((item->u1.list)->u1.str,"${")
1187 && !strstr(item->u1.list->next->u1.str,"${")
1188 && !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ {
1189 struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str);
1190 if (!x) {
1191
1192 struct pval *p3;
1193 struct pval *that_context = find_context(item->u1.list->u1.str);
1194
1195 /* the target of the goto could be in an included context!! Fancy that!! */
1196 /* look for includes in the current context */
1197 if (that_context) {
1198 for (p3=that_context->u2.statements; p3; p3=p3->next) {
1199 if (p3->type == PV_INCLUDES) {
1200 struct pval *p4;
1201 for (p4=p3->u1.list; p4; p4=p4->next) {
1202 /* for each context pointed to, find it, then find a context/label that matches the
1203 target here! */
1204 char *incl_context = p4->u1.str;
1205 /* find a matching context name */
1206 struct pval *that_other_context = find_context(incl_context);
1207 if (that_other_context) {
1208 struct pval *x3;
1209 x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context);
1210 if (x3) {
1211 return x3;
1212 }
1213 }
1214 }
1215 }
1216 }
1217 }
1218 }
1219 return x;
1220 }
1221 }
1222 return NULL;
1223}

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(), item, pval::list, pval::next, NULL, PV_INCLUDES, pval::statements, pval::str, pval::type, pval::u1, and pval::u2.

Referenced by gen_prios().

◆ in_context()

static struct pval * in_context ( pval item)
static

Definition at line 1090 of file pval.c.

1091{
1092 struct pval *curr;
1093 curr = item;
1094 while( curr ) {
1095 if( curr->type == PV_MACRO || curr->type == PV_CONTEXT ) {
1096 return curr;
1097 }
1098 curr = curr->dad;
1099 }
1100 return 0;
1101}

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

Referenced by check_goto().

◆ in_macro()

static struct pval * in_macro ( pval item)
static

Definition at line 1077 of file pval.c.

1078{
1079 struct pval *curr;
1080 curr = item;
1081 while( curr ) {
1082 if( curr->type == PV_MACRO ) {
1083 return curr;
1084 }
1085 curr = curr->dad;
1086 }
1087 return 0;
1088}

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

Referenced by check_goto().

◆ is_empty()

int is_empty ( char *  arg)

Definition at line 1981 of file pval.c.

1982{
1983 if (!arg)
1984 return 1;
1985 if (*arg == 0)
1986 return 1;
1987 while (*arg) {
1988 if (*arg != ' ' && *arg != '\t')
1989 return 0;
1990 arg++;
1991 }
1992 return 1;
1993}

◆ is_float()

int is_float ( char *  arg)

Definition at line 1963 of file pval.c.

1964{
1965 char *s;
1966 for (s=arg; *s; s++) {
1967 if (*s != '.' && (*s < '0' || *s > '9'))
1968 return 0;
1969 }
1970 return 1;
1971}

◆ is_int()

int is_int ( char *  arg)

Definition at line 1972 of file pval.c.

1973{
1974 char *s;
1975 for (s=arg; *s; s++) {
1976 if (*s < '0' || *s > '9')
1977 return 0;
1978 }
1979 return 1;
1980}

◆ label_inside_case()

static int label_inside_case ( pval label)
static

Definition at line 3018 of file pval.c.

3019{
3020 pval *p = label;
3021
3022 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ {
3023 if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN ) {
3024 return 1;
3025 }
3026
3027 p = p->dad;
3028 }
3029 return 0;
3030}

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

Referenced by gen_prios().

◆ linkexten()

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

Definition at line 3032 of file pval.c.

3033{
3034 add->next_exten = exten->next_exten; /* this will reverse the order. Big deal. */
3035 exten->next_exten = add;
3036}

References ael_priority::exten, and ael_extension::next_exten.

Referenced by gen_prios().

◆ linkprio()

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

Definition at line 2936 of file pval.c.

2937{
2938 char *p1, *p2;
2939
2940 if (!exten->plist) {
2941 exten->plist = prio;
2942 exten->plist_last = prio;
2943 } else {
2944 exten->plist_last->next = prio;
2945 exten->plist_last = prio;
2946 }
2947 if( !prio->exten )
2948 prio->exten = exten; /* don't override the switch value */
2949 /* The following code will cause all priorities within an extension
2950 to have ${EXTEN} or ${EXTEN: replaced with ~~EXTEN~~, which is
2951 set just before the first switch in an exten. The switches
2952 will muck up the original ${EXTEN} value, so we save it away
2953 and the user accesses this copy instead. */
2954 if (prio->appargs && ((mother_exten && mother_exten->has_switch) || exten->has_switch) ) {
2955 while ((p1 = strstr(prio->appargs, "${EXTEN}"))) {
2956 p2 = malloc(strlen(prio->appargs)+5);
2957 *p1 = 0;
2958 strcpy(p2, prio->appargs);
2959 strcat(p2, "${~~EXTEN~~}");
2960 if (*(p1+8))
2961 strcat(p2, p1+8);
2962 free(prio->appargs);
2963 prio->appargs = p2;
2964 }
2965 while ((p1 = strstr(prio->appargs, "${EXTEN:"))) {
2966 p2 = malloc(strlen(prio->appargs)+5);
2967 *p1 = 0;
2968 strcpy(p2, prio->appargs);
2969 strcat(p2, "${~~EXTEN~~:");
2970 if (*(p1+8))
2971 strcat(p2, p1+8);
2972 free(prio->appargs);
2973 prio->appargs = p2;
2974 }
2975 }
2976}

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

◆ linku1()

pval * linku1 ( pval head,
pval tail 
)

Definition at line 5922 of file pval.c.

5923{
5924 if (!head)
5925 return tail;
5926 if (tail) {
5927 if (!head->next) {
5928 head->next = tail;
5929 } else {
5930 head->u1_last->next = tail;
5931 }
5932 head->u1_last = tail;
5933 tail->prev = head; /* the dad link only points to containers */
5934 }
5935 return head;
5936}
struct pval * u1_last
Definition: pval.h:64
struct pval * prev
Definition: pval.h:97

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

◆ localized_pbx_load_module()

int localized_pbx_load_module ( void  )

Definition at line 5644 of file extconf.c.

5645{
5646 struct ast_context *con;
5647
5649 return -1 /* AST_MODULE_LOAD_DECLINE*/;
5650
5651 /* pbx_load_users(); */ /* does this affect the dialplan? */
5652
5654
5655 for (con = NULL; (con = ast_walk_contexts(con));)
5657
5658 printf("=== Loading extensions.conf ===\n");
5659 con = 0;
5660 while ((con = ast_walk_contexts(con)) ) {
5661 printf("Context: %s\n", con->name);
5662 }
5663 printf("=========\n");
5664
5665 return 0;
5666}
static struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: extconf.c:4024
static void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar)
Definition: extconf.c:5570
static struct ast_context * local_contexts
Definition: extconf.c:3596
static int ast_context_verify_includes(struct ast_context *con)
Definition: extconf.c:5620
static int pbx_load_config(const char *config_file)
Definition: extconf.c:5336
static char * global_registrar
Definition: extconf.c:2121
static char * config_filename
Definition: extconf.c:2120
const char * name
Definition: pbx.c:285

Referenced by check_goto(), and check_pval_item().

◆ match_pval()

struct pval * match_pval ( pval item)

Definition at line 1811 of file pval.c.

1812{
1813 pval *i;
1814
1815 for (i=item; i; i=i->next) {
1816 pval *x;
1817 /* printf(" -- match pval: item %d\n", i->type); */
1818
1819 if ((x = match_pval_item(i))) {
1820 /* printf("match_pval: returning x=%x\n", (int)x); */
1821 return x; /* cut the search short */
1822 }
1823 }
1824 return 0;
1825}
static struct pval * match_pval_item(pval *item)
Definition: pval.c:1563

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

◆ match_pval_item()

static struct pval * match_pval_item ( pval item)
static

Definition at line 1563 of file pval.c.

1564{
1565 pval *x;
1566
1567 switch ( item->type ) {
1568 case PV_MACRO:
1569 /* fields: item->u1.str == name of macro
1570 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
1571 item->u2.arglist->u1.str == argument
1572 item->u2.arglist->next == next arg
1573
1574 item->u3.macro_statements == pval list of statements in macro body.
1575 */
1576 /* printf(" matching in MACRO %s, match_context=%s; retoncontmtch=%d; \n", item->u1.str, match_context, return_on_context_match); */
1577 if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) {
1578
1579 /* printf("MACRO: match context is: %s\n", match_context); */
1580
1581 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 */ {
1582 /* printf("Returning on matching macro %s\n", match_context); */
1583 return item;
1584 }
1585
1586
1588 /* printf("Descending into matching macro %s/%s\n", match_context, item->u1.str); */
1589 if ((x=match_pval(item->u3.macro_statements))) {
1590 /* printf("Responded with pval match %x\n", x); */
1591 return x;
1592 }
1593 }
1594 } else {
1595 /* printf("Skipping context/macro %s\n", item->u1.str); */
1596 }
1597
1598 break;
1599
1600 case PV_CONTEXT:
1601 /* fields: item->u1.str == name of context
1602 item->u2.statements == pval list of statements in context body
1603 item->u3.abstract == int 1 if an abstract keyword were present
1604 */
1605 /* printf(" matching in CONTEXT\n"); */
1606 if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) {
1607 if (return_on_context_match && !strcmp(item->u1.str, match_context)) {
1608 /* printf("Returning on matching context %s\n", match_context); */
1609 /* printf("non-CONTEXT: Responded with pval match %x\n", x); */
1610 return item;
1611 }
1612
1614 /* printf("Descending into matching context %s\n", match_context); */
1615 if ((x=match_pval(item->u2.statements))) /* if we're just searching for a context, don't bother descending into them */ {
1616 /* printf("CONTEXT: Responded with pval match %x\n", x); */
1617 return x;
1618 }
1619 }
1620 } else {
1621 /* printf("Skipping context/macro %s\n", item->u1.str); */
1622 }
1623 break;
1624
1625 case PV_CASE:
1626 /* fields: item->u1.str == value of case
1627 item->u2.statements == pval list of statements under the case
1628 */
1629 /* printf(" matching in CASE\n"); */
1630 if ((x=match_pval(item->u2.statements))) {
1631 /* printf("CASE: Responded with pval match %x\n", x); */
1632 return x;
1633 }
1634 break;
1635
1636 case PV_PATTERN:
1637 /* fields: item->u1.str == value of case
1638 item->u2.statements == pval list of statements under the case
1639 */
1640 /* printf(" matching in PATTERN\n"); */
1641 if ((x=match_pval(item->u2.statements))) {
1642 /* printf("PATTERN: Responded with pval match %x\n", x); */
1643 return x;
1644 }
1645 break;
1646
1647 case PV_DEFAULT:
1648 /* fields:
1649 item->u2.statements == pval list of statements under the case
1650 */
1651 /* printf(" matching in DEFAULT\n"); */
1652 if ((x=match_pval(item->u2.statements))) {
1653 /* printf("DEFAULT: Responded with pval match %x\n", x); */
1654 return x;
1655 }
1656 break;
1657
1658 case PV_CATCH:
1659 /* fields: item->u1.str == name of extension to catch
1660 item->u2.statements == pval list of statements in context body
1661 */
1662 /* printf(" matching in CATCH\n"); */
1663 if ((x=match_pval(item->u2.statements))) {
1664 /* printf("CATCH: Responded with pval match %x\n", x); */
1665 return x;
1666 }
1667 break;
1668
1669 case PV_STATEMENTBLOCK:
1670 /* fields: item->u1.list == pval list of statements in block, one per entry in the list
1671 */
1672 /* printf(" matching in STATEMENTBLOCK\n"); */
1673 if ((x=match_pval(item->u1.list))) {
1674 /* printf("STATEMENTBLOCK: Responded with pval match %x\n", x); */
1675 return x;
1676 }
1677 break;
1678
1679 case PV_LABEL:
1680 /* fields: item->u1.str == label name
1681 */
1682 /* printf("PV_LABEL %s (cont=%s, exten=%s\n",
1683 item->u1.str, current_context->u1.str, (current_extension?current_extension->u1.str:"<macro>"));*/
1684
1685 if (count_labels) {
1686 if (!strcmp(match_label, item->u1.str)) {
1687 label_count++;
1689 }
1690
1691 } else {
1692 if (!strcmp(match_label, item->u1.str)) {
1693 /* printf("LABEL: Responded with pval match %x\n", x); */
1694 return item;
1695 }
1696 }
1697 break;
1698
1699 case PV_FOR:
1700 /* fields: item->u1.for_init == a string containing the initializer
1701 item->u2.for_test == a string containing the loop test
1702 item->u3.for_inc == a string containing the loop increment
1703
1704 item->u4.for_statements == a pval list of statements in the for ()
1705 */
1706 /* printf(" matching in FOR\n"); */
1707 if ((x=match_pval(item->u4.for_statements))) {
1708 /* printf("FOR: Responded with pval match %x\n", x);*/
1709 return x;
1710 }
1711 break;
1712
1713 case PV_WHILE:
1714 /* fields: item->u1.str == the while conditional, as supplied by user
1715
1716 item->u2.statements == a pval list of statements in the while ()
1717 */
1718 /* printf(" matching in WHILE\n"); */
1719 if ((x=match_pval(item->u2.statements))) {
1720 /* printf("WHILE: Responded with pval match %x\n", x); */
1721 return x;
1722 }
1723 break;
1724
1725 case PV_RANDOM:
1726 /* fields: item->u1.str == the random number expression, as supplied by user
1727
1728 item->u2.statements == a pval list of statements in the if ()
1729 item->u3.else_statements == a pval list of statements in the else
1730 (could be zero)
1731 fall thru to PV_IF */
1732
1733 case PV_IFTIME:
1734 /* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list
1735
1736 item->u2.statements == a pval list of statements in the if ()
1737 item->u3.else_statements == a pval list of statements in the else
1738 (could be zero)
1739 fall thru to PV_IF*/
1740 case PV_IF:
1741 /* fields: item->u1.str == the if conditional, as supplied by user
1742
1743 item->u2.statements == a pval list of statements in the if ()
1744 item->u3.else_statements == a pval list of statements in the else
1745 (could be zero)
1746 */
1747 /* printf(" matching in IF/IFTIME/RANDOM\n"); */
1748 if ((x=match_pval(item->u2.statements))) {
1749 return x;
1750 }
1751 if (item->u3.else_statements) {
1752 if ((x=match_pval(item->u3.else_statements))) {
1753 /* printf("IF/IFTIME/RANDOM: Responded with pval match %x\n", x); */
1754 return x;
1755 }
1756 }
1757 break;
1758
1759 case PV_SWITCH:
1760 /* fields: item->u1.str == the switch expression
1761
1762 item->u2.statements == a pval list of statements in the switch,
1763 (will be case statements, most likely!)
1764 */
1765 /* printf(" matching in SWITCH\n"); */
1766 if ((x=match_pval(item->u2.statements))) {
1767 /* printf("SWITCH: Responded with pval match %x\n", x); */
1768 return x;
1769 }
1770 break;
1771
1772 case PV_EXTENSION:
1773 /* fields: item->u1.str == the extension name, label, whatever it's called
1774
1775 item->u2.statements == a pval list of statements in the extension
1776 item->u3.hints == a char * hint argument
1777 item->u4.regexten == an int boolean. non-zero says that regexten was specified
1778 */
1779 /* printf(" matching in EXTENSION\n"); */
1780 if (!strcmp(match_exten,"*") || extension_matches(item, match_exten, item->u1.str) ) {
1781 /* printf("Descending into matching exten %s => %s\n", match_exten, item->u1.str); */
1782 if (strcmp(match_label,"1") == 0) {
1783 if (item->u2.statements) {
1784 struct pval *p5 = item->u2.statements;
1785 while (p5 && p5->type == PV_LABEL) /* find the first non-label statement in this context. If it exists, there's a "1" */
1786 p5 = p5->next;
1787 if (p5)
1788 return p5;
1789 else
1790 return 0;
1791 }
1792 else
1793 return 0;
1794 }
1795
1796 if ((x=match_pval(item->u2.statements))) {
1797 /* printf("EXTENSION: Responded with pval match %x\n", x); */
1798 return x;
1799 }
1800 } else {
1801 /* printf("Skipping exten %s\n", item->u1.str); */
1802 }
1803 break;
1804 default:
1805 /* printf(" matching in default = %d\n", item->type); */
1806 break;
1807 }
1808 return 0;
1809}
static int label_count
Definition: pval.c:81
static pval * last_matched_label
Definition: pval.c:83
static int extension_matches(pval *here, const char *exten, const char *pattern)
Definition: pval.c:694

References count_labels, extension_matches(), item, label_count, last_matched_label, match_context, match_exten, match_label, 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, return_on_context_match, aco_type::type, and pval::type.

Referenced by match_pval().

◆ new_exten()

struct ael_extension * new_exten ( void  )

Definition at line 2930 of file pval.c.

2931{
2932 struct ael_extension *x = (struct ael_extension *)calloc(sizeof(struct ael_extension),1);
2933 return x;
2934}

References calloc.

Referenced by ast_compile_ael2(), and gen_prios().

◆ new_prio()

struct ael_priority * new_prio ( void  )

Definition at line 2924 of file pval.c.

2925{
2926 struct ael_priority *x = (struct ael_priority *)calloc(sizeof(struct ael_priority),1);
2927 return x;
2928}

References calloc.

Referenced by ast_compile_ael2(), and gen_prios().

◆ print_pval()

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

Definition at line 115 of file pval.c.

116{
117 int i;
118 pval *lp;
119
120 for (i=0; i<depth; i++) {
121 fprintf(fin, "\t"); /* depth == indentation */
122 }
123
124 switch ( item->type ) {
125 case PV_WORD:
126 fprintf(fin,"%s;\n", item->u1.str); /* usually, words are encapsulated in something else */
127 break;
128
129 case PV_MACRO:
130 fprintf(fin,"macro %s(", item->u1.str);
131 for (lp=item->u2.arglist; lp; lp=lp->next) {
132 if (lp != item->u2.arglist )
133 fprintf(fin,", ");
134 fprintf(fin,"%s", lp->u1.str);
135 }
136 fprintf(fin,") {\n");
137 print_pval_list(fin,item->u3.macro_statements,depth+1);
138 for (i=0; i<depth; i++) {
139 fprintf(fin,"\t"); /* depth == indentation */
140 }
141 fprintf(fin,"};\n\n");
142 break;
143
144 case PV_CONTEXT:
145 if ( item->u3.abstract )
146 fprintf(fin,"abstract context %s {\n", item->u1.str);
147 else
148 fprintf(fin,"context %s {\n", item->u1.str);
149 print_pval_list(fin,item->u2.statements,depth+1);
150 for (i=0; i<depth; i++) {
151 fprintf(fin,"\t"); /* depth == indentation */
152 }
153 fprintf(fin,"};\n\n");
154 break;
155
156 case PV_MACRO_CALL:
157 fprintf(fin,"&%s(", item->u1.str);
158 for (lp=item->u2.arglist; lp; lp=lp->next) {
159 if ( lp != item->u2.arglist )
160 fprintf(fin,", ");
161 fprintf(fin,"%s", lp->u1.str);
162 }
163 fprintf(fin,");\n");
164 break;
165
167 fprintf(fin,"%s(", item->u1.str);
168 for (lp=item->u2.arglist; lp; lp=lp->next) {
169 if ( lp != item->u2.arglist )
170 fprintf(fin,",");
171 fprintf(fin,"%s", lp->u1.str);
172 }
173 fprintf(fin,");\n");
174 break;
175
176 case PV_CASE:
177 fprintf(fin,"case %s:\n", item->u1.str);
178 print_pval_list(fin,item->u2.statements, depth+1);
179 break;
180
181 case PV_PATTERN:
182 fprintf(fin,"pattern %s:\n", item->u1.str);
183 print_pval_list(fin,item->u2.statements, depth+1);
184 break;
185
186 case PV_DEFAULT:
187 fprintf(fin,"default:\n");
188 print_pval_list(fin,item->u2.statements, depth+1);
189 break;
190
191 case PV_CATCH:
192 fprintf(fin,"catch %s {\n", item->u1.str);
193 print_pval_list(fin,item->u2.statements, depth+1);
194 for (i=0; i<depth; i++) {
195 fprintf(fin,"\t"); /* depth == indentation */
196 }
197 fprintf(fin,"};\n");
198 break;
199
200 case PV_SWITCHES:
201 fprintf(fin,"switches {\n");
202 print_pval_list(fin,item->u1.list,depth+1);
203 for (i=0; i<depth; i++) {
204 fprintf(fin,"\t"); /* depth == indentation */
205 }
206 fprintf(fin,"};\n");
207 break;
208
209 case PV_ESWITCHES:
210 fprintf(fin,"eswitches {\n");
211 print_pval_list(fin,item->u1.list,depth+1);
212 for (i=0; i<depth; i++) {
213 fprintf(fin,"\t"); /* depth == indentation */
214 }
215 fprintf(fin,"};\n");
216 break;
217
218 case PV_INCLUDES:
219 fprintf(fin,"includes {\n");
220 for (lp=item->u1.list; lp; lp=lp->next) {
221 for (i=0; i<depth+1; i++) {
222 fprintf(fin,"\t"); /* depth == indentation */
223 }
224 fprintf(fin,"%s", lp->u1.str); /* usually, words are encapsulated in something else */
225 if (lp->u2.arglist)
226 fprintf(fin,"|%s|%s|%s|%s",
227 lp->u2.arglist->u1.str,
228 lp->u2.arglist->next->u1.str,
229 lp->u2.arglist->next->next->u1.str,
230 lp->u2.arglist->next->next->next->u1.str
231 );
232 fprintf(fin,";\n"); /* usually, words are encapsulated in something else */
233 }
234
235 for (i=0; i<depth; i++) {
236 fprintf(fin,"\t"); /* depth == indentation */
237 }
238 fprintf(fin,"};\n");
239 break;
240
242 fprintf(fin,"{\n");
243 print_pval_list(fin,item->u1.list, depth+1);
244 for (i=0; i<depth; i++) {
245 fprintf(fin,"\t"); /* depth == indentation */
246 }
247 fprintf(fin,"}\n");
248 break;
249
250 case PV_VARDEC:
251 fprintf(fin,"%s=%s;\n", item->u1.str, item->u2.val);
252 break;
253
254 case PV_LOCALVARDEC:
255 fprintf(fin,"local %s=%s;\n", item->u1.str, item->u2.val);
256 break;
257
258 case PV_GOTO:
259 fprintf(fin,"goto %s", item->u1.list->u1.str);
260 if ( item->u1.list->next )
261 fprintf(fin,",%s", item->u1.list->next->u1.str);
262 if ( item->u1.list->next && item->u1.list->next->next )
263 fprintf(fin,",%s", item->u1.list->next->next->u1.str);
264 fprintf(fin,"\n");
265 break;
266
267 case PV_LABEL:
268 fprintf(fin,"%s:\n", item->u1.str);
269 break;
270
271 case PV_FOR:
272 fprintf(fin,"for (%s; %s; %s)\n", item->u1.for_init, item->u2.for_test, item->u3.for_inc);
273 print_pval_list(fin,item->u4.for_statements,depth+1);
274 break;
275
276 case PV_WHILE:
277 fprintf(fin,"while (%s)\n", item->u1.str);
278 print_pval_list(fin,item->u2.statements,depth+1);
279 break;
280
281 case PV_BREAK:
282 fprintf(fin,"break;\n");
283 break;
284
285 case PV_RETURN:
286 fprintf(fin,"return;\n");
287 break;
288
289 case PV_CONTINUE:
290 fprintf(fin,"continue;\n");
291 break;
292
293 case PV_RANDOM:
294 case PV_IFTIME:
295 case PV_IF:
296 if ( item->type == PV_IFTIME ) {
297
298 fprintf(fin,"ifTime ( %s|%s|%s|%s )\n",
299 item->u1.list->u1.str,
300 item->u1.list->next->u1.str,
301 item->u1.list->next->next->u1.str,
302 item->u1.list->next->next->next->u1.str
303 );
304 } else if ( item->type == PV_RANDOM ) {
305 fprintf(fin,"random ( %s )\n", item->u1.str );
306 } else
307 fprintf(fin,"if ( %s )\n", item->u1.str);
308 if ( item->u2.statements && item->u2.statements->next ) {
309 for (i=0; i<depth; i++) {
310 fprintf(fin,"\t"); /* depth == indentation */
311 }
312 fprintf(fin,"{\n");
313 print_pval_list(fin,item->u2.statements,depth+1);
314 for (i=0; i<depth; i++) {
315 fprintf(fin,"\t"); /* depth == indentation */
316 }
317 if ( item->u3.else_statements )
318 fprintf(fin,"}\n");
319 else
320 fprintf(fin,"};\n");
321 } else if (item->u2.statements ) {
322 print_pval_list(fin,item->u2.statements,depth+1);
323 } else {
324 if (item->u3.else_statements )
325 fprintf(fin, " {} ");
326 else
327 fprintf(fin, " {}; ");
328 }
329 if ( item->u3.else_statements ) {
330 for (i=0; i<depth; i++) {
331 fprintf(fin,"\t"); /* depth == indentation */
332 }
333 fprintf(fin,"else\n");
334 print_pval_list(fin,item->u3.else_statements, depth);
335 }
336 break;
337
338 case PV_SWITCH:
339 fprintf(fin,"switch( %s ) {\n", item->u1.str);
340 print_pval_list(fin,item->u2.statements,depth+1);
341 for (i=0; i<depth; i++) {
342 fprintf(fin,"\t"); /* depth == indentation */
343 }
344 fprintf(fin,"}\n");
345 break;
346
347 case PV_EXTENSION:
348 if ( item->u4.regexten )
349 fprintf(fin, "regexten ");
350 if ( item->u3.hints )
351 fprintf(fin,"hints(%s) ", item->u3.hints);
352
353 fprintf(fin,"%s => ", item->u1.str);
354 print_pval_list(fin,item->u2.statements,depth+1);
355 fprintf(fin,"\n");
356 break;
357
358 case PV_IGNOREPAT:
359 fprintf(fin,"ignorepat => %s;\n", item->u1.str);
360 break;
361
362 case PV_GLOBALS:
363 fprintf(fin,"globals {\n");
364 print_pval_list(fin,item->u1.statements,depth+1);
365 for (i=0; i<depth; i++) {
366 fprintf(fin,"\t"); /* depth == indentation */
367 }
368 fprintf(fin,"}\n");
369 break;
370 }
371}

References pval::arglist, item, 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::str, aco_type::type, pval::u1, and pval::u2.

Referenced by print_pval_list().

◆ print_pval_list()

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

Definition at line 373 of file pval.c.

374{
375 pval *i;
376
377 for (i=item; i; i=i->next) {
378 print_pval(fin, i, depth);
379 }
380}
static void print_pval(FILE *fin, pval *item, int depth)
Definition: pval.c:115

References item, pval::next, and print_pval().

Referenced by ael2_print(), and print_pval().

◆ pvalAppCallAddArg()

void pvalAppCallAddArg ( pval p,
pval arg 
)

Definition at line 5268 of file pval.c.

5269{
5270 if (!pvalCheckType(p, "pvalAppCallAddArg", PV_APPLICATION_CALL))
5271 return;
5272 if (!p->u2.arglist)
5273 p->u2.arglist = arg;
5274 else
5275 linku1(p->u2.arglist, arg);
5276}
int pvalCheckType(pval *p, char *funcname, pvaltype type)
Definition: pval.c:5031
pval * linku1(pval *head, pval *tail)
Definition: pval.c:5922

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

◆ pvalAppCallGetAppName()

char * pvalAppCallGetAppName ( pval p)

Definition at line 5254 of file pval.c.

5255{
5256 if (!pvalCheckType(p, "pvalAppCallGetAppName", PV_APPLICATION_CALL))
5257 return 0;
5258 return p->u1.str;
5259}

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

◆ pvalAppCallSetAppName()

void pvalAppCallSetAppName ( pval p,
char *  name 
)

Definition at line 5247 of file pval.c.

5248{
5249 if (!pvalCheckType(p, "pvalAppCallSetAppName", PV_APPLICATION_CALL))
5250 return;
5251 p->u1.str = name;
5252}

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

◆ pvalAppCallSetArglist()

void pvalAppCallSetArglist ( pval p,
pval arglist 
)

Definition at line 5261 of file pval.c.

5262{
5263 if (!pvalCheckType(p, "pvalAppCallSetArglist", PV_APPLICATION_CALL))
5264 return;
5265 p->u2.arglist = arglist;
5266}

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

◆ pvalAppCallWalkArgs()

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

Definition at line 5278 of file pval.c.

5279{
5280 if (!pvalCheckType(p, "pvalAppCallWalkArgs", PV_APPLICATION_CALL))
5281 return 0;
5282 if (!(*args))
5283 *args = p->u2.arglist;
5284 else {
5285 *args = (*args)->next;
5286 }
5287 return *args;
5288}
const char * args

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

◆ pvalCasePatDefAddStatement()

void pvalCasePatDefAddStatement ( pval p,
pval statement 
)

Definition at line 5303 of file pval.c.

5304{
5305 if (!p->u2.arglist)
5306 p->u2.statements = statement;
5307 else
5308 linku1(p->u2.statements, statement);
5309}

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

◆ pvalCasePatDefWalkStatements()

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

Definition at line 5311 of file pval.c.

5312{
5313 if (!(*statement))
5314 *statement = p->u2.statements;
5315 else {
5316 *statement = (*statement)->next;
5317 }
5318 return *statement;
5319}

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

◆ pvalCasePatGetVal()

char * pvalCasePatGetVal ( pval p)

Definition at line 5298 of file pval.c.

5299{
5300 return p->u1.str;
5301}

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

◆ pvalCasePatSetVal()

void pvalCasePatSetVal ( pval p,
char *  val 
)

Definition at line 5291 of file pval.c.

5292{
5293 if (!pvalCheckType(p, "pvalAppCallWalkArgs", PV_APPLICATION_CALL))
5294 return;
5295 p->u1.str = val;
5296}
Definition: ast_expr2.c:325

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

◆ pvalCatchGetExtName()

char * pvalCatchGetExtName ( pval p)

Definition at line 5329 of file pval.c.

5330{
5331 if (!pvalCheckType(p, "pvalCatchGetExtName", PV_CATCH))
5332 return 0;
5333 return p->u1.str;
5334}

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

◆ pvalCatchGetStatement()

pval * pvalCatchGetStatement ( pval p)

Definition at line 5343 of file pval.c.

5344{
5345 if (!pvalCheckType(p, "pvalCatchGetStatement", PV_CATCH))
5346 return 0;
5347 return p->u2.statements;
5348}

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

◆ pvalCatchSetExtName()

void pvalCatchSetExtName ( pval p,
char *  name 
)

Definition at line 5322 of file pval.c.

5323{
5324 if (!pvalCheckType(p, "pvalCatchSetExtName", PV_CATCH))
5325 return;
5326 p->u1.str = name;
5327}

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

◆ pvalCatchSetStatement()

void pvalCatchSetStatement ( pval p,
pval statement 
)

Definition at line 5336 of file pval.c.

5337{
5338 if (!pvalCheckType(p, "pvalCatchSetStatement", PV_CATCH))
5339 return;
5340 p->u2.statements = statement;
5341}

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

◆ pvalCheckType()

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

Definition at line 5031 of file pval.c.

5032{
5033 if (p->type != type)
5034 {
5035 ast_log(LOG_ERROR, "Func: %s the pval passed is not appropriate for this function!\n", funcname);
5036 return 0;
5037 }
5038 return 1;
5039}
static const char type[]
Definition: chan_ooh323.c:109

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

◆ pvalConditionalGetElseStatement()

pval * pvalConditionalGetElseStatement ( pval p)

Definition at line 5751 of file pval.c.

5752{
5753 return p->u3.else_statements;
5754}

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

◆ pvalConditionalGetThenStatement()

pval * pvalConditionalGetThenStatement ( pval p)

Definition at line 5746 of file pval.c.

5747{
5748 return p->u2.statements;
5749}

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

◆ pvalConditionalSetElseStatement()

void pvalConditionalSetElseStatement ( pval p,
pval statement 
)

Definition at line 5741 of file pval.c.

5742{
5743 p->u3.else_statements = statement;
5744}

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

◆ pvalConditionalSetThenStatement()

void pvalConditionalSetThenStatement ( pval p,
pval statement 
)

Definition at line 5736 of file pval.c.

5737{
5738 p->u2.statements = statement;
5739}

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

◆ pvalContextAddStatement()

void pvalContextAddStatement ( pval p,
pval statement 
)

Definition at line 5180 of file pval.c.

5181{
5182 if (!pvalCheckType(p, "pvalContextAddStatement", PV_CONTEXT))
5183 return;
5184 if (!p->u2.statements)
5185 p->u2.statements = statement;
5186 else
5187 linku1(p->u2.statements, statement);
5188}

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

◆ pvalContextGetAbstract()

int pvalContextGetAbstract ( pval p)

Definition at line 5171 of file pval.c.

5172{
5173 if (!pvalCheckType(p, "pvalContextGetAbstract", PV_CONTEXT))
5174 return 0;
5175 return p->u3.abstract;
5176}

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

◆ pvalContextGetName()

char * pvalContextGetName ( pval p)

Definition at line 5150 of file pval.c.

5151{
5152 if (!pvalCheckType(p, "pvalContextGetName", PV_CONTEXT))
5153 return 0;
5154 return p->u1.str;
5155}

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

◆ pvalContextSetAbstract()

void pvalContextSetAbstract ( pval p)

Definition at line 5157 of file pval.c.

5158{
5159 if (!pvalCheckType(p, "pvalContextSetAbstract", PV_CONTEXT))
5160 return;
5161 p->u3.abstract = 1;
5162}

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

◆ pvalContextSetName()

void pvalContextSetName ( pval p,
char *  name 
)

Definition at line 5143 of file pval.c.

5144{
5145 if (!pvalCheckType(p, "pvalContextSetName", PV_CONTEXT))
5146 return;
5147 p->u1.str = name;
5148}

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

◆ pvalContextUnsetAbstract()

void pvalContextUnsetAbstract ( pval p)

Definition at line 5164 of file pval.c.

5165{
5166 if (!pvalCheckType(p, "pvalContextUnsetAbstract", PV_CONTEXT))
5167 return;
5168 p->u3.abstract = 0;
5169}

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

◆ pvalContextWalkStatements()

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

Definition at line 5190 of file pval.c.

5191{
5192 if (!pvalCheckType(p, "pvalContextWalkStatements", PV_CONTEXT))
5193 return 0;
5194 if (!(*statements))
5195 *statements = p->u2.statements;
5196 else {
5197 *statements = (*statements)->next;
5198 }
5199 return *statements;
5200}

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

◆ pvalCreateNode()

pval * pvalCreateNode ( pvaltype  type)

Definition at line 5042 of file pval.c.

5043{
5044 pval *p = calloc(1,sizeof(pval)); /* why, oh why, don't I use ast_calloc? Way, way, way too messy if I do! */
5045 /* remember, this can be used externally or internally to asterisk */
5046 if (p) {
5047 p->type = type;
5048 }
5049 return p;
5050}

References calloc, type, and pval::type.

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

◆ pvalESwitchesAddSwitch()

void pvalESwitchesAddSwitch ( pval p,
char *  name 
)

Definition at line 5373 of file pval.c.

5374{
5375 pval *s;
5376 if (!pvalCheckType(p, "pvalESwitchesAddSwitch", PV_ESWITCHES))
5377 return;
5379 s->u1.str = name;
5380 p->u1.list = linku1(p->u1.list, s);
5381}
pval * pvalCreateNode(pvaltype type)
Definition: pval.c:5042

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

◆ pvalESwitchesWalkNames()

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

Definition at line 5383 of file pval.c.

5384{
5385 if (!pvalCheckType(p, "pvalESwitchesWalkNames", PV_ESWITCHES))
5386 return 0;
5387 if (!(*next_item))
5388 *next_item = p->u1.list;
5389 else {
5390 *next_item = (*next_item)->next;
5391 }
5392 return (*next_item)->u1.str;
5393}
static char next_item(const char *format)
Definition: say.c:4645

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

◆ pvalExtenGetHints()

char * pvalExtenGetHints ( pval p)

Definition at line 5837 of file pval.c.

5838{
5839 if (!pvalCheckType(p, "pvalExtenGetHints", PV_EXTENSION))
5840 return 0;
5841 return p->u3.hints;
5842}

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

◆ pvalExtenGetName()

char * pvalExtenGetName ( pval p)

Definition at line 5802 of file pval.c.

5803{
5804 if (!pvalCheckType(p, "pvalExtenGetName", PV_EXTENSION))
5805 return 0;
5806 return p->u1.str;
5807}

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

◆ pvalExtenGetRegexten()

int pvalExtenGetRegexten ( pval p)

Definition at line 5823 of file pval.c.

5824{
5825 if (!pvalCheckType(p, "pvalExtenGetRegexten", PV_EXTENSION))
5826 return 0;
5827 return p->u4.regexten;
5828}

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

◆ pvalExtenGetStatement()

pval * pvalExtenGetStatement ( pval p)

Definition at line 5851 of file pval.c.

5852{
5853 if (!pvalCheckType(p, "pvalExtenGetStatement", PV_EXTENSION))
5854 return 0;
5855 return p->u2.statements;
5856}

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

◆ pvalExtenSetHints()

void pvalExtenSetHints ( pval p,
char *  hints 
)

Definition at line 5830 of file pval.c.

5831{
5832 if (!pvalCheckType(p, "pvalExtenSetHints", PV_EXTENSION))
5833 return;
5834 p->u3.hints = hints;
5835}
static struct ao2_container * hints
Definition: pbx.c:806

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

◆ pvalExtenSetName()

void pvalExtenSetName ( pval p,
char *  name 
)

Definition at line 5795 of file pval.c.

5796{
5797 if (!pvalCheckType(p, "pvalExtenSetName", PV_EXTENSION))
5798 return;
5799 p->u1.str = name;
5800}

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

◆ pvalExtenSetRegexten()

void pvalExtenSetRegexten ( pval p)

Definition at line 5809 of file pval.c.

5810{
5811 if (!pvalCheckType(p, "pvalExtenSetRegexten", PV_EXTENSION))
5812 return;
5813 p->u4.regexten = 1;
5814}

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

◆ pvalExtenSetStatement()

void pvalExtenSetStatement ( pval p,
pval statement 
)

Definition at line 5844 of file pval.c.

5845{
5846 if (!pvalCheckType(p, "pvalExtenSetStatement", PV_EXTENSION))
5847 return;
5848 p->u2.statements = statement;
5849}

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

◆ pvalExtenUnSetRegexten()

void pvalExtenUnSetRegexten ( pval p)

Definition at line 5816 of file pval.c.

5817{
5818 if (!pvalCheckType(p, "pvalExtenUnSetRegexten", PV_EXTENSION))
5819 return;
5820 p->u4.regexten = 0;
5821}

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

◆ pvalForGetInc()

char * pvalForGetInc ( pval p)

Definition at line 5647 of file pval.c.

5648{
5649 if (!pvalCheckType(p, "pvalForGetInc", PV_FOR))
5650 return 0;
5651 return p->u3.for_inc;
5652}

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

◆ pvalForGetInit()

char * pvalForGetInit ( pval p)

Definition at line 5633 of file pval.c.

5634{
5635 if (!pvalCheckType(p, "pvalForGetInit", PV_FOR))
5636 return 0;
5637 return p->u1.for_init;
5638}

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

◆ pvalForGetStatement()

pval * pvalForGetStatement ( pval p)

Definition at line 5654 of file pval.c.

5655{
5656 if (!pvalCheckType(p, "pvalForGetStatement", PV_FOR))
5657 return 0;
5658 return p->u4.for_statements;
5659}

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

◆ pvalForGetTest()

char * pvalForGetTest ( pval p)

Definition at line 5640 of file pval.c.

5641{
5642 if (!pvalCheckType(p, "pvalForGetTest", PV_FOR))
5643 return 0;
5644 return p->u2.for_test;
5645}

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

◆ pvalForSetInc()

void pvalForSetInc ( pval p,
char *  inc 
)

Definition at line 5619 of file pval.c.

5620{
5621 if (!pvalCheckType(p, "pvalForSetInc", PV_FOR))
5622 return;
5623 p->u3.for_inc = inc;
5624}

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

◆ pvalForSetInit()

void pvalForSetInit ( pval p,
char *  init 
)

Definition at line 5605 of file pval.c.

5606{
5607 if (!pvalCheckType(p, "pvalForSetInit", PV_FOR))
5608 return;
5609 p->u1.for_init = init;
5610}

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

◆ pvalForSetStatement()

void pvalForSetStatement ( pval p,
pval statement 
)

Definition at line 5626 of file pval.c.

5627{
5628 if (!pvalCheckType(p, "pvalForSetStatement", PV_FOR))
5629 return;
5630 p->u4.for_statements = statement;
5631}

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

◆ pvalForSetTest()

void pvalForSetTest ( pval p,
char *  test 
)

Definition at line 5612 of file pval.c.

5613{
5614 if (!pvalCheckType(p, "pvalForSetTest", PV_FOR))
5615 return;
5616 p->u2.for_test = test;
5617}

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

◆ pvalGlobalsAddStatement()

void pvalGlobalsAddStatement ( pval p,
pval statement 
)

Definition at line 5874 of file pval.c.

5875{
5876 if (p->type != PV_GLOBALS) {
5877 ast_log(LOG_ERROR, "pvalGlobalsAddStatement called where first arg is not a Globals!\n");
5878 } else {
5879 if (!p->u1.statements) {
5880 p->u1.statements = statement;
5881 } else {
5882 p->u1.statements = linku1(p->u1.statements,statement);
5883 }
5884 }
5885}

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

◆ pvalGlobalsWalkStatements()

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

Definition at line 5887 of file pval.c.

5888{
5889 if (!pvalCheckType(p, "pvalGlobalsWalkStatements", PV_GLOBALS))
5890 return 0;
5891 if (!*next_statement) {
5892 *next_statement = p;
5893 return p;
5894 } else {
5895 *next_statement = (*next_statement)->next;
5896 return (*next_statement)->next;
5897 }
5898}

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

◆ pvalGotoGetTarget()

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

Definition at line 5563 of file pval.c.

5564{
5565 if (!pvalCheckType(p, "pvalGotoGetTarget", PV_GOTO))
5566 return;
5567 if (p->u1.list && p->u1.list->next && p->u1.list->next->next) {
5568 *context = p->u1.list->u1.str;
5569 *exten = p->u1.list->next->u1.str;
5570 *label = p->u1.list->next->next->u1.str;
5571
5572 } else if (p->u1.list && p->u1.list->next ) {
5573 *exten = p->u1.list->u1.str;
5574 *label = p->u1.list->next->u1.str;
5575 *context = 0;
5576
5577 } else if (p->u1.list) {
5578 *label = p->u1.list->u1.str;
5579 *context = 0;
5580 *exten = 0;
5581
5582 } else {
5583 *context = 0;
5584 *exten = 0;
5585 *label = 0;
5586 }
5587}

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

◆ pvalGotoSetTarget()

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

Definition at line 5527 of file pval.c.

5528{
5529 pval *con, *ext, *pri;
5530
5531 if (!pvalCheckType(p, "pvalGotoSetTarget", PV_GOTO))
5532 return;
5533 if (context && strlen(context)) {
5534 con = pvalCreateNode(PV_WORD);
5536 pri = pvalCreateNode(PV_WORD);
5537
5538 con->u1.str = context;
5539 ext->u1.str = exten;
5540 pri->u1.str = label;
5541
5542 con->next = ext;
5543 ext->next = pri;
5544 p->u1.list = con;
5545 } else if (exten && strlen(exten)) {
5547 pri = pvalCreateNode(PV_WORD);
5548
5549 ext->u1.str = exten;
5550 pri->u1.str = label;
5551
5552 ext->next = pri;
5553 p->u1.list = ext;
5554 } else {
5555 pri = pvalCreateNode(PV_WORD);
5556
5557 pri->u1.str = label;
5558
5559 p->u1.list = pri;
5560 }
5561}
const char * ext
Definition: http.c:150

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

◆ pvalIfGetCondition()

char * pvalIfGetCondition ( pval p)

Definition at line 5670 of file pval.c.

5671{
5672 if (!pvalCheckType(p, "pvalIfGetCondition", PV_IFTIME))
5673 return 0;
5674 return p->u1.str;
5675}

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

◆ pvalIfSetCondition()

void pvalIfSetCondition ( pval p,
char *  expr 
)

Definition at line 5663 of file pval.c.

5664{
5665 if (!pvalCheckType(p, "pvalIfSetCondition", PV_IF))
5666 return;
5667 p->u1.str = expr;
5668}

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

◆ pvalIfTimeGetCondition()

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

Definition at line 5712 of file pval.c.

5713{
5714 if (!pvalCheckType(p, "pvalIfTimeGetCondition", PV_IFTIME))
5715 return;
5716 *hour_range = p->u1.list->u1.str;
5717 *dow_range = p->u1.list->next->u1.str;
5718 *dom_range = p->u1.list->next->next->u1.str;
5719 *month_range = p->u1.list->next->next->next->u1.str;
5720}

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

◆ pvalIfTimeSetCondition()

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

Definition at line 5677 of file pval.c.

5678{
5679 pval *hr;
5680 pval *dow;
5681 pval *dom;
5682 pval *mon;
5683
5684 if (!pvalCheckType(p, "pvalIfTimeSetCondition", PV_IFTIME)) {
5685 return;
5686 }
5687
5688 hr = pvalCreateNode(PV_WORD);
5689 dow = pvalCreateNode(PV_WORD);
5690 dom = pvalCreateNode(PV_WORD);
5691 mon = pvalCreateNode(PV_WORD);
5692
5693 if (!hr || !dom || !dow || !mon) {
5694 destroy_pval(hr);
5695 destroy_pval(dom);
5696 destroy_pval(dow);
5697 destroy_pval(mon);
5698 return;
5699 }
5700
5701 pvalWordSetString(hr, hour_range);
5702 pvalWordSetString(dow, dow_range);
5703 pvalWordSetString(dom, dom_range);
5704 pvalWordSetString(mon, mon_range);
5705 dom->next = mon;
5706 dow->next = dom;
5707 hr->next = dow;
5708 p->u1.list = hr;
5709}
void pvalWordSetString(pval *p, char *str)
Definition: pval.c:5058

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

◆ pvalIgnorePatGetPattern()

char * pvalIgnorePatGetPattern ( pval p)

Definition at line 5866 of file pval.c.

5867{
5868 if (!pvalCheckType(p, "pvalIgnorePatGetPattern", PV_IGNOREPAT))
5869 return 0;
5870 return p->u1.str;
5871}

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

◆ pvalIgnorePatSetPattern()

void pvalIgnorePatSetPattern ( pval p,
char *  pat 
)

Definition at line 5859 of file pval.c.

5860{
5861 if (!pvalCheckType(p, "pvalIgnorePatSetPattern", PV_IGNOREPAT))
5862 return;
5863 p->u1.str = pat;
5864}

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

◆ pvalIncludeGetTimeConstraints()

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

Definition at line 5450 of file pval.c.

5451{
5452 if (!pvalCheckType(p, "pvalIncludeGetTimeConstraints", PV_WORD))
5453 return;
5454 if (p->u2.arglist) {
5455 *hour_range = p->u2.arglist->u1.str;
5456 *dom_range = p->u2.arglist->next->u1.str;
5457 *dow_range = p->u2.arglist->next->next->u1.str;
5458 *month_range = p->u2.arglist->next->next->next->u1.str;
5459 } else {
5460 *hour_range = 0;
5461 *dom_range = 0;
5462 *dow_range = 0;
5463 *month_range = 0;
5464 }
5465}

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

◆ pvalIncludesAddInclude()

void pvalIncludesAddInclude ( pval p,
const char *  include 
)

Definition at line 5396 of file pval.c.

5397{
5398 pval *s;
5399 if (!pvalCheckType(p, "pvalIncludesAddSwitch", PV_INCLUDES))
5400 return;
5402 s->u1.str = (char *)include;
5403 p->u1.list = linku1(p->u1.list, s);
5404}

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

◆ pvalIncludesAddIncludeWithTimeConstraints()

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

Definition at line 5407 of file pval.c.

5408{
5409 pval *hr;
5410 pval *dom;
5411 pval *dow;
5412 pval *mon;
5413 pval *s;
5414
5415 if (!pvalCheckType(p, "pvalIncludeAddIncludeWithTimeConstraints", PV_INCLUDES)) {
5416 return;
5417 }
5418
5419 hr = pvalCreateNode(PV_WORD);
5420 dom = pvalCreateNode(PV_WORD);
5421 dow = pvalCreateNode(PV_WORD);
5422 mon = pvalCreateNode(PV_WORD);
5424
5425 if (!hr || !dom || !dow || !mon || !s) {
5426 destroy_pval(hr);
5427 destroy_pval(dom);
5428 destroy_pval(dow);
5429 destroy_pval(mon);
5430 destroy_pval(s);
5431 return;
5432 }
5433
5434 s->u1.str = (char *)include;
5435 p->u1.list = linku1(p->u1.list, s);
5436
5437 hr->u1.str = hour_range;
5438 dom->u1.str = dom_range;
5439 dow->u1.str = dow_range;
5440 mon->u1.str = month_range;
5441
5442 s->u2.arglist = hr;
5443
5444 hr->next = dom;
5445 dom->next = dow;
5446 dow->next = mon;
5447 mon->next = 0;
5448}

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

◆ pvalIncludesWalk()

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

Definition at line 5467 of file pval.c.

5468{
5469 if (!pvalCheckType(p, "pvalIncludesWalk", PV_INCLUDES))
5470 return 0;
5471 if (!(*next_item))
5472 *next_item = p->u1.list;
5473 else {
5474 *next_item = (*next_item)->next;
5475 }
5476 return (*next_item)->u1.str;
5477}

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

◆ pvalLabelGetName()

char * pvalLabelGetName ( pval p)

Definition at line 5597 of file pval.c.

5598{
5599 if (!pvalCheckType(p, "pvalLabelGetName", PV_LABEL))
5600 return 0;
5601 return p->u1.str;
5602}

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

◆ pvalLabelSetName()

void pvalLabelSetName ( pval p,
char *  name 
)

Definition at line 5590 of file pval.c.

5591{
5592 if (!pvalCheckType(p, "pvalLabelSetName", PV_LABEL))
5593 return;
5594 p->u1.str = name;
5595}

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

◆ pvalMacroAddArg()

void pvalMacroAddArg ( pval p,
pval arg 
)

Definition at line 5094 of file pval.c.

5095{
5096 if (!pvalCheckType(p, "pvalMacroAddArg", PV_MACRO))
5097 return;
5098 if (!p->u2.arglist)
5099 p->u2.arglist = arg;
5100 else
5101 linku1(p->u2.arglist, arg);
5102
5103}

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

◆ pvalMacroAddStatement()

void pvalMacroAddStatement ( pval p,
pval statement 
)

Definition at line 5117 of file pval.c.

5118{
5119 if (!pvalCheckType(p, "pvalMacroAddStatement", PV_MACRO))
5120 return;
5121 if (!p->u3.macro_statements)
5122 p->u3.macro_statements = statement;
5123 else
5124 linku1(p->u3.macro_statements, statement);
5125
5126
5127}

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

◆ pvalMacroCallAddArg()

void pvalMacroCallAddArg ( pval p,
pval arg 
)

Definition at line 5224 of file pval.c.

5225{
5226 if (!pvalCheckType(p, "pvalMacroCallGetAddArg", PV_MACRO_CALL))
5227 return;
5228 if (!p->u2.arglist)
5229 p->u2.arglist = arg;
5230 else
5231 linku1(p->u2.arglist, arg);
5232}

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

◆ pvalMacroCallGetMacroName()

char * pvalMacroCallGetMacroName ( pval p)

Definition at line 5210 of file pval.c.

5211{
5212 if (!pvalCheckType(p, "pvalMacroCallGetMacroName", PV_MACRO_CALL))
5213 return 0;
5214 return p->u1.str;
5215}

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

◆ pvalMacroCallSetArglist()

void pvalMacroCallSetArglist ( pval p,
pval arglist 
)

Definition at line 5217 of file pval.c.

5218{
5219 if (!pvalCheckType(p, "pvalMacroCallSetArglist", PV_MACRO_CALL))
5220 return;
5221 p->u2.arglist = arglist;
5222}

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

◆ pvalMacroCallSetMacroName()

void pvalMacroCallSetMacroName ( pval p,
char *  name 
)

Definition at line 5203 of file pval.c.

5204{
5205 if (!pvalCheckType(p, "pvalMacroCallSetMacroName", PV_MACRO_CALL))
5206 return;
5207 p->u1.str = name;
5208}

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

◆ pvalMacroCallWalkArgs()

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

Definition at line 5234 of file pval.c.

5235{
5236 if (!pvalCheckType(p, "pvalMacroCallWalkArgs", PV_MACRO_CALL))
5237 return 0;
5238 if (!(*args))
5239 *args = p->u2.arglist;
5240 else {
5241 *args = (*args)->next;
5242 }
5243 return *args;
5244}

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

◆ pvalMacroGetName()

char * pvalMacroGetName ( pval p)

Definition at line 5080 of file pval.c.

5081{
5082 if (!pvalCheckType(p, "pvalMacroGetName", PV_MACRO))
5083 return 0;
5084 return p->u1.str;
5085}

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

◆ pvalMacroSetArglist()

void pvalMacroSetArglist ( pval p,
pval arglist 
)

Definition at line 5087 of file pval.c.

5088{
5089 if (!pvalCheckType(p, "pvalMacroSetArglist", PV_MACRO))
5090 return;
5091 p->u2.arglist = arglist;
5092}

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

◆ pvalMacroSetName()

void pvalMacroSetName ( pval p,
char *  name 
)

Definition at line 5073 of file pval.c.

5074{
5075 if (!pvalCheckType(p, "pvalMacroSetName", PV_MACRO))
5076 return;
5077 p->u1.str = name;
5078}

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

◆ pvalMacroWalkArgs()

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

Definition at line 5105 of file pval.c.

5106{
5107 if (!pvalCheckType(p, "pvalMacroWalkArgs", PV_MACRO))
5108 return 0;
5109 if (!(*arg))
5110 *arg = p->u2.arglist;
5111 else {
5112 *arg = (*arg)->next;
5113 }
5114 return *arg;
5115}

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

◆ pvalMacroWalkStatements()

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

Definition at line 5129 of file pval.c.

5130{
5131 if (!pvalCheckType(p, "pvalMacroWalkStatements", PV_MACRO))
5132 return 0;
5133 if (!(*next_statement))
5134 *next_statement = p->u3.macro_statements;
5135 else {
5136 *next_statement = (*next_statement)->next;
5137 }
5138 return *next_statement;
5139}

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

◆ pvalObjectGetType()

pvaltype pvalObjectGetType ( pval p)

Definition at line 5052 of file pval.c.

5053{
5054 return p->type;
5055}

References pval::type.

◆ pvalRandomGetCondition()

char * pvalRandomGetCondition ( pval p)

Definition at line 5729 of file pval.c.

5730{
5731 if (!pvalCheckType(p, "pvalRandomGetCondition", PV_RANDOM))
5732 return 0;
5733 return p->u1.str;
5734}

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

◆ pvalRandomSetCondition()

void pvalRandomSetCondition ( pval p,
char *  percent 
)

Definition at line 5722 of file pval.c.

5723{
5724 if (!pvalCheckType(p, "pvalRandomSetCondition", PV_RANDOM))
5725 return;
5726 p->u1.str = percent;
5727}

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

◆ pvalStatementBlockAddStatement()

void pvalStatementBlockAddStatement ( pval p,
pval statement 
)

Definition at line 5480 of file pval.c.

5481{
5482 if (!pvalCheckType(p, "pvalStatementBlockAddStatement", PV_STATEMENTBLOCK))
5483 return;
5484 p->u1.list = linku1(p->u1.list, statement);
5485}

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

◆ pvalStatementBlockWalkStatements()

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

Definition at line 5487 of file pval.c.

5488{
5489 if (!pvalCheckType(p, "pvalStatementBlockWalkStatements", PV_STATEMENTBLOCK))
5490 return 0;
5491 if (!(*next_statement))
5492 *next_statement = p->u1.list;
5493 else {
5494 *next_statement = (*next_statement)->next;
5495 }
5496 return *next_statement;
5497}

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

◆ pvalSwitchAddCase()

void pvalSwitchAddCase ( pval p,
pval Case 
)

Definition at line 5770 of file pval.c.

5771{
5772 if (!pvalCheckType(p, "pvalSwitchAddCase", PV_SWITCH))
5773 return;
5774 if (!pvalCheckType(Case, "pvalSwitchAddCase", PV_CASE))
5775 return;
5776 if (!p->u2.statements)
5777 p->u2.statements = Case;
5778 else
5779 linku1(p->u2.statements, Case);
5780}

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

◆ pvalSwitchesAddSwitch()

void pvalSwitchesAddSwitch ( pval p,
char *  name 
)

Definition at line 5351 of file pval.c.

5352{
5353 pval *s;
5354 if (!pvalCheckType(p, "pvalSwitchesAddSwitch", PV_SWITCHES))
5355 return;
5357 s->u1.str = name;
5358 p->u1.list = linku1(p->u1.list, s);
5359}

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

◆ pvalSwitchesWalkNames()

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

Definition at line 5361 of file pval.c.

5362{
5363 if (!pvalCheckType(p, "pvalSwitchesWalkNames", PV_SWITCHES))
5364 return 0;
5365 if (!(*next_item))
5366 *next_item = p->u1.list;
5367 else {
5368 *next_item = (*next_item)->next;
5369 }
5370 return (*next_item)->u1.str;
5371}

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

◆ pvalSwitchGetTestexpr()

char * pvalSwitchGetTestexpr ( pval p)

Definition at line 5763 of file pval.c.

5764{
5765 if (!pvalCheckType(p, "pvalSwitchGetTestexpr", PV_SWITCH))
5766 return 0;
5767 return p->u1.str;
5768}

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

◆ pvalSwitchSetTestexpr()

void pvalSwitchSetTestexpr ( pval p,
char *  expr 
)

Definition at line 5756 of file pval.c.

5757{
5758 if (!pvalCheckType(p, "pvalSwitchSetTestexpr", PV_SWITCH))
5759 return;
5760 p->u1.str = expr;
5761}

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

◆ pvalSwitchWalkCases()

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

Definition at line 5782 of file pval.c.

5783{
5784 if (!pvalCheckType(p, "pvalSwitchWalkCases", PV_SWITCH))
5785 return 0;
5786 if (!(*next_case))
5787 *next_case = p->u2.statements;
5788 else {
5789 *next_case = (*next_case)->next;
5790 }
5791 return *next_case;
5792}

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

◆ pvalTopLevAddObject()

void pvalTopLevAddObject ( pval p,
pval contextOrObj 
)

Definition at line 5901 of file pval.c.

5902{
5903 if (p) {
5904 linku1(p,contextOrObj);
5905 } else {
5906 ast_log(LOG_ERROR, "First arg to pvalTopLevel is NULL!\n");
5907 }
5908}

References ast_log, linku1(), and LOG_ERROR.

◆ pvalTopLevWalkObjects()

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

Definition at line 5910 of file pval.c.

5911{
5912 if (!*next_obj) {
5913 *next_obj = p;
5914 return p;
5915 } else {
5916 *next_obj = (*next_obj)->next;
5917 return (*next_obj)->next;
5918 }
5919}

References pval::next.

◆ pvalVarDecGetValue()

char * pvalVarDecGetValue ( pval p)

Definition at line 5520 of file pval.c.

5521{
5522 if (!pvalCheckType(p, "pvalVarDecGetValue", PV_VARDEC))
5523 return 0;
5524 return p->u2.val;
5525}

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

◆ pvalVarDecGetVarname()

char * pvalVarDecGetVarname ( pval p)

Definition at line 5513 of file pval.c.

5514{
5515 if (!pvalCheckType(p, "pvalVarDecGetVarname", PV_VARDEC))
5516 return 0;
5517 return p->u1.str;
5518}

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

◆ pvalVarDecSetValue()

void pvalVarDecSetValue ( pval p,
char *  value 
)

Definition at line 5506 of file pval.c.

5507{
5508 if (!pvalCheckType(p, "pvalVarDecSetValue", PV_VARDEC))
5509 return;
5510 p->u2.val = value;
5511}
int value
Definition: syslog.c:37

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

◆ pvalVarDecSetVarname()

void pvalVarDecSetVarname ( pval p,
char *  name 
)

Definition at line 5499 of file pval.c.

5500{
5501 if (!pvalCheckType(p, "pvalVarDecSetVarname", PV_VARDEC))
5502 return;
5503 p->u1.str = name;
5504}

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

◆ pvalWordGetString()

char * pvalWordGetString ( pval p)

Definition at line 5065 of file pval.c.

5066{
5067 if (!pvalCheckType(p, "pvalWordGetString", PV_WORD))
5068 return 0;
5069 return p->u1.str;
5070}

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

◆ pvalWordSetString()

void pvalWordSetString ( pval p,
char *  str 
)

Definition at line 5058 of file pval.c.

5059{
5060 if (!pvalCheckType(p, "pvalWordSetString", PV_WORD))
5061 return;
5062 p->u1.str = str;
5063}

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

Referenced by pvalIfTimeSetCondition().

◆ remove_spaces_before_equals()

static void remove_spaces_before_equals ( char *  str)
static

Definition at line 3038 of file pval.c.

3039{
3040 char *p;
3041 while( str && *str && *str != '=' )
3042 {
3043 if( *str == ' ' || *str == '\n' || *str == '\r' || *str == '\t' )
3044 {
3045 p = str;
3046 while( *p )
3047 {
3048 *p = *(p+1);
3049 p++;
3050 }
3051 }
3052 else
3053 str++;
3054 }
3055}

References str.

Referenced by ast_compile_ael2(), and gen_prios().

◆ set_priorities()

void set_priorities ( struct ael_extension exten)

Definition at line 4187 of file pval.c.

4188{
4189 int i;
4190 struct ael_priority *pr;
4191 do {
4192 if (exten->is_switch)
4193 i = 10;
4194 else if (exten->regexten)
4195 i=2;
4196 else
4197 i=1;
4198
4199 for (pr=exten->plist; pr; pr=pr->next) {
4200 pr->priority_num = i;
4201
4202 if (!pr->origin || (pr->origin && pr->origin->type != PV_LABEL) ) /* Labels don't show up in the dialplan,
4203 but we want them to point to the right
4204 priority, which would be the next line
4205 after the label; */
4206 i++;
4207 }
4208
4210 } while ( exten );
4211}

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

Referenced by ast_compile_ael2().

◆ traverse_pval_item_template()

void traverse_pval_item_template ( pval item,
int  depth 
)

Definition at line 400 of file pval.c.

402{
403 pval *lp;
404
405 switch ( item->type ) {
406 case PV_WORD:
407 /* fields: item->u1.str == string associated with this (word). */
408 break;
409
410 case PV_MACRO:
411 /* fields: item->u1.str == name of macro
412 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
413 item->u2.arglist->u1.str == argument
414 item->u2.arglist->next == next arg
415
416 item->u3.macro_statements == pval list of statements in macro body.
417 */
418 for (lp=item->u2.arglist; lp; lp=lp->next) {
419
420 }
421 traverse_pval_item_template(item->u3.macro_statements,depth+1);
422 break;
423
424 case PV_CONTEXT:
425 /* fields: item->u1.str == name of context
426 item->u2.statements == pval list of statements in context body
427 item->u3.abstract == int 1 if an abstract keyword were present
428 */
429 traverse_pval_item_template(item->u2.statements,depth+1);
430 break;
431
432 case PV_MACRO_CALL:
433 /* fields: item->u1.str == name of macro to call
434 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
435 item->u2.arglist->u1.str == argument
436 item->u2.arglist->next == next arg
437 */
438 for (lp=item->u2.arglist; lp; lp=lp->next) {
439 }
440 break;
441
443 /* fields: item->u1.str == name of application to call
444 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
445 item->u2.arglist->u1.str == argument
446 item->u2.arglist->next == next arg
447 */
448 for (lp=item->u2.arglist; lp; lp=lp->next) {
449 }
450 break;
451
452 case PV_CASE:
453 /* fields: item->u1.str == value of case
454 item->u2.statements == pval list of statements under the case
455 */
456 traverse_pval_item_template(item->u2.statements,depth+1);
457 break;
458
459 case PV_PATTERN:
460 /* fields: item->u1.str == value of case
461 item->u2.statements == pval list of statements under the case
462 */
463 traverse_pval_item_template(item->u2.statements,depth+1);
464 break;
465
466 case PV_DEFAULT:
467 /* fields:
468 item->u2.statements == pval list of statements under the case
469 */
470 traverse_pval_item_template(item->u2.statements,depth+1);
471 break;
472
473 case PV_CATCH:
474 /* fields: item->u1.str == name of extension to catch
475 item->u2.statements == pval list of statements in context body
476 */
477 traverse_pval_item_template(item->u2.statements,depth+1);
478 break;
479
480 case PV_SWITCHES:
481 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
482 */
483 traverse_pval_item_template(item->u1.list,depth+1);
484 break;
485
486 case PV_ESWITCHES:
487 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
488 */
489 traverse_pval_item_template(item->u1.list,depth+1);
490 break;
491
492 case PV_INCLUDES:
493 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
494 item->u2.arglist == pval list of 4 PV_WORD elements for time values
495 */
496 traverse_pval_item_template(item->u1.list,depth+1);
497 traverse_pval_item_template(item->u2.arglist,depth+1);
498 break;
499
501 /* fields: item->u1.list == pval list of statements in block, one per entry in the list
502 */
503 traverse_pval_item_template(item->u1.list,depth+1);
504 break;
505
506 case PV_LOCALVARDEC:
507 case PV_VARDEC:
508 /* fields: item->u1.str == variable name
509 item->u2.val == variable value to assign
510 */
511 break;
512
513 case PV_GOTO:
514 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user.
515 item->u1.list->u1.str == where the data on a PV_WORD will always be.
516 */
517
518 if ( item->u1.list->next )
519 ;
520 if ( item->u1.list->next && item->u1.list->next->next )
521 ;
522
523 break;
524
525 case PV_LABEL:
526 /* fields: item->u1.str == label name
527 */
528 break;
529
530 case PV_FOR:
531 /* fields: item->u1.for_init == a string containing the initializer
532 item->u2.for_test == a string containing the loop test
533 item->u3.for_inc == a string containing the loop increment
534
535 item->u4.for_statements == a pval list of statements in the for ()
536 */
537 traverse_pval_item_template(item->u4.for_statements,depth+1);
538 break;
539
540 case PV_WHILE:
541 /* fields: item->u1.str == the while conditional, as supplied by user
542
543 item->u2.statements == a pval list of statements in the while ()
544 */
545 traverse_pval_item_template(item->u2.statements,depth+1);
546 break;
547
548 case PV_BREAK:
549 /* fields: none
550 */
551 break;
552
553 case PV_RETURN:
554 /* fields: none
555 */
556 break;
557
558 case PV_CONTINUE:
559 /* fields: none
560 */
561 break;
562
563 case PV_IFTIME:
564 /* fields: item->u1.list == there are 4 linked PV_WORDs here.
565
566 item->u2.statements == a pval list of statements in the if ()
567 item->u3.else_statements == a pval list of statements in the else
568 (could be zero)
569 */
570 traverse_pval_item_template(item->u2.statements,depth+1);
571 if ( item->u3.else_statements ) {
572 traverse_pval_item_template(item->u3.else_statements,depth+1);
573 }
574 break;
575
576 case PV_RANDOM:
577 /* fields: item->u1.str == the random number expression, as supplied by user
578
579 item->u2.statements == a pval list of statements in the if ()
580 item->u3.else_statements == a pval list of statements in the else
581 (could be zero)
582 */
583 traverse_pval_item_template(item->u2.statements,depth+1);
584 if ( item->u3.else_statements ) {
585 traverse_pval_item_template(item->u3.else_statements,depth+1);
586 }
587 break;
588
589 case PV_IF:
590 /* fields: item->u1.str == the if conditional, as supplied by user
591
592 item->u2.statements == a pval list of statements in the if ()
593 item->u3.else_statements == a pval list of statements in the else
594 (could be zero)
595 */
596 traverse_pval_item_template(item->u2.statements,depth+1);
597 if ( item->u3.else_statements ) {
598 traverse_pval_item_template(item->u3.else_statements,depth+1);
599 }
600 break;
601
602 case PV_SWITCH:
603 /* fields: item->u1.str == the switch expression
604
605 item->u2.statements == a pval list of statements in the switch,
606 (will be case statements, most likely!)
607 */
608 traverse_pval_item_template(item->u2.statements,depth+1);
609 break;
610
611 case PV_EXTENSION:
612 /* fields: item->u1.str == the extension name, label, whatever it's called
613
614 item->u2.statements == a pval list of statements in the extension
615 item->u3.hints == a char * hint argument
616 item->u4.regexten == an int boolean. non-zero says that regexten was specified
617 */
618 traverse_pval_item_template(item->u2.statements,depth+1);
619 break;
620
621 case PV_IGNOREPAT:
622 /* fields: item->u1.str == the ignorepat data
623 */
624 break;
625
626 case PV_GLOBALS:
627 /* fields: item->u1.statements == pval list of statements, usually vardecs
628 */
629 traverse_pval_item_template(item->u1.statements,depth+1);
630 break;
631 }
632}
void traverse_pval_item_template(pval *item, int depth)
Definition: pval.c:400

References item, pval::next, PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTEXT, PV_CONTINUE, PV_DEFAULT, PV_ESWITCHES, PV_EXTENSION, PV_FOR, PV_GLOBALS, PV_GOTO, PV_IF, PV_IFTIME, PV_IGNOREPAT, PV_INCLUDES, PV_LABEL, PV_LOCALVARDEC, PV_MACRO, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_SWITCHES, PV_VARDEC, PV_WHILE, PV_WORD, traverse_pval_item_template(), and aco_type::type.

Referenced by traverse_pval_item_template(), and traverse_pval_template().

◆ traverse_pval_template()

void traverse_pval_template ( pval item,
int  depth 
)

Definition at line 634 of file pval.c.

636{
637 pval *i;
638
639 for (i=item; i; i=i->next) {
641 }
642}

References item, pval::next, and traverse_pval_item_template().

Variable Documentation

◆ control_statement_count

int control_statement_count
static

Definition at line 2922 of file pval.c.

Referenced by ast_compile_ael2(), and gen_prios().

◆ count_labels

int count_labels
static

◆ current_context

pval* current_context
static

Definition at line 73 of file pval.c.

Referenced by check_label(), and check_pval_item().

◆ current_db

pval* current_db
static

◆ current_extension

pval* current_extension
static

Definition at line 74 of file pval.c.

Referenced by check_label(), check_pval_item(), and check_switch_expr().

◆ days

char* days[]
static

Definition at line 886 of file pval.c.

Referenced by check_dow().

◆ errs

int errs
static

◆ expr_output

char expr_output[2096]
static

Definition at line 60 of file pval.c.

Referenced by check_pval_item().

◆ in_abstract_context

int in_abstract_context
static

Definition at line 79 of file pval.c.

Referenced by check_pval_item().

◆ label_count

int label_count
static

Definition at line 81 of file pval.c.

Referenced by match_pval_item().

◆ last_matched_label

pval* last_matched_label
static

Definition at line 83 of file pval.c.

Referenced by match_pval_item().

◆ match_context

const char* match_context
static

◆ match_exten

const char* match_exten
static

◆ match_label

const char* match_label
static

◆ months

char* months[]
static

Definition at line 984 of file pval.c.

Referenced by check_month().

◆ notes

int notes
static

◆ registrar

char* registrar = "pbx_ael"
static

Definition at line 70 of file pval.c.

Referenced by add_extensions(), and ast_compile_ael2().

◆ return_on_context_match

int return_on_context_match
static

◆ warns

int warns
static