30 #define ASTMM_LIBC ASTMM_REDIRECT
33 #include <sys/types.h>
51 #include "asterisk/pval.h"
54 #include "asterisk/argdesc.h"
58 extern int localized_pbx_load_module(
void);
60 static char expr_output[2096];
65 static int errs, warns;
68 static int extensions_dot_conf_loaded = 0;
70 static char *registrar =
"pbx_ael";
72 static pval *current_db;
73 static pval *current_context;
74 static pval *current_extension;
76 static const char *match_context;
77 static const char *match_exten;
78 static const char *match_label;
79 static int in_abstract_context;
80 static int count_labels;
81 static int label_count;
82 static int return_on_context_match;
83 static pval *last_matched_label;
85 static void check_timerange(
pval *p);
87 static void check_day(
pval *DAY);
88 static void check_month(
pval *MON);
89 static void check_expr2_input(
pval *expr,
char *str);
90 static int extension_matches(
pval *here,
const char *exten,
const char *pattern);
91 static void check_goto(
pval *item);
92 static void find_pval_goto_item(
pval *item,
int lev);
93 static void find_pval_gotos(
pval *item,
int lev);
94 static int check_break(
pval *item);
95 static int check_continue(
pval *item);
96 static void check_label(
pval *item);
97 static void check_macro_returns(
pval *macro);
99 static struct pval *find_label_in_current_context(
char *exten,
char *label,
pval *curr_cont);
100 static struct pval *find_first_label_in_current_context(
char *label,
pval *curr_cont);
101 static void print_pval_list(FILE *fin,
pval *item,
int depth);
103 static struct pval *find_label_in_current_extension(
const char *label,
pval *curr_ext);
104 static struct pval *find_label_in_current_db(
const char *context,
const char *exten,
const char *label);
105 static pval *get_goto_target(
pval *item);
106 static int label_inside_case(
pval *label);
108 static void fix_gotos_in_extensions(
struct ael_extension *exten);
109 static pval *get_extension_or_contxt(
pval *p);
111 static void remove_spaces_before_equals(
char *str);
115 static void print_pval(FILE *fin,
pval *item,
int depth)
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);
131 for (lp=item->u2.arglist; lp; lp=lp->next) {
132 if (lp != item->u2.arglist )
134 fprintf(fin,
"%s", lp->u1.str);
136 fprintf(fin,
") {\n");
137 print_pval_list(fin,item->u3.macro_statements,depth+1);
138 for (i=0; i<depth; i++) {
141 fprintf(fin,
"};\n\n");
145 if ( item->u3.abstract )
146 fprintf(fin,
"abstract context %s {\n", item->u1.str);
148 fprintf(fin,
"context %s {\n", item->u1.str);
149 print_pval_list(fin,item->u2.statements,depth+1);
150 for (i=0; i<depth; i++) {
153 fprintf(fin,
"};\n\n");
157 fprintf(fin,
"&%s(", item->u1.str);
158 for (lp=item->u2.arglist; lp; lp=lp->next) {
159 if ( lp != item->u2.arglist )
161 fprintf(fin,
"%s", lp->u1.str);
166 case PV_APPLICATION_CALL:
167 fprintf(fin,
"%s(", item->u1.str);
168 for (lp=item->u2.arglist; lp; lp=lp->next) {
169 if ( lp != item->u2.arglist )
171 fprintf(fin,
"%s", lp->u1.str);
177 fprintf(fin,
"case %s:\n", item->u1.str);
178 print_pval_list(fin,item->u2.statements, depth+1);
182 fprintf(fin,
"pattern %s:\n", item->u1.str);
183 print_pval_list(fin,item->u2.statements, depth+1);
187 fprintf(fin,
"default:\n");
188 print_pval_list(fin,item->u2.statements, depth+1);
192 fprintf(fin,
"catch %s {\n", item->u1.str);
193 print_pval_list(fin,item->u2.statements, depth+1);
194 for (i=0; i<depth; i++) {
201 fprintf(fin,
"switches {\n");
202 print_pval_list(fin,item->u1.list,depth+1);
203 for (i=0; i<depth; i++) {
210 fprintf(fin,
"eswitches {\n");
211 print_pval_list(fin,item->u1.list,depth+1);
212 for (i=0; i<depth; i++) {
219 fprintf(fin,
"includes {\n");
220 for (lp=item->u1.list; lp; lp=lp->next) {
221 for (i=0; i<depth+1; i++) {
224 fprintf(fin,
"%s", lp->u1.str);
226 fprintf(fin,
"|%s|%s|%s|%s",
227 lp->u2.arglist->u1.str,
228 lp->u2.arglist->next->u1.str,
229 lp->u2.arglist->next->next->u1.str,
230 lp->u2.arglist->next->next->next->u1.str
235 for (i=0; i<depth; i++) {
241 case PV_STATEMENTBLOCK:
243 print_pval_list(fin,item->u1.list, depth+1);
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);
259 fprintf(fin,
"goto %s", item->u1.list->u1.str);
260 if ( item->u1.list->next )
261 fprintf(fin,
",%s", item->u1.list->next->u1.str);
262 if ( item->u1.list->next && item->u1.list->next->next )
263 fprintf(fin,
",%s", item->u1.list->next->next->u1.str);
268 fprintf(fin,
"%s:\n", item->u1.str);
272 fprintf(fin,
"for (%s; %s; %s)\n", item->u1.for_init, item->u2.for_test, item->u3.for_inc);
273 print_pval_list(fin,item->u4.for_statements,depth+1);
277 fprintf(fin,
"while (%s)\n", item->u1.str);
278 print_pval_list(fin,item->u2.statements,depth+1);
282 fprintf(fin,
"break;\n");
286 fprintf(fin,
"return;\n");
290 fprintf(fin,
"continue;\n");
296 if ( item->type == PV_IFTIME ) {
298 fprintf(fin,
"ifTime ( %s|%s|%s|%s )\n",
299 item->u1.list->u1.str,
300 item->u1.list->next->u1.str,
301 item->u1.list->next->next->u1.str,
302 item->u1.list->next->next->next->u1.str
304 }
else if ( item->type == PV_RANDOM ) {
305 fprintf(fin,
"random ( %s )\n", item->u1.str );
307 fprintf(fin,
"if ( %s )\n", item->u1.str);
308 if ( item->u2.statements && item->u2.statements->next ) {
309 for (i=0; i<depth; i++) {
313 print_pval_list(fin,item->u2.statements,depth+1);
314 for (i=0; i<depth; i++) {
317 if ( item->u3.else_statements )
321 }
else if (item->u2.statements ) {
322 print_pval_list(fin,item->u2.statements,depth+1);
324 if (item->u3.else_statements )
325 fprintf(fin,
" {} ");
327 fprintf(fin,
" {}; ");
329 if ( item->u3.else_statements ) {
330 for (i=0; i<depth; i++) {
333 fprintf(fin,
"else\n");
334 print_pval_list(fin,item->u3.else_statements, depth);
339 fprintf(fin,
"switch( %s ) {\n", item->u1.str);
340 print_pval_list(fin,item->u2.statements,depth+1);
341 for (i=0; i<depth; i++) {
348 if ( item->u4.regexten )
349 fprintf(fin,
"regexten ");
350 if ( item->u3.hints )
351 fprintf(fin,
"hints(%s) ", item->u3.hints);
353 fprintf(fin,
"%s => ", item->u1.str);
354 print_pval_list(fin,item->u2.statements,depth+1);
359 fprintf(fin,
"ignorepat => %s;\n", item->u1.str);
363 fprintf(fin,
"globals {\n");
364 print_pval_list(fin,item->u1.statements,depth+1);
365 for (i=0; i<depth; i++) {
373 static void print_pval_list(FILE *fin,
pval *item,
int depth)
377 for (i=item; i; i=i->next) {
378 print_pval(fin, i, depth);
382 void ael2_print(
char *fname,
pval *tree)
384 FILE *fin = fopen(fname,
"w");
386 ast_log(LOG_ERROR,
"Couldn't open %s for writing.\n", fname);
389 print_pval_list(fin, tree, 0);
396 void traverse_pval_template(
pval *item,
int depth);
397 void traverse_pval_item_template(
pval *item,
int depth);
400 void traverse_pval_item_template(
pval *item,
int depth)
405 switch ( item->type ) {
418 for (lp=item->u2.arglist; lp; lp=lp->next) {
421 traverse_pval_item_template(item->u3.macro_statements,depth+1);
429 traverse_pval_item_template(item->u2.statements,depth+1);
438 for (lp=item->u2.arglist; lp; lp=lp->next) {
442 case PV_APPLICATION_CALL:
448 for (lp=item->u2.arglist; lp; lp=lp->next) {
456 traverse_pval_item_template(item->u2.statements,depth+1);
463 traverse_pval_item_template(item->u2.statements,depth+1);
470 traverse_pval_item_template(item->u2.statements,depth+1);
477 traverse_pval_item_template(item->u2.statements,depth+1);
483 traverse_pval_item_template(item->u1.list,depth+1);
489 traverse_pval_item_template(item->u1.list,depth+1);
496 traverse_pval_item_template(item->u1.list,depth+1);
497 traverse_pval_item_template(item->u2.arglist,depth+1);
500 case PV_STATEMENTBLOCK:
503 traverse_pval_item_template(item->u1.list,depth+1);
518 if ( item->u1.list->next )
520 if ( item->u1.list->next && item->u1.list->next->next )
537 traverse_pval_item_template(item->u4.for_statements,depth+1);
545 traverse_pval_item_template(item->u2.statements,depth+1);
570 traverse_pval_item_template(item->u2.statements,depth+1);
571 if ( item->u3.else_statements ) {
572 traverse_pval_item_template(item->u3.else_statements,depth+1);
583 traverse_pval_item_template(item->u2.statements,depth+1);
584 if ( item->u3.else_statements ) {
585 traverse_pval_item_template(item->u3.else_statements,depth+1);
596 traverse_pval_item_template(item->u2.statements,depth+1);
597 if ( item->u3.else_statements ) {
598 traverse_pval_item_template(item->u3.else_statements,depth+1);
608 traverse_pval_item_template(item->u2.statements,depth+1);
618 traverse_pval_item_template(item->u2.statements,depth+1);
629 traverse_pval_item_template(item->u1.statements,depth+1);
634 void traverse_pval_template(
pval *item,
int depth)
639 for (i=item; i; i=i->next) {
640 traverse_pval_item_template(i, depth);
650 static void check_macro_returns(
pval *macro)
653 if (!macro->u3.macro_statements)
655 pval *z = calloc(1,
sizeof(
struct pval));
656 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: The macro %s is empty! I will insert a return.\n",
657 macro->filename, macro->startline, macro->endline, macro->u1.str);
660 z->startline = macro->startline;
661 z->endline = macro->endline;
662 z->startcol = macro->startcol;
663 z->endcol = macro->endcol;
664 z->filename = strdup(macro->filename);
666 macro->u3.macro_statements = z;
669 for (i=macro->u3.macro_statements; i; i=i->next) {
671 if (i->next == NULL) {
672 if (i->type != PV_RETURN) {
673 pval *z = calloc(1,
sizeof(
struct pval));
674 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: The macro %s does not end with a return; I will insert one.\n",
675 macro->filename, macro->startline, macro->endline, macro->u1.str);
678 z->startline = macro->startline;
679 z->endline = macro->endline;
680 z->startcol = macro->startcol;
681 z->endcol = macro->endcol;
682 z->filename = strdup(macro->filename);
694 static int extension_matches(
pval *here,
const char *exten,
const char *pattern)
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",
753 here->filename, here->startline, here->endline, pattern);
774 err1 = regcomp(&preg, reg1, REG_NOSUB|REG_EXTENDED);
777 regerror(err1,&preg,errmess,
sizeof(errmess));
779 ast_log(LOG_WARNING,
"Regcomp of %s failed, error code %d\n",
783 err1 = regexec(&preg, exten, 0, 0, 0);
801 static void check_expr2_input(
pval *expr,
char *str)
803 int spaces = strspn(str,
"\t \n");
804 if ( !strncmp(str+spaces,
"$[",2) ) {
805 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: The expression '%s' is redundantly wrapped in '$[ ]'. \n",
806 expr->filename, expr->startline, expr->endline, str);
811 static void check_includes(
pval *includes)
814 for (p4=includes->u1.list; p4; p4=p4->next) {
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",
823 includes->filename, includes->startline, includes->endline, incl_context, incl_context);
830 static void check_timerange(
pval *p)
840 if (ast_strlen_zero(times) || !strcmp(times,
"*")) {
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",
847 p->filename, p->startline, p->endline, times);
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",
857 p->filename, p->startline, p->endline, p->u1.str);
860 if (sscanf(times,
"%2d:%2d", &s1, &s2) != 2) {
861 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: The start time (%s) isn't quite right!\n",
862 p->filename, p->startline, p->endline, times);
865 if (sscanf(e,
"%2d:%2d", &e1, &e2) != 2) {
866 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: The end time (%s) isn't quite right!\n",
867 p->filename, p->startline, p->endline, times);
872 if ((s1 < 0) || (s1 >= 24*30)) {
873 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: The start time (%s) is out of range!\n",
874 p->filename, p->startline, p->endline, times);
878 if ((e1 < 0) || (e1 >= 24*30)) {
879 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: The end time (%s) is out of range!\n",
880 p->filename, p->startline, p->endline, e);
886 static char *days[] =
908 if (ast_strlen_zero(dow) || !strcmp(dow,
"*"))
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",
922 DOW->filename, DOW->startline, DOW->endline, dow);
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",
930 DOW->filename, DOW->startline, DOW->endline, c);
937 static void check_day(
pval *DAY)
947 if (ast_strlen_zero(day) || !strcmp(day,
"*")) {
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",
959 DAY->filename, DAY->startline, DAY->endline, day);
962 else if ((s < 1) || (s > 31)) {
963 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: The start day of month (%s) must be a number in the range [1-31]!\n",
964 DAY->filename, DAY->startline, DAY->endline, day);
969 if (sscanf(c,
"%2d", &e) != 1) {
970 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: The end day of month (%s) must be a number!\n",
971 DAY->filename, DAY->startline, DAY->endline, c);
974 else if ((e < 1) || (e > 31)) {
975 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: The end day of month (%s) must be a number in the range [1-31]!\n",
976 DAY->filename, DAY->startline, DAY->endline, day);
984 static char *months[] =
1000 static void check_month(
pval *MON)
1010 if (ast_strlen_zero(mon) || !strcmp(mon,
"*"))
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",
1023 MON->filename, MON->startline, MON->endline, mon);
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",
1031 MON->filename, MON->startline, MON->endline, c);
1038 static int check_break(
pval *item)
1042 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) {
1045 if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN
1046 || p->type == PV_WHILE || p->type == PV_FOR ) {
1051 ast_log(LOG_ERROR,
"Error: file %s, line %d-%d: 'break' not in switch, for, or while statement!\n",
1052 item->filename, item->startline, item->endline);
1058 static int check_continue(
pval *item)
1062 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) {
1065 if( p->type == PV_WHILE || p->type == PV_FOR ) {
1070 ast_log(LOG_ERROR,
"Error: file %s, line %d-%d: 'continue' not in 'for' or 'while' statement!\n",
1071 item->filename, item->startline, item->endline);
1077 static struct pval *in_macro(
pval *item)
1082 if( curr->type == PV_MACRO ) {
1090 static struct pval *in_context(
pval *item)
1095 if( curr->type == PV_MACRO || curr->type == PV_CONTEXT ) {
1106 static void check_label(
pval *item)
1117 if( curr->type == PV_MACRO || curr->type == PV_EXTENSION ) {
1125 ast_log(LOG_ERROR,
"Error: file %s, line %d-%d: Label %s is not within an extension or macro!\n",
1126 item->filename, item->startline, item->endline, item->u1.str);
1137 if( !current_extension )
1138 curr = current_context;
1140 curr = current_extension;
1142 x = find_first_label_in_current_context((
char *)item->u1.str, curr);
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",
1147 item->filename, item->startline, item->endline, item->u1.str, x->filename, x->startline);
1153 static pval *get_goto_target(
pval *item)
1156 pval *curr_ext = get_extension_or_contxt(item);
1159 if (!item->u1.list) {
1163 if (!item->u1.list->next && !strstr((item->u1.list)->u1.str,
"${")) {
1164 struct pval *x = find_label_in_current_extension((
char*)((item->u1.list)->u1.str), curr_ext);
1168 curr_cont = get_contxt(item);
1171 if (item->u1.list->next && !item->u1.list->next->next) {
1172 if (!strstr((item->u1.list)->u1.str,
"${")
1173 && !strstr(item->u1.list->next->u1.str,
"${") ) {
1174 struct pval *x = find_label_in_current_context((
char *)item->u1.list->u1.str, (
char *)item->u1.list->next->u1.str, curr_cont);
1180 if (item->u1.list->next && item->u1.list->next->next) {
1182 pval *first = item->u1.list;
1183 pval *second = item->u1.list->next;
1184 pval *third = item->u1.list->next->next;
1186 if (!strstr((item->u1.list)->u1.str,
"${")
1187 && !strstr(item->u1.list->next->u1.str,
"${")
1188 && !strstr(item->u1.list->next->next->u1.str,
"${")) {
1189 struct pval *x = find_label_in_current_db((
char*)first->u1.str, (
char*)second->u1.str, (
char*)third->u1.str);
1198 for (p3=that_context->u2.statements; p3; p3=p3->next) {
1199 if (p3->type == PV_INCLUDES) {
1201 for (p4=p3->u1.list; p4; p4=p4->next) {
1204 char *incl_context = p4->u1.str;
1207 if (that_other_context) {
1209 x3 = find_label_in_current_context((
char *)item->u1.list->next->u1.str, (
char *)item->u1.list->next->next->u1.str, that_other_context);
1225 static void check_goto(
pval *item)
1227 if (!item->u1.list) {
1232 if ( !(item->u1.list)->next && !(item->u1.list)->u1.str ) {
1233 ast_log(LOG_ERROR,
"Error: file %s, line %d-%d: goto: empty label reference found!\n",
1234 item->filename, item->startline, item->endline);
1239 if (!item->u1.list->next && !strstr(item->u1.list->u1.str,
"${")) {
1240 struct pval *z = get_extension_or_contxt(item);
1243 x = find_label_in_current_extension((
char*)((item->u1.list)->u1.str), z);
1247 ast_log(LOG_ERROR,
"Error: file %s, line %d-%d: goto: no label %s exists in the current extension!\n",
1248 item->filename, item->startline, item->endline, item->u1.list->u1.str);
1256 if (item->u1.list->next && !item->u1.list->next->next) {
1260 if (!strstr((item->u1.list)->u1.str,
"${")
1261 && !strstr(item->u1.list->next->u1.str,
"${") ) {
1262 struct pval *z = get_contxt(item);
1266 x = find_label_in_current_context((
char *)item->u1.list->u1.str, (
char *)item->u1.list->next->u1.str, z);
1269 ast_log(LOG_ERROR,
"Error: file %s, line %d-%d: goto: no label '%s,%s' exists in the current context, or any of its inclusions!\n",
1270 item->filename, item->startline, item->endline, item->u1.list->u1.str, item->u1.list->next->u1.str );
1279 if (item->u1.list->next && item->u1.list->next->next) {
1281 pval *first = item->u1.list;
1282 pval *second = item->u1.list->next;
1283 pval *third = item->u1.list->next->next;
1287 if (!strstr((item->u1.list)->u1.str,
"${")
1288 && !strstr(item->u1.list->next->u1.str,
"${")
1289 && !strstr(item->u1.list->next->next->u1.str,
"${")) {
1290 struct pval *x = find_label_in_current_db((
char*)first->u1.str, (
char*)second->u1.str, (
char*)third->u1.str);
1293 struct pval *found = 0;
1299 for (p3=that_context->u2.statements; p3; p3=p3->next) {
1300 if (p3->type == PV_INCLUDES) {
1302 for (p4=p3->u1.list; p4; p4=p4->next) {
1305 char *incl_context = p4->u1.str;
1308 if (that_other_context) {
1310 x3 = find_label_in_current_context((
char *)item->u1.list->next->u1.str, (
char *)item->u1.list->next->next->u1.str, that_other_context);
1320 ast_log(LOG_ERROR,
"Error: file %s, line %d-%d: goto: no label %s|%s exists in the context %s or its inclusions!\n",
1321 item->filename, item->startline, item->endline, item->u1.list->next->u1.str, item->u1.list->next->next->u1.str, item->u1.list->u1.str );
1324 struct pval *mac = in_macro(item);
1326 struct pval *targ = in_context(found);
1329 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: It's bad form to have a goto in a macro to a target outside the macro!\n",
1330 item->filename, item->startline, item->endline);
1339 extern int localized_pbx_load_module(
void);
1342 if (!extensions_dot_conf_loaded) {
1343 localized_pbx_load_module();
1344 extensions_dot_conf_loaded++;
1347 pbx_find_extension(NULL, NULL, &pfiq, first->u1.str, second->u1.str, atoi(third->u1.str),
1348 atoi(third->u1.str) ? NULL : third->u1.str, NULL,
1349 atoi(third->u1.str) ? E_MATCH : E_FINDLABEL);
1351 if (pfiq.status != STATUS_SUCCESS) {
1352 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: goto: Couldn't find goto target %s|%s|%s, not even in extensions.conf!\n",
1353 item->filename, item->startline, item->endline, first->u1.str, second->u1.str, third->u1.str);
1357 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: goto: Couldn't find goto target %s|%s|%s in the AEL code!\n",
1358 item->filename, item->startline, item->endline, first->u1.str, second->u1.str, third->u1.str);
1363 struct pval *mac = in_macro(item);
1365 struct pval *targ = in_context(x);
1368 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: It's bad form to have a goto in a macro to a target outside the macro!\n",
1369 item->filename, item->startline, item->endline);
1379 static void find_pval_goto_item(
pval *item,
int lev)
1384 ast_log(LOG_ERROR,
"find_pval_goto in infinite loop! item_type: %u\n\n", item->type);
1388 switch ( item->type ) {
1399 find_pval_gotos(item->u3.macro_statements,lev+1);
1415 find_pval_gotos(item->u2.statements,lev+1);
1423 find_pval_gotos(item->u2.statements,lev+1);
1431 find_pval_gotos(item->u2.statements,lev+1);
1439 find_pval_gotos(item->u2.statements,lev+1);
1442 case PV_STATEMENTBLOCK:
1446 find_pval_gotos(item->u1.list,lev+1);
1459 for (p4=item->u1.list; p4; p4=p4->next) {
1462 char *incl_context = p4->u1.str;
1465 if (that_context && that_context->u2.statements) {
1467 find_pval_gotos(that_context->u2.statements,lev+1);
1480 find_pval_gotos(item->u4.for_statements,lev+1);
1489 find_pval_gotos(item->u2.statements,lev+1);
1515 find_pval_gotos(item->u2.statements,lev+1);
1517 if (item->u3.else_statements) {
1519 find_pval_gotos(item->u3.else_statements,lev+1);
1530 find_pval_gotos(item->u3.else_statements,lev+1);
1542 find_pval_gotos(item->u2.statements,lev+1);
1550 static void find_pval_gotos(
pval *item,
int lev)
1554 for (i=item; i; i=i->next) {
1556 find_pval_goto_item(i, lev);
1563 static struct pval *match_pval_item(
pval *item)
1567 switch ( item->type ) {
1577 if (!strcmp(match_context,
"*") || !strcmp(item->u1.str, match_context)) {
1581 if (return_on_context_match && !strcmp(item->u1.str, match_context)) {
1587 if (!return_on_context_match) {
1589 if ((x=match_pval(item->u3.macro_statements))) {
1606 if (!strcmp(match_context,
"*") || !strcmp(item->u1.str, match_context)) {
1607 if (return_on_context_match && !strcmp(item->u1.str, match_context)) {
1613 if (!return_on_context_match ) {
1615 if ((x=match_pval(item->u2.statements))) {
1630 if ((x=match_pval(item->u2.statements))) {
1641 if ((x=match_pval(item->u2.statements))) {
1652 if ((x=match_pval(item->u2.statements))) {
1663 if ((x=match_pval(item->u2.statements))) {
1669 case PV_STATEMENTBLOCK:
1673 if ((x=match_pval(item->u1.list))) {
1686 if (!strcmp(match_label, item->u1.str)) {
1688 last_matched_label = item;
1692 if (!strcmp(match_label, item->u1.str)) {
1707 if ((x=match_pval(item->u4.for_statements))) {
1719 if ((x=match_pval(item->u2.statements))) {
1748 if ((x=match_pval(item->u2.statements))) {
1751 if (item->u3.else_statements) {
1752 if ((x=match_pval(item->u3.else_statements))) {
1766 if ((x=match_pval(item->u2.statements))) {
1780 if (!strcmp(match_exten,
"*") || extension_matches(item, match_exten, item->u1.str) ) {
1782 if (strcmp(match_label,
"1") == 0) {
1783 if (item->u2.statements) {
1784 struct pval *p5 = item->u2.statements;
1785 while (p5 && p5->type == PV_LABEL)
1796 if ((x=match_pval(item->u2.statements))) {
1811 struct pval *match_pval(
pval *item)
1815 for (i=item; i; i=i->next) {
1819 if ((x = match_pval_item(i))) {
1828 int count_labels_in_current_context(
char *label)
1832 return_on_context_match = 0;
1833 match_pval(current_context->u2.statements);
1839 struct pval *find_first_label_in_current_context(
char *label,
pval *curr_cont)
1846 return_on_context_match = 0;
1847 match_context =
"*";
1849 match_label = label;
1851 ret = match_pval(curr_cont);
1857 for (p3=curr_cont->u2.statements; p3; p3=p3->next) {
1858 if (p3->type == PV_INCLUDES) {
1860 for (p4=p3->u1.list; p4; p4=p4->next) {
1863 char *incl_context = p4->u1.str;
1868 x3 = find_first_label_in_current_context(label, that_context);
1879 struct pval *find_label_in_current_context(
char *exten,
char *label,
pval *curr_cont)
1886 return_on_context_match = 0;
1887 match_context =
"*";
1888 match_exten = exten;
1889 match_label = label;
1890 ret = match_pval(curr_cont->u2.statements);
1896 for (p3=curr_cont->u2.statements; p3; p3=p3->next) {
1897 if (p3->type == PV_INCLUDES) {
1899 for (p4=p3->u1.list; p4; p4=p4->next) {
1902 char *incl_context = p4->u1.str;
1907 x3 = find_label_in_current_context(exten, label, that_context);
1918 static struct pval *find_label_in_current_extension(
const char *label,
pval *curr_ext)
1922 return_on_context_match = 0;
1923 match_context =
"*";
1925 match_label = label;
1926 return match_pval(curr_ext);
1929 static struct pval *find_label_in_current_db(
const char *context,
const char *exten,
const char *label)
1933 return_on_context_match = 0;
1935 match_context = context;
1936 match_exten = exten;
1937 match_label = label;
1939 return match_pval(current_db);
1943 struct pval *find_macro(
char *name)
1945 return_on_context_match = 1;
1947 match_context = name;
1950 return match_pval(current_db);
1955 return_on_context_match = 1;
1957 match_context = name;
1960 return match_pval(current_db);
1963 int is_float(
char *arg )
1966 for (s=arg; *s; s++) {
1967 if (*s !=
'.' && (*s < '0' || *s >
'9'))
1972 int is_int(
char *arg )
1975 for (s=arg; *s; s++) {
1976 if (*s < '0' || *s >
'9')
1981 int is_empty(
char *arg)
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",
2027 is->filename, is->startline, is->endline, app->name);
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",
2036 is->filename, is->startline, is->endline, ac->name[0], app->name);
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",
2046 is->filename, is->startline, is->endline, *q, app->name);
2058 int option_matches(
struct argdesc *should,
pval *is,
struct argapp *app)
2060 struct argchoice *ac;
2063 switch (should->dtype) {
2065 if (is_empty(is->u1.str) && should->type == ARGD_REQUIRED)
2067 if (is->u1.str && strlen(is->u1.str) > 0)
2072 if (is_int(is->u1.str))
2079 if (is_float(is->u1.str))
2086 if( !is->u1.str || strlen(is->u1.str) == 0 )
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 !=
')') {
2130 int check_app_args(
pval* appcall,
pval *arglist,
struct argapp *app)
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",
2140 arglist->filename, arglist->startline, arglist->endline, pa->u1.str, app->name);
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",
2156 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?
"options":ad->name, app->name);
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",
2173 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?
"options":ad->name, app->name);
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) {
2220 for (t=item->u2.statements; t; t=t->next) {
2221 if (t->type == PV_DEFAULT) {
2225 if (t->type == PV_PATTERN) {
2231 for (c=v->vals; c; c=c->next) {
2233 for (t=item->u2.statements; t; t=t->next) {
2234 if (t->type == PV_CASE || t->type == PV_PATTERN) {
2235 if (!strcmp(t->u1.str,c->name)) {
2242 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: switch with expression(%s) does not handle the case of %s !\n",
2243 item->filename, item->startline, item->endline, item->u1.str, c->name);
2249 t = current_extension->u2.statements;
2250 if ( t && t->type == PV_STATEMENTBLOCK )
2251 t = t->u1.statements;
2252 for (; t && t != item; t=t->next) {
2253 if (t->type == PV_APPLICATION_CALL) {
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",
2276 item->filename, item->startline, item->endline, item->u1.str);
2285 for (t=item->u2.statements; t; t=t->next) {
2286 if (t->type == PV_DEFAULT) {
2295 p2 = tl->next = calloc(1,
sizeof(
struct pval));
2297 p2->type = PV_DEFAULT;
2298 p2->startline = tl->startline;
2299 p2->endline = tl->endline;
2300 p2->startcol = tl->startcol;
2301 p2->endcol = tl->endcol;
2302 p2->filename = strdup(tl->filename);
2303 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: A default case was automatically added to the switch.\n",
2304 p2->filename, p2->startline, p2->endline);
2310 static void check_context_names(
void)
2313 for (i=current_db; i; i=i->next) {
2314 if (i->type == PV_CONTEXT || i->type == PV_MACRO) {
2315 for (j=i->next; j; j=j->next) {
2316 if ( j->type == PV_CONTEXT || j->type == PV_MACRO ) {
2317 if ( !strcmp(i->u1.str, j->u1.str) && !(i->u3.abstract&2) && !(j->u3.abstract&2) )
2319 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: The context name (%s) is also declared in file %s, line %d-%d! (and neither is marked 'extend')\n",
2320 i->filename, i->startline, i->endline, i->u1.str, j->filename, j->startline, j->endline);
2329 static void check_abstract_reference(
pval *abstract_context)
2336 for (i=current_db; i; i=i->next) {
2337 if (i->type == PV_CONTEXT) {
2338 for (j=i->u2. statements; j; j=j->next) {
2339 if ( j->type == PV_INCLUDES ) {
2341 for (p4=j->u1.list; p4; p4=p4->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",
2352 abstract_context->filename, abstract_context->startline, abstract_context->endline, abstract_context->u1.str);
2357 void check_pval_item(
pval *item,
struct argapp *apps,
int in_globals)
2361 struct argapp *app, *found;
2363 struct pval *macro_def;
2364 struct pval *app_def;
2369 switch (item->type) {
2383 in_abstract_context = 0;
2384 current_context = item;
2385 current_extension = 0;
2387 check_macro_returns(item);
2389 for (lp=item->u2.arglist; lp; lp=lp->next) {
2392 check_pval(item->u3.macro_statements, apps,in_globals);
2400 current_context = item;
2401 current_extension = 0;
2402 if ( item->u3.abstract ) {
2403 in_abstract_context = 1;
2404 check_abstract_reference(item);
2406 in_abstract_context = 0;
2407 check_pval(item->u2.statements, apps,in_globals);
2419 if (!extensions_dot_conf_loaded) {
2420 localized_pbx_load_module();
2421 extensions_dot_conf_loaded++;
2424 macro_def = find_macro(item->u1.str);
2431 pbx_find_extension(NULL, NULL, &pfiq, item->u1.str,
"s", 1, NULL, NULL, E_MATCH);
2433 if (pfiq.status != STATUS_SUCCESS) {
2435 snprintf(namebuf2, 256,
"macro-%s", item->u1.str);
2438 pbx_find_extension(NULL, NULL, &pfiq2, namebuf2,
"s", 1, NULL, NULL, E_MATCH);
2440 if (pfiq2.status == STATUS_SUCCESS) {
2441 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: macro call to non-existent %s! (macro-%s was found in the extensions.conf stuff, but we are using gosubs!)\n",
2442 item->filename, item->startline, item->endline, item->u1.str, item->u1.str);
2445 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: macro call to non-existent %s! (Not even in the extensions.conf stuff!)\n",
2446 item->filename, item->startline, item->endline, item->u1.str);
2451 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: macro call to %s cannot be found in the AEL code!\n",
2452 item->filename, item->startline, item->endline, item->u1.str);
2456 #ifdef THIS_IS_1DOT4
2458 snprintf(namebuf2, 256,
"macro-%s", item->u1.str);
2461 pbx_find_extension(NULL, NULL, &pfiq, namebuf2,
"s", 1, NULL, NULL, E_MATCH);
2463 if (pfiq.status != STATUS_SUCCESS) {
2464 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: macro call to %s was not found in the AEL, nor the extensions.conf !\n",
2465 item->filename, item->startline, item->endline, item->u1.str);
2471 }
else if (macro_def->type != PV_MACRO) {
2472 ast_log(LOG_ERROR,
"Error: file %s, line %d-%d: macro call to %s references a context, not a macro!\n",
2473 item->filename, item->startline, item->endline, item->u1.str);
2480 for (lp=item->u2.arglist; lp; lp=lp->next) {
2483 for (lp=macro_def->u2.arglist; lp; lp=lp->next) {
2486 if (hereargs != thereargs ) {
2487 ast_log(LOG_ERROR,
"Error: file %s, line %d-%d: The macro call to %s has %d arguments, but the macro definition has %d arguments\n",
2488 item->filename, item->startline, item->endline, item->u1.str, hereargs, thereargs);
2494 case PV_APPLICATION_CALL:
2502 if (app_def && app_def->type == PV_MACRO) {
2503 ast_log(LOG_ERROR,
"Error: file %s, line %d-%d: application call to %s references an existing macro, but had no & preceding it!\n",
2504 item->filename, item->startline, item->endline, item->u1.str);
2507 if (strcasecmp(item->u1.str,
"GotoIf") == 0
2508 || strcasecmp(item->u1.str,
"GotoIfTime") == 0
2509 || strcasecmp(item->u1.str,
"while") == 0
2510 || strcasecmp(item->u1.str,
"endwhile") == 0
2511 || strcasecmp(item->u1.str,
"random") == 0
2512 || strcasecmp(item->u1.str,
"gosub") == 0
2513 || strcasecmp(item->u1.str,
"gosubif") == 0
2514 || strcasecmp(item->u1.str,
"continuewhile") == 0
2515 || strcasecmp(item->u1.str,
"endwhile") == 0
2516 || strcasecmp(item->u1.str,
"execif") == 0
2517 || strcasecmp(item->u1.str,
"execiftime") == 0
2518 || strcasecmp(item->u1.str,
"exitwhile") == 0
2519 || strcasecmp(item->u1.str,
"goto") == 0
2520 || strcasecmp(item->u1.str,
"macro") == 0
2521 || strcasecmp(item->u1.str,
"macroexclusive") == 0
2522 || strcasecmp(item->u1.str,
"macroif") == 0
2523 || strcasecmp(item->u1.str,
"stackpop") == 0
2524 || strcasecmp(item->u1.str,
"execIf") == 0 ) {
2525 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: application call to %s affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead!\n",
2526 item->filename, item->startline, item->endline, item->u1.str);
2529 if (strcasecmp(item->u1.str,
"macroexit") == 0) {
2530 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: I am converting the MacroExit call here to a return statement.\n",
2531 item->filename, item->startline, item->endline);
2532 item->type = PV_RETURN;
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",
2547 item->filename, item->startline, item->endline, item->u1.str);
2550 check_app_args(item, item->u2.arglist, app);
2560 check_pval(item->u2.statements, apps,in_globals);
2570 check_pval(item->u2.statements, apps,in_globals);
2578 check_pval(item->u2.statements, apps,in_globals);
2585 check_pval(item->u2.statements, apps,in_globals);
2591 check_pval(item->u1.list, apps,in_globals);
2597 check_pval(item->u1.list, apps,in_globals);
2603 check_pval(item->u1.list, apps,in_globals);
2604 check_includes(item);
2605 for (lp=item->u1.list; lp; lp=lp->next){
2606 char *incl_context = lp->u1.str;
2609 if ( lp->u2.arglist ) {
2610 check_timerange(lp->u2.arglist);
2612 check_day(lp->u2.arglist->next->next);
2613 check_month(lp->u2.arglist->next->next->next);
2617 find_pval_gotos(that_context->u2.statements,0);
2623 case PV_STATEMENTBLOCK:
2626 check_pval(item->u1.list, apps,in_globals);
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);
2636 ast_expr_register_extra_error_info(errmsg);
2637 ast_expr(item->u2.val, expr_output,
sizeof(expr_output),NULL);
2638 ast_expr_clear_extra_error_info();
2639 if ( strpbrk(item->u2.val,
"~!-+<>=*/&^") && !strstr(item->u2.val,
"${") ) {
2640 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
2641 item->filename, item->startline, item->endline, item->u2.val);
2644 check_expr2_input(item,item->u2.val);
2648 case PV_LOCALVARDEC:
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);
2654 ast_expr_register_extra_error_info(errmsg);
2655 ast_expr(item->u2.val, expr_output,
sizeof(expr_output),NULL);
2656 ast_expr_clear_extra_error_info();
2657 if ( strpbrk(item->u2.val,
"~!-+<>=*/&^") && !strstr(item->u2.val,
"${") ) {
2658 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
2659 item->filename, item->startline, item->endline, item->u2.val);
2662 check_expr2_input(item,item->u2.val);
2670 if ( in_abstract_context )
2679 if ( strspn(item->u1.str,
"0123456789") == strlen(item->u1.str) ) {
2680 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: label '%s' is numeric, this is bad practice!\n",
2681 item->filename, item->startline, item->endline, item->u1.str);
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);
2696 ast_expr_register_extra_error_info(errmsg);
2698 strp = strchr(item->u1.for_init,
'=');
2700 ast_expr(strp+1, expr_output,
sizeof(expr_output),NULL);
2702 ast_expr(item->u2.for_test, expr_output,
sizeof(expr_output),NULL);
2703 strp = strchr(item->u3.for_inc,
'=');
2705 ast_expr(strp+1, expr_output,
sizeof(expr_output),NULL);
2707 if ( strpbrk(item->u2.for_test,
"~!-+<>=*/&^") && !strstr(item->u2.for_test,
"${") ) {
2708 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
2709 item->filename, item->startline, item->endline, item->u2.for_test);
2712 if ( strpbrk(item->u3.for_inc,
"~!-+<>=*/&^") && !strstr(item->u3.for_inc,
"${") ) {
2713 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
2714 item->filename, item->startline, item->endline, item->u3.for_inc);
2717 check_expr2_input(item,item->u2.for_test);
2718 check_expr2_input(item,item->u3.for_inc);
2720 ast_expr_clear_extra_error_info();
2721 check_pval(item->u4.for_statements, apps,in_globals);
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);
2730 ast_expr_register_extra_error_info(errmsg);
2731 ast_expr(item->u1.str, expr_output,
sizeof(expr_output),NULL);
2732 ast_expr_clear_extra_error_info();
2733 if ( strpbrk(item->u1.str,
"~!-+<>=*/&^") && !strstr(item->u1.str,
"${") ) {
2734 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
2735 item->filename, item->startline, item->endline, item->u1.str);
2738 check_expr2_input(item,item->u1.str);
2739 check_pval(item->u2.statements, apps,in_globals);
2756 check_continue(item);
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);
2767 ast_expr_register_extra_error_info(errmsg);
2768 ast_expr(item->u1.str, expr_output,
sizeof(expr_output),NULL);
2769 ast_expr_clear_extra_error_info();
2770 if ( strpbrk(item->u1.str,
"~!-+<>=*/&^") && !strstr(item->u1.str,
"${") ) {
2771 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: random expression '%s' has operators, but no variables. Interesting...\n",
2772 item->filename, item->startline, item->endline, item->u1.str);
2775 check_expr2_input(item,item->u1.str);
2776 check_pval(item->u2.statements, apps,in_globals);
2777 if (item->u3.else_statements) {
2778 check_pval(item->u3.else_statements, apps,in_globals);
2789 if ( item->u2.arglist ) {
2790 check_timerange(item->u1.list);
2792 check_day(item->u1.list->next->next);
2793 check_month(item->u1.list->next->next->next);
2796 check_pval(item->u2.statements, apps,in_globals);
2797 if (item->u3.else_statements) {
2798 check_pval(item->u3.else_statements, apps,in_globals);
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);
2810 ast_expr_register_extra_error_info(errmsg);
2811 ast_expr(item->u1.str, expr_output,
sizeof(expr_output),NULL);
2812 ast_expr_clear_extra_error_info();
2813 if ( strpbrk(item->u1.str,
"~!-+<>=*/&^") && !strstr(item->u1.str,
"${") ) {
2814 ast_log(LOG_WARNING,
"Warning: file %s, line %d-%d: expression '%s' has operators, but no variables. Interesting...\n",
2815 item->filename, item->startline, item->endline, item->u1.str);
2818 check_expr2_input(item,item->u1.str);
2819 check_pval(item->u2.statements, apps,in_globals);
2820 if (item->u3.else_statements) {
2821 check_pval(item->u3.else_statements, apps,in_globals);
2833 check_switch_expr(item, apps);
2834 check_pval(item->u2.statements, apps,in_globals);
2844 current_extension = item ;
2846 check_pval(item->u2.statements, apps,in_globals);
2857 in_abstract_context = 0;
2858 check_pval(item->u1.statements, apps, 1);
2865 void check_pval(
pval *item,
struct argapp *apps,
int in_globals)
2880 for (i=item; i; i=i->next) {
2881 check_pval_item(i,apps,in_globals);
2885 void ael2_semantic_check(
pval *item,
int *arg_errs,
int *arg_warns,
int *arg_notes)
2897 rfilename =
ast_alloca(10 + strlen(ast_config_AST_VAR_DIR));
2898 sprintf(rfilename,
"%s/applist", ast_config_AST_VAR_DIR);
2900 apps = argdesc_parse(rfilename, &argapp_errs);
2903 errs = warns = notes = 0;
2905 check_context_names();
2906 check_pval(item, apps, 0);
2909 argdesc_destroy(apps);
2922 static int control_statement_count;
2940 if (!exten->plist) {
2941 exten->plist = prio;
2942 exten->plist_last = prio;
2944 exten->plist_last->next = prio;
2945 exten->plist_last = prio;
2948 prio->exten = exten;
2954 if (prio->appargs && ((mother_exten && mother_exten->has_switch) || exten->has_switch) ) {
2955 while ((p1 = strstr(prio->appargs,
"${EXTEN}"))) {
2956 p2 = malloc(strlen(prio->appargs)+5);
2958 strcpy(p2, prio->appargs);
2959 strcat(p2,
"${~~EXTEN~~}");
2962 free(prio->appargs);
2965 while ((p1 = strstr(prio->appargs,
"${EXTEN:"))) {
2966 p2 = malloc(strlen(prio->appargs)+5);
2968 strcpy(p2, prio->appargs);
2969 strcat(p2,
"${~~EXTEN~~:");
2972 free(prio->appargs);
2981 for (ne=exten; ne; ne=nen) {
2994 for (pe=ne->plist; pe; pe=pen) {
3007 nen = ne->next_exten;
3018 static int label_inside_case(
pval *label)
3022 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) {
3023 if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN ) {
3034 add->next_exten = exten->next_exten;
3035 exten->next_exten = add;
3038 static void remove_spaces_before_equals(
char *str)
3041 while( str && *str && *str !=
'=' )
3043 if( *str ==
' ' || *str ==
'\n' || *str ==
'\r' || *str ==
'\t' )
3061 static void gen_match_to_pattern(
char *pattern,
char *result)
3064 char *p=pattern, *t=result;
3066 if (*p ==
'x' || *p ==
'n' || *p ==
'z' || *p ==
'X' || *p ==
'N' || *p ==
'Z')
3068 else if (*p ==
'[') {
3086 int find_switch_item(
pval *item);
3087 int contains_switch(
pval *item);
3090 int find_switch_item(
pval *item)
3092 switch ( item->type ) {
3093 case PV_LOCALVARDEC:
3110 if (contains_switch(item->u3.macro_statements))
3120 if (contains_switch(item->u2.statements))
3132 case PV_APPLICATION_CALL:
3145 if (contains_switch(item->u2.statements))
3154 if (contains_switch(item->u2.statements))
3163 if (contains_switch(item->u2.statements))
3172 if (contains_switch(item->u2.statements))
3192 case PV_STATEMENTBLOCK:
3195 if (contains_switch(item->u1.list) )
3223 if (contains_switch(item->u4.for_statements))
3232 if (contains_switch(item->u2.statements))
3258 if (contains_switch(item->u2.statements))
3260 if ( item->u3.else_statements ) {
3261 if (contains_switch(item->u3.else_statements))
3273 if (contains_switch(item->u2.statements))
3275 if ( item->u3.else_statements ) {
3276 if (contains_switch(item->u3.else_statements))
3288 if (contains_switch(item->u2.statements))
3290 if ( item->u3.else_statements ) {
3291 if (contains_switch(item->u3.else_statements))
3312 if (contains_switch(item->u2.statements))
3329 int contains_switch(
pval *item)
3333 for (i=item; i; i=i->next) {
3334 if (find_switch_item(i))
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
3352 RAII_VAR(
char *, buf1, NULL, free);
3353 RAII_VAR(
char *, buf2, NULL, free);
3354 RAII_VAR(
char *, new_label, NULL, free);
3357 int local_control_statement_count;
3363 if (!(buf1 = malloc(BUF_SIZE))) {
3366 if (!(buf2 = malloc(BUF_SIZE))) {
3369 if (!(new_label = malloc(BUF_SIZE))) {
3373 if ((mother_exten && !mother_exten->checked_switch) || (exten && !exten->checked_switch)) {
3374 if (contains_switch(statement)) {
3376 if (!mother_exten->has_switch) {
3377 for (first = 1; first >= 0; first--) {
3378 switch_set = new_prio();
3379 switch_set->type = AEL_APPCALL;
3380 switch_set->app = strdup(
"MSet");
3382 if (!strcmp(mother_exten->name,
"~~s~~") && first) {
3386 switch_set->appargs = strdup(
"LOCAL(~~EXTEN~~)=${EXTEN}");
3388 switch_set->appargs = strdup(
"~~EXTEN~~=${EXTEN}");
3391 linkprio(exten, switch_set, mother_exten);
3392 mother_exten->has_switch = 1;
3393 mother_exten->checked_switch = 1;
3395 exten->has_switch = 1;
3396 exten->checked_switch = 1;
3401 if (!exten->has_switch) {
3402 for (first = 1; first >= 0; first--) {
3403 switch_set = new_prio();
3404 switch_set->type = AEL_APPCALL;
3405 switch_set->app = strdup(
"MSet");
3407 if (!strcmp(exten->name,
"~~s~~")) {
3411 switch_set->appargs = strdup(
"LOCAL(~~EXTEN~~)=${EXTEN}");
3413 switch_set->appargs = strdup(
"~~EXTEN~~=${EXTEN}");
3416 linkprio(exten, switch_set, mother_exten);
3417 exten->has_switch = 1;
3418 exten->checked_switch = 1;
3420 mother_exten->has_switch = 1;
3421 mother_exten->checked_switch = 1;
3428 mother_exten->checked_switch = 1;
3431 exten->checked_switch = 1;
3435 for (p=statement; p; p=p->next) {
3439 pr->type = AEL_APPCALL;
3440 snprintf(buf1, BUF_SIZE,
"%s=$[%s]", p->u1.str, p->u2.val);
3441 pr->app = strdup(
"MSet");
3442 remove_spaces_before_equals(buf1);
3443 pr->appargs = strdup(buf1);
3445 linkprio(exten, pr, mother_exten);
3448 case PV_LOCALVARDEC:
3450 pr->type = AEL_APPCALL;
3451 snprintf(buf1, BUF_SIZE,
"LOCAL(%s)=$[%s]", p->u1.str, p->u2.val);
3452 pr->app = strdup(
"MSet");
3453 remove_spaces_before_equals(buf1);
3454 pr->appargs = strdup(buf1);
3456 linkprio(exten, pr, mother_exten);
3461 pr->type = AEL_APPCALL;
3462 p->u2.goto_target = get_goto_target(p);
3463 if( p->u2.goto_target ) {
3464 p->u3.goto_target_in_case = label_inside_case(p->u2.goto_target);
3467 if (!p->u1.list->next) {
3468 pr->app = strdup(
"Goto");
3470 pr->appargs = strdup(p->u1.list->u1.str);
3472 snprintf(buf1, BUF_SIZE,
"%s,%s", mother_exten->name, p->u1.list->u1.str);
3473 pr->appargs = strdup(buf1);
3476 }
else if (p->u1.list->next && !p->u1.list->next->next) {
3477 snprintf(buf1, BUF_SIZE,
"%s,%s", p->u1.list->u1.str, p->u1.list->next->u1.str);
3478 pr->app = strdup(
"Goto");
3479 pr->appargs = strdup(buf1);
3480 }
else if (p->u1.list->next && p->u1.list->next->next) {
3481 snprintf(buf1, BUF_SIZE,
"%s,%s,%s", p->u1.list->u1.str,
3482 p->u1.list->next->u1.str,
3483 p->u1.list->next->next->u1.str);
3484 pr->app = strdup(
"Goto");
3485 pr->appargs = strdup(buf1);
3488 linkprio(exten, pr, mother_exten);
3493 pr->type = AEL_LABEL;
3495 p->u3.compiled_label = exten;
3496 linkprio(exten, pr, mother_exten);
3500 control_statement_count++;
3503 snprintf(new_label, BUF_SIZE,
"for_%s_%d", label, control_statement_count);
3504 for_init = new_prio();
3505 for_inc = new_prio();
3506 for_test = new_prio();
3507 for_loop = new_prio();
3508 for_end = new_prio();
3509 for_init->type = AEL_APPCALL;
3510 for_inc->type = AEL_APPCALL;
3511 for_test->type = AEL_FOR_CONTROL;
3512 for_test->goto_false = for_end;
3513 for_loop->type = AEL_CONTROL1;
3514 for_end->type = AEL_APPCALL;
3515 for_init->app = strdup(
"MSet");
3517 strcpy(buf2,p->u1.for_init);
3518 remove_spaces_before_equals(buf2);
3519 strp = strchr(buf2,
'=');
3521 strp2 = strchr(p->u1.for_init,
'=');
3524 strncat(buf2,strp2+1, BUF_SIZE-strlen(strp2+1)-2);
3526 for_init->appargs = strdup(buf2);
3528 strp2 = p->u1.for_init;
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,
')');
3543 for_init->appargs = strdup(buf2);
3544 free(for_init->app);
3545 for_init->app = strdup(
"Gosub");
3548 strcpy(buf2, strp2);
3549 strp3 = strchr(buf2,
'(');
3552 free(for_init->app);
3553 for_init->app = strdup(buf2);
3554 for_init->appargs = strdup(strp3+1);
3555 strp3 = strrchr(for_init->appargs,
')');
3562 strcpy(buf2,p->u3.for_inc);
3563 remove_spaces_before_equals(buf2);
3564 strp = strchr(buf2,
'=');
3566 strp2 = strchr(p->u3.for_inc,
'=');
3569 strncat(buf2,strp2+1, BUF_SIZE-strlen(strp2+1)-2);
3571 for_inc->appargs = strdup(buf2);
3572 for_inc->app = strdup(
"MSet");
3574 strp2 = p->u3.for_inc;
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,
')');
3590 for_inc->appargs = strdup(buf2);
3592 for_inc->app = strdup(
"Gosub");
3595 strcpy(buf2, strp2);
3596 strp3 = strchr(buf2,
'(');
3599 for_inc->app = strdup(buf2);
3600 for_inc->appargs = strdup(strp3+1);
3601 strp3 = strrchr(for_inc->appargs,
')');
3607 snprintf(buf1, BUF_SIZE,
"$[%s]",p->u2.for_test);
3609 for_test->appargs = strdup(buf1);
3610 for_loop->goto_true = for_test;
3611 snprintf(buf1, BUF_SIZE,
"Finish for_%s_%d", label, control_statement_count);
3612 for_end->app = strdup(
"NoOp");
3613 for_end->appargs = strdup(buf1);
3615 linkprio(exten, for_init, mother_exten);
3616 linkprio(exten, for_test, mother_exten);
3622 if (gen_prios(exten, new_label, p->u4.for_statements, mother_exten, this_context)) {
3626 linkprio(exten, for_inc, mother_exten);
3627 linkprio(exten, for_loop, mother_exten);
3628 linkprio(exten, for_end, mother_exten);
3633 for_loop->origin = p;
3637 control_statement_count++;
3640 snprintf(new_label, BUF_SIZE,
"while_%s_%d", label, control_statement_count);
3641 while_test = new_prio();
3642 while_loop = new_prio();
3643 while_end = new_prio();
3644 while_test->type = AEL_FOR_CONTROL;
3645 while_test->goto_false = while_end;
3646 while_loop->type = AEL_CONTROL1;
3647 while_end->type = AEL_APPCALL;
3648 snprintf(buf1, BUF_SIZE,
"$[%s]",p->u1.str);
3649 while_test->app = 0;
3650 while_test->appargs = strdup(buf1);
3651 while_loop->goto_true = while_test;
3652 snprintf(buf1, BUF_SIZE,
"Finish while_%s_%d", label, control_statement_count);
3653 while_end->app = strdup(
"NoOp");
3654 while_end->appargs = strdup(buf1);
3656 linkprio(exten, while_test, mother_exten);
3662 if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) {
3666 linkprio(exten, while_loop, mother_exten);
3667 linkprio(exten, while_end, mother_exten);
3672 while_loop->origin = p;
3676 control_statement_count++;
3677 local_control_statement_count = control_statement_count;
3680 snprintf(new_label, BUF_SIZE,
"sw_%s_%d", label, control_statement_count);
3681 switch_test = new_prio();
3682 switch_end = new_prio();
3683 switch_test->type = AEL_APPCALL;
3684 switch_end->type = AEL_APPCALL;
3685 snprintf(buf1, BUF_SIZE,
"sw_%d_%s,10", control_statement_count, p->u1.str);
3686 switch_test->app = strdup(
"Goto");
3687 switch_test->appargs = strdup(buf1);
3688 snprintf(buf1, BUF_SIZE,
"Finish switch_%s_%d", label, control_statement_count);
3689 switch_end->app = strdup(
"NoOp");
3690 switch_end->appargs = strdup(buf1);
3691 switch_end->origin = p;
3692 switch_end->exten = exten;
3694 linkprio(exten, switch_test, mother_exten);
3695 linkprio(exten, switch_end, mother_exten);
3701 for (p2=p->u2.statements; p2; p2=p2->next) {
3703 if (p2->type == PV_CASE) {
3705 switch_case = new_exten();
3706 if (mother_exten && mother_exten->checked_switch) {
3707 switch_case->has_switch = mother_exten->has_switch;
3708 switch_case->checked_switch = mother_exten->checked_switch;
3710 if (exten && exten->checked_switch) {
3711 switch_case->has_switch = exten->has_switch;
3712 switch_case->checked_switch = exten->checked_switch;
3714 switch_case->context = this_context;
3715 switch_case->is_switch = 1;
3720 linkexten(exten,switch_case);
3721 snprintf(buf1, BUF_SIZE,
"sw_%d_%s", local_control_statement_count, p2->u1.str);
3722 switch_case->name = strdup(buf1);
3723 snprintf(new_label, BUF_SIZE,
"sw_%s_%s_%d", label, p2->u1.str, local_control_statement_count);
3725 if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) {
3730 for (p3=p2->u2.statements; p3; p3=p3->next) {
3735 if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN) ) {
3737 if (p2->next && p2->next->type == PV_CASE) {
3738 fall_thru = new_prio();
3739 fall_thru->type = AEL_APPCALL;
3740 fall_thru->app = strdup(
"Goto");
3741 snprintf(buf1, BUF_SIZE,
"sw_%d_%s,10", local_control_statement_count, p2->next->u1.str);
3742 fall_thru->appargs = strdup(buf1);
3743 linkprio(switch_case, fall_thru, mother_exten);
3744 }
else if (p2->next && p2->next->type == PV_PATTERN) {
3745 fall_thru = new_prio();
3746 fall_thru->type = AEL_APPCALL;
3747 fall_thru->app = strdup(
"Goto");
3748 gen_match_to_pattern(p2->next->u1.str, buf2);
3749 snprintf(buf1, BUF_SIZE,
"sw_%d_%s,10", local_control_statement_count, buf2);
3750 fall_thru->appargs = strdup(buf1);
3751 linkprio(switch_case, fall_thru, mother_exten);
3752 }
else if (p2->next && p2->next->type == PV_DEFAULT) {
3753 fall_thru = new_prio();
3754 fall_thru->type = AEL_APPCALL;
3755 fall_thru->app = strdup(
"Goto");
3756 snprintf(buf1, BUF_SIZE,
"sw_%d_.,10", local_control_statement_count);
3757 fall_thru->appargs = strdup(buf1);
3758 linkprio(switch_case, fall_thru, mother_exten);
3759 }
else if (!p2->next) {
3760 fall_thru = new_prio();
3761 fall_thru->type = AEL_CONTROL1;
3762 fall_thru->goto_true = switch_end;
3763 fall_thru->app = strdup(
"Goto");
3764 linkprio(switch_case, fall_thru, mother_exten);
3767 if (switch_case->return_needed) {
3770 np2->type = AEL_APPCALL;
3771 np2->app = strdup(
"NoOp");
3772 snprintf(buf, BUF_SIZE,
"End of Extension %s", switch_case->name);
3773 np2->appargs = strdup(buf);
3774 linkprio(switch_case, np2, mother_exten);
3775 switch_case-> return_target = np2;
3777 }
else if (p2->type == PV_PATTERN) {
3779 switch_case = new_exten();
3780 if (mother_exten && mother_exten->checked_switch) {
3781 switch_case->has_switch = mother_exten->has_switch;
3782 switch_case->checked_switch = mother_exten->checked_switch;
3784 if (exten && exten->checked_switch) {
3785 switch_case->has_switch = exten->has_switch;
3786 switch_case->checked_switch = exten->checked_switch;
3788 switch_case->context = this_context;
3789 switch_case->is_switch = 1;
3794 linkexten(exten,switch_case);
3795 snprintf(buf1, BUF_SIZE,
"_sw_%d_%s", local_control_statement_count, p2->u1.str);
3796 switch_case->name = strdup(buf1);
3797 snprintf(new_label, BUF_SIZE,
"sw_%s_%s_%d", label, p2->u1.str, local_control_statement_count);
3799 if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) {
3803 for (p3=p2->u2.statements; p3; p3=p3->next) {
3808 if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) {
3810 if (p2->next && p2->next->type == PV_CASE) {
3811 fall_thru = new_prio();
3812 fall_thru->type = AEL_APPCALL;
3813 fall_thru->app = strdup(
"Goto");
3814 snprintf(buf1, BUF_SIZE,
"sw_%d_%s,10", local_control_statement_count, p2->next->u1.str);
3815 fall_thru->appargs = strdup(buf1);
3816 linkprio(switch_case, fall_thru, mother_exten);
3817 }
else if (p2->next && p2->next->type == PV_PATTERN) {
3818 fall_thru = new_prio();
3819 fall_thru->type = AEL_APPCALL;
3820 fall_thru->app = strdup(
"Goto");
3821 gen_match_to_pattern(p2->next->u1.str, buf2);
3822 snprintf(buf1, BUF_SIZE,
"sw_%d_%s,10", local_control_statement_count, buf2);
3823 fall_thru->appargs = strdup(buf1);
3824 linkprio(switch_case, fall_thru, mother_exten);
3825 }
else if (p2->next && p2->next->type == PV_DEFAULT) {
3826 fall_thru = new_prio();
3827 fall_thru->type = AEL_APPCALL;
3828 fall_thru->app = strdup(
"Goto");
3829 snprintf(buf1, BUF_SIZE,
"sw_%d_.,10", local_control_statement_count);
3830 fall_thru->appargs = strdup(buf1);
3831 linkprio(switch_case, fall_thru, mother_exten);
3832 }
else if (!p2->next) {
3833 fall_thru = new_prio();
3834 fall_thru->type = AEL_CONTROL1;
3835 fall_thru->goto_true = switch_end;
3836 fall_thru->app = strdup(
"Goto");
3837 linkprio(switch_case, fall_thru, mother_exten);
3840 if (switch_case->return_needed) {
3843 np2->type = AEL_APPCALL;
3844 np2->app = strdup(
"NoOp");
3845 snprintf(buf,
sizeof(buf),
"End of Extension %s", switch_case->name);
3846 np2->appargs = strdup(buf);
3847 linkprio(switch_case, np2, mother_exten);
3848 switch_case-> return_target = np2;
3850 }
else if (p2->type == PV_DEFAULT) {
3852 switch_case = new_exten();
3853 if (mother_exten && mother_exten->checked_switch) {
3854 switch_case->has_switch = mother_exten->has_switch;
3855 switch_case->checked_switch = mother_exten->checked_switch;
3857 if (exten && exten->checked_switch) {
3858 switch_case->has_switch = exten->has_switch;
3859 switch_case->checked_switch = exten->checked_switch;
3861 switch_case->context = this_context;
3862 switch_case->is_switch = 1;
3869 switch_null = new_exten();
3870 if (mother_exten && mother_exten->checked_switch) {
3871 switch_null->has_switch = mother_exten->has_switch;
3872 switch_null->checked_switch = mother_exten->checked_switch;
3874 if (exten && exten->checked_switch) {
3875 switch_null->has_switch = exten->has_switch;
3876 switch_null->checked_switch = exten->checked_switch;
3878 switch_null->context = this_context;
3879 switch_null->is_switch = 1;
3880 switch_empty = new_prio();
3881 snprintf(buf1, BUF_SIZE,
"sw_%d_.,10", local_control_statement_count);
3882 switch_empty->app = strdup(
"Goto");
3883 switch_empty->appargs = strdup(buf1);
3884 linkprio(switch_null, switch_empty, mother_exten);
3885 snprintf(buf1, BUF_SIZE,
"sw_%d_", local_control_statement_count);
3886 switch_null->name = strdup(buf1);
3889 linkexten(exten,switch_null);
3894 linkexten(exten,switch_case);
3895 snprintf(buf1, BUF_SIZE,
"_sw_%d_.", local_control_statement_count);
3896 switch_case->name = strdup(buf1);
3898 snprintf(new_label, BUF_SIZE,
"sw_%s_default_%d", label, local_control_statement_count);
3900 if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) {
3905 for (p3=p2->u2.statements; p3; p3=p3->next) {
3910 if (!p3 || (p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) {
3912 if (p2->next && p2->next->type == PV_CASE) {
3913 fall_thru = new_prio();
3914 fall_thru->type = AEL_APPCALL;
3915 fall_thru->app = strdup(
"Goto");
3916 snprintf(buf1, BUF_SIZE,
"sw_%d_%s,10", local_control_statement_count, p2->next->u1.str);
3917 fall_thru->appargs = strdup(buf1);
3918 linkprio(switch_case, fall_thru, mother_exten);
3919 }
else if (p2->next && p2->next->type == PV_PATTERN) {
3920 fall_thru = new_prio();
3921 fall_thru->type = AEL_APPCALL;
3922 fall_thru->app = strdup(
"Goto");
3923 gen_match_to_pattern(p2->next->u1.str, buf2);
3924 snprintf(buf1, BUF_SIZE,
"sw_%d_%s,10", local_control_statement_count, buf2);
3925 fall_thru->appargs = strdup(buf1);
3926 linkprio(switch_case, fall_thru, mother_exten);
3927 }
else if (p2->next && p2->next->type == PV_DEFAULT) {
3928 fall_thru = new_prio();
3929 fall_thru->type = AEL_APPCALL;
3930 fall_thru->app = strdup(
"Goto");
3931 snprintf(buf1, BUF_SIZE,
"sw_%d_.,10", local_control_statement_count);
3932 fall_thru->appargs = strdup(buf1);
3933 linkprio(switch_case, fall_thru, mother_exten);
3934 }
else if (!p2->next) {
3935 fall_thru = new_prio();
3936 fall_thru->type = AEL_CONTROL1;
3937 fall_thru->goto_true = switch_end;
3938 fall_thru->app = strdup(
"Goto");
3939 linkprio(switch_case, fall_thru, mother_exten);
3942 if (switch_case->return_needed) {
3945 np2->type = AEL_APPCALL;
3946 np2->app = strdup(
"NoOp");
3947 snprintf(buf,
sizeof(buf),
"End of Extension %s", switch_case->name);
3948 np2->appargs = strdup(buf);
3949 linkprio(switch_case, np2, mother_exten);
3950 switch_case-> return_target = np2;
3959 switch_test->origin = p;
3960 switch_end->origin = p;
3965 pr->type = AEL_APPCALL;
3966 snprintf(buf1, BUF_SIZE,
"%s,~~s~~,1", p->u1.str);
3968 for (p2 = p->u2.arglist; p2; p2 = p2->next) {
3976 strcat(buf1,p2->u1.str);
3981 pr->app = strdup(
"Gosub");
3982 pr->appargs = strdup(buf1);
3984 linkprio(exten, pr, mother_exten);
3987 case PV_APPLICATION_CALL:
3989 pr->type = AEL_APPCALL;
3991 for (p2 = p->u2.arglist; p2; p2 = p2->next) {
3992 if (p2 != p->u2.arglist )
3994 strcat(buf1,p2->u1.str);
3996 pr->app = strdup(p->u1.str);
3997 pr->appargs = strdup(buf1);
3999 linkprio(exten, pr, mother_exten);
4004 pr->type = AEL_CONTROL1;
4007 linkprio(exten, pr, mother_exten);
4012 pr->type = AEL_RETURN;
4014 pr->app = strdup(
"Return");
4015 pr->appargs = strdup(
"");
4017 linkprio(exten, pr, mother_exten);
4022 pr->type = AEL_CONTROL1;
4025 linkprio(exten, pr, mother_exten);
4029 control_statement_count++;
4030 snprintf(new_label, BUF_SIZE,
"iftime_%s_%d", label, control_statement_count);
4032 if_test = new_prio();
4033 if_test->type = AEL_IFTIME_CONTROL;
4034 snprintf(buf1, BUF_SIZE,
"%s,%s,%s,%s",
4036 p->u1.list->next->u1.str,
4037 p->u1.list->next->next->u1.str,
4038 p->u1.list->next->next->next->u1.str);
4040 if_test->appargs = strdup(buf1);
4041 if_test->origin = p;
4043 if_end = new_prio();
4044 if_end->type = AEL_APPCALL;
4045 snprintf(buf1, BUF_SIZE,
"Finish iftime_%s_%d", label, control_statement_count);
4046 if_end->app = strdup(
"NoOp");
4047 if_end->appargs = strdup(buf1);
4049 if (p->u3.else_statements) {
4050 if_skip = new_prio();
4051 if_skip->type = AEL_CONTROL1;
4052 if_skip->goto_true = if_end;
4053 if_skip->origin = p;
4058 if_test->goto_false = if_end;
4061 if_false = new_prio();
4062 if_false->type = AEL_CONTROL1;
4063 if (p->u3.else_statements) {
4064 if_false->goto_true = if_skip;
4066 if_false->goto_true = if_end;
4070 linkprio(exten, if_test, mother_exten);
4071 linkprio(exten, if_false, mother_exten);
4075 if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) {
4079 if (p->u3.else_statements) {
4080 linkprio(exten, if_skip, mother_exten);
4081 if (gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context)) {
4086 linkprio(exten, if_end, mother_exten);
4092 control_statement_count++;
4093 snprintf(new_label, BUF_SIZE,
"if_%s_%d", label, control_statement_count);
4095 if_test = new_prio();
4096 if_end = new_prio();
4097 if_test->type = AEL_IF_CONTROL;
4098 if_end->type = AEL_APPCALL;
4099 if ( p->type == PV_RANDOM )
4100 snprintf(buf1, BUF_SIZE,
"$[${RAND(0,99)} < (%s)]", p->u1.str);
4102 snprintf(buf1, BUF_SIZE,
"$[%s]", p->u1.str);
4104 if_test->appargs = strdup(buf1);
4105 snprintf(buf1, BUF_SIZE,
"Finish if_%s_%d", label, control_statement_count);
4106 if_end->app = strdup(
"NoOp");
4107 if_end->appargs = strdup(buf1);
4108 if_test->origin = p;
4110 if (p->u3.else_statements) {
4111 if_skip = new_prio();
4112 if_skip->type = AEL_CONTROL1;
4113 if_skip->goto_true = if_end;
4114 if_test->goto_false = if_skip;;
4117 if_test->goto_false = if_end;;
4121 linkprio(exten, if_test, mother_exten);
4125 if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) {
4129 if (p->u3.else_statements) {
4130 linkprio(exten, if_skip, mother_exten);
4131 if (gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context)) {
4136 linkprio(exten, if_end, mother_exten);
4140 case PV_STATEMENTBLOCK:
4141 if (gen_prios(exten, label, p->u1.list, mother_exten, this_context)) {
4147 control_statement_count++;
4150 switch_case = new_exten();
4151 if (mother_exten && mother_exten->checked_switch) {
4152 switch_case->has_switch = mother_exten->has_switch;
4153 switch_case->checked_switch = mother_exten->checked_switch;
4155 if (exten && exten->checked_switch) {
4156 switch_case->has_switch = exten->has_switch;
4157 switch_case->checked_switch = exten->checked_switch;
4160 switch_case->context = this_context;
4161 linkexten(exten,switch_case);
4162 switch_case->name = strdup(p->u1.str);
4163 snprintf(new_label, BUF_SIZE,
"catch_%s_%d",p->u1.str, control_statement_count);
4165 if (gen_prios(switch_case, new_label, p->u2.statements, mother_exten,this_context)) {
4168 if (switch_case->return_needed) {
4171 np2->type = AEL_APPCALL;
4172 np2->app = strdup(
"NoOp");
4173 snprintf(buf,
sizeof(buf),
"End of Extension %s", switch_case->name);
4174 np2->appargs = strdup(buf);
4175 linkprio(switch_case, np2, mother_exten);
4176 switch_case-> return_target = np2;
4192 if (exten->is_switch)
4194 else if (exten->regexten)
4199 for (pr=exten->plist; pr; pr=pr->next) {
4200 pr->priority_num = i;
4202 if (!pr->origin || (pr->origin && pr->origin->type != PV_LABEL) )
4209 exten = exten->next_exten;
4219 ast_log(LOG_WARNING,
"This file is Empty!\n" );
4225 pbx_substitute_variables_helper(NULL, exten->name, realext,
sizeof(realext) - 1);
4228 exten->hints, NULL,
ast_free_ptr, registrar, NULL, 0)) {
4229 ast_log(LOG_WARNING,
"Unable to add step at priority 'hint' of extension '%s'\n",
4234 for (pr=exten->plist; pr; pr=pr->next) {
4241 if (pr->type == AEL_LABEL) {
4247 strcpy(app, pr->app);
4251 strcpy(appargs, pr->appargs);
4254 switch( pr->type ) {
4262 if (pr->goto_true->origin && pr->goto_true->origin->type == PV_SWITCH ) {
4263 snprintf(appargs,
sizeof(appargs),
"%s,%d", pr->goto_true->exten->name, pr->goto_true->priority_num);
4264 }
else if (pr->goto_true->origin && pr->goto_true->origin->type == PV_IFTIME && pr->goto_true->origin->u3.else_statements ) {
4265 snprintf(appargs,
sizeof(appargs),
"%d", pr->goto_true->priority_num+1);
4267 snprintf(appargs,
sizeof(appargs),
"%d", pr->goto_true->priority_num);
4270 case AEL_FOR_CONTROL:
4271 strcpy(app,
"GotoIf");
4272 snprintf(appargs,
sizeof(appargs),
"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num);
4275 case AEL_IF_CONTROL:
4276 strcpy(app,
"GotoIf");
4277 if (pr->origin->u3.else_statements )
4278 snprintf(appargs,
sizeof(appargs),
"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num+1);
4280 snprintf(appargs,
sizeof(appargs),
"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num);
4283 case AEL_RAND_CONTROL:
4284 strcpy(app,
"Random");
4285 snprintf(appargs,
sizeof(appargs),
"%s:%d", pr->appargs, pr->goto_true->priority_num+1);
4288 case AEL_IFTIME_CONTROL:
4289 strcpy(app,
"GotoIfTime");
4290 snprintf(appargs,
sizeof(appargs),
"%s?%d", pr->appargs, pr->priority_num+2);
4294 strcpy(app,
"Return");
4301 if (last && last->type == AEL_LABEL ) {
4302 label = last->origin->u1.str;
4307 if (
ast_add_extension2(exten->context, 0 , realext, pr->priority_num, (label?label:NULL), exten->cidmatch,
4308 app, strdup(appargs),
ast_free_ptr, registrar, NULL, 0)) {
4309 ast_log(LOG_WARNING,
"Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num,
4314 exten = exten->next_exten;
4328 while( lptr->next_exten ) {
4329 lptr = lptr->next_exten;
4332 lptr->next_exten = newmem;
4335 static pval *get_extension_or_contxt(
pval *p)
4337 while( p && p->type != PV_EXTENSION && p->type != PV_CONTEXT && p->type != PV_MACRO ) {
4347 while( p && p->type != PV_CONTEXT && p->type != PV_MACRO ) {
4355 static void fix_gotos_in_extensions(
struct ael_extension *exten)
4358 for(e=exten;e;e=e->next_exten) {
4361 for(p=e->plist;p;p=p->next) {
4363 if( p->origin && p->origin->type == PV_GOTO && p->origin->u3.goto_target_in_case ) {
4367 pval *target = p->origin->u2.goto_target;
4369 pval *pv2 = p->origin;
4371 char *apparg_save = p->appargs;
4374 if (!pv2->u1.list->next) {
4375 snprintf(buf1,
sizeof(buf1),
"%s,%s", z->name, pv2->u1.list->u1.str);
4376 p->appargs = strdup(buf1);
4378 }
else if (pv2->u1.list->next && !pv2->u1.list->next->next) {
4379 snprintf(buf1,
sizeof(buf1),
"%s,%s", z->name, pv2->u1.list->next->u1.str);
4380 p->appargs = strdup(buf1);
4381 }
else if (pv2->u1.list->next && pv2->u1.list->next->next) {
4382 snprintf(buf1,
sizeof(buf1),
"%s,%s,%s", pv2->u1.list->u1.str,
4384 pv2->u1.list->next->next->u1.str);
4385 p->appargs = strdup(buf1);
4388 printf(
"WHAT? The goto doesn't fall into one of three cases for GOTO????\n");
4402 if (ast_walk_context_extensions(context, NULL) || ast_context_includes_count(context) || ast_context_ignorepats_count(context) || ast_context_switches_count(context)) {
4405 for (exten = exten_list; exten; exten = exten->next_exten) {
4406 if (exten->context == context) {
4422 control_statement_count = 0;
4424 for (p=root; p; p=p->next ) {
4429 for (p2=p->u1.list; p2; p2=p2->next) {
4431 snprintf(buf2,
sizeof(buf2),
"%s=%s", p2->u1.str, p2->u2.val);
4440 for (p=root; p; p=p->next ) {
4449 exten = new_exten();
4450 exten->context = context;
4451 exten->name = strdup(
"~~s~~");
4453 for (lp=p->u2.arglist; lp; lp=lp->next) {
4456 np2->type = AEL_APPCALL;
4457 np2->app = strdup(
"MSet");
4458 snprintf(buf,
sizeof(buf),
"LOCAL(%s)=${ARG%d}", lp->u1.str, argc++);
4459 remove_spaces_before_equals(buf);
4460 np2->appargs = strdup(buf);
4461 linkprio(exten, np2, NULL);
4465 if (gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context)) {
4468 if (exten->return_needed) {
4470 np2->type = AEL_APPCALL;
4471 np2->app = strdup(
"NoOp");
4472 snprintf(buf,
sizeof(buf),
"End of Macro %s-%s",p->u1.str, exten->name);
4473 np2->appargs = strdup(buf);
4474 linkprio(exten, np2, NULL);
4475 exten-> return_target = np2;
4478 set_priorities(exten);
4479 attach_exten(&exten_list, exten);
4490 for (p2=p->u2.statements; p2; p2=p2->next) {
4496 exten = new_exten();
4497 exten->name = strdup(p2->u1.str);
4498 exten->context = context;
4500 if( (s3=strchr(exten->name,
'/') ) != 0 )
4503 exten->cidmatch = s3+1;
4507 exten->hints = strdup(p2->u3.hints);
4508 exten->regexten = p2->u4.regexten;
4509 if (gen_prios(exten, p->u1.str, p2->u2.statements, 0, context)) {
4512 if (exten->return_needed) {
4514 np2->type = AEL_APPCALL;
4515 np2->app = strdup(
"NoOp");
4516 snprintf(buf,
sizeof(buf),
"End of Extension %s", exten->name);
4517 np2->appargs = strdup(buf);
4518 linkprio(exten, np2, NULL);
4519 exten-> return_target = np2;
4522 if ( exten->plist_last && exten->plist_last->type == AEL_LABEL ) {
4524 np2->type = AEL_APPCALL;
4525 np2->app = strdup(
"NoOp");
4526 snprintf(buf,
sizeof(buf),
"A NoOp to follow a trailing label %s", exten->plist_last->origin->u1.str);
4527 np2->appargs = strdup(buf);
4528 linkprio(exten, np2, NULL);
4531 set_priorities(exten);
4532 attach_exten(&exten_list, exten);
4536 ast_context_add_ignorepat2(context, p2->u1.str, registrar);
4540 for (p3 = p2->u1.list; p3 ;p3=p3->next) {
4541 if ( p3->u2.arglist ) {
4542 snprintf(buf,
sizeof(buf),
"%s,%s,%s,%s,%s",
4544 p3->u2.arglist->u1.str,
4545 p3->u2.arglist->next->u1.str,
4546 p3->u2.arglist->next->next->u1.str,
4547 p3->u2.arglist->next->next->next->u1.str);
4555 for (p3 = p2->u1.list; p3 ;p3=p3->next) {
4556 char *c = strchr(p3->u1.str,
'/');
4568 for (p3 = p2->u1.list; p3 ;p3=p3->next) {
4569 char *c = strchr(p3->u1.str,
'/');
4594 if (ast_custom_function_find(
"DIALPLAN_EXISTS") && ast_custom_function_find(
"STACK_PEEK")) {
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",
"" }
4619 if (context_used(exten_list, context)) {
4623 char h_context_template[] =
"/tmp/ael-builtin-h-bubble-XXXXXX";
4624 int fd = mkstemp(h_context_template);
4625 unlink(h_context_template);
4628 found = !context_used(exten_list, context);
4630 h_context = ast_get_context_name(context);
4632 exten = new_exten();
4633 exten->context = context;
4634 exten->name = strdup(
"h");
4636 for (i = 0; i < ARRAY_LEN(steps); i++) {
4638 np->type = AEL_APPCALL;
4639 np->priority_num = steps[i].priority;
4640 np->app = strdup(steps[i].app);
4641 np->appargs = strdup(steps[i].arg);
4642 linkprio(exten, np, NULL);
4644 attach_exten(&exten_list, exten);
4647 for (exten = exten_list; exten; exten = exten->next_exten) {
4651 if (!strcmp(exten->name,
"~~s~~")) {
4660 fix_gotos_in_extensions(exten_list);
4661 add_extensions(exten_list);
4662 destroy_extensions(exten_list);
4672 void destroy_pval_item(
pval *item)
4675 ast_log(LOG_WARNING,
"null item\n");
4680 free(item->filename);
4682 switch (item->type) {
4687 if ( item->u2.arglist )
4688 destroy_pval(item->u2.arglist);
4699 destroy_pval(item->u2.arglist);
4702 destroy_pval(item->u3.macro_statements);
4712 destroy_pval(item->u2.statements);
4723 destroy_pval(item->u2.arglist);
4726 case PV_APPLICATION_CALL:
4734 destroy_pval(item->u2.arglist);
4743 destroy_pval(item->u2.statements);
4752 destroy_pval(item->u2.statements);
4759 destroy_pval(item->u2.statements);
4768 destroy_pval(item->u2.statements);
4774 destroy_pval(item->u1.list);
4780 destroy_pval(item->u1.list);
4787 destroy_pval(item->u1.list);
4790 case PV_STATEMENTBLOCK:
4793 destroy_pval(item->u1.list);
4796 case PV_LOCALVARDEC:
4812 destroy_pval(item->u1.list);
4829 if (item->u1.for_init)
4830 free(item->u1.for_init);
4831 if (item->u2.for_test)
4832 free(item->u2.for_test);
4833 if (item->u3.for_inc)
4834 free(item->u3.for_inc);
4835 destroy_pval(item->u4.for_statements);
4845 destroy_pval(item->u2.statements);
4870 destroy_pval(item->u1.list);
4871 destroy_pval(item->u2.statements);
4872 if (item->u3.else_statements) {
4873 destroy_pval(item->u3.else_statements);
4893 destroy_pval(item->u2.statements);
4894 if (item->u3.else_statements) {
4895 destroy_pval(item->u3.else_statements);
4907 destroy_pval(item->u2.statements);
4920 free(item->u3.hints);
4921 destroy_pval(item->u2.statements);
4934 destroy_pval(item->u1.statements);
4940 void destroy_pval(
pval *item)
4944 for (i=item; i; i=nxt) {
4947 destroy_pval_item(i);
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]))
5031 int pvalCheckType(
pval *p,
char *funcname, pvaltype type )
5033 if (p->type != type)
5035 ast_log(LOG_ERROR,
"Func: %s the pval passed is not appropriate for this function!\n", funcname);
5042 pval *pvalCreateNode( pvaltype type )
5052 pvaltype pvalObjectGetType(
pval *p )
5058 void pvalWordSetString(
pval *p,
char *str)
5060 if (!pvalCheckType(p,
"pvalWordSetString", PV_WORD))
5065 char *pvalWordGetString(
pval *p )
5067 if (!pvalCheckType(p,
"pvalWordGetString", PV_WORD))
5073 void pvalMacroSetName(
pval *p,
char *name)
5075 if (!pvalCheckType(p,
"pvalMacroSetName", PV_MACRO))
5080 char *pvalMacroGetName(
pval *p )
5082 if (!pvalCheckType(p,
"pvalMacroGetName", PV_MACRO))
5087 void pvalMacroSetArglist(
pval *p,
pval *arglist )
5089 if (!pvalCheckType(p,
"pvalMacroSetArglist", PV_MACRO))
5091 p->u2.arglist = arglist;
5094 void pvalMacroAddArg(
pval *p,
pval *arg )
5096 if (!pvalCheckType(p,
"pvalMacroAddArg", PV_MACRO))
5099 p->u2.arglist = arg;
5101 linku1(p->u2.arglist, arg);
5107 if (!pvalCheckType(p,
"pvalMacroWalkArgs", PV_MACRO))
5110 *arg = p->u2.arglist;
5112 *arg = (*arg)->next;
5117 void pvalMacroAddStatement(
pval *p,
pval *statement )
5119 if (!pvalCheckType(p,
"pvalMacroAddStatement", PV_MACRO))
5121 if (!p->u3.macro_statements)
5122 p->u3.macro_statements = statement;
5124 linku1(p->u3.macro_statements, statement);
5129 pval *pvalMacroWalkStatements(
pval *p,
pval **next_statement )
5131 if (!pvalCheckType(p,
"pvalMacroWalkStatements", PV_MACRO))
5133 if (!(*next_statement))
5134 *next_statement = p->u3.macro_statements;
5136 *next_statement = (*next_statement)->next;
5138 return *next_statement;
5143 void pvalContextSetName(
pval *p,
char *name)
5145 if (!pvalCheckType(p,
"pvalContextSetName", PV_CONTEXT))
5150 char *pvalContextGetName(
pval *p )
5152 if (!pvalCheckType(p,
"pvalContextGetName", PV_CONTEXT))
5157 void pvalContextSetAbstract(
pval *p )
5159 if (!pvalCheckType(p,
"pvalContextSetAbstract", PV_CONTEXT))
5164 void pvalContextUnsetAbstract(
pval *p )
5166 if (!pvalCheckType(p,
"pvalContextUnsetAbstract", PV_CONTEXT))
5171 int pvalContextGetAbstract(
pval *p )
5173 if (!pvalCheckType(p,
"pvalContextGetAbstract", PV_CONTEXT))
5175 return p->u3.abstract;
5180 void pvalContextAddStatement(
pval *p,
pval *statement)
5182 if (!pvalCheckType(p,
"pvalContextAddStatement", PV_CONTEXT))
5184 if (!p->u2.statements)
5185 p->u2.statements = statement;
5187 linku1(p->u2.statements, statement);
5190 pval *pvalContextWalkStatements(
pval *p,
pval **statements )
5192 if (!pvalCheckType(p,
"pvalContextWalkStatements", PV_CONTEXT))
5195 *statements = p->u2.statements;
5197 *statements = (*statements)->next;
5203 void pvalMacroCallSetMacroName(
pval *p,
char *name )
5205 if (!pvalCheckType(p,
"pvalMacroCallSetMacroName", PV_MACRO_CALL))
5210 char* pvalMacroCallGetMacroName(
pval *p )
5212 if (!pvalCheckType(p,
"pvalMacroCallGetMacroName", PV_MACRO_CALL))
5217 void pvalMacroCallSetArglist(
pval *p,
pval *arglist )
5219 if (!pvalCheckType(p,
"pvalMacroCallSetArglist", PV_MACRO_CALL))
5221 p->u2.arglist = arglist;
5224 void pvalMacroCallAddArg(
pval *p,
pval *arg )
5226 if (!pvalCheckType(p,
"pvalMacroCallGetAddArg", PV_MACRO_CALL))
5229 p->u2.arglist = arg;
5231 linku1(p->u2.arglist, arg);
5236 if (!pvalCheckType(p,
"pvalMacroCallWalkArgs", PV_MACRO_CALL))
5239 *args = p->u2.arglist;
5241 *args = (*args)->next;
5247 void pvalAppCallSetAppName(
pval *p,
char *name )
5249 if (!pvalCheckType(p,
"pvalAppCallSetAppName", PV_APPLICATION_CALL))
5254 char* pvalAppCallGetAppName(
pval *p )
5256 if (!pvalCheckType(p,
"pvalAppCallGetAppName", PV_APPLICATION_CALL))
5261 void pvalAppCallSetArglist(
pval *p,
pval *arglist )
5263 if (!pvalCheckType(p,
"pvalAppCallSetArglist", PV_APPLICATION_CALL))
5265 p->u2.arglist = arglist;
5268 void pvalAppCallAddArg(
pval *p,
pval *arg )
5270 if (!pvalCheckType(p,
"pvalAppCallAddArg", PV_APPLICATION_CALL))
5273 p->u2.arglist = arg;
5275 linku1(p->u2.arglist, arg);
5280 if (!pvalCheckType(p,
"pvalAppCallWalkArgs", PV_APPLICATION_CALL))
5283 *args = p->u2.arglist;
5285 *args = (*args)->next;
5291 void pvalCasePatSetVal(
pval *p,
char *
val )
5293 if (!pvalCheckType(p,
"pvalAppCallWalkArgs", PV_APPLICATION_CALL))
5298 char* pvalCasePatGetVal(
pval *p )
5303 void pvalCasePatDefAddStatement(
pval *p,
pval *statement )
5306 p->u2.statements = statement;
5308 linku1(p->u2.statements, statement);
5311 pval *pvalCasePatDefWalkStatements(
pval *p,
pval **statement )
5314 *statement = p->u2.statements;
5316 *statement = (*statement)->next;
5322 void pvalCatchSetExtName(
pval *p,
char *name )
5324 if (!pvalCheckType(p,
"pvalCatchSetExtName", PV_CATCH))
5329 char* pvalCatchGetExtName(
pval *p )
5331 if (!pvalCheckType(p,
"pvalCatchGetExtName", PV_CATCH))
5336 void pvalCatchSetStatement(
pval *p,
pval *statement )
5338 if (!pvalCheckType(p,
"pvalCatchSetStatement", PV_CATCH))
5340 p->u2.statements = statement;
5343 pval *pvalCatchGetStatement(
pval *p )
5345 if (!pvalCheckType(p,
"pvalCatchGetStatement", PV_CATCH))
5347 return p->u2.statements;
5351 void pvalSwitchesAddSwitch(
pval *p,
char *name )
5354 if (!pvalCheckType(p,
"pvalSwitchesAddSwitch", PV_SWITCHES))
5356 s = pvalCreateNode(PV_WORD);
5358 p->u1.list = linku1(p->u1.list, s);
5361 char* pvalSwitchesWalkNames(
pval *p,
pval **next_item )
5363 if (!pvalCheckType(p,
"pvalSwitchesWalkNames", PV_SWITCHES))
5366 *next_item = p->u1.list;
5368 *next_item = (*next_item)->next;
5370 return (*next_item)->u1.str;
5373 void pvalESwitchesAddSwitch(
pval *p,
char *name )
5376 if (!pvalCheckType(p,
"pvalESwitchesAddSwitch", PV_ESWITCHES))
5378 s = pvalCreateNode(PV_WORD);
5380 p->u1.list = linku1(p->u1.list, s);
5383 char* pvalESwitchesWalkNames(
pval *p,
pval **next_item )
5385 if (!pvalCheckType(p,
"pvalESwitchesWalkNames", PV_ESWITCHES))
5388 *next_item = p->u1.list;
5390 *next_item = (*next_item)->next;
5392 return (*next_item)->u1.str;
5396 void pvalIncludesAddInclude(
pval *p,
const char *include )
5399 if (!pvalCheckType(p,
"pvalIncludesAddSwitch", PV_INCLUDES))
5401 s = pvalCreateNode(PV_WORD);
5402 s->u1.str = (
char *)include;
5403 p->u1.list = linku1(p->u1.list, s);
5407 void pvalIncludesAddIncludeWithTimeConstraints(
pval *p,
const char *include,
char *hour_range,
char *dom_range,
char *dow_range,
char *month_range )
5415 if (!pvalCheckType(p,
"pvalIncludeAddIncludeWithTimeConstraints", PV_INCLUDES)) {
5419 hr = pvalCreateNode(PV_WORD);
5420 dom = pvalCreateNode(PV_WORD);
5421 dow = pvalCreateNode(PV_WORD);
5422 mon = pvalCreateNode(PV_WORD);
5423 s = pvalCreateNode(PV_WORD);
5425 if (!hr || !dom || !dow || !mon || !s) {
5434 s->u1.str = (
char *)include;
5435 p->u1.list = linku1(p->u1.list, s);
5437 hr->u1.str = hour_range;
5438 dom->u1.str = dom_range;
5439 dow->u1.str = dow_range;
5440 mon->u1.str = month_range;
5450 void pvalIncludeGetTimeConstraints(
pval *p,
char **hour_range,
char **dom_range,
char **dow_range,
char **month_range )
5452 if (!pvalCheckType(p,
"pvalIncludeGetTimeConstraints", PV_WORD))
5454 if (p->u2.arglist) {
5455 *hour_range = p->u2.arglist->u1.str;
5456 *dom_range = p->u2.arglist->next->u1.str;
5457 *dow_range = p->u2.arglist->next->next->u1.str;
5458 *month_range = p->u2.arglist->next->next->next->u1.str;
5467 char* pvalIncludesWalk(
pval *p,
pval **next_item )
5469 if (!pvalCheckType(p,
"pvalIncludesWalk", PV_INCLUDES))
5472 *next_item = p->u1.list;
5474 *next_item = (*next_item)->next;
5476 return (*next_item)->u1.str;
5480 void pvalStatementBlockAddStatement(
pval *p,
pval *statement)
5482 if (!pvalCheckType(p,
"pvalStatementBlockAddStatement", PV_STATEMENTBLOCK))
5484 p->u1.list = linku1(p->u1.list, statement);
5487 pval *pvalStatementBlockWalkStatements(
pval *p,
pval **next_statement)
5489 if (!pvalCheckType(p,
"pvalStatementBlockWalkStatements", PV_STATEMENTBLOCK))
5491 if (!(*next_statement))
5492 *next_statement = p->u1.list;
5494 *next_statement = (*next_statement)->next;
5496 return *next_statement;
5499 void pvalVarDecSetVarname(
pval *p,
char *name )
5501 if (!pvalCheckType(p,
"pvalVarDecSetVarname", PV_VARDEC))
5506 void pvalVarDecSetValue(
pval *p,
char *value )
5508 if (!pvalCheckType(p,
"pvalVarDecSetValue", PV_VARDEC))
5513 char* pvalVarDecGetVarname(
pval *p )
5515 if (!pvalCheckType(p,
"pvalVarDecGetVarname", PV_VARDEC))
5520 char* pvalVarDecGetValue(
pval *p )
5522 if (!pvalCheckType(p,
"pvalVarDecGetValue", PV_VARDEC))
5527 void pvalGotoSetTarget(
pval *p,
char *context,
char *exten,
char *label )
5529 pval *con, *ext, *pri;
5531 if (!pvalCheckType(p,
"pvalGotoSetTarget", PV_GOTO))
5533 if (context && strlen(context)) {
5534 con = pvalCreateNode(PV_WORD);
5535 ext = pvalCreateNode(PV_WORD);
5536 pri = pvalCreateNode(PV_WORD);
5538 con->u1.str = context;
5539 ext->u1.str = exten;
5540 pri->u1.str = label;
5545 }
else if (exten && strlen(exten)) {
5546 ext = pvalCreateNode(PV_WORD);
5547 pri = pvalCreateNode(PV_WORD);
5549 ext->u1.str = exten;
5550 pri->u1.str = label;
5555 pri = pvalCreateNode(PV_WORD);
5557 pri->u1.str = label;
5563 void pvalGotoGetTarget(
pval *p,
char **context,
char **exten,
char **label )
5565 if (!pvalCheckType(p,
"pvalGotoGetTarget", PV_GOTO))
5567 if (p->u1.list && p->u1.list->next && p->u1.list->next->next) {
5568 *context = p->u1.list->u1.str;
5569 *exten = p->u1.list->next->u1.str;
5570 *label = p->u1.list->next->next->u1.str;
5572 }
else if (p->u1.list && p->u1.list->next ) {
5573 *exten = p->u1.list->u1.str;
5574 *label = p->u1.list->next->u1.str;
5577 }
else if (p->u1.list) {
5578 *label = p->u1.list->u1.str;
5590 void pvalLabelSetName(
pval *p,
char *name )
5592 if (!pvalCheckType(p,
"pvalLabelSetName", PV_LABEL))
5597 char* pvalLabelGetName(
pval *p )
5599 if (!pvalCheckType(p,
"pvalLabelGetName", PV_LABEL))
5605 void pvalForSetInit(
pval *p,
char *init )
5607 if (!pvalCheckType(p,
"pvalForSetInit", PV_FOR))
5609 p->u1.for_init = init;
5612 void pvalForSetTest(
pval *p,
char *
test )
5614 if (!pvalCheckType(p,
"pvalForSetTest", PV_FOR))
5616 p->u2.for_test = test;
5619 void pvalForSetInc(
pval *p,
char *inc )
5621 if (!pvalCheckType(p,
"pvalForSetInc", PV_FOR))
5623 p->u3.for_inc = inc;
5626 void pvalForSetStatement(
pval *p,
pval *statement )
5628 if (!pvalCheckType(p,
"pvalForSetStatement", PV_FOR))
5630 p->u4.for_statements = statement;
5633 char* pvalForGetInit(
pval *p )
5635 if (!pvalCheckType(p,
"pvalForGetInit", PV_FOR))
5637 return p->u1.for_init;
5640 char* pvalForGetTest(
pval *p )
5642 if (!pvalCheckType(p,
"pvalForGetTest", PV_FOR))
5644 return p->u2.for_test;
5647 char* pvalForGetInc(
pval *p )
5649 if (!pvalCheckType(p,
"pvalForGetInc", PV_FOR))
5651 return p->u3.for_inc;
5654 pval* pvalForGetStatement(
pval *p )
5656 if (!pvalCheckType(p,
"pvalForGetStatement", PV_FOR))
5658 return p->u4.for_statements;
5663 void pvalIfSetCondition(
pval *p,
char *expr )
5665 if (!pvalCheckType(p,
"pvalIfSetCondition", PV_IF))
5670 char* pvalIfGetCondition(
pval *p )
5672 if (!pvalCheckType(p,
"pvalIfGetCondition", PV_IFTIME))
5677 void pvalIfTimeSetCondition(
pval *p,
char *hour_range,
char *dow_range,
char *dom_range,
char *mon_range )
5684 if (!pvalCheckType(p,
"pvalIfTimeSetCondition", PV_IFTIME)) {
5688 hr = pvalCreateNode(PV_WORD);
5689 dow = pvalCreateNode(PV_WORD);
5690 dom = pvalCreateNode(PV_WORD);
5691 mon = pvalCreateNode(PV_WORD);
5693 if (!hr || !dom || !dow || !mon) {
5701 pvalWordSetString(hr, hour_range);
5702 pvalWordSetString(dow, dow_range);
5703 pvalWordSetString(dom, dom_range);
5704 pvalWordSetString(mon, mon_range);
5712 void pvalIfTimeGetCondition(
pval *p,
char **hour_range,
char **dow_range,
char **dom_range,
char **month_range )
5714 if (!pvalCheckType(p,
"pvalIfTimeGetCondition", PV_IFTIME))
5716 *hour_range = p->u1.list->u1.str;
5717 *dow_range = p->u1.list->next->u1.str;
5718 *dom_range = p->u1.list->next->next->u1.str;
5719 *month_range = p->u1.list->next->next->next->u1.str;
5722 void pvalRandomSetCondition(
pval *p,
char *percent )
5724 if (!pvalCheckType(p,
"pvalRandomSetCondition", PV_RANDOM))
5726 p->u1.str = percent;
5729 char* pvalRandomGetCondition(
pval *p )
5731 if (!pvalCheckType(p,
"pvalRandomGetCondition", PV_RANDOM))
5736 void pvalConditionalSetThenStatement(
pval *p,
pval *statement )
5738 p->u2.statements = statement;
5741 void pvalConditionalSetElseStatement(
pval *p,
pval *statement )
5743 p->u3.else_statements = statement;
5746 pval* pvalConditionalGetThenStatement(
pval *p )
5748 return p->u2.statements;
5751 pval* pvalConditionalGetElseStatement(
pval *p )
5753 return p->u3.else_statements;
5756 void pvalSwitchSetTestexpr(
pval *p,
char *expr )
5758 if (!pvalCheckType(p,
"pvalSwitchSetTestexpr", PV_SWITCH))
5763 char* pvalSwitchGetTestexpr(
pval *p )
5765 if (!pvalCheckType(p,
"pvalSwitchGetTestexpr", PV_SWITCH))
5770 void pvalSwitchAddCase(
pval *p,
pval *Case )
5772 if (!pvalCheckType(p,
"pvalSwitchAddCase", PV_SWITCH))
5774 if (!pvalCheckType(Case,
"pvalSwitchAddCase", PV_CASE))
5776 if (!p->u2.statements)
5777 p->u2.statements = Case;
5779 linku1(p->u2.statements, Case);
5784 if (!pvalCheckType(p,
"pvalSwitchWalkCases", PV_SWITCH))
5787 *next_case = p->u2.statements;
5789 *next_case = (*next_case)->next;
5795 void pvalExtenSetName(
pval *p,
char *name )
5797 if (!pvalCheckType(p,
"pvalExtenSetName", PV_EXTENSION))
5802 char* pvalExtenGetName(
pval *p )
5804 if (!pvalCheckType(p,
"pvalExtenGetName", PV_EXTENSION))
5809 void pvalExtenSetRegexten(
pval *p )
5811 if (!pvalCheckType(p,
"pvalExtenSetRegexten", PV_EXTENSION))
5816 void pvalExtenUnSetRegexten(
pval *p )
5818 if (!pvalCheckType(p,
"pvalExtenUnSetRegexten", PV_EXTENSION))
5823 int pvalExtenGetRegexten(
pval *p )
5825 if (!pvalCheckType(p,
"pvalExtenGetRegexten", PV_EXTENSION))
5827 return p->u4.regexten;
5830 void pvalExtenSetHints(
pval *p,
char *
hints )
5832 if (!pvalCheckType(p,
"pvalExtenSetHints", PV_EXTENSION))
5834 p->u3.hints =
hints;
5837 char* pvalExtenGetHints(
pval *p )
5839 if (!pvalCheckType(p,
"pvalExtenGetHints", PV_EXTENSION))
5844 void pvalExtenSetStatement(
pval *p,
pval *statement )
5846 if (!pvalCheckType(p,
"pvalExtenSetStatement", PV_EXTENSION))
5848 p->u2.statements = statement;
5851 pval* pvalExtenGetStatement(
pval *p )
5853 if (!pvalCheckType(p,
"pvalExtenGetStatement", PV_EXTENSION))
5855 return p->u2.statements;
5859 void pvalIgnorePatSetPattern(
pval *p,
char *pat )
5861 if (!pvalCheckType(p,
"pvalIgnorePatSetPattern", PV_IGNOREPAT))
5866 char* pvalIgnorePatGetPattern(
pval *p )
5868 if (!pvalCheckType(p,
"pvalIgnorePatGetPattern", PV_IGNOREPAT))
5874 void pvalGlobalsAddStatement(
pval *p,
pval *statement )
5876 if (p->type != PV_GLOBALS) {
5877 ast_log(LOG_ERROR,
"pvalGlobalsAddStatement called where first arg is not a Globals!\n");
5879 if (!p->u1.statements) {
5880 p->u1.statements = statement;
5882 p->u1.statements = linku1(p->u1.statements,statement);
5887 pval* pvalGlobalsWalkStatements(
pval *p,
pval **next_statement )
5889 if (!pvalCheckType(p,
"pvalGlobalsWalkStatements", PV_GLOBALS))
5891 if (!*next_statement) {
5892 *next_statement = p;
5895 *next_statement = (*next_statement)->next;
5896 return (*next_statement)->next;
5901 void pvalTopLevAddObject(
pval *p,
pval *contextOrObj )
5904 linku1(p,contextOrObj);
5906 ast_log(LOG_ERROR,
"First arg to pvalTopLevel is NULL!\n");
5916 *next_obj = (*next_obj)->next;
5917 return (*next_obj)->next;
5930 head->u1_last->next = tail;
5932 head->u1_last = tail;
Asterisk main include file. File version handling, generic pbx functions.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
Registered applications container.
static void check_dow(pval *DOW)
get_dow: Get day of week
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)
static struct ao2_container * hints
void ast_free_ptr(void *ptr)
free() wrapper
Configuration File Parser.
General Asterisk PBX channel definitions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define AST_MAX_EXTENSION
struct ael_priority * loop_break
Core PBX routines and definitions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
struct ael_priority * loop_continue
int ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
Add a context include.
static struct ast_context * find_context(const char *context)
lookup for a context with a given name,
Structures for AEL - the Asterisk extension language.
Support for logging to various files, console and syslog Configuration in file logger.conf.
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...
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 *.
Standard Command Line Interface.
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.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
ast_context: An extension context
int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan)
Evaluate the given expression.