Sat Nov 1 06:29:12 2008

Asterisk developer's documentation


pbx_ael.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/callerid.h"
#include "asterisk/ael_structs.h"

Include dependency graph for pbx_ael.c:

Go to the source code of this file.

Data Structures

struct  argapp

Defines

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

Functions

void add_extensions (struct ael_extension *exten)
static int ael2_debug_contexts (int fd, int argc, char *argv[])
static int ael2_debug_macros (int fd, int argc, char *argv[])
static int ael2_debug_read (int fd, int argc, char *argv[])
static int ael2_debug_tokens (int fd, int argc, char *argv[])
static int ael2_no_debug (int fd, int argc, char *argv[])
static int ael2_reload (int fd, int argc, char *argv[])
static void ael2_semantic_check (pval *item, int *arg_errs, int *arg_warns, int *arg_notes)
void ast_compile_ael2 (struct ast_context **local_contexts, struct pval *root)
int ast_expr (char *expr, char *buf, int length)
void ast_expr_clear_extra_error_info (void)
void ast_expr_register_extra_error_info (char *errmsg)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Asterisk Extension Language Compiler",.load=load_module,.unload=unload_module,.reload=reload,)
static void attach_exten (struct ael_extension **list, struct ael_extension *newmem)
static void check_abstract_reference (pval *abstract_context)
int check_app_args (pval *appcall, pval *arglist, struct argapp *app)
static int check_break (pval *item)
static void check_context_names (void)
static int check_continue (pval *item)
static void check_day (pval *DAY)
static void check_dow (pval *DOW)
 get_dow: Get day of week
static void check_expr2_input (pval *expr, char *str)
static void check_goto (pval *item)
static void check_includes (pval *includes)
static void check_label (pval *item)
static void check_month (pval *MON)
void check_pval (pval *item, struct argapp *apps, int in_globals)
void check_pval_item (pval *item, struct argapp *apps, int in_globals)
void check_switch_expr (pval *item, struct argapp *apps)
static void check_timerange (pval *p)
int contains_switch (pval *item)
void destroy_extensions (struct ael_extension *exten)
void destroy_pval (pval *item)
void destroy_pval_item (pval *item)
static int extension_matches (pval *here, const char *exten, const char *pattern)
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)
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 void gen_prios (struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *context)
static pvalget_contxt (pval *p)
static pvalget_extension_or_contxt (pval *p)
static pvalget_goto_target (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)
static int load_module (void)
pvalmatch_pval (pval *item)
static struct pvalmatch_pval_item (pval *item)
ael_extensionnew_exten (void)
ael_prioritynew_prio (void)
static int pbx_load_module (void)
static void print_pval (FILE *fin, pval *item, int depth)
static void print_pval_list (FILE *fin, pval *item, int depth)
static int reload (void)
static void remove_spaces_before_equals (char *str)
void set_priorities (struct ael_extension *exten)
static void substitute_commas (char *str)
void traverse_pval_item_template (pval *item, int depth)
void traverse_pval_template (pval *item, int depth)
static int unload_module (void)

Variables

static int aeldebug = 0
static struct ast_cli_entry cli_ael []
static struct ast_cli_entry cli_ael_no_debug
static char * config = "extensions.ael"
static int control_statement_count = 0
static int count_labels
static pvalcurrent_context = 0
static pvalcurrent_db = 0
static pvalcurrent_extension = 0
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 pbx_ael.c.


Define Documentation

#define DEBUG_CONTEXTS   (1 << 3)

Definition at line 60 of file pbx_ael.c.

Referenced by ael2_debug_contexts().

#define DEBUG_MACROS   (1 << 2)

Definition at line 59 of file pbx_ael.c.

Referenced by ael2_debug_macros().

#define DEBUG_READ   (1 << 0)

Definition at line 57 of file pbx_ael.c.

Referenced by ael2_debug_read().

#define DEBUG_TOKENS   (1 << 1)

Definition at line 58 of file pbx_ael.c.

Referenced by ael2_debug_tokens().


Function Documentation

void add_extensions ( struct ael_extension exten  ) 

Definition at line 4065 of file pbx_ael.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, app, ael_priority::appargs, ast_add_extension2(), ast_free, ast_log(), AST_MAX_EXTENSION, pval::else_statements, ael_priority::exten, exten, ael_priority::goto_false, ael_priority::goto_true, last, LOG_WARNING, ael_extension::name, ael_priority::next, ael_priority::origin, pbx_substitute_variables_helper(), PRIORITY_HINT, ael_priority::priority_num, PV_IFTIME, PV_SWITCH, strdup, pval::type, ael_priority::type, and pval::u3.

04066 {
04067    struct ael_priority *pr;
04068    char *label=0;
04069    char realext[AST_MAX_EXTENSION];
04070    if (!exten) {
04071       ast_log(LOG_WARNING, "This file is Empty!\n" );
04072       return;
04073    }
04074    do {
04075       struct ael_priority *last = 0;
04076 
04077       memset(realext, '\0', sizeof(realext));
04078       pbx_substitute_variables_helper(NULL, exten->name, realext, sizeof(realext) - 1);
04079       if (exten->hints) {
04080          if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, PRIORITY_HINT, NULL, exten->cidmatch, 
04081                           exten->hints, NULL, ast_free, registrar)) {
04082             ast_log(LOG_WARNING, "Unable to add step at priority 'hint' of extension '%s'\n",
04083                   exten->name);
04084          }
04085       }
04086       
04087       for (pr=exten->plist; pr; pr=pr->next) {
04088          char app[2000];
04089          char appargs[2000];
04090 
04091          /* before we can add the extension, we need to prep the app/appargs;
04092             the CONTROL types need to be done after the priority numbers are calculated.
04093          */
04094          if (pr->type == AEL_LABEL) /* don't try to put labels in the dialplan! */ {
04095             last = pr;
04096             continue;
04097          }
04098          
04099          if (pr->app)
04100             strcpy(app, pr->app);
04101          else
04102             app[0] = 0;
04103          if (pr->appargs )
04104             strcpy(appargs, pr->appargs);
04105          else
04106             appargs[0] = 0;
04107          switch( pr->type ) {
04108          case AEL_APPCALL:
04109             /* easy case. Everything is all set up */
04110             break;
04111             
04112          case AEL_CONTROL1: /* FOR loop, WHILE loop, BREAK, CONTINUE, IF, IFTIME */
04113             /* simple, unconditional goto. */
04114             strcpy(app,"Goto");
04115             if (pr->goto_true->origin && pr->goto_true->origin->type == PV_SWITCH ) {
04116                snprintf(appargs,sizeof(appargs),"%s|%d", pr->goto_true->exten->name, pr->goto_true->priority_num);
04117             } else if (pr->goto_true->origin && pr->goto_true->origin->type == PV_IFTIME && pr->goto_true->origin->u3.else_statements ) {
04118                snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num+1);
04119             } else
04120                snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num);
04121             break;
04122             
04123          case AEL_FOR_CONTROL:  /* WHILE loop test, FOR loop test */
04124             strcpy(app,"GotoIf");
04125             snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num);
04126             break;
04127             
04128          case AEL_IF_CONTROL:
04129             strcpy(app,"GotoIf");
04130             if (pr->origin->u3.else_statements )
04131                snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num+1);
04132             else
04133                snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num);
04134             break;
04135 
04136          case AEL_RAND_CONTROL:
04137             strcpy(app,"Random");
04138             snprintf(appargs,sizeof(appargs),"%s:%d", pr->appargs, pr->goto_true->priority_num+1);
04139             break;
04140 
04141          case AEL_IFTIME_CONTROL:
04142             strcpy(app,"GotoIfTime");
04143             snprintf(appargs,sizeof(appargs),"%s?%d", pr->appargs, pr->priority_num+2);
04144             break;
04145 
04146          case AEL_RETURN:
04147             strcpy(app,"Goto");
04148             snprintf(appargs,sizeof(appargs), "%d", exten->return_target->priority_num);
04149             break;
04150             
04151          default:
04152             break;
04153          }
04154          if (last && last->type == AEL_LABEL ) {
04155             label = last->origin->u1.str;
04156          }
04157          else
04158             label = 0;
04159          
04160          if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, pr->priority_num, (label?label:NULL), exten->cidmatch, 
04161                           app, strdup(appargs), ast_free, registrar)) {
04162             ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num, 
04163                   exten->name);
04164          }
04165          last = pr;
04166       }
04167       exten = exten->next_exten;
04168    } while ( exten );
04169 }

static int ael2_debug_contexts ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4526 of file pbx_ael.c.

References DEBUG_CONTEXTS.

04527 {
04528    aeldebug |= DEBUG_CONTEXTS;
04529    return 0;
04530 }

static int ael2_debug_macros ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4520 of file pbx_ael.c.

References DEBUG_MACROS.

04521 {
04522    aeldebug |= DEBUG_MACROS;
04523    return 0;
04524 }

static int ael2_debug_read ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4508 of file pbx_ael.c.

References DEBUG_READ.

04509 {
04510    aeldebug |= DEBUG_READ;
04511    return 0;
04512 }

static int ael2_debug_tokens ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4514 of file pbx_ael.c.

References DEBUG_TOKENS.

04515 {
04516    aeldebug |= DEBUG_TOKENS;
04517    return 0;
04518 }

static int ael2_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4532 of file pbx_ael.c.

04533 {
04534    aeldebug = 0;
04535    return 0;
04536 }

static int ael2_reload ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4538 of file pbx_ael.c.

References pbx_load_module().

04539 {
04540    return (pbx_load_module());
04541 }

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

Definition at line 2743 of file pbx_ael.c.

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

Referenced by pbx_load_module().

02744 {
02745    
02746 #ifdef AAL_ARGCHECK
02747    int argapp_errs =0;
02748    char *rfilename;
02749 #endif
02750    struct argapp *apps=0;
02751 
02752    if (!item)
02753       return; /* don't check an empty tree */
02754 #ifdef AAL_ARGCHECK
02755    rfilename = alloca(10 + strlen(ast_config_AST_VAR_DIR));
02756    sprintf(rfilename, "%s/applist", ast_config_AST_VAR_DIR);
02757    
02758    apps = argdesc_parse(rfilename, &argapp_errs); /* giveth */
02759 #endif
02760    current_db = item;
02761    errs = warns = notes = 0;
02762 
02763    check_context_names();
02764    check_pval(item, apps, 0);
02765 
02766 #ifdef AAL_ARGCHECK
02767    argdesc_destroy(apps);  /* taketh away */
02768 #endif
02769    current_db = 0;
02770 
02771    *arg_errs = errs;
02772    *arg_warns = warns;
02773    *arg_notes = notes;
02774 }

void ast_compile_ael2 ( struct ast_context **  local_contexts,
struct pval root 
)

Definition at line 4252 of file pbx_ael.c.

References context, exten, pval::list, pval::next, pbx_builtin_setvar(), PV_GLOBALS, pval::str, pval::type, pval::u1, pval::u2, and pval::val.

Referenced by pbx_load_module().

04253 {
04254    pval *p,*p2;
04255    struct ast_context *context;
04256    char buf[2000];
04257    struct ael_extension *exten;
04258    struct ael_extension *exten_list = 0;
04259 
04260    for (p=root; p; p=p->next ) { /* do the globals first, so they'll be there
04261                             when we try to eval them */
04262       switch (p->type) {
04263       case PV_GLOBALS:
04264          /* just VARDEC elements */
04265          for (p2=p->u1.list; p2; p2=p2->next) {
04266             char buf2[2000];
04267             snprintf(buf2,sizeof(buf2),"%s=%s", p2->u1.str, p2->u2.val);
04268             pbx_builtin_setvar(NULL, buf2);
04269          }
04270          break;
04271       default:
04272          break;
04273       }
04274    }
04275    
04276    for (p=root; p; p=p->next ) {
04277       pval *lp;
04278       int argc;
04279       
04280       switch (p->type) {
04281       case PV_MACRO:
04282          strcpy(buf,"macro-");
04283          strcat(buf,p->u1.str);
04284          context = ast_context_create(local_contexts, buf, registrar);
04285          
04286          exten = new_exten();
04287          exten->context = context;
04288          exten->name = strdup("s");
04289          argc = 1;
04290          for (lp=p->u2.arglist; lp; lp=lp->next) {
04291             /* for each arg, set up a "Set" command */
04292             struct ael_priority *np2 = new_prio();
04293             np2->type = AEL_APPCALL;
04294             np2->app = strdup("Set");
04295             snprintf(buf,sizeof(buf),"%s=${ARG%d}", lp->u1.str, argc++);
04296             remove_spaces_before_equals(buf);
04297             np2->appargs = strdup(buf);
04298             linkprio(exten, np2, NULL);
04299          }
04300          /* add any includes */
04301          for (p2=p->u3.macro_statements; p2; p2=p2->next) {
04302             pval *p3;
04303             
04304             switch (p2->type) {
04305             case PV_INCLUDES:
04306                for (p3 = p2->u1.list; p3 ;p3=p3->next) {
04307                   if ( p3->u2.arglist ) {
04308                      snprintf(buf,sizeof(buf), "%s|%s|%s|%s|%s", 
04309                             p3->u1.str,
04310                             p3->u2.arglist->u1.str,
04311                             p3->u2.arglist->next->u1.str,
04312                             p3->u2.arglist->next->next->u1.str,
04313                             p3->u2.arglist->next->next->next->u1.str);
04314                      ast_context_add_include2(context, buf, registrar);
04315                   } else
04316                      ast_context_add_include2(context, p3->u1.str, registrar);
04317                }
04318                break;
04319             default:
04320                break;
04321             }
04322          }
04323          /* CONTAINS APPCALLS, CATCH, just like extensions... */
04324          gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context );
04325          if (exten->return_needed) {
04326             struct ael_priority *np2 = new_prio();
04327             np2->type = AEL_APPCALL;
04328             np2->app = strdup("NoOp");
04329             snprintf(buf,sizeof(buf),"End of Macro %s-%s",p->u1.str, exten->name);
04330             np2->appargs = strdup(buf);
04331             linkprio(exten, np2, NULL);
04332             exten-> return_target = np2;
04333          }
04334          
04335          set_priorities(exten);
04336          attach_exten(&exten_list, exten);
04337          break;
04338          
04339       case PV_GLOBALS:
04340          /* already done */
04341          break;
04342          
04343       case PV_CONTEXT:
04344          context = ast_context_find_or_create(local_contexts, p->u1.str, registrar);
04345          
04346          /* contexts contain: ignorepat, includes, switches, eswitches, extensions,  */
04347          for (p2=p->u2.statements; p2; p2=p2->next) {
04348             pval *p3;
04349             char *s3;
04350             
04351             switch (p2->type) {
04352             case PV_EXTENSION:
04353                exten = new_exten();
04354                exten->name = strdup(p2->u1.str);
04355                exten->context = context;
04356                
04357                if( (s3=strchr(exten->name, '/') ) != 0 )
04358                {
04359                   *s3 = 0;
04360                   exten->cidmatch = s3+1;
04361                }
04362                
04363                if ( p2->u3.hints )
04364                   exten->hints = strdup(p2->u3.hints);
04365                exten->regexten = p2->u4.regexten;
04366                gen_prios(exten, p->u1.str, p2->u2.statements, 0, context );
04367                if (exten->return_needed) {
04368                   struct ael_priority *np2 = new_prio();
04369                   np2->type = AEL_APPCALL;
04370                   np2->app = strdup("NoOp");
04371                   snprintf(buf,sizeof(buf),"End of Extension %s", exten->name);
04372                   np2->appargs = strdup(buf);
04373                   linkprio(exten, np2, NULL);
04374                   exten-> return_target = np2;
04375                }
04376                /* is the last priority in the extension a label? Then add a trailing no-op */
04377                if ( exten->plist_last && exten->plist_last->type == AEL_LABEL ) {
04378                   struct ael_priority *np2 = new_prio();
04379                   np2->type = AEL_APPCALL;
04380                   np2->app = strdup("NoOp");
04381                   snprintf(buf,sizeof(buf),"A NoOp to follow a trailing label %s", exten->plist_last->origin->u1.str);
04382                   np2->appargs = strdup(buf);
04383                   linkprio(exten, np2, NULL);
04384                }
04385 
04386                set_priorities(exten);
04387                attach_exten(&exten_list, exten);
04388                break;
04389                
04390             case PV_IGNOREPAT:
04391                ast_context_add_ignorepat2(context, p2->u1.str, registrar);
04392                break;
04393                
04394             case PV_INCLUDES:
04395                for (p3 = p2->u1.list; p3 ;p3=p3->next) {
04396                   if ( p3->u2.arglist ) {
04397                      snprintf(buf,sizeof(buf), "%s|%s|%s|%s|%s", 
04398                             p3->u1.str,
04399                             p3->u2.arglist->u1.str,
04400                             p3->u2.arglist->next->u1.str,
04401                             p3->u2.arglist->next->next->u1.str,
04402                             p3->u2.arglist->next->next->next->u1.str);
04403                      ast_context_add_include2(context, buf, registrar);
04404                   } else
04405                      ast_context_add_include2(context, p3->u1.str, registrar);
04406                }
04407                break;
04408                
04409             case PV_SWITCHES:
04410                for (p3 = p2->u1.list; p3 ;p3=p3->next) {
04411                   char *c = strchr(p3->u1.str, '/');
04412                   if (c) {
04413                      *c = '\0';
04414                      c++;
04415                   } else
04416                      c = "";
04417 
04418                   ast_context_add_switch2(context, p3->u1.str, c, 0, registrar);
04419                }
04420                break;
04421 
04422             case PV_ESWITCHES:
04423                for (p3 = p2->u1.list; p3 ;p3=p3->next) {
04424                   char *c = strchr(p3->u1.str, '/');
04425                   if (c) {
04426                      *c = '\0';
04427                      c++;
04428                   } else
04429                      c = "";
04430 
04431                   ast_context_add_switch2(context, p3->u1.str, c, 1, registrar);
04432                }
04433                break;
04434             default:
04435                break;
04436             }
04437          }
04438          
04439          break;
04440          
04441       default:
04442          /* huh? what? */
04443          break;
04444          
04445       }
04446    }
04447    /* moved these from being done after a macro or extension were processed,
04448       to after all processing is done, for the sake of fixing gotos to labels inside cases... */
04449    /* I guess this would be considered 2nd pass of compiler now... */
04450    fix_gotos_in_extensions(exten_list); /* find and fix extension ref in gotos to labels that are in case statements */
04451    add_extensions(exten_list);   /* actually makes calls to create priorities in ast_contexts -- feeds dialplan to asterisk */
04452    destroy_extensions(exten_list);  /* all that remains is an empty husk, discard of it as is proper */
04453    
04454 }

int ast_expr ( char *  expr,
char *  buf,
int  length 
)

Definition at line 2288 of file ast_expr2f.c.

References AST_EXPR_integer, ast_yy_scan_string(), ast_yylex_destroy(), ast_yylex_init(), ast_yyparse(), free, and io.

Referenced by check_pval_item(), and pbx_substitute_variables_helper_full().

02289 {
02290    struct parse_io io;
02291    int return_value = 0;
02292    
02293    memset(&io, 0, sizeof(io));
02294    io.string = expr;  /* to pass to the error routine */
02295    
02296    ast_yylex_init(&io.scanner);
02297    
02298    ast_yy_scan_string(expr, io.scanner);
02299    
02300    ast_yyparse ((void *) &io);
02301 
02302    ast_yylex_destroy(io.scanner);
02303 
02304    if (!io.val) {
02305       if (length > 1) {
02306          strcpy(buf, "0");
02307          return_value = 1;
02308       }
02309    } else {
02310       if (io.val->type == AST_EXPR_integer) {
02311          int res_length;
02312 
02313          res_length = snprintf(buf, length, "%ld", (long int) io.val->u.i);
02314          return_value = (res_length <= length) ? res_length : length;
02315       } else {
02316 #if defined(STANDALONE) || defined(LOW_MEMORY) || defined(STANDALONE_AEL)
02317          strncpy(buf, io.val->u.s, length - 1);
02318 #else /* !STANDALONE && !LOW_MEMORY */
02319          ast_copy_string(buf, io.val->u.s, length);
02320 #endif /* STANDALONE || LOW_MEMORY */
02321          return_value = strlen(buf);
02322          free(io.val->u.s);
02323       }
02324       free(io.val);
02325    }
02326    return return_value;
02327 }

void ast_expr_clear_extra_error_info ( void   ) 

void ast_expr_register_extra_error_info ( char *  errmsg  ) 

AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_DEFAULT  ,
"Asterisk Extension Language Compiler"  ,
load = load_module,
unload = unload_module,
reload = reload 
)

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

Definition at line 4171 of file pbx_ael.c.

References ael_extension::next_exten.

04172 {
04173    /* travel to the end of the list... */
04174    struct ael_extension *lptr;
04175    if( !*list ) {
04176       *list = newmem;
04177       return;
04178    }
04179    lptr = *list;
04180    
04181    while( lptr->next_exten ) {
04182       lptr = lptr->next_exten;
04183    }
04184    /* lptr should now pointing to the last element in the list; it has a null next_exten pointer */
04185    lptr->next_exten = newmem;
04186 }

static void check_abstract_reference ( pval abstract_context  )  [static]

Definition at line 2276 of file pbx_ael.c.

References current_db, pval::list, pval::next, PV_CONTEXT, PV_INCLUDES, pval::str, pval::type, pval::u1, and pval::u2.

Referenced by check_pval_item().

02277 {
02278    pval *i,*j;
02279    /* find some context includes that reference this context */
02280    
02281 
02282    /* otherwise, print out a warning */
02283    for (i=current_db; i; i=i->next) {
02284       if (i->type == PV_CONTEXT) {
02285          for (j=i->u2. statements; j; j=j->next) {
02286             if ( j->type == PV_INCLUDES ) {
02287                struct pval *p4;
02288                for (p4=j->u1.list; p4; p4=p4->next) {
02289                   /* for each context pointed to, find it, then find a context/label that matches the
02290                      target here! */
02291                   if ( !strcmp(p4->u1.str, abstract_context->u1.str) )
02292                      return; /* found a match! */
02293                }
02294             }
02295          }
02296       }
02297    }
02298    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",
02299          abstract_context->filename, abstract_context->startline, abstract_context->endline, abstract_context->u1.str);
02300    warns++;
02301 }