Asterisk - The Open Source Telephony Project  18.5.0
Macros | Functions | Variables
pbx_ael.c File Reference

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

#include "asterisk.h"
#include <ctype.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/callerid.h"
#include "asterisk/hashtab.h"
#include "asterisk/ael_structs.h"
#include "asterisk/pval.h"
Include dependency graph for pbx_ael.c:

Go to the source code of this file.

Macros

#define DEBUG_CONTEXTS   (1 << 3)
 
#define DEBUG_MACROS   (1 << 2)
 
#define DEBUG_READ   (1 << 0)
 
#define DEBUG_TOKENS   (1 << 1)
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
void add_extensions (struct ael_extension *exten)
 
static int aelsub_exec (struct ast_channel *chan, const char *vdata)
 
int ast_compile_ael2 (struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root)
 
void ast_expr_clear_extra_error_info (void)
 
void ast_expr_register_extra_error_info (char *errmsg)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
int check_app_args (pval *appcall, pval *arglist, struct argapp *app)
 
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)
 
void destroy_extensions (struct ael_extension *exten)
 
void destroy_pval (pval *item)
 
void destroy_pval_item (pval *item)
 
struct pvalfind_context (char *name)
 
struct pvalfind_macro (char *name)
 
static char * handle_cli_ael_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_ael_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
int is_empty (char *arg)
 
int is_float (char *arg)
 
int is_int (char *arg)
 
static int load_module (void)
 
struct ael_extensionnew_exten (void)
 
struct ael_prioritynew_prio (void)
 
static int pbx_load_module (void)
 
static int reload (void)
 
void set_priorities (struct ael_extension *exten)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Asterisk Extension Language Compiler" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .requires = "res_ael_share", }
 
static int aeldebug = 0
 
static char * aelsub = "AELSub"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry cli_ael []
 
static char * config = "extensions.ael"
 
static char * registrar = "pbx_ael"
 

Detailed Description

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

Definition in file pbx_ael.c.

Macro Definition Documentation

◆ DEBUG_CONTEXTS

#define DEBUG_CONTEXTS   (1 << 3)

Definition at line 75 of file pbx_ael.c.

Referenced by handle_cli_ael_set_debug().

◆ DEBUG_MACROS

#define DEBUG_MACROS   (1 << 2)

Definition at line 74 of file pbx_ael.c.

Referenced by handle_cli_ael_set_debug().

◆ DEBUG_READ

#define DEBUG_READ   (1 << 0)

Definition at line 72 of file pbx_ael.c.

Referenced by handle_cli_ael_set_debug().

◆ DEBUG_TOKENS

#define DEBUG_TOKENS   (1 << 1)

Definition at line 73 of file pbx_ael.c.

Referenced by handle_cli_ael_set_debug().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 296 of file pbx_ael.c.

300 {

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 296 of file pbx_ael.c.

300 {

◆ 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 }
union pval::@285 u1
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
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
union pval::@287 u3
struct ael_priority * next
Definition: ael_structs.h:100
pvaltype type
Definition: pval.h:50
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

◆ aelsub_exec()

static int aelsub_exec ( struct ast_channel chan,
const char *  vdata 
)
static

Definition at line 126 of file pbx_ael.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_STANDARD_RAW_ARGS, ast_strdupa, buf, name, pbx_exec(), and pbx_findapp().

Referenced by load_module().

127 {
128  char buf[256], *data = ast_strdupa(vdata);
129  struct ast_app *gosub = pbx_findapp("Gosub");
131  AST_APP_ARG(name);
132  AST_APP_ARG(args);
133  );
134 
135  if (gosub) {
137  snprintf(buf, sizeof(buf), "%s,~~s~~,1(%s)", args.name, args.args);
138  return pbx_exec(chan, gosub, buf);
139  }
140  return -1;
141 }
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_STANDARD_RAW_ARGS(args, parse)
const char * args
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static const char name[]
Definition: cdr_mysql.c:74
ast_app: A registered application
Definition: pbx_app.c:45
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ 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
union pval::@285 u1
#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
struct pval * statements
Definition: pval.h:61
static struct ast_threadstorage buf2
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
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
union pval::@287 u3
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...
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
union pval::@288 u4
union pval::@286 u2

◆ ast_expr_clear_extra_error_info()

void ast_expr_clear_extra_error_info ( void  )

Definition at line 2483 of file ast_expr2f.c.

2484 {
2486  extra_error_message[0] = 0;
2487 }
char extra_error_message[4095]
Definition: ast_expr2f.c:2472
int extra_error_message_supplied
Definition: ast_expr2f.c:2473

◆ ast_expr_register_extra_error_info()

void ast_expr_register_extra_error_info ( char *  errmsg)

Definition at line 2477 of file ast_expr2f.c.

2478 {
2480  strcpy(extra_error_message, message);
2481 }
char extra_error_message[4095]
Definition: ast_expr2f.c:2472
int extra_error_message_supplied
Definition: ast_expr2f.c:2473

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 296 of file pbx_ael.c.

300 {

◆ 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 }
union pval::@285 u1
#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
static int warns
Definition: pval.c:65
struct pval * next
Definition: pval.h:93
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
union pval::@285 u1
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
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
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
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
union pval::@287 u3
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
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
union pval::@288 u4
union pval::@286 u2
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 }
union pval::@285 u1
#define LOG_WARNING
Definition: logger.h:274
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
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
union pval::@286 u2
static struct test_val a

◆ 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(), and pvalIncludesAddIncludeWithTimeConstraints().

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
union pval::@285 u1
struct pval * list
Definition: pval.h:60
Definition: pval.h:32
Definition: pval.h:29
#define LOG_WARNING
Definition: logger.h:274
struct pval * statements
Definition: pval.h:61
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
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
union pval::@287 u3
Definition: pval.h:31
Definition: pval.h:25
pvaltype type
Definition: pval.h:50
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
union pval::@288 u4
union pval::@286 u2

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

◆ handle_cli_ael_reload()

static char* handle_cli_ael_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 232 of file pbx_ael.c.

References ast_cli_args::argc, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, pbx_load_module(), and ast_cli_entry::usage.

233 {
234  switch (cmd) {
235  case CLI_INIT:
236  e->command = "ael reload";
237  e->usage =
238  "Usage: ael reload\n"
239  " Reloads AEL configuration.\n";
240  return NULL;
241  case CLI_GENERATE:
242  return NULL;
243  }
244 
245  if (a->argc != 2)
246  return CLI_SHOWUSAGE;
247 
248  return (pbx_load_module() ? CLI_FAILURE : CLI_SUCCESS);
249 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
static int pbx_load_module(void)
Definition: pbx_ael.c:146

◆ handle_cli_ael_set_debug()

static char* handle_cli_ael_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 198 of file pbx_ael.c.

References aeldebug, ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, DEBUG_CONTEXTS, DEBUG_MACROS, DEBUG_READ, DEBUG_TOKENS, NULL, and ast_cli_entry::usage.

199 {
200  switch (cmd) {
201  case CLI_INIT:
202  e->command = "ael set debug {read|tokens|macros|contexts|off}";
203  e->usage =
204  "Usage: ael set debug {read|tokens|macros|contexts|off}\n"
205  " Enable AEL read, token, macro, or context debugging,\n"
206  " or disable all AEL debugging messages. Note: this\n"
207  " currently does nothing.\n";
208  return NULL;
209  case CLI_GENERATE:
210  return NULL;
211  }
212 
213  if (a->argc != e->args)
214  return CLI_SHOWUSAGE;
215 
216  if (!strcasecmp(a->argv[3], "read"))
217  aeldebug |= DEBUG_READ;
218  else if (!strcasecmp(a->argv[3], "tokens"))
220  else if (!strcasecmp(a->argv[3], "macros"))
222  else if (!strcasecmp(a->argv[3], "contexts"))
224  else if (!strcasecmp(a->argv[3], "off"))
225  aeldebug = 0;
226  else
227  return CLI_SHOWUSAGE;
228 
229  return CLI_SUCCESS;
230 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
static int aeldebug
Definition: pbx_ael.c:119
#define NULL
Definition: resample.c:96
#define DEBUG_MACROS
Definition: pbx_ael.c:74
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define DEBUG_CONTEXTS
Definition: pbx_ael.c:75
char * command
Definition: cli.h:186
#define DEBUG_TOKENS
Definition: pbx_ael.c:73
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define DEBUG_READ
Definition: pbx_ael.c:72

◆ is_empty()

int is_empty ( char *  arg)

Definition at line 1981 of file pval.c.

References app, ast_log, ast_strdupa, pval::endline, errs, pval::filename, is_float(), is_int(), LOG_ERROR, LOG_WARNING, argapp::next, pval::startline, pval::str, pval::u1, and warns.

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

◆ is_float()

int is_float ( char *  arg)

Definition at line 1963 of file pval.c.

Referenced by is_empty().

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

◆ is_int()

int is_int ( char *  arg)

Definition at line 1972 of file pval.c.

Referenced by is_empty().

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

◆ load_module()

static int load_module ( void  )
static

Definition at line 266 of file pbx_ael.c.

References aelsub, aelsub_exec(), ARRAY_LEN, ast_cli_register_multiple, ast_register_application_xml, and pbx_load_module().

Referenced by reload().

267 {
269 #ifndef STANDALONE
271 #endif
272  return (pbx_load_module());
273 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static char * aelsub
Definition: pbx_ael.c:124
static int aelsub_exec(struct ast_channel *chan, const char *vdata)
Definition: pbx_ael.c:126
static struct ast_cli_entry cli_ael[]
Definition: pbx_ael.c:251
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
static int pbx_load_module(void)
Definition: pbx_ael.c:146

◆ new_exten()

struct ael_extension* new_exten ( void  )

Definition at line 2930 of file pval.c.

References calloc.

Referenced by ast_compile_ael2(), and gen_prios().

2931 {
2932  struct ael_extension *x = (struct ael_extension *)calloc(sizeof(struct ael_extension),1);
2933  return x;
2934 }
#define calloc(a, b)
Definition: astmm.h:157

◆ new_prio()

struct ael_priority* new_prio ( void  )

Definition at line 2924 of file pval.c.

References calloc.

Referenced by ast_compile_ael2(), and gen_prios().

2925 {
2926  struct ael_priority *x = (struct ael_priority *)calloc(sizeof(struct ael_priority),1);
2927  return x;
2928 }
#define calloc(a, b)
Definition: astmm.h:157

◆ pbx_load_module()

static int pbx_load_module ( void  )
static

Definition at line 146 of file pbx_ael.c.

References ael2_parse(), ael2_semantic_check(), ast_alloca, ast_compile_ael2(), ast_config_AST_CONFIG_DIR, ast_context_verify_includes(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create, ast_hashtab_hash_contexts(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log, ast_merge_contexts_and_delete(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_walk_contexts(), config, destroy_pval(), errs, local_contexts, local_table, LOG_ERROR, LOG_NOTICE, NULL, and registrar.

Referenced by handle_cli_ael_reload(), load_module(), and reload().

147 {
148  int errs=0, sem_err=0, sem_warn=0, sem_note=0;
149  char *rfilename;
150  struct ast_context *local_contexts=NULL, *con;
151  struct ast_hashtab *local_table=NULL;
152 
153  struct pval *parse_tree;
154 
155  ast_debug(1, "Starting AEL load process.\n");
156  if (config[0] == '/')
157  rfilename = (char *)config;
158  else {
159  rfilename = ast_alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2);
160  sprintf(rfilename, "%s/%s", ast_config_AST_CONFIG_DIR, config);
161  }
162  if (access(rfilename,R_OK) != 0) {
163  ast_log(LOG_NOTICE, "File %s not found; AEL declining load\n", rfilename);
165  }
166 
167  parse_tree = ael2_parse(rfilename, &errs);
168  ast_debug(1, "AEL load process: parsed config file name '%s'.\n", rfilename);
169  ael2_semantic_check(parse_tree, &sem_err, &sem_warn, &sem_note);
170  if (errs == 0 && sem_err == 0) {
171  ast_debug(1, "AEL load process: checked config file name '%s'.\n", rfilename);
173  if (ast_compile_ael2(&local_contexts, local_table, parse_tree)) {
174  ast_log(LOG_ERROR, "AEL compile failed! Aborting.\n");
175  destroy_pval(parse_tree); /* free up the memory */
177  }
178  ast_debug(1, "AEL load process: compiled config file name '%s'.\n", rfilename);
179 
180  ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);
181  local_table = NULL; /* it's the dialplan global now */
182  local_contexts = NULL;
183  ast_debug(1, "AEL load process: merged config file name '%s'.\n", rfilename);
184  for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con))
186  ast_debug(1, "AEL load process: verified config file name '%s'.\n", rfilename);
187  } else {
188  ast_log(LOG_ERROR, "Sorry, but %d syntax errors and %d semantic errors were detected. It doesn't make sense to compile.\n", errs, sem_err);
189  destroy_pval(parse_tree); /* free up the memory */
191  }
192  destroy_pval(parse_tree); /* free up the memory */
193 
195 }
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition: ael_main.c:589
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition: hashtab.c:127
static int errs
Definition: pval.c:65
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: conf2ael.c:618
#define NULL
Definition: resample.c:96
struct ast_context * local_contexts
int ast_hashtab_resize_java(struct ast_hashtab *tab)
Determines if a table resize should occur using the Java algorithm (if the table load factor is 75% o...
Definition: hashtab.c:84
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
Definition: pval.h:48
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define LOG_ERROR
Definition: logger.h:285
int ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root)
Definition: pval.c:4413
const char * ast_config_AST_CONFIG_DIR
Definition: options.c:151
void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
Merge the temporary contexts into a global contexts list and delete from the global list the ones tha...
Definition: conf2ael.c:639
static char * config
Definition: pbx_ael.c:77
#define LOG_NOTICE
Definition: logger.h:263
static struct ast_hashtab * local_table
Definition: pbx_config.c:112
static char * registrar
Definition: pbx_ael.c:78
unsigned int ast_hashtab_hash_contexts(const void *obj)
Definition: ael_main.c:596
void destroy_pval(pval *item)
Definition: pval.c:4940
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
struct pval * ael2_parse(char *fname, int *errs)
Definition: ael_lex.c:3360
void ael2_semantic_check(pval *item, int *errs, int *warns, int *notes)
Definition: pval.c:2885
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Definition: hashtab.h:261
int ast_context_verify_includes(struct ast_context *con)
Verifies includes in an ast_contect structure.
Definition: conf2ael.c:632
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

◆ reload()

static int reload ( void  )
static

Definition at line 275 of file pbx_ael.c.

References ael_external_load_module(), AST_MODFLAG_DEFAULT, AST_MODULE_INFO(), AST_MODULE_SUPPORT_EXTENDED, ASTERISK_GPL_KEY, load_module(), pbx_load_module(), and unload_module().

276 {
277  return pbx_load_module();
278 }
static int pbx_load_module(void)
Definition: pbx_ael.c:146

◆ set_priorities()

void set_priorities ( struct ael_extension exten)

Definition at line 4187 of file pval.c.

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

Referenced by ast_compile_ael2().

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

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 256 of file pbx_ael.c.

References aelsub, ARRAY_LEN, ast_cli_unregister_multiple(), ast_context_destroy(), ast_unregister_application(), NULL, and registrar.

Referenced by reload().

257 {
260 #ifndef STANDALONE
262 #endif
263  return 0;
264 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define NULL
Definition: resample.c:96
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static char * aelsub
Definition: pbx_ael.c:124
static char * registrar
Definition: pbx_ael.c:78
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: conf2ael.c:625
static struct ast_cli_entry cli_ael[]
Definition: pbx_ael.c:251

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Asterisk Extension Language Compiler" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .requires = "res_ael_share", }
static

Definition at line 296 of file pbx_ael.c.

◆ aeldebug

int aeldebug = 0
static

Definition at line 119 of file pbx_ael.c.

Referenced by handle_cli_ael_set_debug().

◆ aelsub

char* aelsub = "AELSub"
static

Definition at line 124 of file pbx_ael.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 296 of file pbx_ael.c.

◆ cli_ael

struct ast_cli_entry cli_ael[]
static
Initial value:
= {
{ .handler = handle_cli_ael_reload , .summary = "Reload AEL configuration" ,},
{ .handler = handle_cli_ael_set_debug , .summary = "Enable AEL debugging flags" ,}
}
static char * handle_cli_ael_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx_ael.c:198
static char * handle_cli_ael_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx_ael.c:232

Definition at line 251 of file pbx_ael.c.

◆ config

char* config = "extensions.ael"
static

Definition at line 77 of file pbx_ael.c.

Referenced by pbx_load_module().

◆ registrar

char* registrar = "pbx_ael"
static