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.
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...
static void check_dow(pval *DOW)
get_dow: Get day of week
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.