Asterisk - The Open Source Telephony Project  GIT-master-44aef04
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"

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.

Referenced by gen_prios().

Function Documentation

◆ add_extensions()

void add_extensions ( struct ael_extension exten)

Definition at line 4213 of file pval.c.

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

Referenced by ast_compile_ael2().

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,
4228  exten->hints, NULL, ast_free_ptr, registrar, NULL, 0)) {
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,
4308  app, strdup(appargs), ast_free_ptr, registrar, NULL, 0)) {
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  }
4314  exten = exten->next_exten;
4315  } while ( exten );
4316 }
struct pval * origin
Definition: ael_structs.h:95
Definition: pval.h:32
struct ael_priority * goto_true
Definition: ael_structs.h:98
#define LOG_WARNING
Definition: logger.h:274
union pval::@281 u3
struct ael_priority * plist
Definition: ael_structs.h:115
#define NULL
Definition: resample.c:96
struct ael_priority * goto_false
Definition: ael_structs.h:99
char * appargs
Definition: ael_structs.h:93
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1771
struct ael_extension * next_exten
Definition: ael_structs.h:117
struct ast_context * context
Definition: ael_structs.h:113
char * cidmatch
Definition: ael_structs.h:106
#define ast_log
Definition: astobj2.c:42
struct sla_ringing_trunk * last
Definition: app_meetme.c:1092
#define AST_MAX_EXTENSION
Definition: channel.h:135
struct ael_extension * exten
Definition: ael_structs.h:96
char * str
Definition: pval.h:59
#define PRIORITY_HINT
Definition: pbx.h:54
char * app
Definition: ael_structs.h:92
static char * registrar
Definition: pval.c:70
struct pval * else_statements
Definition: pval.h:78
struct ael_priority * next
Definition: ael_structs.h:100
pvaltype type
Definition: pval.h:50
union pval::@279 u1
int priority_num
Definition: ael_structs.h:89
Definition: pval.h:30
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:7299
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211
ael_priority_type type
Definition: ael_structs.h:90
#define strdup(a)
Definition: astmm.h:165
static const char app[]
Definition: app_mysql.c:62

◆ ael2_print()

void ael2_print ( char *  fname,
pval tree 
)

Definition at line 382 of file pval.c.

References ast_log, item, LOG_ERROR, print_pval_list(), traverse_pval_item_template(), and traverse_pval_template().

Referenced by main().

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 ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static void print_pval_list(FILE *fin, pval *item, int depth)
Definition: pval.c:373

◆ 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.

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

Referenced by pbx_load_module().

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 }
static int errs
Definition: pval.c:65
Registered applications container.
Definition: pbx_app.c:67
static struct aco_type item
Definition: test_config.c:1463
Definition: pval.h:110
static int notes
Definition: pval.c:66
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
static int warns
Definition: pval.c:65
const char * ast_config_AST_VAR_DIR
Definition: options.c:157
static pval * current_db
Definition: pval.c:72
static void check_context_names(void)
Definition: pval.c:2310
void check_pval(pval *item, struct argapp *apps, int in_globals)
Definition: pval.c:2865

◆ 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.

References add_extensions(), AEL_APPCALL, AEL_LABEL, 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, ael_extension::context, context, context_used(), control_statement_count, destroy_extensions(), ael_priority::exten, exten, fix_gotos_in_extensions(), gen_prios(), pval::hints, ael_extension::hints, linkprio(), pval::list, 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, pval::regexten, ael_extension::regexten, registrar, remove_spaces_before_equals(), ael_extension::return_needed, set_priorities(), pval::statements, pval::str, strdup, pval::type, ael_priority::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.

Referenced by pbx_load_module().

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);
4432  pbx_builtin_setvar(NULL, buf2);
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 
4447  context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar);
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 
4478  set_priorities(exten);
4479  attach_exten(&exten_list, exten);
4480  break;
4481 
4482  case PV_GLOBALS:
4483  /* already done */
4484  break;
4485 
4486  case PV_CONTEXT:
4487  context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar);
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);
4498  exten->context = context;
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 
4531  set_priorities(exten);
4532  attach_exten(&exten_list, exten);
4533  break;
4534 
4535  case PV_IGNOREPAT:
4536  ast_context_add_ignorepat2(context, p2->u1.str, registrar);
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);
4548  ast_context_add_include2(context, buf, registrar);
4549  } else
4550  ast_context_add_include2(context, p3->u1.str, registrar);
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 
4563  ast_context_add_switch2(context, p3->u1.str, c, 0, registrar);
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 
4576  ast_context_add_switch2(context, p3->u1.str, c, 1, registrar);
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  };
4618  context = ast_context_find_or_create(local_contexts, local_table, h_context, registrar);
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);
4627  context = ast_context_find_or_create(local_contexts, local_table, h_context_template + 5, registrar);
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 context_used(struct ael_extension *exten_list, struct ast_context *context)
Definition: pval.c:4398
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int regexten
Definition: pval.h:90
static int control_statement_count
Definition: pval.c:2922
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
struct pval * origin
Definition: ael_structs.h:95
const char * ast_get_context_name(struct ast_context *con)
Definition: ael_main.c:421
struct pval * list
Definition: pval.h:60
void set_priorities(struct ael_extension *exten)
Definition: pval.c:4187
static void fix_gotos_in_extensions(struct ael_extension *exten)
Definition: pval.c:4355
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
struct ael_extension * new_exten(void)
Definition: pval.c:2930
struct ael_priority * plist_last
Definition: ael_structs.h:116
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
union pval::@280 u2
struct pval * statements
Definition: pval.h:61
static struct ast_threadstorage buf2
union pval::@281 u3
static struct test_val c
#define NULL
Definition: resample.c:96
char * appargs
Definition: ael_structs.h:93
static int priority
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
struct ael_extension * next_exten
Definition: ael_structs.h:117
void linkprio(struct ael_extension *exten, struct ael_priority *prio, struct ael_extension *mother_exten)
Definition: pval.c:2936
struct ast_context * context
Definition: ael_structs.h:113
int ast_context_add_include2(struct ast_context *con, const char *include, const char *registrar)
Add a context include.
Definition: ael_main.c:359
char * cidmatch
Definition: ael_structs.h:106
char * val
Definition: pval.h:70
struct ael_extension * exten
Definition: ael_structs.h:96
union pval::@282 u4
char * str
Definition: pval.h:59
Definition: pval.h:48
struct ael_priority * new_prio(void)
Definition: pval.c:2924
void destroy_extensions(struct ael_extension *exten)
Definition: pval.c:2978
char * hints
Definition: pval.h:81
struct ast_custom_function * ast_custom_function_find(const char *name)
Definition: ael_main.c:173
char * app
Definition: ael_structs.h:92
static char * registrar
Definition: pval.c:70
struct pval * arglist
Definition: pval.h:68
Definition: pval.h:9
pvaltype type
Definition: pval.h:50
static void attach_exten(struct ael_extension **list, struct ael_extension *newmem)
Definition: pval.c:4318
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 &#39;=&#39; character...
union pval::@279 u1
int priority_num
Definition: ael_structs.h:89
static void remove_spaces_before_equals(char *str)
Definition: pval.c:3038
struct pval * next
Definition: pval.h:93
int ast_context_add_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
Definition: ael_main.c:348
ael_priority_type type
Definition: ael_structs.h:90
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
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:6198
#define strdup(a)
Definition: astmm.h:165
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
void add_extensions(struct ael_extension *exten)
Definition: pval.c:4213
struct pval * macro_statements
Definition: pval.h:79

◆ attach_exten()

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

Definition at line 4318 of file pval.c.

References ael_extension::next_exten.

Referenced by ast_compile_ael2().

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 }
struct ael_extension * next_exten
Definition: ael_structs.h:117

◆ check_abstract_reference()

static void check_abstract_reference ( pval abstract_context)
static

Definition at line 2329 of file pval.c.

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

Referenced by check_pval_item().

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 }
struct pval * list
Definition: pval.h:60
#define LOG_WARNING
Definition: logger.h:274
union pval::@280 u2
int startline
Definition: pval.h:51
#define ast_log
Definition: astobj2.c:42
char * filename
Definition: pval.h:55
char * str
Definition: pval.h:59
Definition: pval.h:48
pvaltype type
Definition: pval.h:50
union pval::@279 u1
static int warns
Definition: pval.c:65
struct pval * next
Definition: pval.h:93
int endline
Definition: pval.h:52
static pval * current_db
Definition: pval.c:72

◆ check_app_args()

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

Definition at line 2130 of file pval.c.

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

Referenced by check_pval_item().

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 }
#define LOG_WARNING
Definition: logger.h:274
int startline
Definition: pval.h:51
#define ast_log
Definition: astobj2.c:42
char * filename
Definition: pval.h:55
char * str
Definition: pval.h:59
Definition: pval.h:48
union pval::@279 u1
static int warns
Definition: pval.c:65
struct pval * next
Definition: pval.h:93
int endline
Definition: pval.h:52

◆ check_break()

static int check_break ( pval item)
static

Definition at line 1038 of file pval.c.

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

Referenced by check_pval_item().

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 }
static int errs
Definition: pval.c:65
struct pval * dad
Definition: pval.h:96
static struct aco_type item
Definition: test_config.c:1463
int startline
Definition: pval.h:51
#define ast_log
Definition: astobj2.c:42
Definition: pval.h:13
char * filename
Definition: pval.h:55
Definition: pval.h:48
#define LOG_ERROR
Definition: logger.h:285
Definition: pval.h:24
Definition: pval.h:9
Definition: pval.h:25
pvaltype type
Definition: pval.h:50
int endline
Definition: pval.h:52

◆ check_context_names()

static void check_context_names ( void  )
static

Definition at line 2310 of file pval.c.

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

Referenced by ael2_semantic_check().

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 }
#define LOG_WARNING
Definition: logger.h:274
union pval::@281 u3
int startline
Definition: pval.h:51
int abstract
Definition: pval.h:80
#define ast_log
Definition: astobj2.c:42
char * filename
Definition: pval.h:55
char * str
Definition: pval.h:59
Definition: pval.h:48
Definition: pval.h:9
pvaltype type
Definition: pval.h:50
union pval::@279 u1
static int warns
Definition: pval.c:65
struct pval * next
Definition: pval.h:93
int endline
Definition: pval.h:52
static pval * current_db
Definition: pval.c:72

◆ check_continue()

static int check_continue ( pval item)
static

Definition at line 1058 of file pval.c.

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

Referenced by check_pval_item().

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 }
static int errs
Definition: pval.c:65
struct pval * dad
Definition: pval.h:96
static struct aco_type item
Definition: test_config.c:1463
int startline
Definition: pval.h:51
#define ast_log
Definition: astobj2.c:42
char * filename
Definition: pval.h:55
Definition: pval.h:48
#define LOG_ERROR
Definition: logger.h:285
Definition: pval.h:24
Definition: pval.h:9
Definition: pval.h:25
pvaltype type
Definition: pval.h:50
int endline
Definition: pval.h:52

◆ check_day()

static void check_day ( pval DAY)
static

Definition at line 937 of file pval.c.

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

Referenced by check_pval_item().

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 LOG_WARNING
Definition: logger.h:274
int startline
Definition: pval.h:51
static struct test_val c
#define ast_log
Definition: astobj2.c:42
char * filename
Definition: pval.h:55
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
char * str
Definition: pval.h:59
#define ast_strlen_zero(a)
Definition: muted.c:73
union pval::@279 u1
static int warns
Definition: pval.c:65
int endline
Definition: pval.h:52

◆ check_dow()

static void check_dow ( pval DOW)
static

get_dow: Get day of week

Definition at line 898 of file pval.c.

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

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 }
#define LOG_WARNING
Definition: logger.h:274
int startline
Definition: pval.h:51
static struct test_val c
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
char * filename
Definition: pval.h:55
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
char * str
Definition: pval.h:59
#define ast_strlen_zero(a)
Definition: muted.c:73
union pval::@279 u1
static char * days[]
Definition: pval.c:886
static int warns
Definition: pval.c:65
int endline
Definition: pval.h:52

◆ check_expr2_input()

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

Definition at line 801 of file pval.c.

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

Referenced by check_pval_item().

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 }
#define LOG_WARNING
Definition: logger.h:274
int startline
Definition: pval.h:51
const char * str
Definition: app_jack.c:147
#define ast_log
Definition: astobj2.c:42
char * filename
Definition: pval.h:55
static int warns
Definition: pval.c:65
int endline
Definition: pval.h:52

◆ check_goto()

static void check_goto ( pval item)
static

Definition at line 1225 of file pval.c.

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

Referenced by check_pval_item(), and find_pval_goto_item().

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 }
static struct pval * in_macro(pval *item)
Definition: pval.c:1077
static int errs
Definition: pval.c:65
struct pval * list
Definition: pval.h:60
static struct pval * find_label_in_current_extension(const char *label, pval *curr_ext)
Definition: pval.c:1918
#define LOG_WARNING
Definition: logger.h:274
union pval::@280 u2
struct pval * statements
Definition: pval.h:61
struct pval * find_context(char *name)
Definition: pval.c:1953
int startline
Definition: pval.h:51
#define NULL
Definition: resample.c:96
static struct pval * in_context(pval *item)
Definition: pval.c:1090
static pval * get_contxt(pval *p)
Definition: pval.c:4345
#define ast_log
Definition: astobj2.c:42
char * filename
Definition: pval.h:55
int localized_pbx_load_module(void)
Definition: extconf.c:5647
char * str
Definition: pval.h:59
Definition: pval.h:48
static struct pval * find_label_in_current_context(char *exten, char *label, pval *curr_cont)
Definition: pval.c:1879
#define LOG_ERROR
Definition: logger.h:285
struct sla_ringing_trunk * first
Definition: app_meetme.c:1092
static struct pval * find_label_in_current_db(const char *context, const char *exten, const char *label)
Definition: pval.c:1929
#define STATUS_SUCCESS
Definition: extconf.h:249
int stacklen
Definition: extconf.h:238
pvaltype type
Definition: pval.h:50
union pval::@279 u1
static int warns
Definition: pval.c:65
struct pval * next
Definition: pval.h:93
int endline
Definition: pval.h:52
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 pval * get_extension_or_contxt(pval *p)
Definition: pval.c:4335

◆ check_includes()

static void check_includes ( pval includes)
static

Definition at line 811 of file pval.c.

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

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 }
struct pval * list
Definition: pval.h:60
#define LOG_WARNING
Definition: logger.h:274
struct pval * find_context(char *name)
Definition: pval.c:1953
int startline
Definition: pval.h:51
#define ast_log
Definition: astobj2.c:42
char * filename
Definition: pval.h:55
char * str
Definition: pval.h:59
Definition: pval.h:48
union pval::@279 u1
static int warns
Definition: pval.c:65
struct pval * next
Definition: pval.h:93
int endline
Definition: pval.h:52

◆ check_label()

static void check_label ( pval item)
static

Definition at line 1106 of file pval.c.

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

Referenced by check_pval_item().

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 int errs
Definition: pval.c:65
struct pval * dad
Definition: pval.h:96
static struct aco_type item
Definition: test_config.c:1463
int startline
Definition: pval.h:51
#define ast_log
Definition: astobj2.c:42
static pval * current_extension
Definition: pval.c:74
char * filename
Definition: pval.h:55
char * str
Definition: pval.h:59
Definition: pval.h:48
#define LOG_ERROR
Definition: logger.h:285
Definition: pval.h:9
pvaltype type
Definition: pval.h:50
union pval::@279 u1
static pval * current_context
Definition: pval.c:73
static struct pval * find_first_label_in_current_context(char *label, pval *curr_cont)
Definition: pval.c:1839
int endline
Definition: pval.h:52

◆ check_macro_returns()

static void check_macro_returns ( pval macro)
static

Definition at line 650 of file pval.c.

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

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 LOG_WARNING
Definition: logger.h:274
union pval::@281 u3
int startline
Definition: pval.h:51
#define NULL
Definition: resample.c:96
#define calloc(a, b)
Definition: astmm.h:157
#define ast_log
Definition: astobj2.c:42
char * filename
Definition: pval.h:55
char * str
Definition: pval.h:59
Definition: pval.h:48
int endcol
Definition: pval.h:54
pvaltype type
Definition: pval.h:50
union pval::@279 u1
struct pval * next
Definition: pval.h:93
Definition: pval.h:27
#define strdup(a)
Definition: astmm.h:165
int endline
Definition: pval.h:52
int startcol
Definition: pval.h:53
struct pval * macro_statements
Definition: pval.h:79

◆ check_month()

static void check_month ( pval MON)
static

Definition at line 1000 of file pval.c.

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

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 }
#define LOG_WARNING
Definition: logger.h:274
int startline
Definition: pval.h:51
static struct test_val c
#define ast_log
Definition: astobj2.c:42
char * filename
Definition: pval.h:55
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
char * str
Definition: pval.h:59
#define ast_strlen_zero(a)
Definition: muted.c:73
union pval::@279 u1
static char * months[]
Definition: pval.c:984
static int warns
Definition: pval.c:65
int endline
Definition: pval.h:52

◆ check_pval()

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

Definition at line 2865 of file pval.c.

References check_pval_item(), and pval::next.

Referenced by ael2_semantic_check(), and check_pval_item().

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
Definition: pval.h:48
struct pval * next
Definition: pval.h:93

◆ check_pval_item()

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

Definition at line 2357 of file pval.c.

References pval::abstract, app, pval::arglist, ast_expr(), ast_expr_clear_extra_error_info(), ast_expr_register_extra_error_info(), ast_log, check_abstract_reference(), check_app_args(), check_break(), check_continue(), check_day(), check_dow(), check_expr2_input(), check_goto(), check_includes(), check_label(), check_macro_returns(), check_month(), check_pval(), check_switch_expr(), check_timerange(), E_MATCH, pval::else_statements, pval::endcol, pval::endline, errs, expr_output, pval::filename, find_context(), find_macro(), find_pval_gotos(), pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, free(), in_abstract_context, item, pval::list, localized_pbx_load_module(), LOG_ERROR, LOG_WARNING, pval::macro_statements, pval::next, argapp::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::startcol, pval::startline, pval::statements, pbx_find_info::status, STATUS_SUCCESS, pval::str, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, pval::val, and warns.

Referenced by check_pval().

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  */
2383  in_abstract_context = 0;
2385  current_extension = 0;
2386 
2387  check_macro_returns(item);
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  */
2401  current_extension = 0;
2402  if ( item->u3.abstract ) {
2403  in_abstract_context = 1;
2405  } else
2406  in_abstract_context = 0;
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 
2494  case PV_APPLICATION_CALL:
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);
2604  check_includes(item);
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 ) {
2610  check_timerange(lp->u2.arglist);
2611  check_dow(lp->u2.arglist->next);
2612  check_day(lp->u2.arglist->next->next);
2613  check_month(lp->u2.arglist->next->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 
2673  check_goto(item);
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 
2685  check_label(item);
2686  break;
2687 
2688  case PV_FOR:
2689  /* fields: item->u1.for_init == a string containing the initalizer
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  */
2745  check_break(item);
2746  break;
2747 
2748  case PV_RETURN:
2749  /* fields: none
2750  */
2751  break;
2752 
2753  case PV_CONTINUE:
2754  /* fields: none
2755  */
2756  check_continue(item);
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? */
2833  check_switch_expr(item, apps);
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  */
2857  in_abstract_context = 0;
2858  check_pval(item->u1.statements, apps, 1);
2859  break;
2860  default:
2861  break;
2862  }
2863 }
char * for_inc
Definition: pval.h:77
static void find_pval_gotos(pval *item, int lev)
Definition: pval.c:1550
static int check_break(pval *item)
Definition: pval.c:1038
static int errs
Definition: pval.c:65
struct pval * list
Definition: pval.h:60
Definition: pval.h:32
Definition: pval.h:29
#define LOG_WARNING
Definition: logger.h:274
union pval::@280 u2
struct pval * statements
Definition: pval.h:61
struct pval * find_macro(char *name)
Definition: pval.c:1943
struct pval * find_context(char *name)
Definition: pval.c:1953
static struct aco_type item
Definition: test_config.c:1463
union pval::@281 u3
static void check_day(pval *DAY)
Definition: pval.c:937
Definition: pval.h:22
int startline
Definition: pval.h:51
#define NULL
Definition: resample.c:96
int abstract
Definition: pval.h:80
Definition: pval.h:8
Definition: pval.h:110
static void check_abstract_reference(pval *abstract_context)
Definition: pval.c:2329
char * val
Definition: pval.h:70
#define ast_log
Definition: astobj2.c:42
void free()
static int check_continue(pval *item)
Definition: pval.c:1058
static pval * current_extension
Definition: pval.c:74
Definition: pval.h:13
static int in_abstract_context
Definition: pval.c:79
static void check_timerange(pval *p)
Definition: pval.c:830
char * filename
Definition: pval.h:55
static void check_macro_returns(pval *macro)
Definition: pval.c:650
Definition: pval.h:21
union pval::@282 u4
int localized_pbx_load_module(void)
Definition: extconf.c:5647
char * str
Definition: pval.h:59
Definition: pval.h:48
char * for_test
Definition: pval.h:71
static char expr_output[2096]
Definition: pval.c:60
void ast_expr_clear_extra_error_info(void)
Definition: ast_expr2f.c:2483
#define LOG_ERROR
Definition: logger.h:285
struct pval * else_statements
Definition: pval.h:78
static void check_goto(pval *item)
Definition: pval.c:1225
Definition: pval.h:24
struct pval * arglist
Definition: pval.h:68
int endcol
Definition: pval.h:54
static void check_label(pval *item)
Definition: pval.c:1106
#define STATUS_SUCCESS
Definition: extconf.h:249
Definition: pval.h:9
Definition: pval.h:31
static void check_includes(pval *includes)
Definition: pval.c:811
Definition: pval.h:25
int stacklen
Definition: extconf.h:238
pvaltype type
Definition: pval.h:50
union pval::@279 u1
void ast_expr_register_extra_error_info(char *errmsg)
Definition: ast_expr2f.c:2477
static void check_month(pval *MON)
Definition: pval.c:1000
Definition: pval.h:30
Definition: pval.h:23
static pval * current_context
Definition: pval.c:73
static int warns
Definition: pval.c:65
struct argapp * next
Definition: pval.h:112
struct pval * next
Definition: pval.h:93
static void check_expr2_input(pval *expr, char *str)
Definition: pval.c:801
Definition: pval.h:27
struct pval * for_statements
Definition: pval.h:89
void check_switch_expr(pval *item, struct argapp *apps)
Definition: pval.c:2184
static const char app[]
Definition: app_mysql.c:62
int endline
Definition: pval.h:52
int startcol
Definition: pval.h:53
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
int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan)
Evaluate the given expression.
Definition: ast_expr2f.c:2405
Definition: pval.h:26
char * for_init
Definition: pval.h:62
int check_app_args(pval *appcall, pval *arglist, struct argapp *app)
Definition: pval.c:2130
Definition: pval.h:16
static void check_dow(pval *DOW)
get_dow: Get day of week
Definition: pval.c:898
struct pval * macro_statements
Definition: pval.h:79
void check_pval(pval *item, struct argapp *apps, int in_globals)
Definition: pval.c:2865

◆ check_switch_expr()

void check_switch_expr ( pval item,
struct argapp apps 
)

Definition at line 2184 of file pval.c.

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

Referenced by check_pval_item().

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 }
#define LOG_WARNING
Definition: logger.h:274
union pval::@280 u2
struct pval * statements
Definition: pval.h:61
static struct aco_type item
Definition: test_config.c:1463
int startline
Definition: pval.h:51
static struct test_val c
Definition: pval.h:110
#define calloc(a, b)
Definition: astmm.h:157
#define ast_log
Definition: astobj2.c:42
static pval * current_extension
Definition: pval.c:74
Definition: pval.h:13
char * filename
Definition: pval.h:55
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
char * str
Definition: pval.h:59
Definition: pval.h:48
int endcol
Definition: pval.h:54
pvaltype type
Definition: pval.h:50
union pval::@279 u1
static int warns
Definition: pval.c:65
struct argapp * next
Definition: pval.h:112
struct pval * next
Definition: pval.h:93
#define strdup(a)
Definition: astmm.h:165
int endline
Definition: pval.h:52
int startcol
Definition: pval.h:53
static struct test_val a

◆ check_timerange()

static void check_timerange ( pval p)
static

Definition at line 830 of file pval.c.

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

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 }
#define LOG_WARNING
Definition: logger.h:274
int startline
Definition: pval.h:51
#define ast_log
Definition: astobj2.c:42
char * filename
Definition: pval.h:55
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
char * str
Definition: pval.h:59
#define ast_strlen_zero(a)
Definition: muted.c:73
union pval::@279 u1
static int warns
Definition: pval.c:65
int endline
Definition: pval.h:52

◆ contains_switch()

int contains_switch ( pval item)

Definition at line 3329 of file pval.c.

References find_switch_item(), and pval::next.

Referenced by find_switch_item(), gen_match_to_pattern(), and gen_prios().

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 }
Definition: pval.h:48
int find_switch_item(pval *item)
Definition: pval.c:3090
struct pval * next
Definition: pval.h:93

◆ context_used()

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

Definition at line 4398 of file pval.c.

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

Referenced by ast_compile_ael2().

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 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int ast_context_switches_count(const struct ast_context *con)
Definition: pbx.c:8652
#define NULL
Definition: resample.c:96
struct ael_extension * next_exten
Definition: ael_structs.h:117
struct ast_context * context
Definition: ael_structs.h:113
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8697
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
Definition: ael_main.c:427
int ast_context_ignorepats_count(const struct ast_context *con)
Definition: pbx.c:8740

◆ destroy_extensions()

void destroy_extensions ( struct ael_extension exten)

Definition at line 2978 of file pval.c.

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

Referenced by ast_compile_ael2().

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 pval * origin
Definition: ael_structs.h:95
struct ael_priority * goto_true
Definition: ael_structs.h:98
struct ael_priority * plist_last
Definition: ael_structs.h:116
struct ael_priority * plist
Definition: ael_structs.h:115
struct ael_priority * goto_false
Definition: ael_structs.h:99
char * appargs
Definition: ael_structs.h:93
struct ael_extension * next_exten
Definition: ael_structs.h:117
void free()
struct ael_priority * loop_break
Definition: ael_structs.h:119
char * app
Definition: ael_structs.h:92
struct ael_priority * loop_continue
Definition: ael_structs.h:120
struct ael_priority * next
Definition: ael_structs.h:100

◆ destroy_pval()

void destroy_pval ( pval item)

Definition at line 4940 of file pval.c.

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

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

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

◆ destroy_pval_item()

void destroy_pval_item ( pval item)

Definition at line 4672 of file pval.c.

References pval::arglist, ast_log, destroy_pval(), pval::else_statements, pval::filename, pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, free(), pval::hints, pval::list, LOG_WARNING, pval::macro_statements, 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, pval::statements, pval::str, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.

Referenced by destroy_pval().

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);
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 
4726  case PV_APPLICATION_CALL:
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 initalizer
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);
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) {
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) {
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 }
char * for_inc
Definition: pval.h:77
struct pval * list
Definition: pval.h:60
Definition: pval.h:32
Definition: pval.h:29
#define LOG_WARNING
Definition: logger.h:274
union pval::@280 u2
struct pval * statements
Definition: pval.h:61
union pval::@281 u3
Definition: pval.h:22
#define NULL
Definition: resample.c:96
Definition: pval.h:8
char * val
Definition: pval.h:70
#define ast_log
Definition: astobj2.c:42
void free()
Definition: pval.h:13
char * filename
Definition: pval.h:55
Definition: pval.h:21
union pval::@282 u4
void destroy_pval(pval *item)
Definition: pval.c:4940
char * str
Definition: pval.h:59
char * for_test
Definition: pval.h:71
char * hints
Definition: pval.h:81
struct pval * else_statements
Definition: pval.h:78
Definition: pval.h:24
struct pval * arglist
Definition: pval.h:68
Definition: pval.h:9
Definition: pval.h:31
Definition: pval.h:25
pvaltype type
Definition: pval.h:50
union pval::@279 u1
Definition: pval.h:30
Definition: pval.h:23
Definition: pval.h:27
struct pval * for_statements
Definition: pval.h:89
Definition: pval.h:26
char * for_init
Definition: pval.h:62
Definition: pval.h:16
struct pval * macro_statements
Definition: pval.h:79

◆ extension_matches()

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

Definition at line 694 of file pval.c.

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

Referenced by match_pval_item().

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 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define LOG_WARNING
Definition: logger.h:274
int startline
Definition: pval.h:51
#define ast_log
Definition: astobj2.c:42
char * filename
Definition: pval.h:55
#define LOG_ERROR
Definition: logger.h:285
int endline
Definition: pval.h:52

◆ find_context()

struct pval* find_context ( char *  name)

Definition at line 1953 of file pval.c.

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

1954 {
1956  count_labels = 0;
1957  match_context = name;
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 int count_labels
Definition: pval.c:80
static const char name[]
Definition: cdr_mysql.c:74
static const char * match_exten
Definition: pval.c:77
static int return_on_context_match
Definition: pval.c:82
static pval * current_db
Definition: pval.c:72
struct pval * match_pval(pval *item)
Definition: pval.c:1811
static const char * match_context
Definition: pval.c:76
static const char * match_label
Definition: pval.c:78

◆ 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.

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

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 }
struct pval * list
Definition: pval.h:60
union pval::@280 u2
struct pval * statements
Definition: pval.h:61
struct pval * find_context(char *name)
Definition: pval.c:1953
char * str
Definition: pval.h:59
Definition: pval.h:48
static int count_labels
Definition: pval.c:80
pvaltype type
Definition: pval.h:50
union pval::@279 u1
static struct pval * find_first_label_in_current_context(char *label, pval *curr_cont)
Definition: pval.c:1839
struct pval * next
Definition: pval.h:93
static const char * match_exten
Definition: pval.c:77
static int return_on_context_match
Definition: pval.c:82
struct pval * match_pval(pval *item)
Definition: pval.c:1811
static const char * match_context
Definition: pval.c:76
static const char * match_label
Definition: pval.c:78

◆ 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.

References count_labels, exten, find_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(), and get_goto_target().

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 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
struct pval * list
Definition: pval.h:60
union pval::@280 u2
struct pval * statements
Definition: pval.h:61
struct pval * find_context(char *name)
Definition: pval.c:1953
char * str
Definition: pval.h:59
Definition: pval.h:48
static struct pval * find_label_in_current_context(char *exten, char *label, pval *curr_cont)
Definition: pval.c:1879
static int count_labels
Definition: pval.c:80
pvaltype type
Definition: pval.h:50
union pval::@279 u1
struct pval * next
Definition: pval.h:93
static const char * match_exten
Definition: pval.c:77
static int return_on_context_match
Definition: pval.c:82
struct pval * match_pval(pval *item)
Definition: pval.c:1811
static const char * match_context
Definition: pval.c:76
static const char * match_label
Definition: pval.c:78

◆ 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.

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

Referenced by check_goto(), and get_goto_target().

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 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static int count_labels
Definition: pval.c:80
static const char * match_exten
Definition: pval.c:77
static int return_on_context_match
Definition: pval.c:82
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static pval * current_db
Definition: pval.c:72
struct pval * match_pval(pval *item)
Definition: pval.c:1811
static const char * match_context
Definition: pval.c:76
static const char * match_label
Definition: pval.c:78

◆ 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.

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

Referenced by check_goto(), and get_goto_target().

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 }
static int count_labels
Definition: pval.c:80
static const char * match_exten
Definition: pval.c:77
static int return_on_context_match
Definition: pval.c:82
struct pval * match_pval(pval *item)
Definition: pval.c:1811
static const char * match_context
Definition: pval.c:76
static const char * match_label
Definition: pval.c:78

◆ find_macro()

struct pval* find_macro ( char *  name)

Definition at line 1943 of file pval.c.

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

Referenced by check_pval_item().

1944 {
1946  count_labels = 0;
1947  match_context = name;
1948  match_exten = "*"; /* don't really need to set these, shouldn't be reached */
1949  match_label = "*";
1950  return match_pval(current_db);
1951 }
static int count_labels
Definition: pval.c:80
static const char name[]
Definition: cdr_mysql.c:74
static const char * match_exten
Definition: pval.c:77
static int return_on_context_match
Definition: pval.c:82
static pval * current_db
Definition: pval.c:72
struct pval * match_pval(pval *item)
Definition: pval.c:1811
static const char * match_context
Definition: pval.c:76
static const char * match_label
Definition: pval.c:78

◆ find_pval_goto_item()

static void find_pval_goto_item ( pval item,
int  lev 
)
static

Definition at line 1379 of file pval.c.

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

Referenced by find_pval_gotos().

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 initalizer
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 }
static void find_pval_gotos(pval *item, int lev)
Definition: pval.c:1550
struct pval * list
Definition: pval.h:60
Definition: pval.h:32
Definition: pval.h:29
union pval::@280 u2
struct pval * statements
Definition: pval.h:61
struct pval * find_context(char *name)
Definition: pval.c:1953
union pval::@281 u3
Definition: pval.h:22
#define ast_log
Definition: astobj2.c:42
Definition: pval.h:13
union pval::@282 u4
char * str
Definition: pval.h:59
Definition: pval.h:48
#define LOG_ERROR
Definition: logger.h:285
struct pval * else_statements
Definition: pval.h:78
static void check_goto(pval *item)
Definition: pval.c:1225
Definition: pval.h:24
Definition: pval.h:9
Definition: pval.h:31
Definition: pval.h:25
pvaltype type
Definition: pval.h:50
union pval::@279 u1
Definition: pval.h:30
struct pval * next
Definition: pval.h:93
struct pval * for_statements
Definition: pval.h:89
Definition: pval.h:16
struct pval * macro_statements
Definition: pval.h:79

◆ find_pval_gotos()

static void find_pval_gotos ( pval item,
int  lev 
)
static

Definition at line 1550 of file pval.c.

References find_pval_goto_item(), and pval::next.

Referenced by check_pval_item(), and find_pval_goto_item().

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 }
Definition: pval.h:48
struct pval * next
Definition: pval.h:93
static void find_pval_goto_item(pval *item, int lev)
Definition: pval.c:1379

◆ find_switch_item()

int find_switch_item ( pval item)

Definition at line 3090 of file pval.c.

References contains_switch(), pval::else_statements, pval::for_statements, pval::list, pval::macro_statements, PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTEXT, PV_CONTINUE, PV_DEFAULT, PV_ESWITCHES, PV_EXTENSION, PV_FOR, PV_GLOBALS, PV_GOTO, PV_IF, PV_IFTIME, PV_IGNOREPAT, PV_INCLUDES, PV_LABEL, PV_LOCALVARDEC, PV_MACRO, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_SWITCHES, PV_VARDEC, PV_WHILE, PV_WORD, pval::statements, pval::type, pval::u1, pval::u2, pval::u3, and pval::u4.

Referenced by contains_switch(), and gen_match_to_pattern().

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 
3132  case PV_APPLICATION_CALL:
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 initalizer
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 }
struct pval * list
Definition: pval.h:60
Definition: pval.h:32
Definition: pval.h:29
union pval::@280 u2
struct pval * statements
Definition: pval.h:61
union pval::@281 u3
Definition: pval.h:22
Definition: pval.h:8
Definition: pval.h:13
Definition: pval.h:21
union pval::@282 u4
struct pval * else_statements
Definition: pval.h:78
Definition: pval.h:24
Definition: pval.h:9
Definition: pval.h:31
Definition: pval.h:25
int contains_switch(pval *item)
Definition: pval.c:3329
pvaltype type
Definition: pval.h:50
union pval::@279 u1
Definition: pval.h:30
Definition: pval.h:23
Definition: pval.h:27
struct pval * for_statements
Definition: pval.h:89
Definition: pval.h:26
Definition: pval.h:16
struct pval * macro_statements
Definition: pval.h:79

◆ fix_gotos_in_extensions()

static void fix_gotos_in_extensions ( struct ael_extension exten)
static

Definition at line 4355 of file pval.c.

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

Referenced by ast_compile_ael2().

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 }
struct pval * origin
Definition: ael_structs.h:95
struct pval * list
Definition: pval.h:60
union pval::@280 u2
union pval::@281 u3
struct ael_priority * plist
Definition: ael_structs.h:115
Definition: pval.h:22
char * appargs
Definition: ael_structs.h:93
struct ael_extension * next_exten
Definition: ael_structs.h:117
void free()
struct pval * goto_target
Definition: pval.h:72
char * str
Definition: pval.h:59
Definition: pval.h:48
struct ael_extension * compiled_label
Definition: pval.h:83
int goto_target_in_case
Definition: pval.h:82
static struct ast_threadstorage buf1
struct ael_priority * next
Definition: ael_structs.h:100
pvaltype type
Definition: pval.h:50
union pval::@279 u1
struct pval * next
Definition: pval.h:93
#define strdup(a)
Definition: astmm.h:165

◆ gen_match_to_pattern()

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

Definition at line 3061 of file pval.c.

References contains_switch(), find_switch_item(), and result.

Referenced by gen_prios().

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:88

◆ 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.

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, exten, first, pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, free(), gen_match_to_pattern(), get_goto_target(), ael_priority::goto_false, pval::goto_target, pval::goto_target_in_case, ael_priority::goto_true, ael_extension::has_switch, ael_extension::is_switch, label_inside_case(), linkexten(), linkprio(), pval::list, ael_extension::loop_break, ael_extension::loop_continue, malloc(), ael_extension::name, new_exten(), new_prio(), pval::next, 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, pval::type, ael_priority::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.

Referenced by ast_compile_ael2().

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;