mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 03:20:57 +00:00
Merged revisions 87168 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r87168 | murf | 2007-10-26 10:34:02 -0600 (Fri, 26 Oct 2007) | 1 line closes issue #11086 where a user complains that references to following contexts report a problem; The problem was REALLy that he was referring to empty contexts, which were being ignored. Reporter stated that empty contexts should be OK. I checked it out against extensions.conf, and sure enough, empty contexts ARE ok. So, I removed the restriction from AEL. This, though, highlighted a problem with multiple contexts of the same name. This should be OK, also. So, I added the extend keyword to AEL, and it can preceed the 'context' keyword (mixed with 'abstract', if nec.). This will turn off the warnings in AEL if the same context name is used 2 or more times. Also, I now call ast_context_find_or_create for contexts now, instead of just ast_context_create; I did this because pbx_config does this. The 'extend' keyword thus becomes a statement of intent. AEL can now duplicate the behavior of pbx_config, ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@87187 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -77,10 +77,11 @@ struct pval
|
||||
char *for_inc; /* used in FOR */
|
||||
struct pval *else_statements; /* used in IF */
|
||||
struct pval *macro_statements; /* used in MACRO */
|
||||
int abstract; /* used for context */
|
||||
int abstract; /* used for context 1=abstract; 2=extend; 3=both */
|
||||
char *hints; /* used in EXTENSION */
|
||||
int goto_target_in_case; /* used in GOTO */
|
||||
struct ael_extension *compiled_label;
|
||||
struct pval *extend; /* to link extended contexts to the 'original' */
|
||||
} u3;
|
||||
|
||||
union
|
||||
|
@@ -2,13 +2,12 @@
|
||||
(If you find progress and other non-error messages irritating, you can use -q to suppress them)
|
||||
|
||||
(You can use the -w option to dump extensions.conf format to extensions.conf.aeldump)
|
||||
LOG: lev:2 file:pbx_ael.c line:113 func: pbx_load_module Starting AEL load process.
|
||||
LOG: lev:2 file:pbx_ael.c line:120 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'.
|
||||
LOG: lev:3 file:ael.y line:205 func: ael_yyparse ==== File: ./extensions.ael, Line 1, Cols: 19-19: Warning! The empty context real-small will be IGNORED!
|
||||
LOG: lev:2 file:pbx_ael.c line:128 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'.
|
||||
LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: checked config file name './extensions.ael'.
|
||||
LOG: lev:3 file:pval.c line:3633 func: add_extensions This file is Empty!
|
||||
LOG: lev:2 file:pbx_ael.c line:133 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'.
|
||||
LOG: lev:2 file:pbx_ael.c line:136 func: pbx_load_module AEL load process: merged config file name './extensions.ael'.
|
||||
LOG: lev:2 file:pbx_ael.c line:139 func: pbx_load_module AEL load process: verified config file name './extensions.ael'.
|
||||
LOG: lev:4 file:ael2_parse line:499 func: main 0 contexts, 0 extensions, 0 priorities
|
||||
LOG: lev:2 file:pbx_ael.c line:913 func: pbx_load_module Starting AEL load process.
|
||||
LOG: lev:2 file:pbx_ael.c line:920 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'.
|
||||
LOG: lev:2 file:pbx_ael.c line:928 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'.
|
||||
LOG: lev:2 file:pbx_ael.c line:931 func: pbx_load_module AEL load process: checked config file name './extensions.ael'.
|
||||
LOG: lev:3 file:pval.c line:3784 func: add_extensions This file is Empty!
|
||||
LOG: lev:2 file:pbx_ael.c line:933 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'.
|
||||
LOG: lev:2 file:pbx_ael.c line:936 func: pbx_load_module AEL load process: merged config file name './extensions.ael'.
|
||||
LOG: lev:2 file:pbx_ael.c line:939 func: pbx_load_module AEL load process: verified config file name './extensions.ael'.
|
||||
LOG: lev:4 file:ael2_parse line:543 func: main 1 contexts, 0 extensions, 0 priorities
|
||||
|
@@ -5,7 +5,7 @@
|
||||
LOG: lev:2 file:pbx_ael.c line:913 func: pbx_load_module Starting AEL load process.
|
||||
LOG: lev:2 file:pbx_ael.c line:920 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'.
|
||||
LOG: lev:2 file:pbx_ael.c line:928 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'.
|
||||
LOG: lev:3 file:pval.c line:2298 func: check_context_names Warning: file ./extensions.ael, line 49-62: The context name (incoming) is also declared in file ./extensions.ael, line 62-69!
|
||||
LOG: lev:3 file:pval.c line:2298 func: check_context_names Warning: file ./extensions.ael, line 49-62: The context name (incoming) is also declared in file ./extensions.ael, line 62-69! (and neither is marked 'extend')
|
||||
LOG: lev:3 file:pval.c line:670 func: check_macro_returns Warning: file ./extensions.ael, line 71-175: The macro std-priv-exten does not end with a return; I will insert one.
|
||||
LOG: lev:3 file:pval.c line:2282 func: check_switch_expr Warning: file ./extensions.ael, line 245-246: A default case was automatically added to the switch.
|
||||
LOG: lev:3 file:pval.c line:2424 func: check_pval_item Warning: file ./extensions.ael, line 312-312: macro call to non-existent funcA! (Not even in the extensions.conf stuff!)
|
||||
@@ -16,4 +16,4 @@ LOG: lev:2 file:pbx_ael.c line:931 func: pbx_load_module AEL load process: che
|
||||
LOG: lev:2 file:pbx_ael.c line:933 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'.
|
||||
LOG: lev:2 file:pbx_ael.c line:936 func: pbx_load_module AEL load process: merged config file name './extensions.ael'.
|
||||
LOG: lev:2 file:pbx_ael.c line:939 func: pbx_load_module AEL load process: verified config file name './extensions.ael'.
|
||||
LOG: lev:4 file:ael2_parse line:527 func: main 13 contexts, 57 extensions, 188 priorities
|
||||
LOG: lev:4 file:ael2_parse line:543 func: main 13 contexts, 57 extensions, 188 priorities
|
||||
|
794
pbx/pbx_ael.c
794
pbx/pbx_ael.c
@@ -63,8 +63,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
static char *config = "extensions.ael";
|
||||
static char *registrar = "pbx_ael";
|
||||
static int pbx_load_module(void);
|
||||
static int warns, errs;
|
||||
static struct pval *current_db;
|
||||
|
||||
#ifndef AAL_ARGCHECK
|
||||
/* for the time being, short circuit all the AAL related structures
|
||||
@@ -103,799 +101,7 @@ int is_float(char *arg );
|
||||
int is_int(char *arg );
|
||||
int is_empty(char *arg);
|
||||
|
||||
static const char *match_context;
|
||||
static const char *match_exten;
|
||||
static const char *match_label;
|
||||
static int count_labels; /* true, put matcher in label counting mode */
|
||||
static int return_on_context_match;
|
||||
struct pval *match_pval(pval *item);
|
||||
static void check_goto(pval *item);
|
||||
static void find_pval_goto_item(pval *item, int lev);
|
||||
static void find_pval_gotos(pval *item, int lev);
|
||||
|
||||
static struct pval *find_label_in_current_context(char *exten, char *label, pval *curr_cont);
|
||||
static struct pval *find_first_label_in_current_context(char *label, pval *curr_cont);
|
||||
static void print_pval_list(FILE *fin, pval *item, int depth);
|
||||
|
||||
static struct pval *find_label_in_current_extension(const char *label, pval *curr_ext);
|
||||
static struct pval *find_label_in_current_db(const char *context, const char *exten, const char *label);
|
||||
static pval *get_extension_or_contxt(pval *p);
|
||||
static pval *get_contxt(pval *p);
|
||||
/* static void substitute_commas(char *str); */
|
||||
#ifdef NOMORE
|
||||
/*! \brief I am adding this code to substitute commas with vertbars in the args to apps */
|
||||
static void substitute_commas(char *str)
|
||||
{
|
||||
char *p = str;
|
||||
|
||||
while (p && *p)
|
||||
{
|
||||
if (*p == ',' && ((p != str && *(p-1) != '\\')
|
||||
|| p == str))
|
||||
*p = '|';
|
||||
if (*p == '\\' && *(p+1) == ',') { /* learning experience: the '\,' is turned into just ',' by pbx_config; So we need to do the same */
|
||||
char *q = p;
|
||||
while (*q) { /* move the ',' and everything after it up 1 char */
|
||||
*q = *(q+1);
|
||||
q++;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* PRETTY PRINTER FOR AEL: ============================================================================= */
|
||||
|
||||
static void print_pval(FILE *fin, pval *item, int depth)
|
||||
{
|
||||
int i;
|
||||
pval *lp;
|
||||
|
||||
for (i=0; i<depth; i++) {
|
||||
fprintf(fin, "\t"); /* depth == indentation */
|
||||
}
|
||||
|
||||
switch ( item->type ) {
|
||||
case PV_WORD:
|
||||
fprintf(fin,"%s;\n", item->u1.str); /* usually, words are encapsulated in something else */
|
||||
break;
|
||||
|
||||
case PV_MACRO:
|
||||
fprintf(fin,"macro %s(", item->u1.str);
|
||||
for (lp=item->u2.arglist; lp; lp=lp->next) {
|
||||
if (lp != item->u2.arglist )
|
||||
fprintf(fin,", ");
|
||||
fprintf(fin,"%s", lp->u1.str);
|
||||
}
|
||||
fprintf(fin,") {\n");
|
||||
print_pval_list(fin,item->u3.macro_statements,depth+1);
|
||||
for (i=0; i<depth; i++) {
|
||||
fprintf(fin,"\t"); /* depth == indentation */
|
||||
}
|
||||
fprintf(fin,"};\n\n");
|
||||
break;
|
||||
|
||||
case PV_CONTEXT:
|
||||
if ( item->u3.abstract )
|
||||
fprintf(fin,"abstract context %s {\n", item->u1.str);
|
||||
else
|
||||
fprintf(fin,"context %s {\n", item->u1.str);
|
||||
print_pval_list(fin,item->u2.statements,depth+1);
|
||||
for (i=0; i<depth; i++) {
|
||||
fprintf(fin,"\t"); /* depth == indentation */
|
||||
}
|
||||
fprintf(fin,"};\n\n");
|
||||
break;
|
||||
|
||||
case PV_MACRO_CALL:
|
||||
fprintf(fin,"&%s(", item->u1.str);
|
||||
for (lp=item->u2.arglist; lp; lp=lp->next) {
|
||||
if ( lp != item->u2.arglist )
|
||||
fprintf(fin,", ");
|
||||
fprintf(fin,"%s", lp->u1.str);
|
||||
}
|
||||
fprintf(fin,");\n");
|
||||
break;
|
||||
|
||||
case PV_APPLICATION_CALL:
|
||||
fprintf(fin,"%s(", item->u1.str);
|
||||
for (lp=item->u2.arglist; lp; lp=lp->next) {
|
||||
if ( lp != item->u2.arglist )
|
||||
fprintf(fin,",");
|
||||
fprintf(fin,"%s", lp->u1.str);
|
||||
}
|
||||
fprintf(fin,");\n");
|
||||
break;
|
||||
|
||||
case PV_CASE:
|
||||
fprintf(fin,"case %s:\n", item->u1.str);
|
||||
print_pval_list(fin,item->u2.statements, depth+1);
|
||||
break;
|
||||
|
||||
case PV_PATTERN:
|
||||
fprintf(fin,"pattern %s:\n", item->u1.str);
|
||||
print_pval_list(fin,item->u2.statements, depth+1);
|
||||
break;
|
||||
|
||||
case PV_DEFAULT:
|
||||
fprintf(fin,"default:\n");
|
||||
print_pval_list(fin,item->u2.statements, depth+1);
|
||||
break;
|
||||
|
||||
case PV_CATCH:
|
||||
fprintf(fin,"catch %s {\n", item->u1.str);
|
||||
print_pval_list(fin,item->u2.statements, depth+1);
|
||||
for (i=0; i<depth; i++) {
|
||||
fprintf(fin,"\t"); /* depth == indentation */
|
||||
}
|
||||
fprintf(fin,"};\n");
|
||||
break;
|
||||
|
||||
case PV_SWITCHES:
|
||||
fprintf(fin,"switches {\n");
|
||||
print_pval_list(fin,item->u1.list,depth+1);
|
||||
for (i=0; i<depth; i++) {
|
||||
fprintf(fin,"\t"); /* depth == indentation */
|
||||
}
|
||||
fprintf(fin,"};\n");
|
||||
break;
|
||||
|
||||
case PV_ESWITCHES:
|
||||
fprintf(fin,"eswitches {\n");
|
||||
print_pval_list(fin,item->u1.list,depth+1);
|
||||
for (i=0; i<depth; i++) {
|
||||
fprintf(fin,"\t"); /* depth == indentation */
|
||||
}
|
||||
fprintf(fin,"};\n");
|
||||
break;
|
||||
|
||||
case PV_INCLUDES:
|
||||
fprintf(fin,"includes {\n");
|
||||
for (lp=item->u1.list; lp; lp=lp->next) {
|
||||
for (i=0; i<depth+1; i++) {
|
||||
fprintf(fin,"\t"); /* depth == indentation */
|
||||
}
|
||||
fprintf(fin,"%s", lp->u1.str); /* usually, words are encapsulated in something else */
|
||||
if ( lp->u2.arglist )
|
||||
fprintf(fin,"|%s|%s|%s|%s",
|
||||
lp->u2.arglist->u1.str,
|
||||
lp->u2.arglist->next->u1.str,
|
||||
lp->u2.arglist->next->next->u1.str,
|
||||
lp->u2.arglist->next->next->next->u1.str
|
||||
);
|
||||
fprintf(fin,";\n"); /* usually, words are encapsulated in something else */
|
||||
}
|
||||
|
||||
print_pval_list(fin,item->u1.list,depth+1);
|
||||
for (i=0; i<depth; i++) {
|
||||
fprintf(fin,"\t"); /* depth == indentation */
|
||||
}
|
||||
fprintf(fin,"};\n");
|
||||
break;
|
||||
|
||||
case PV_STATEMENTBLOCK:
|
||||
fprintf(fin,"{\n");
|
||||
print_pval_list(fin,item->u1.list, depth+1);
|
||||
for (i=0; i<depth; i++) {
|
||||
fprintf(fin,"\t"); /* depth == indentation */
|
||||
}
|
||||
fprintf(fin,"};\n");
|
||||
break;
|
||||
|
||||
case PV_VARDEC:
|
||||
fprintf(fin,"%s=%s;\n", item->u1.str, item->u2.val);
|
||||
break;
|
||||
|
||||
case PV_LOCALVARDEC:
|
||||
fprintf(fin,"local %s=%s;\n", item->u1.str, item->u2.val);
|
||||
break;
|
||||
|
||||
case PV_GOTO:
|
||||
fprintf(fin,"goto %s", item->u1.list->u1.str);
|
||||
if ( item->u1.list->next )
|
||||
fprintf(fin,",%s", item->u1.list->next->u1.str);
|
||||
if ( item->u1.list->next && item->u1.list->next->next )
|
||||
fprintf(fin,",%s", item->u1.list->next->next->u1.str);
|
||||
fprintf(fin,"\n");
|
||||
break;
|
||||
|
||||
case PV_LABEL:
|
||||
fprintf(fin,"%s:\n", item->u1.str);
|
||||
break;
|
||||
|
||||
case PV_FOR:
|
||||
fprintf(fin,"for (%s; %s; %s)\n", item->u1.for_init, item->u2.for_test, item->u3.for_inc);
|
||||
print_pval_list(fin,item->u4.for_statements,depth+1);
|
||||
break;
|
||||
|
||||
case PV_WHILE:
|
||||
fprintf(fin,"while (%s)\n", item->u1.str);
|
||||
print_pval_list(fin,item->u2.statements,depth+1);
|
||||
break;
|
||||
|
||||
case PV_BREAK:
|
||||
fprintf(fin,"break;\n");
|
||||
break;
|
||||
|
||||
case PV_RETURN:
|
||||
fprintf(fin,"return;\n");
|
||||
break;
|
||||
|
||||
case PV_CONTINUE:
|
||||
fprintf(fin,"continue;\n");
|
||||
break;
|
||||
|
||||
case PV_RANDOM:
|
||||
case PV_IFTIME:
|
||||
case PV_IF:
|
||||
if ( item->type == PV_IFTIME ) {
|
||||
|
||||
fprintf(fin,"ifTime ( %s|%s|%s|%s )\n",
|
||||
item->u1.list->u1.str,
|
||||
item->u1.list->next->u1.str,
|
||||
item->u1.list->next->next->u1.str,
|
||||
item->u1.list->next->next->next->u1.str
|
||||
);
|
||||
} else if ( item->type == PV_RANDOM ) {
|
||||
fprintf(fin,"random ( %s )\n", item->u1.str );
|
||||
} else
|
||||
fprintf(fin,"if ( %s )\n", item->u1.str);
|
||||
if ( item->u2.statements && item->u2.statements->next ) {
|
||||
for (i=0; i<depth; i++) {
|
||||
fprintf(fin,"\t"); /* depth == indentation */
|
||||
}
|
||||
fprintf(fin,"{\n");
|
||||
print_pval_list(fin,item->u2.statements,depth+1);
|
||||
for (i=0; i<depth; i++) {
|
||||
fprintf(fin,"\t"); /* depth == indentation */
|
||||
}
|
||||
if ( item->u3.else_statements )
|
||||
fprintf(fin,"}\n");
|
||||
else
|
||||
fprintf(fin,"};\n");
|
||||
} else if (item->u2.statements ) {
|
||||
print_pval_list(fin,item->u2.statements,depth+1);
|
||||
} else {
|
||||
if (item->u3.else_statements )
|
||||
fprintf(fin, " {} ");
|
||||
else
|
||||
fprintf(fin, " {}; ");
|
||||
}
|
||||
if ( item->u3.else_statements ) {
|
||||
for (i=0; i<depth; i++) {
|
||||
fprintf(fin,"\t"); /* depth == indentation */
|
||||
}
|
||||
fprintf(fin,"else\n");
|
||||
print_pval_list(fin,item->u3.else_statements, depth);
|
||||
}
|
||||
break;
|
||||
|
||||
case PV_SWITCH:
|
||||
fprintf(fin,"switch( %s ) {\n", item->u1.str);
|
||||
print_pval_list(fin,item->u2.statements,depth+1);
|
||||
for (i=0; i<depth; i++) {
|
||||
fprintf(fin,"\t"); /* depth == indentation */
|
||||
}
|
||||
fprintf(fin,"}\n");
|
||||
break;
|
||||
|
||||
case PV_EXTENSION:
|
||||
if ( item->u4.regexten )
|
||||
fprintf(fin, "regexten ");
|
||||
if ( item->u3.hints )
|
||||
fprintf(fin,"hints(%s) ", item->u3.hints);
|
||||
|
||||
fprintf(fin,"%s => \n", item->u1.str);
|
||||
print_pval_list(fin,item->u2.statements,depth+1);
|
||||
break;
|
||||
|
||||
case PV_IGNOREPAT:
|
||||
fprintf(fin,"ignorepat => %s\n", item->u1.str);
|
||||
break;
|
||||
|
||||
case PV_GLOBALS:
|
||||
fprintf(fin,"globals {\n");
|
||||
print_pval_list(fin,item->u1.statements,depth+1);
|
||||
for (i=0; i<depth; i++) {
|
||||
fprintf(fin,"\t"); /* depth == indentation */
|
||||
}
|
||||
fprintf(fin,"}\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void print_pval_list(FILE *fin, pval *item, int depth)
|
||||
{
|
||||
pval *i;
|
||||
|
||||
for (i=item; i; i=i->next) {
|
||||
print_pval(fin, i, depth);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void ael2_print(char *fname, pval *tree)
|
||||
{
|
||||
FILE *fin = fopen(fname,"w");
|
||||
if ( !fin ) {
|
||||
ast_log(LOG_ERROR, "Couldn't open %s for writing.\n", fname);
|
||||
return;
|
||||
}
|
||||
print_pval_list(fin, tree, 0);
|
||||
fclose(fin);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* SEMANTIC CHECKING FOR AEL: ============================================================================= */
|
||||
|
||||
/* (not all that is syntactically legal is good! */
|
||||
|
||||
|
||||
static struct pval *in_macro(pval *item)
|
||||
{
|
||||
struct pval *curr;
|
||||
curr = item;
|
||||
while( curr ) {
|
||||
if( curr->type == PV_MACRO ) {
|
||||
return curr;
|
||||
}
|
||||
curr = curr->dad;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pval *in_context(pval *item)
|
||||
{
|
||||
struct pval *curr;
|
||||
curr = item;
|
||||
while( curr ) {
|
||||
if( curr->type == PV_MACRO || curr->type == PV_CONTEXT ) {
|
||||
return curr;
|
||||
}
|
||||
curr = curr->dad;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void check_goto(pval *item)
|
||||
{
|
||||
/* check for the target of the goto-- does it exist? */
|
||||
if ( !(item->u1.list)->next && !(item->u1.list)->u1.str ) {
|
||||
ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: empty label reference found!\n",
|
||||
item->filename, item->startline, item->endline);
|
||||
errs++;
|
||||
}
|
||||
|
||||
/* just one item-- the label should be in the current extension */
|
||||
|
||||
if (item->u1.list && !item->u1.list->next && !strstr((item->u1.list)->u1.str,"${")) {
|
||||
struct pval *z = get_extension_or_contxt(item);
|
||||
struct pval *x = 0;
|
||||
if (z)
|
||||
x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), z); /* if in macro, use current context instead */
|
||||
/* printf("Called find_label_in_current_extension with arg %s; current_extension is %x: %d\n",
|
||||
(char*)((item->u1.list)->u1.str), current_extension?current_extension:current_context, current_extension?current_extension->type:current_context->type); */
|
||||
if (!x) {
|
||||
ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s exists in the current extension!\n",
|
||||
item->filename, item->startline, item->endline, item->u1.list->u1.str);
|
||||
errs++;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
/* TWO items */
|
||||
if (item->u1.list->next && !item->u1.list->next->next) {
|
||||
/* two items */
|
||||
/* printf("Calling find_label_in_current_context with args %s, %s\n",
|
||||
(char*)((item->u1.list)->u1.str), (char *)item->u1.list->next->u1.str); */
|
||||
if (!strstr((item->u1.list)->u1.str,"${")
|
||||
&& !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ {
|
||||
struct pval *z = get_contxt(item);
|
||||
struct pval *x = 0;
|
||||
|
||||
if (z)
|
||||
x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, z);
|
||||
|
||||
if (!x) {
|
||||
ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s|%s exists in the current context, or any of its inclusions!\n",
|
||||
item->filename, item->startline, item->endline, item->u1.list->u1.str, item->u1.list->next->u1.str );
|
||||
errs++;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* All 3 items! */
|
||||
if (item->u1.list->next && item->u1.list->next->next) {
|
||||
/* all three */
|
||||
pval *first = item->u1.list;
|
||||
pval *second = item->u1.list->next;
|
||||
pval *third = item->u1.list->next->next;
|
||||
|
||||
/* printf("Calling find_label_in_current_db with args %s, %s, %s\n",
|
||||
(char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); */
|
||||
if (!strstr((item->u1.list)->u1.str,"${")
|
||||
&& !strstr(item->u1.list->next->u1.str,"${")
|
||||
&& !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ {
|
||||
struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str);
|
||||
if (!x) {
|
||||
struct pval *p3;
|
||||
struct pval *found = 0;
|
||||
struct pval *that_context = find_context(item->u1.list->u1.str);
|
||||
|
||||
/* the target of the goto could be in an included context!! Fancy that!! */
|
||||
/* look for includes in the current context */
|
||||
if (that_context) {
|
||||
for (p3=that_context->u2.statements; p3; p3=p3->next) {
|
||||
if (p3->type == PV_INCLUDES) {
|
||||
struct pval *p4;
|
||||
for (p4=p3->u1.list; p4; p4=p4->next) {
|
||||
/* for each context pointed to, find it, then find a context/label that matches the
|
||||
target here! */
|
||||
char *incl_context = p4->u1.str;
|
||||
/* find a matching context name */
|
||||
struct pval *that_other_context = find_context(incl_context);
|
||||
if (that_other_context) {
|
||||
struct pval *x3;
|
||||
x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context);
|
||||
if (x3) {
|
||||
found = x3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s|%s exists in the context %s or its inclusions!\n",
|
||||
item->filename, item->startline, item->endline, item->u1.list->next->u1.str, item->u1.list->next->next->u1.str, item->u1.list->u1.str );
|
||||
errs++;
|
||||
} else {
|
||||
struct pval *mac = in_macro(item); /* is this goto inside a macro? */
|
||||
if( mac ) { /* yes! */
|
||||
struct pval *targ = in_context(found);
|
||||
if( mac != targ )
|
||||
{
|
||||
ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: It's bad form to have a goto in a macro to a target outside the macro!\n",
|
||||
item->filename, item->startline, item->endline);
|
||||
warns++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* here is where code would go to check for target existence in extensions.conf files */
|
||||
ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: goto: no context %s could be found that matches the goto target!\n",
|
||||
item->filename, item->startline, item->endline, item->u1.list->u1.str);
|
||||
warns++; /* this is just a warning, because this context could be in extensions.conf or somewhere */
|
||||
}
|
||||
} else {
|
||||
struct pval *mac = in_macro(item); /* is this goto inside a macro? */
|
||||
if( mac ) { /* yes! */
|
||||
struct pval *targ = in_context(x);
|
||||
if( mac != targ )
|
||||
{
|
||||
ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: It's bad form to have a goto in a macro to a target outside the macro!\n",
|
||||
item->filename, item->startline, item->endline);
|
||||
warns++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void find_pval_goto_item(pval *item, int lev)
|
||||
{
|
||||
struct pval *p4;
|
||||
if (lev>100) {
|
||||
ast_log(LOG_ERROR,"find_pval_goto in infinite loop!\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( item->type ) {
|
||||
case PV_MACRO:
|
||||
/* fields: item->u1.str == name of macro
|
||||
item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
|
||||
item->u2.arglist->u1.str == argument
|
||||
item->u2.arglist->next == next arg
|
||||
|
||||
item->u3.macro_statements == pval list of statements in macro body.
|
||||
*/
|
||||
|
||||
/* printf("Descending into matching macro %s\n", match_context); */
|
||||
find_pval_gotos(item->u3.macro_statements,lev+1); /* if we're just searching for a context, don't bother descending into them */
|
||||
|
||||
break;
|
||||
|
||||
case PV_CONTEXT:
|
||||
/* fields: item->u1.str == name of context
|
||||
item->u2.statements == pval list of statements in context body
|
||||
item->u3.abstract == int 1 if an abstract keyword were present
|
||||
*/
|
||||
break;
|
||||
|
||||
case PV_CASE:
|
||||
/* fields: item->u1.str == value of case
|
||||
item->u2.statements == pval list of statements under the case
|
||||
*/
|
||||
find_pval_gotos(item->u2.statements,lev+1);
|
||||
break;
|
||||
|
||||
case PV_PATTERN:
|
||||
/* fields: item->u1.str == value of case
|
||||
item->u2.statements == pval list of statements under the case
|
||||
*/
|
||||
find_pval_gotos(item->u2.statements,lev+1);
|
||||
break;
|
||||
|
||||
case PV_DEFAULT:
|
||||
/* fields:
|
||||
item->u2.statements == pval list of statements under the case
|
||||
*/
|
||||
find_pval_gotos(item->u2.statements,lev+1);
|
||||
break;
|
||||
|
||||
case PV_CATCH:
|
||||
/* fields: item->u1.str == name of extension to catch
|
||||
item->u2.statements == pval list of statements in context body
|
||||
*/
|
||||
find_pval_gotos(item->u2.statements,lev+1);
|
||||
break;
|
||||
|
||||
case PV_STATEMENTBLOCK:
|
||||
/* fields: item->u1.list == pval list of statements in block, one per entry in the list
|
||||
*/
|
||||
find_pval_gotos(item->u1.list,lev+1);
|
||||
break;
|
||||
|
||||
case PV_GOTO:
|
||||
/* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user.
|
||||
item->u1.list->u1.str == where the data on a PV_WORD will always be.
|
||||
*/
|
||||
check_goto(item); /* THE WHOLE FUNCTION OF THIS ENTIRE ROUTINE!!!! */
|
||||
break;
|
||||
|
||||
case PV_INCLUDES:
|
||||
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
|
||||
*/
|
||||
for (p4=item->u1.list; p4; p4=p4->next) {
|
||||
/* for each context pointed to, find it, then find a context/label that matches the
|
||||
target here! */
|
||||
char *incl_context = p4->u1.str;
|
||||
/* find a matching context name */
|
||||
struct pval *that_context = find_context(incl_context);
|
||||
if (that_context) {
|
||||
find_pval_gotos(that_context,lev+1); /* keep working up the includes */
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PV_FOR:
|
||||
/* fields: item->u1.for_init == a string containing the initalizer
|
||||
item->u2.for_test == a string containing the loop test
|
||||
item->u3.for_inc == a string containing the loop increment
|
||||
|
||||
item->u4.for_statements == a pval list of statements in the for ()
|
||||
*/
|
||||
find_pval_gotos(item->u4.for_statements,lev+1);
|
||||
break;
|
||||
|
||||
case PV_WHILE:
|
||||
/* fields: item->u1.str == the while conditional, as supplied by user
|
||||
|
||||
item->u2.statements == a pval list of statements in the while ()
|
||||
*/
|
||||
find_pval_gotos(item->u2.statements,lev+1);
|
||||
break;
|
||||
|
||||
case PV_RANDOM:
|
||||
/* fields: item->u1.str == the random number expression, as supplied by user
|
||||
|
||||
item->u2.statements == a pval list of statements in the if ()
|
||||
item->u3.else_statements == a pval list of statements in the else
|
||||
(could be zero)
|
||||
fall thru to PV_IF */
|
||||
|
||||
case PV_IFTIME:
|
||||
/* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list
|
||||
|
||||
item->u2.statements == a pval list of statements in the if ()
|
||||
item->u3.else_statements == a pval list of statements in the else
|
||||
(could be zero)
|
||||
fall thru to PV_IF*/
|
||||
case PV_IF:
|
||||
/* fields: item->u1.str == the if conditional, as supplied by user
|
||||
|
||||
item->u2.statements == a pval list of statements in the if ()
|
||||
item->u3.else_statements == a pval list of statements in the else
|
||||
(could be zero)
|
||||
*/
|
||||
find_pval_gotos(item->u2.statements,lev+1);
|
||||
|
||||
if (item->u3.else_statements) {
|
||||
find_pval_gotos(item->u3.else_statements,lev+1);
|
||||
}
|
||||
break;
|
||||
|
||||
case PV_SWITCH:
|
||||
/* fields: item->u1.str == the switch expression
|
||||
|
||||
item->u2.statements == a pval list of statements in the switch,
|
||||
(will be case statements, most likely!)
|
||||
*/
|
||||
find_pval_gotos(item->u3.else_statements,lev+1);
|
||||
break;
|
||||
|
||||
case PV_EXTENSION:
|
||||
/* fields: item->u1.str == the extension name, label, whatever it's called
|
||||
|
||||
item->u2.statements == a pval list of statements in the extension
|
||||
item->u3.hints == a char * hint argument
|
||||
item->u4.regexten == an int boolean. non-zero says that regexten was specified
|
||||
*/
|
||||
|
||||
find_pval_gotos(item->u2.statements,lev+1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void find_pval_gotos(pval *item,int lev)
|
||||
{
|
||||
pval *i;
|
||||
|
||||
for (i=item; i; i=i->next) {
|
||||
|
||||
find_pval_goto_item(i, lev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct pval *find_first_label_in_current_context(char *label, pval *curr_cont)
|
||||
{
|
||||
/* printf(" --- Got args %s, %s\n", exten, label); */
|
||||
struct pval *ret;
|
||||
struct pval *p3;
|
||||
struct pval *startpt = ((curr_cont->type==PV_MACRO)?curr_cont->u3.macro_statements: curr_cont->u2.statements);
|
||||
|
||||
count_labels = 0;
|
||||
return_on_context_match = 0;
|
||||
match_context = "*";
|
||||
match_exten = "*";
|
||||
match_label = label;
|
||||
|
||||
ret = match_pval(curr_cont);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* the target of the goto could be in an included context!! Fancy that!! */
|
||||
/* look for includes in the current context */
|
||||
for (p3=startpt; p3; p3=p3->next) {
|
||||
if (p3->type == PV_INCLUDES) {
|
||||
struct pval *p4;
|
||||
for (p4=p3->u1.list; p4; p4=p4->next) {
|
||||
/* for each context pointed to, find it, then find a context/label that matches the
|
||||
target here! */
|
||||
char *incl_context = p4->u1.str;
|
||||
/* find a matching context name */
|
||||
struct pval *that_context = find_context(incl_context);
|
||||
if (that_context) {
|
||||
struct pval *x3;
|
||||
x3 = find_first_label_in_current_context(label, that_context);
|
||||
if (x3) {
|
||||
return x3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pval *find_label_in_current_context(char *exten, char *label, pval *curr_cont)
|
||||
{
|
||||
/* printf(" --- Got args %s, %s\n", exten, label); */
|
||||
struct pval *ret;
|
||||
struct pval *p3;
|
||||
struct pval *startpt;
|
||||
|
||||
count_labels = 0;
|
||||
return_on_context_match = 0;
|
||||
match_context = "*";
|
||||
match_exten = exten;
|
||||
match_label = label;
|
||||
if (curr_cont->type == PV_MACRO)
|
||||
startpt = curr_cont->u3.macro_statements;
|
||||
else
|
||||
startpt = curr_cont->u2.statements;
|
||||
|
||||
ret = match_pval(startpt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* the target of the goto could be in an included context!! Fancy that!! */
|
||||
/* look for includes in the current context */
|
||||
for (p3=startpt; p3; p3=p3->next) {
|
||||
if (p3->type == PV_INCLUDES) {
|
||||
struct pval *p4;
|
||||
for (p4=p3->u1.list; p4; p4=p4->next) {
|
||||
/* for each context pointed to, find it, then find a context/label that matches the
|
||||
target here! */
|
||||
char *incl_context = p4->u1.str;
|
||||
/* find a matching context name */
|
||||
struct pval *that_context = find_context(incl_context);
|
||||
if (that_context) {
|
||||
struct pval *x3;
|
||||
x3 = find_label_in_current_context(exten, label, that_context);
|
||||
if (x3) {
|
||||
return x3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pval *find_label_in_current_extension(const char *label, pval *curr_ext)
|
||||
{
|
||||
/* printf(" --- Got args %s\n", label); */
|
||||
count_labels = 0;
|
||||
return_on_context_match = 0;
|
||||
match_context = "*";
|
||||
match_exten = "*";
|
||||
match_label = label;
|
||||
return match_pval(curr_ext);
|
||||
}
|
||||
|
||||
static struct pval *find_label_in_current_db(const char *context, const char *exten, const char *label)
|
||||
{
|
||||
/* printf(" --- Got args %s, %s, %s\n", context, exten, label); */
|
||||
count_labels = 0;
|
||||
return_on_context_match = 0;
|
||||
|
||||
match_context = context;
|
||||
match_exten = exten;
|
||||
match_label = label;
|
||||
|
||||
return match_pval(current_db);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* =============================================================================================== */
|
||||
/* "CODE" GENERATOR -- Convert the AEL representation to asterisk extension language */
|
||||
/* =============================================================================================== */
|
||||
|
||||
static pval *get_extension_or_contxt(pval *p)
|
||||
{
|
||||
while( p && p->type != PV_EXTENSION && p->type != PV_CONTEXT && p->type != PV_MACRO ) {
|
||||
|
||||
p = p->dad;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static pval *get_contxt(pval *p)
|
||||
{
|
||||
while( p && p->type != PV_CONTEXT && p->type != PV_MACRO ) {
|
||||
|
||||
p = p->dad;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static int aeldebug = 0;
|
||||
|
||||
|
@@ -195,6 +195,7 @@ NOSEMIC ([^;()\{\}\[\]]|\\[;()\[\]\{\}])*
|
||||
\/\/[^\n]* {/*comment*/}
|
||||
context { STORE_POS; return KW_CONTEXT;}
|
||||
abstract { STORE_POS; return KW_ABSTRACT;}
|
||||
extend { STORE_POS; return KW_EXTEND;}
|
||||
macro { STORE_POS; return KW_MACRO;};
|
||||
globals { STORE_POS; return KW_GLOBALS;}
|
||||
local { STORE_POS; return KW_LOCAL;}
|
||||
|
1684
res/ael/ael.tab.c
1684
res/ael/ael.tab.c
File diff suppressed because it is too large
Load Diff
@@ -50,25 +50,26 @@
|
||||
KW_ELSE = 276,
|
||||
KW_RANDOM = 277,
|
||||
KW_ABSTRACT = 278,
|
||||
EXTENMARK = 279,
|
||||
KW_GOTO = 280,
|
||||
KW_JUMP = 281,
|
||||
KW_RETURN = 282,
|
||||
KW_BREAK = 283,
|
||||
KW_CONTINUE = 284,
|
||||
KW_REGEXTEN = 285,
|
||||
KW_HINT = 286,
|
||||
KW_FOR = 287,
|
||||
KW_WHILE = 288,
|
||||
KW_CASE = 289,
|
||||
KW_PATTERN = 290,
|
||||
KW_DEFAULT = 291,
|
||||
KW_CATCH = 292,
|
||||
KW_SWITCHES = 293,
|
||||
KW_ESWITCHES = 294,
|
||||
KW_INCLUDES = 295,
|
||||
KW_LOCAL = 296,
|
||||
word = 297
|
||||
KW_EXTEND = 279,
|
||||
EXTENMARK = 280,
|
||||
KW_GOTO = 281,
|
||||
KW_JUMP = 282,
|
||||
KW_RETURN = 283,
|
||||
KW_BREAK = 284,
|
||||
KW_CONTINUE = 285,
|
||||
KW_REGEXTEN = 286,
|
||||
KW_HINT = 287,
|
||||
KW_FOR = 288,
|
||||
KW_WHILE = 289,
|
||||
KW_CASE = 290,
|
||||
KW_PATTERN = 291,
|
||||
KW_DEFAULT = 292,
|
||||
KW_CATCH = 293,
|
||||
KW_SWITCHES = 294,
|
||||
KW_ESWITCHES = 295,
|
||||
KW_INCLUDES = 296,
|
||||
KW_LOCAL = 297,
|
||||
word = 298
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
@@ -93,25 +94,26 @@
|
||||
#define KW_ELSE 276
|
||||
#define KW_RANDOM 277
|
||||
#define KW_ABSTRACT 278
|
||||
#define EXTENMARK 279
|
||||
#define KW_GOTO 280
|
||||
#define KW_JUMP 281
|
||||
#define KW_RETURN 282
|
||||
#define KW_BREAK 283
|
||||
#define KW_CONTINUE 284
|
||||
#define KW_REGEXTEN 285
|
||||
#define KW_HINT 286
|
||||
#define KW_FOR 287
|
||||
#define KW_WHILE 288
|
||||
#define KW_CASE 289
|
||||
#define KW_PATTERN 290
|
||||
#define KW_DEFAULT 291
|
||||
#define KW_CATCH 292
|
||||
#define KW_SWITCHES 293
|
||||
#define KW_ESWITCHES 294
|
||||
#define KW_INCLUDES 295
|
||||
#define KW_LOCAL 296
|
||||
#define word 297
|
||||
#define KW_EXTEND 279
|
||||
#define EXTENMARK 280
|
||||
#define KW_GOTO 281
|
||||
#define KW_JUMP 282
|
||||
#define KW_RETURN 283
|
||||
#define KW_BREAK 284
|
||||
#define KW_CONTINUE 285
|
||||
#define KW_REGEXTEN 286
|
||||
#define KW_HINT 287
|
||||
#define KW_FOR 288
|
||||
#define KW_WHILE 289
|
||||
#define KW_CASE 290
|
||||
#define KW_PATTERN 291
|
||||
#define KW_DEFAULT 292
|
||||
#define KW_CATCH 293
|
||||
#define KW_SWITCHES 294
|
||||
#define KW_ESWITCHES 295
|
||||
#define KW_INCLUDES 296
|
||||
#define KW_LOCAL 297
|
||||
#define word 298
|
||||
|
||||
|
||||
|
||||
@@ -125,7 +127,7 @@ typedef union YYSTYPE
|
||||
struct pval *pval; /* full objects */
|
||||
}
|
||||
/* Line 1536 of yacc.c. */
|
||||
#line 129 "ael.tab.h"
|
||||
#line 131 "ael.tab.h"
|
||||
YYSTYPE;
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
|
@@ -80,7 +80,7 @@ static pval *update_last(pval *, YYLTYPE *);
|
||||
|
||||
|
||||
%token KW_CONTEXT LC RC LP RP SEMI EQ COMMA COLON AMPER BAR AT
|
||||
%token KW_MACRO KW_GLOBALS KW_IGNOREPAT KW_SWITCH KW_IF KW_IFTIME KW_ELSE KW_RANDOM KW_ABSTRACT
|
||||
%token KW_MACRO KW_GLOBALS KW_IGNOREPAT KW_SWITCH KW_IF KW_IFTIME KW_ELSE KW_RANDOM KW_ABSTRACT KW_EXTEND
|
||||
%token EXTENMARK KW_GOTO KW_JUMP KW_RETURN KW_BREAK KW_CONTINUE KW_REGEXTEN KW_HINT
|
||||
%token KW_FOR KW_WHILE KW_CASE KW_PATTERN KW_DEFAULT KW_CATCH KW_SWITCHES KW_ESWITCHES
|
||||
%token KW_INCLUDES KW_LOCAL
|
||||
@@ -202,22 +202,19 @@ context_name : word { $$ = $1; }
|
||||
;
|
||||
|
||||
context : opt_abstract KW_CONTEXT context_name LC elements RC {
|
||||
if (!$5) {
|
||||
ast_log(LOG_WARNING, "==== File: %s, Line %d, Cols: %d-%d: Warning! The empty context %s will be IGNORED!\n",
|
||||
my_file, @4.first_line, @4.first_column, @4.last_column, $3 );
|
||||
$$ = 0;
|
||||
free($3);
|
||||
} else {
|
||||
$$ = npval2(PV_CONTEXT, &@1, &@6);
|
||||
$$->u1.str = $3;
|
||||
$$->u2.statements = $5;
|
||||
set_dads($$,$5);
|
||||
$$->u3.abstract = $1;} }
|
||||
$$ = npval2(PV_CONTEXT, &@1, &@6);
|
||||
$$->u1.str = $3;
|
||||
$$->u2.statements = $5;
|
||||
set_dads($$,$5);
|
||||
$$->u3.abstract = $1;}
|
||||
;
|
||||
|
||||
/* optional "abstract" keyword XXX there is no regression test for this */
|
||||
opt_abstract: KW_ABSTRACT { $$ = 1; }
|
||||
| /* nothing */ { $$ = 0; }
|
||||
| KW_EXTEND { $$ = 2; }
|
||||
| KW_EXTEND KW_ABSTRACT { $$=3; }
|
||||
| KW_ABSTRACT KW_EXTEND { $$=3; }
|
||||
;
|
||||
|
||||
macro : KW_MACRO word LP arglist RP LC macro_statements RC {
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -2293,9 +2293,9 @@ static void check_context_names(void)
|
||||
if (i->type == PV_CONTEXT || i->type == PV_MACRO) {
|
||||
for (j=i->next; j; j=j->next) {
|
||||
if ( j->type == PV_CONTEXT || j->type == PV_MACRO ) {
|
||||
if ( !strcmp(i->u1.str, j->u1.str) )
|
||||
if ( !strcmp(i->u1.str, j->u1.str) && !(i->u3.abstract&2) && !(j->u3.abstract&2) )
|
||||
{
|
||||
ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: The context name (%s) is also declared in file %s, line %d-%d!\n",
|
||||
ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: The context name (%s) is also declared in file %s, line %d-%d! (and neither is marked 'extend')\n",
|
||||
i->filename, i->startline, i->endline, i->u1.str, j->filename, j->startline, j->endline);
|
||||
warns++;
|
||||
}
|
||||
@@ -4031,7 +4031,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root)
|
||||
break;
|
||||
|
||||
case PV_CONTEXT:
|
||||
context = ast_context_create(local_contexts, p->u1.str, registrar);
|
||||
context = ast_context_find_or_create(local_contexts, p->u1.str, registrar);
|
||||
|
||||
/* contexts contain: ignorepat, includes, switches, eswitches, extensions, */
|
||||
for (p2=p->u2.statements; p2; p2=p2->next) {
|
||||
|
@@ -91,6 +91,7 @@ int ast_add_extension2(struct ast_context *con,
|
||||
const char *registrar);
|
||||
void pbx_builtin_setvar(void *chan, void *data);
|
||||
struct ast_context * ast_context_create(void **extcontexts, const char *name, const char *registrar);
|
||||
struct ast_context * ast_context_find_or_create(void **extcontexts, const char *name, const char *registrar);
|
||||
void ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar);
|
||||
void ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar);
|
||||
void ast_context_add_switch2(struct ast_context *con, const char *value, const char *data, int eval, const char *registrar);
|
||||
@@ -359,6 +360,21 @@ struct ast_context * ast_context_create(void **extcontexts, const char *name, co
|
||||
return x;
|
||||
}
|
||||
|
||||
struct ast_context * ast_context_find_or_create(void **extcontexts, const char *name, const char *registrar)
|
||||
{
|
||||
struct ast_context *x = calloc(1, sizeof(*x));
|
||||
if (!x)
|
||||
return NULL;
|
||||
x->next = context_list;
|
||||
context_list = x;
|
||||
if (!no_comp)
|
||||
printf("Executed ast_context_find_or_create(conts, name=%s, registrar=%s);\n", name, registrar);
|
||||
conts++;
|
||||
strncpy(x->name, name, sizeof(x->name) - 1);
|
||||
strncpy(x->registrar, registrar, sizeof(x->registrar) - 1);
|
||||
return x;
|
||||
}
|
||||
|
||||
void ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
|
||||
{
|
||||
if(!no_comp)
|
||||
|
@@ -630,6 +630,13 @@ struct ast_context *ast_context_create(struct ast_context **extcontexts, const c
|
||||
return localized_context_create(extcontexts, name, registrar);
|
||||
}
|
||||
|
||||
struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, const char *name, const char *registrar)
|
||||
{
|
||||
printf("find/Creating context %s, registrar=%s\n", name, registrar);
|
||||
|
||||
return localized_context_create(extcontexts, name, registrar);
|
||||
}
|
||||
|
||||
void ast_cli_register_multiple(void);
|
||||
|
||||
void ast_cli_register_multiple(void)
|
||||
|
Reference in New Issue
Block a user