30 #define ASTMM_LIBC ASTMM_REDIRECT 33 #include <sys/types.h> 54 #include "asterisk/argdesc.h" 68 static int extensions_dot_conf_loaded = 0;
120 for (i=0; i<depth; i++) {
124 switch ( item->
type ) {
126 fprintf(fin,
"%s;\n", item->
u1.
str);
130 fprintf(fin,
"macro %s(", item->
u1.
str);
134 fprintf(fin,
"%s", lp->
u1.
str);
136 fprintf(fin,
") {\n");
138 for (i=0; i<depth; i++) {
141 fprintf(fin,
"};\n\n");
146 fprintf(fin,
"abstract context %s {\n", item->
u1.
str);
148 fprintf(fin,
"context %s {\n", item->
u1.
str);
150 for (i=0; i<depth; i++) {
153 fprintf(fin,
"};\n\n");
157 fprintf(fin,
"&%s(", item->
u1.
str);
161 fprintf(fin,
"%s", lp->
u1.
str);
167 fprintf(fin,
"%s(", item->
u1.
str);
171 fprintf(fin,
"%s", lp->
u1.
str);
177 fprintf(fin,
"case %s:\n", item->
u1.
str);
182 fprintf(fin,
"pattern %s:\n", item->
u1.
str);
187 fprintf(fin,
"default:\n");
192 fprintf(fin,
"catch %s {\n", item->
u1.
str);
194 for (i=0; i<depth; i++) {
201 fprintf(fin,
"switches {\n");
203 for (i=0; i<depth; i++) {
210 fprintf(fin,
"eswitches {\n");
212 for (i=0; i<depth; i++) {
219 fprintf(fin,
"includes {\n");
221 for (i=0; i<depth+1; i++) {
224 fprintf(fin,
"%s", lp->
u1.
str);
226 fprintf(fin,
"|%s|%s|%s|%s",
235 for (i=0; i<depth; i++) {
244 for (i=0; i<depth; i++) {
251 fprintf(fin,
"%s=%s;\n", item->
u1.
str, item->
u2.
val);
255 fprintf(fin,
"local %s=%s;\n", item->
u1.
str, item->
u2.
val);
268 fprintf(fin,
"%s:\n", item->
u1.
str);
277 fprintf(fin,
"while (%s)\n", item->
u1.
str);
282 fprintf(fin,
"break;\n");
286 fprintf(fin,
"return;\n");
290 fprintf(fin,
"continue;\n");
298 fprintf(fin,
"ifTime ( %s|%s|%s|%s )\n",
305 fprintf(fin,
"random ( %s )\n", item->
u1.
str );
307 fprintf(fin,
"if ( %s )\n", item->
u1.
str);
309 for (i=0; i<depth; i++) {
314 for (i=0; i<depth; i++) {
325 fprintf(fin,
" {} ");
327 fprintf(fin,
" {}; ");
330 for (i=0; i<depth; i++) {
333 fprintf(fin,
"else\n");
339 fprintf(fin,
"switch( %s ) {\n", item->
u1.
str);
341 for (i=0; i<depth; i++) {
349 fprintf(fin,
"regexten ");
351 fprintf(fin,
"hints(%s) ", item->
u3.
hints);
353 fprintf(fin,
"%s => ", item->
u1.
str);
359 fprintf(fin,
"ignorepat => %s;\n", item->
u1.
str);
363 fprintf(fin,
"globals {\n");
365 for (i=0; i<depth; i++) {
377 for (i=item; i; i=i->
next) {
384 FILE *fin = fopen(fname,
"w");
405 switch ( item->
type ) {
639 for (i=item; i; i=i->
next) {
656 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The macro %s is empty! I will insert a return.\n",
674 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The macro %s does not end with a return; I will insert one.\n",
700 if (strcmp(pattern,exten) == 0)
703 if (pattern[0] ==
'_') {
708 if ( strlen(pattern)*5 >= 2000 ) {
709 ast_log(
LOG_ERROR,
"Error: The pattern %s is way too big. Pattern matching cancelled.\n",
717 for (p=pattern+1; *p; p++) {
747 while ( *p && *p !=
']' ) {
752 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The extension pattern '%s' is missing a closing bracket \n",
774 err1 = regcomp(&preg, reg1, REG_NOSUB|REG_EXTENDED);
777 regerror(err1,&preg,errmess,
sizeof(errmess));
783 err1 = regexec(&preg, exten, 0, 0, 0);
803 int spaces = strspn(str,
"\t \n");
804 if ( !strncmp(str+spaces,
"$[",2) ) {
805 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The expression '%s' is redundantly wrapped in '$[ ]'. \n",
817 char *incl_context = p4->
u1.
str;
820 if (!that_other_context && strcmp(incl_context,
"parkedcalls") != 0) {
821 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The included context '%s' cannot be found.\n\ 822 (You may ignore this warning if '%s' exists in extensions.conf, or is created by another module. I cannot check for those.)\n",
844 e = strchr(times,
'-');
846 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The time range format (%s) requires a '-' surrounded by two 24-hour times of day!\n",
853 while (*e && !isdigit(*e))
856 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The time range format (%s) is missing the end time!\n",
860 if (sscanf(times,
"%2d:%2d", &s1, &s2) != 2) {
861 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The start time (%s) isn't quite right!\n",
865 if (sscanf(e,
"%2d:%2d", &e1, &e2) != 2) {
866 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The end time (%s) isn't quite right!\n",
872 if ((s1 < 0) || (s1 >= 24*30)) {
873 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The start time (%s) is out of range!\n",
878 if ((e1 < 0) || (e1 >= 24*30)) {
879 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The end time (%s) is out of range!\n",
911 c = strchr(dow,
'-');
919 while ((s < 7) && strcasecmp(dow,
days[s])) s++;
921 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The day (%s) must be one of 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', or 'sat'!\n",
927 while ((e < 7) && strcasecmp(c,
days[e])) e++;
929 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The end day (%s) must be one of 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', or 'sat'!\n",
951 c = strchr(day,
'-');
957 if (sscanf(day,
"%2d", &s) != 1) {
958 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The start day of month (%s) must be a number!\n",
962 else if ((s < 1) || (s > 31)) {
963 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The start day of month (%s) must be a number in the range [1-31]!\n",
969 if (sscanf(c,
"%2d", &e) != 1) {
970 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The end day of month (%s) must be a number!\n",
974 else if ((e < 1) || (e > 31)) {
975 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The end day of month (%s) must be a number in the range [1-31]!\n",
1013 c = strchr(mon,
'-');
1020 while ((s < 12) && strcasecmp(mon,
months[s])) s++;
1022 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The start month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n",
1028 while ((e < 12) && strcasecmp(mon,
months[e])) e++;
1030 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The end month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n",
1051 ast_log(
LOG_ERROR,
"Error: file %s, line %d-%d: 'break' not in switch, for, or while statement!\n",
1070 ast_log(
LOG_ERROR,
"Error: file %s, line %d-%d: 'continue' not in 'for' or 'while' statement!\n",
1125 ast_log(
LOG_ERROR,
"Error: file %s, line %d-%d: Label %s is not within an extension or macro!\n",
1137 if( !current_extension )
1144 if( x && x != item )
1146 ast_log(
LOG_ERROR,
"Error: file %s, line %d-%d: Duplicate label %s! Previously defined at file %s, line %d.\n",
1172 if (!strstr((item->
u1.
list)->u1.str,
"${")
1186 if (!strstr((item->
u1.
list)->u1.str,
"${")
1204 char *incl_context = p4->
u1.
str;
1207 if (that_other_context) {
1232 if ( !(item->
u1.
list)->next && !(item->
u1.
list)->u1.str ) {
1233 ast_log(
LOG_ERROR,
"Error: file %s, line %d-%d: goto: empty label reference found!\n",
1247 ast_log(
LOG_ERROR,
"Error: file %s, line %d-%d: goto: no label %s exists in the current extension!\n",
1260 if (!strstr((item->
u1.
list)->u1.str,
"${")
1269 ast_log(
LOG_ERROR,
"Error: file %s, line %d-%d: goto: no label '%s,%s' exists in the current context, or any of its inclusions!\n",
1287 if (!strstr((item->
u1.
list)->u1.str,
"${")
1293 struct pval *found = 0;
1305 char *incl_context = p4->
u1.
str;
1308 if (that_other_context) {
1320 ast_log(
LOG_ERROR,
"Error: file %s, line %d-%d: goto: no label %s|%s exists in the context %s or its inclusions!\n",
1329 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: It's bad form to have a goto in a macro to a target outside the macro!\n",
1342 if (!extensions_dot_conf_loaded) {
1344 extensions_dot_conf_loaded++;
1352 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: goto: Couldn't find goto target %s|%s|%s, not even in extensions.conf!\n",
1357 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: goto: Couldn't find goto target %s|%s|%s in the AEL code!\n",
1368 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: It's bad form to have a goto in a macro to a target outside the macro!\n",
1388 switch ( item->
type ) {
1462 char *incl_context = p4->
u1.
str;
1554 for (i=item; i; i=i->
next) {
1567 switch ( item->
type ) {
1688 last_matched_label =
item;
1815 for (i=item; i; i=i->
next) {
1863 char *incl_context = p4->
u1.
str;
1902 char *incl_context = p4->
u1.
str;
1966 for (s=arg; *s; s++) {
1967 if (*s !=
'.' && (*s < '0' || *s >
'9'))
1975 for (s=arg; *s; s++) {
1976 if (*s < '0' || *s >
'9')
1988 if (*arg !=
' ' && *arg !=
'\t')
1996 int option_matches_j(
struct argdesc *should,
pval *is,
struct argapp *
app)
1998 struct argchoice *ac;
2001 switch (should->dtype) {
2002 case ARGD_OPTIONSET:
2003 if ( strstr(is->
u1.
str,
"${") )
2008 for (q=opcop;*q;q++) {
2011 while (*p && *p !=
')' )
2017 for (ac=app->opts; ac; ac=ac->
next) {
2018 if (strlen(ac->name)>1 && strchr(ac->name,
'(') == 0 && strcmp(ac->name,is->
u1.
str) == 0)
2021 for (ac=app->opts; ac; ac=ac->
next) {
2022 if (strlen(ac->name)==1 || strchr(ac->name,
'(')) {
2023 char *p = strchr(opcop,ac->name[0]);
2025 if (p && *p ==
'j') {
2026 ast_log(
LOG_ERROR,
"Error: file %s, line %d-%d: The j option in the %s application call is not appropriate for AEL!\n",
2033 if (ac->name[1] ==
'(') {
2034 if (*(p+1) !=
'(') {
2035 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The %c option in the %s application call should have an (argument), but doesn't!\n",
2043 for (q=opcop; *q; q++) {
2044 if ( *q !=
'+' && *q !=
'(' && *q !=
')') {
2045 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The %c option in the %s application call is not available as an option!\n",
2058 int option_matches(
struct argdesc *should,
pval *is,
struct argapp *app)
2060 struct argchoice *ac;
2063 switch (should->dtype) {
2088 for (ac=should->choices; ac; ac=ac->next) {
2089 if (strcmp(ac->name,is->
u1.
str) == 0)
2095 case ARGD_OPTIONSET:
2098 for (ac=app->opts; ac; ac=ac->
next) {
2099 if (strlen(ac->name)>1 && strchr(ac->name,
'(') == 0 && strcmp(ac->name,is->
u1.
str) == 0)
2102 for (ac=app->opts; ac; ac=ac->
next) {
2103 if (strlen(ac->name)==1 || strchr(ac->name,
'(')) {
2104 char *p = strchr(opcop,ac->name[0]);
2108 if (ac->name[1] ==
'(') {
2109 if (*(p+1) ==
'(') {
2111 while (*q && *q !=
')') {
2133 struct argdesc *ad = app->args;
2137 for (pa = arglist; pa; pa=pa->
next) {
2139 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: Extra argument %s not in application call to %s !\n",
2146 if ( ad->dtype == ARGD_VARARG )
2149 z= option_matches( ad, pa, app);
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",
2160 }
else if (z && ad->dtype == ARGD_OPTIONSET) {
2161 option_matches_j( ad, pa, app);
2168 for ( ; ad; ad=ad->next) {
2169 if (ad->type == ARGD_REQUIRED && ad->dtype != ARGD_VARARG) {
2172 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n",
2190 struct appsetvar *v,*v2;
2191 struct argchoice *
c;
2195 while (p && *p && (*p ==
' ' || *p ==
'\t' || *p ==
'$' || *p ==
'{' ) )
2200 while (strlen(buff1) > 0 && ( buff1[strlen(buff1)-1] ==
'}' || buff1[strlen(buff1)-1] ==
' ' || buff1[strlen(buff1)-1] ==
'\t'))
2201 buff1[strlen(buff1)-1] = 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) {
2231 for (c=v->vals; c; c=c->next) {
2235 if (!strcmp(t->
u1.
str,c->name)) {
2242 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: switch with expression(%s) does not handle the case of %s !\n",
2252 for (; t && t !=
item; t=t->
next) {
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) {
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",
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);
2313 for (i=current_db; i; i=i->
next) {
2319 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: The context name (%s) is also declared in file %s, line %d-%d! (and neither is marked 'extend')\n",
2336 for (i=current_db; i; i=i->
next) {
2338 for (j=i->
u2. statements; j; j=j->
next) {
2344 if ( !strcmp(p4->
u1.
str, abstract_context->
u1.
str) )
2351 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: Couldn't find a reference to this abstract context (%s) in any other context!\n",
2363 struct pval *macro_def;
2364 struct pval *app_def;
2369 switch (item->
type) {
2384 current_context =
item;
2385 current_extension = 0;
2400 current_context =
item;
2401 current_extension = 0;
2419 if (!extensions_dot_conf_loaded) {
2421 extensions_dot_conf_loaded++;
2435 snprintf(namebuf2, 256,
"macro-%s", item->
u1.
str);
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",
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",
2451 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: macro call to %s cannot be found in the AEL code!\n",
2456 #ifdef THIS_IS_1DOT4 2458 snprintf(namebuf2, 256,
"macro-%s", item->
u1.
str);
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",
2472 ast_log(
LOG_ERROR,
"Error: file %s, line %d-%d: macro call to %s references a context, not a macro!\n",
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",
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",
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",
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",
2539 for (app=apps;
app; app=app->
next) {
2540 if (strcasecmp(app->name, item->
u1.
str) == 0) {
2546 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: application call to %s not listed in applist database!\n",
2606 char *incl_context = lp->
u1.
str;
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);
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",
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);
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",
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",
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);
2708 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
2713 ast_log(
LOG_WARNING,
"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
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);
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",
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);
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",
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);
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",
2844 current_extension =
item ;
2880 for (i=item; i; i=i->
next) {
2900 apps = argdesc_parse(rfilename, &argapp_errs);
2909 argdesc_destroy(apps);
2940 if (!exten->
plist) {
2941 exten->
plist = prio;
2955 while ((p1 = strstr(prio->
appargs,
"${EXTEN}"))) {
2959 strcat(p2,
"${~~EXTEN~~}");
2965 while ((p1 = strstr(prio->
appargs,
"${EXTEN:"))) {
2969 strcat(p2,
"${~~EXTEN~~:");
2981 for (ne=exten; ne; ne=nen) {
2994 for (pe=ne->
plist; pe; pe=pen) {
3041 while( str && *str && *str !=
'=' )
3043 if( *str ==
' ' || *str ==
'\n' || *str ==
'\r' || *str ==
'\t' )
3064 char *p=pattern, *t=
result;
3066 if (*p ==
'x' || *p ==
'n' || *p ==
'z' || *p ==
'X' || *p ==
'N' || *p ==
'Z')
3068 else if (*p ==
'[') {
3092 switch ( item->
type ) {
3333 for (i=item; i; i=i->
next) {
3345 struct ael_priority *for_init, *for_test, *for_inc, *for_loop, *for_end;
3346 struct ael_priority *while_test, *while_loop, *while_end;
3347 struct ael_priority *switch_set, *switch_test, *switch_end, *fall_thru, *switch_empty;
3348 struct ael_priority *if_test, *if_end, *if_skip, *if_false;
3349 #ifdef OLD_RAND_ACTION 3357 int local_control_statement_count;
3377 for (first = 1; first >= 0; first--) {
3382 if (!strcmp(mother_exten->
name,
"~~s~~") && first) {
3391 linkprio(exten, switch_set, mother_exten);
3402 for (first = 1; first >= 0; first--) {
3407 if (!strcmp(exten->
name,
"~~s~~")) {
3416 linkprio(exten, switch_set, mother_exten);
3435 for (p=statement; p; p=p->
next) {
3519 strp = strchr(
buf2,
'=');
3529 while (*strp2 && isspace(*strp2))
3531 if (*strp2 ==
'&') {
3532 char *strp3 = strp2+1;
3533 while (*strp3 && isspace(*strp3))
3535 strcpy(
buf2, strp3);
3536 strp3 = strchr(
buf2,
'(');
3540 strp3 = strrchr(
buf2,
')');
3548 strcpy(
buf2, strp2);
3549 strp3 = strchr(
buf2,
'(');
3555 strp3 = strrchr(for_init->
appargs,
')');
3564 strp = strchr(
buf2,
'=');
3575 while (*strp2 && isspace(*strp2))
3577 if (*strp2 ==
'&') {
3578 char *strp3 = strp2+1;
3579 while (*strp3 && isspace(*strp3))
3581 strcpy(
buf2, strp3);
3582 strp3 = strchr(
buf2,
'(');
3586 strp3 = strrchr(
buf2,
')');
3595 strcpy(
buf2, strp2);
3596 strp3 = strchr(
buf2,
'(');
3601 strp3 = strrchr(for_inc->
appargs,
')');
3615 linkprio(exten, for_init, mother_exten);
3616 linkprio(exten, for_test, mother_exten);
3626 linkprio(exten, for_inc, mother_exten);
3627 linkprio(exten, for_loop, mother_exten);
3628 linkprio(exten, for_end, mother_exten);
3649 while_test->
app = 0;
3656 linkprio(exten, while_test, mother_exten);
3666 linkprio(exten, while_loop, mother_exten);
3667 linkprio(exten, while_end, mother_exten);
3694 linkprio(exten, switch_test, mother_exten);
3695 linkprio(exten, switch_end, mother_exten);
3714 switch_case->
context = this_context;
3721 snprintf(
buf1,
BUF_SIZE,
"sw_%d_%s", local_control_statement_count, p2->
u1.
str);
3723 snprintf(new_label,
BUF_SIZE,
"sw_%s_%s_%d", label, p2->
u1.
str, local_control_statement_count);
3743 linkprio(switch_case, fall_thru, mother_exten);
3749 snprintf(
buf1,
BUF_SIZE,
"sw_%d_%s,10", local_control_statement_count,
buf2);
3751 linkprio(switch_case, fall_thru, mother_exten);
3756 snprintf(
buf1,
BUF_SIZE,
"sw_%d_.,10", local_control_statement_count);
3758 linkprio(switch_case, fall_thru, mother_exten);
3759 }
else if (!p2->
next) {
3764 linkprio(switch_case, fall_thru, mother_exten);
3772 snprintf(buf,
BUF_SIZE,
"End of Extension %s", switch_case->
name);
3774 linkprio(switch_case, np2, mother_exten);
3775 switch_case-> return_target = np2;
3788 switch_case->
context = this_context;
3795 snprintf(
buf1,
BUF_SIZE,
"_sw_%d_%s", local_control_statement_count, p2->
u1.
str);
3797 snprintf(new_label,
BUF_SIZE,
"sw_%s_%s_%d", label, p2->
u1.
str, local_control_statement_count);
3816 linkprio(switch_case, fall_thru, mother_exten);
3822 snprintf(
buf1,
BUF_SIZE,
"sw_%d_%s,10", local_control_statement_count,
buf2);
3824 linkprio(switch_case, fall_thru, mother_exten);
3829 snprintf(
buf1,
BUF_SIZE,
"sw_%d_.,10", local_control_statement_count);
3831 linkprio(switch_case, fall_thru, mother_exten);
3832 }
else if (!p2->
next) {
3837 linkprio(switch_case, fall_thru, mother_exten);
3845 snprintf(buf,
sizeof(buf),
"End of Extension %s", switch_case->
name);
3847 linkprio(switch_case, np2, mother_exten);
3848 switch_case-> return_target = np2;
3861 switch_case->
context = this_context;
3878 switch_null->
context = this_context;
3881 snprintf(
buf1,
BUF_SIZE,
"sw_%d_.,10", local_control_statement_count);
3884 linkprio(switch_null, switch_empty, mother_exten);
3885 snprintf(
buf1,
BUF_SIZE,
"sw_%d_", local_control_statement_count);
3895 snprintf(
buf1,
BUF_SIZE,
"_sw_%d_.", local_control_statement_count);
3898 snprintf(new_label,
BUF_SIZE,
"sw_%s_default_%d", label, local_control_statement_count);
3918 linkprio(switch_case, fall_thru, mother_exten);
3924 snprintf(
buf1,
BUF_SIZE,
"sw_%d_%s,10", local_control_statement_count,
buf2);
3926 linkprio(switch_case, fall_thru, mother_exten);
3931 snprintf(
buf1,
BUF_SIZE,
"sw_%d_.,10", local_control_statement_count);
3933 linkprio(switch_case, fall_thru, mother_exten);
3934 }
else if (!p2->
next) {
3939 linkprio(switch_case, fall_thru, mother_exten);
3947 snprintf(buf,
sizeof(buf),
"End of Extension %s", switch_case->
name);
3949 linkprio(switch_case, np2, mother_exten);
3950 switch_case-> return_target = np2;
4070 linkprio(exten, if_test, mother_exten);
4071 linkprio(exten, if_false, mother_exten);
4080 linkprio(exten, if_skip, mother_exten);
4086 linkprio(exten, if_end, mother_exten);
4121 linkprio(exten, if_test, mother_exten);
4130 linkprio(exten, if_skip, mother_exten);
4136 linkprio(exten, if_end, mother_exten);
4141 if (
gen_prios(exten, label, p->
u1.
list, mother_exten, this_context)) {
4160 switch_case->
context = this_context;
4173 snprintf(buf,
sizeof(buf),
"End of Extension %s", switch_case->
name);
4175 linkprio(switch_case, np2, mother_exten);
4176 switch_case-> return_target = np2;
4199 for (pr=exten->
plist; pr; pr=pr->
next) {
4234 for (pr=exten->
plist; pr; pr=pr->
next) {
4247 strcpy(app, pr->
app);
4254 switch( pr->
type ) {
4271 strcpy(app,
"GotoIf");
4276 strcpy(app,
"GotoIf");
4284 strcpy(app,
"Random");
4289 strcpy(app,
"GotoIfTime");
4294 strcpy(app,
"Return");
4371 char *apparg_save = p->
appargs;
4382 snprintf(buf1,
sizeof(buf1),
"%s,%s,%s", pv2->
u1.
list->
u1.
str,
4388 printf(
"WHAT? The goto doesn't fall into one of three cases for GOTO????\n");
4406 if (exten->
context == context) {
4424 for (p=root; p; p=p->
next ) {
4431 snprintf(buf2,
sizeof(buf2),
"%s=%s", p2->
u1.
str, p2->
u2.
val);
4440 for (p=root; p; p=p->
next ) {
4458 snprintf(buf,
sizeof(buf),
"LOCAL(%s)=${ARG%d}", lp->
u1.
str, argc++);
4472 snprintf(buf,
sizeof(buf),
"End of Macro %s-%s",p->
u1.
str, exten->
name);
4475 exten-> return_target = np2;
4500 if( (s3=strchr(exten->
name,
'/') ) != 0 )
4516 snprintf(buf,
sizeof(buf),
"End of Extension %s", exten->
name);
4519 exten-> return_target = np2;
4526 snprintf(buf,
sizeof(buf),
"A NoOp to follow a trailing label %s", exten->
plist_last->
origin->
u1.
str);
4542 snprintf(buf,
sizeof(buf),
"%s,%s,%s,%s,%s",
4556 char *
c = strchr(p3->
u1.
str,
'/');
4569 char *
c = strchr(p3->
u1.
str,
'/');
4596 const char *h_context =
"ael-builtin-h-bubble";
4604 { 1,
"Goto",
"9991" },
4606 { 9991,
"Set",
"~~parentcxt~~=${STACK_PEEK(1,c,1)}" },
4608 { 9992,
"GotoIf",
"$[\"${~~parentcxt~~}\"=\"\"]?9996" },
4610 { 9993,
"GotoIf",
"${DIALPLAN_EXISTS(${~~parentcxt~~},h,1)}?9994:9996" },
4612 { 9994,
"StackPop",
"" },
4614 { 9995,
"Goto",
"${~~parentcxt~~},h,1" },
4616 { 9996,
"NoOp",
"" }
4623 char h_context_template[] =
"/tmp/ael-builtin-h-bubble-XXXXXX";
4624 int fd = mkstemp(h_context_template);
4625 unlink(h_context_template);
4636 for (i = 0; i <
ARRAY_LEN(steps); i++) {
4651 if (!strcmp(exten->
name,
"~~s~~")) {
4682 switch (item->
type) {
4944 for (i=item; i; i=nxt) {
4952 static char *ael_funclist[] =
4977 "GROUP_MATCH_COUNT",
4989 "QUEUE_MEMBER_COUNT",
4990 "QUEUE_MEMBER_LIST",
5011 int ael_is_funcname(
char *
name)
5014 t =
sizeof(ael_funclist)/
sizeof(
char*);
5016 while ((s < t) && strcasecmp(name, ael_funclist[s]))
5033 if (p->
type != type)
5035 ast_log(
LOG_ERROR,
"Func: %s the pval passed is not appropriate for this function!\n", funcname);
5112 *arg = (*arg)->
next;
5133 if (!(*next_statement))
5136 *next_statement = (*next_statement)->
next;
5138 return *next_statement;
5197 *statements = (*statements)->
next;
5241 *args = (*args)->
next;
5285 *args = (*args)->
next;
5316 *statement = (*statement)->
next;
5368 *next_item = (*next_item)->
next;
5370 return (*next_item)->
u1.
str;
5390 *next_item = (*next_item)->
next;
5392 return (*next_item)->
u1.
str;
5402 s->
u1.
str = (
char *)include;
5425 if (!hr || !dom || !dow || !mon || !s) {
5434 s->
u1.
str = (
char *)include;
5437 hr->
u1.
str = hour_range;
5438 dom->
u1.
str = dom_range;
5439 dow->
u1.
str = dow_range;
5440 mon->
u1.
str = month_range;
5474 *next_item = (*next_item)->
next;
5476 return (*next_item)->
u1.
str;
5491 if (!(*next_statement))
5492 *next_statement = p->
u1.
list;
5494 *next_statement = (*next_statement)->
next;
5496 return *next_statement;
5533 if (context && strlen(context)) {
5540 pri->
u1.
str = label;
5545 }
else if (exten && strlen(exten)) {
5550 pri->
u1.
str = label;
5557 pri->
u1.
str = label;
5693 if (!hr || !dom || !dow || !mon) {
5726 p->
u1.
str = percent;
5789 *next_case = (*next_case)->
next;
5877 ast_log(
LOG_ERROR,
"pvalGlobalsAddStatement called where first arg is not a Globals!\n");
5891 if (!*next_statement) {
5892 *next_statement = p;
5895 *next_statement = (*next_statement)->
next;
5896 return (*next_statement)->
next;
5916 *next_obj = (*next_obj)->
next;
5917 return (*next_obj)->
next;
pval * pvalMacroCallWalkArgs(pval *p, pval **args)
static int context_used(struct ael_extension *exten_list, struct ast_context *context)
char * pvalForGetInc(pval *p)
static char exten[AST_MAX_EXTENSION]
char * pvalAppCallGetAppName(pval *p)
static int control_statement_count
static void find_pval_gotos(pval *item, int lev)
Asterisk main include file. File version handling, generic pbx functions.
static struct pval * in_macro(pval *item)
static int check_break(pval *item)
pval * pvalGlobalsWalkStatements(pval *p, pval **next_statement)
const char * ast_get_context_name(struct ast_context *con)
char * pvalSwitchesWalkNames(pval *p, pval **next_item)
void pvalIncludesAddIncludeWithTimeConstraints(pval *p, const char *include, char *hour_range, char *dom_range, char *dow_range, char *month_range)
static struct pval * find_label_in_current_extension(const char *label, pval *curr_ext)
void pvalCasePatSetVal(pval *p, char *val)
void set_priorities(struct ael_extension *exten)
pvaltype pvalObjectGetType(pval *p)
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
void pvalCatchSetExtName(pval *p, char *name)
static void fix_gotos_in_extensions(struct ael_extension *exten)
void pvalContextSetName(pval *p, char *name)
int pvalCheckType(pval *p, char *funcname, pvaltype type)
int pvalContextGetAbstract(pval *p)
Registered applications container.
pval * pvalMacroWalkStatements(pval *p, pval **next_statement)
void pvalMacroSetName(pval *p, char *name)
struct ael_extension * new_exten(void)
void pvalMacroAddStatement(pval *p, pval *statement)
struct ael_priority * goto_true
void check_pval_item(pval *item, struct argapp *apps, int in_globals)
int ast_context_switches_count(const struct ast_context *con)
static void linkexten(struct ael_extension *exten, struct ael_extension *add)
struct ael_priority * plist_last
static int label_inside_case(pval *label)
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)
pval * pvalExtenGetStatement(pval *p)
struct pval * find_macro(char *name)
void pvalMacroAddArg(pval *p, pval *arg)
void destroy_pval_item(pval *item)
struct pval * find_context(char *name)
void pvalSwitchAddCase(pval *p, pval *Case)
static struct aco_type item
void pvalContextSetAbstract(pval *p)
static struct ast_threadstorage buf2
struct ael_priority * plist
static void check_day(pval *DAY)
pval * pvalMacroWalkArgs(pval *p, pval **arg)
struct ast_context * local_contexts
struct ael_priority * goto_false
void pvalExtenSetRegexten(pval *p)
void pvalGlobalsAddStatement(pval *p, pval *statement)
static struct ao2_container * hints
void ast_free_ptr(void *ptr)
free() wrapper
void pvalESwitchesAddSwitch(pval *p, char *name)
static void check_abstract_reference(pval *abstract_context)
static int gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *this_context)
#define ast_strlen_zero(foo)
struct ael_extension * next_exten
static struct pval * in_context(pval *item)
char * pvalForGetInit(pval *p)
void pvalAppCallSetAppName(pval *p, char *name)
pval * linku1(pval *head, pval *tail)
void linkprio(struct ael_extension *exten, struct ael_priority *prio, struct ael_extension *mother_exten)
struct ast_context * context
char * pvalMacroCallGetMacroName(pval *p)
int ast_context_add_include2(struct ast_context *con, const char *include, const char *registrar)
Add a context include.
Configuration File Parser.
static pval * get_contxt(pval *p)
void pvalGotoSetTarget(pval *p, char *context, char *exten, char *label)
void pvalMacroCallSetMacroName(pval *p, char *name)
char * pvalContextGetName(pval *p)
void pvalCatchSetStatement(pval *p, pval *statement)
pval * pvalCasePatDefWalkStatements(pval *p, pval **statement)
static int check_continue(pval *item)
void pvalMacroCallAddArg(pval *p, pval *arg)
void pvalMacroCallSetArglist(pval *p, pval *arglist)
void pvalContextUnsetAbstract(pval *p)
General Asterisk PBX channel definitions.
void pvalExtenSetName(pval *p, char *name)
static int extension_matches(pval *here, const char *exten, const char *pattern)
static pval * current_extension
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
pval * pvalForGetStatement(pval *p)
struct sla_ringing_trunk * last
static int in_abstract_context
char * pvalRandomGetCondition(pval *p)
#define AST_MAX_EXTENSION
static void check_timerange(pval *p)
static void check_macro_returns(pval *macro)
void pvalIfSetCondition(pval *p, char *expr)
struct pval * goto_target
static void print_pval(FILE *fin, pval *item, int depth)
#define ast_strdupa(s)
duplicate a string in memory from the stack
struct ael_extension * exten
static char next_item(const char *format)
int localized_pbx_load_module(void)
void pvalConditionalSetThenStatement(pval *p, pval *statement)
void pvalIfTimeGetCondition(pval *p, char **hour_range, char **dow_range, char **dom_range, char **month_range)
void destroy_pval(pval *item)
char * pvalCatchGetExtName(pval *p)
struct ael_priority * loop_break
void pvalForSetInc(pval *p, char *inc)
Core PBX routines and definitions.
char * pvalCasePatGetVal(pval *p)
void pvalForSetStatement(pval *p, pval *statement)
void pvalAppCallAddArg(pval *p, pval *arg)
struct ael_priority * new_prio(void)
void destroy_extensions(struct ael_extension *exten)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
int count_labels_in_current_context(char *label)
struct ael_extension * compiled_label
int ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root)
static struct pval * find_label_in_current_context(char *exten, char *label, pval *curr_cont)
int ast_context_includes_count(const struct ast_context *con)
char * pvalESwitchesWalkNames(pval *p, pval **next_item)
char * pvalForGetTest(pval *p)
static char expr_output[2096]
void ast_expr_clear_extra_error_info(void)
struct ast_custom_function * ast_custom_function_find(const char *name)
static void gen_match_to_pattern(char *pattern, char *result)
struct pval * else_statements
static void check_goto(pval *item)
void pvalMacroSetArglist(pval *p, pval *arglist)
struct ael_priority * loop_continue
char * pvalExtenGetName(pval *p)
void pvalExtenSetHints(pval *p, char *hints)
void pvalForSetInit(pval *p, char *init)
struct sla_ringing_trunk * first
static struct ast_hashtab * local_table
pval * pvalTopLevWalkObjects(pval *p, pval **next_obj)
static struct pval * find_label_in_current_db(const char *context, const char *exten, const char *label)
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
static void check_label(pval *item)
static struct ast_threadstorage buf1
static void check_includes(pval *includes)
void pvalExtenSetStatement(pval *p, pval *statement)
int contains_switch(pval *item)
struct ael_priority * next
Structures for AEL - the Asterisk extension language.
char * pvalVarDecGetVarname(pval *p)
char * pvalIncludesWalk(pval *p, pval **next_item)
void pvalContextAddStatement(pval *p, pval *statement)
pval * pvalStatementBlockWalkStatements(pval *p, pval **next_statement)
static void attach_exten(struct ael_extension **list, struct ael_extension *newmem)
int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
Parse and set a single channel variable, where the name and value are separated with an '=' character...
void pvalConditionalSetElseStatement(pval *p, pval *statement)
void pvalIfTimeSetCondition(pval *p, char *hour_range, char *dow_range, char *dom_range, char *mon_range)
void ast_expr_register_extra_error_info(char *errmsg)
Support for logging to various files, console and syslog Configuration in file logger.conf.
pval * pvalSwitchWalkCases(pval *p, pval **next_case)
void pvalIgnorePatSetPattern(pval *p, char *pat)
static void check_month(pval *MON)
void pvalCasePatDefAddStatement(pval *p, pval *statement)
static pval * current_context
char * pvalWordGetString(pval *p)
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 *.
void pvalWordSetString(pval *p, char *str)
void pvalGotoGetTarget(pval *p, char **context, char **exten, char **label)
static void remove_spaces_before_equals(char *str)
pval * pvalAppCallWalkArgs(pval *p, pval **args)
Standard Command Line Interface.
int find_switch_item(pval *item)
char * pvalMacroGetName(pval *p)
void pvalForSetTest(pval *p, char *test)
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
pval * pvalCatchGetStatement(pval *p)
static struct pval * find_first_label_in_current_context(char *label, pval *curr_cont)
pval * pvalConditionalGetElseStatement(pval *p)
void ael2_print(char *fname, pval *tree)
int ast_context_ignorepats_count(const struct ast_context *con)
char * pvalSwitchGetTestexpr(pval *p)
char * pvalIfGetCondition(pval *p)
static void check_expr2_input(pval *expr, char *str)
static const char * match_exten
char * pvalLabelGetName(pval *p)
void pvalTopLevAddObject(pval *p, pval *contextOrObj)
static int return_on_context_match
int ast_context_add_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
pval * pvalContextWalkStatements(pval *p, pval **statements)
static char context[AST_MAX_CONTEXT]
void pvalExtenUnSetRegexten(pval *p)
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.
struct pval * for_statements
void check_switch_expr(pval *item, struct argapp *apps)
void traverse_pval_template(pval *item, int depth)
char * pvalVarDecGetValue(pval *p)
char * pvalExtenGetHints(pval *p)
void pvalStatementBlockAddStatement(pval *p, pval *statement)
int pvalExtenGetRegexten(pval *p)
static pval * get_goto_target(pval *item)
void pvalIncludesAddInclude(pval *p, const char *include)
static pval * last_matched_label
Asterisk module definitions.
void pvalRandomSetCondition(pval *p, char *percent)
const char * ast_config_AST_VAR_DIR
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)
static void print_pval_list(FILE *fin, pval *item, int depth)
struct pval * match_pval(pval *item)
void pvalAppCallSetArglist(pval *p, pval *arglist)
void pvalVarDecSetVarname(pval *p, char *name)
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
ast_context: An extension context - must remain in sync with fake_context
void traverse_pval_item_template(pval *item, int depth)
void pvalSwitchesAddSwitch(pval *p, char *name)
int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan)
Evaluate the given expression.
static const char * match_context
void pvalSwitchSetTestexpr(pval *p, char *expr)
void pvalIncludeGetTimeConstraints(pval *p, char **hour_range, char **dom_range, char **dow_range, char **month_range)
pval * pvalConditionalGetThenStatement(pval *p)
int check_app_args(pval *appcall, pval *arglist, struct argapp *app)
void add_extensions(struct ael_extension *exten)
pval * pvalCreateNode(pvaltype type)
static void check_dow(pval *DOW)
get_dow: Get day of week
struct pval * macro_statements
static struct ast_test * test
static const char * match_label
static void check_context_names(void)
void pvalVarDecSetValue(pval *p, char *value)
void check_pval(pval *item, struct argapp *apps, int in_globals)
static pval * get_extension_or_contxt(pval *p)
static struct pval * match_pval_item(pval *item)
static void find_pval_goto_item(pval *item, int lev)
void ael2_semantic_check(pval *item, int *arg_errs, int *arg_warns, int *arg_notes)
void pvalLabelSetName(pval *p, char *name)
char * pvalIgnorePatGetPattern(pval *p)