Compile symbolic Asterisk Extension Logic into Asterisk extensions, version 2. More...
#include "asterisk.h"
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <regex.h>
#include <sys/stat.h>
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/channel.h"
#include "asterisk/callerid.h"
#include "asterisk/pval.h"
#include "asterisk/ael_structs.h"
#include "asterisk/utils.h"
Go to the source code of this file.
Compile symbolic Asterisk Extension Logic into Asterisk extensions, version 2.
Definition in file pval.c.
void add_extensions | ( | struct ael_extension * | exten | ) |
Definition at line 4251 of file pval.c.
References AEL_APPCALL, AEL_CONTROL1, AEL_FOR_CONTROL, AEL_IF_CONTROL, AEL_IFTIME_CONTROL, AEL_LABEL, AEL_RAND_CONTROL, AEL_RETURN, ael_priority::app, ael_priority::appargs, ast_add_extension2(), ast_free_ptr(), ast_log(), AST_MAX_EXTENSION, ael_extension::cidmatch, ael_extension::context, pval::else_statements, ael_priority::exten, ael_priority::goto_false, ael_priority::goto_true, ael_extension::hints, last, LOG_WARNING, ael_extension::name, ael_priority::next, ael_extension::next_exten, ael_priority::origin, pbx_substitute_variables_helper(), ael_extension::plist, PRIORITY_HINT, ael_priority::priority_num, PV_IFTIME, PV_SWITCH, pval::str, strdup, pval::type, ael_priority::type, pval::u1, and pval::u3.
Referenced by ast_compile_ael2().
04252 { 04253 struct ael_priority *pr; 04254 char *label=0; 04255 char realext[AST_MAX_EXTENSION]; 04256 if (!exten) { 04257 ast_log(LOG_WARNING, "This file is Empty!\n" ); 04258 return; 04259 } 04260 do { 04261 struct ael_priority *last = 0; 04262 04263 pbx_substitute_variables_helper(NULL, exten->name, realext, sizeof(realext) - 1); 04264 if (exten->hints) { 04265 if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, PRIORITY_HINT, NULL, exten->cidmatch, 04266 exten->hints, NULL, ast_free_ptr, registrar)) { 04267 ast_log(LOG_WARNING, "Unable to add step at priority 'hint' of extension '%s'\n", 04268 exten->name); 04269 } 04270 } 04271 04272 for (pr=exten->plist; pr; pr=pr->next) { 04273 char app[2000]; 04274 char appargs[2000]; 04275 04276 /* before we can add the extension, we need to prep the app/appargs; 04277 the CONTROL types need to be done after the priority numbers are calculated. 04278 */ 04279 if (pr->type == AEL_LABEL) /* don't try to put labels in the dialplan! */ { 04280 last = pr; 04281 continue; 04282 } 04283 04284 if (pr->app) 04285 strcpy(app, pr->app); 04286 else 04287 app[0] = 0; 04288 if (pr->appargs ) 04289 strcpy(appargs, pr->appargs); 04290 else 04291 appargs[0] = 0; 04292 switch( pr->type ) { 04293 case AEL_APPCALL: 04294 /* easy case. Everything is all set up */ 04295 break; 04296 04297 case AEL_CONTROL1: /* FOR loop, WHILE loop, BREAK, CONTINUE, IF, IFTIME */ 04298 /* simple, unconditional goto. */ 04299 strcpy(app,"Goto"); 04300 if (pr->goto_true->origin && pr->goto_true->origin->type == PV_SWITCH ) { 04301 snprintf(appargs,sizeof(appargs),"%s,%d", pr->goto_true->exten->name, pr->goto_true->priority_num); 04302 } else if (pr->goto_true->origin && pr->goto_true->origin->type == PV_IFTIME && pr->goto_true->origin->u3.else_statements ) { 04303 snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num+1); 04304 } else 04305 snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num); 04306 break; 04307 04308 case AEL_FOR_CONTROL: /* WHILE loop test, FOR loop test */ 04309 strcpy(app,"GotoIf"); 04310 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); 04311 break; 04312 04313 case AEL_IF_CONTROL: 04314 strcpy(app,"GotoIf"); 04315 if (pr->origin->u3.else_statements ) 04316 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num+1); 04317 else 04318 snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); 04319 break; 04320 04321 case AEL_RAND_CONTROL: 04322 strcpy(app,"Random"); 04323 snprintf(appargs,sizeof(appargs),"%s:%d", pr->appargs, pr->goto_true->priority_num+1); 04324 break; 04325 04326 case AEL_IFTIME_CONTROL: 04327 strcpy(app,"GotoIfTime"); 04328 snprintf(appargs,sizeof(appargs),"%s?%d", pr->appargs, pr->priority_num+2); 04329 break; 04330 04331 case AEL_RETURN: 04332 strcpy(app,"Return"); 04333 appargs[0] = 0; 04334 break; 04335 04336 default: 04337 break; 04338 } 04339 if (last && last->type == AEL_LABEL ) { 04340 label = last->origin->u1.str; 04341 } 04342 else 04343 label = 0; 04344 04345 if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, pr->priority_num, (label?label:NULL), exten->cidmatch, 04346 app, strdup(appargs), ast_free_ptr, registrar)) { 04347 ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num, 04348 exten->name); 04349 } 04350 last = pr; 04351 } 04352 exten = exten->next_exten; 04353 } while ( exten ); 04354 }
void ael2_print | ( | char * | fname, | |
pval * | tree | |||
) |
Definition at line 384 of file pval.c.
References ast_log(), LOG_ERROR, and print_pval_list().
00385 { 00386 FILE *fin = fopen(fname,"w"); 00387 if ( !fin ) { 00388 ast_log(LOG_ERROR, "Couldn't open %s for writing.\n", fname); 00389 return; 00390 } 00391 print_pval_list(fin, tree, 0); 00392 fclose(fin); 00393 }
void ael2_semantic_check | ( | pval * | item, | |
int * | arg_errs, | |||
int * | arg_warns, | |||
int * | arg_notes | |||
) |
Definition at line 2892 of file pval.c.
References ast_alloca, ast_config_AST_VAR_DIR, check_context_names(), and check_pval().
Referenced by pbx_load_module().
02893 { 02894 02895 #ifdef AAL_ARGCHECK 02896 int argapp_errs =0; 02897 char *rfilename; 02898 #endif 02899 struct argapp *apps=0; 02900 02901 if (!item) 02902 return; /* don't check an empty tree */ 02903 #ifdef AAL_ARGCHECK 02904 rfilename = ast_alloca(10 + strlen(ast_config_AST_VAR_DIR)); 02905 sprintf(rfilename, "%s/applist", ast_config_AST_VAR_DIR); 02906 02907 apps = argdesc_parse(rfilename, &argapp_errs); /* giveth */ 02908 #endif 02909 current_db = item; 02910 errs = warns = notes = 0; 02911 02912 check_context_names(); 02913 check_pval(item, apps, 0); 02914 02915 #ifdef AAL_ARGCHECK 02916 argdesc_destroy(apps); /* taketh away */ 02917 #endif 02918 current_db = 0; 02919 02920 *arg_errs = errs; 02921 *arg_warns = warns; 02922 *arg_notes = notes; 02923 }
int ast_compile_ael2 | ( | struct ast_context ** | local_contexts, | |
struct ast_hashtab * | local_table, | |||
struct pval * | root | |||
) |
Definition at line 4451 of file pval.c.
References add_extensions(), AEL_APPCALL, AEL_LABEL, ael_priority::app, ael_priority::appargs, pval::arglist, ARRAY_LEN, ast_compat_app_set, ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_find_or_create(), ast_custom_function_find(), ast_get_context_name(), attach_exten(), ael_extension::cidmatch, ael_extension::context, context, context_used(), destroy_extensions(), exten, fix_gotos_in_extensions(), gen_prios(), ael_extension::hints, pval::hints, linkprio(), pval::list, pval::macro_statements, ael_extension::name, new_exten(), new_prio(), pval::next, ael_extension::next_exten, ael_priority::origin, pbx_builtin_setvar(), ael_extension::plist_last, ael_priority::priority_num, PV_CONTEXT, PV_ESWITCHES, PV_EXTENSION, PV_GLOBALS, PV_IGNOREPAT, PV_INCLUDES, PV_MACRO, PV_SWITCHES, pval::regexten, ael_extension::regexten, remove_spaces_before_equals(), ael_extension::return_needed, set_priorities(), pval::statements, pval::str, strdup, ael_priority::type, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.
Referenced by pbx_load_module().
04452 { 04453 pval *p,*p2; 04454 struct ast_context *context; 04455 char buf[2000]; 04456 struct ael_extension *exten; 04457 struct ael_extension *exten_list = 0; 04458 04459 for (p=root; p; p=p->next ) { /* do the globals first, so they'll be there 04460 when we try to eval them */ 04461 switch (p->type) { 04462 case PV_GLOBALS: 04463 /* just VARDEC elements */ 04464 for (p2=p->u1.list; p2; p2=p2->next) { 04465 char buf2[2000]; 04466 snprintf(buf2,sizeof(buf2),"%s=%s", p2->u1.str, p2->u2.val); 04467 pbx_builtin_setvar(NULL, buf2); 04468 } 04469 break; 04470 default: 04471 break; 04472 } 04473 } 04474 04475 for (p=root; p; p=p->next ) { 04476 pval *lp; 04477 int argc; 04478 04479 switch (p->type) { 04480 case PV_MACRO: 04481 04482 context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar); 04483 04484 exten = new_exten(); 04485 exten->context = context; 04486 exten->name = strdup("~~s~~"); 04487 argc = 1; 04488 for (lp=p->u2.arglist; lp; lp=lp->next) { 04489 /* for each arg, set up a "Set" command */ 04490 struct ael_priority *np2 = new_prio(); 04491 np2->type = AEL_APPCALL; 04492 if (!ast_compat_app_set) { 04493 np2->app = strdup("MSet"); 04494 } else { 04495 np2->app = strdup("Set"); 04496 } 04497 snprintf(buf,sizeof(buf),"LOCAL(%s)=${ARG%d}", lp->u1.str, argc++); 04498 remove_spaces_before_equals(buf); 04499 np2->appargs = strdup(buf); 04500 linkprio(exten, np2, NULL); 04501 } 04502 04503 /* CONTAINS APPCALLS, CATCH, just like extensions... */ 04504 if (gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context)) { 04505 return -1; 04506 } 04507 if (exten->return_needed) { /* most likely, this will go away */ 04508 struct ael_priority *np2 = new_prio(); 04509 np2->type = AEL_APPCALL; 04510 np2->app = strdup("NoOp"); 04511 snprintf(buf,sizeof(buf),"End of Macro %s-%s",p->u1.str, exten->name); 04512 np2->appargs = strdup(buf); 04513 linkprio(exten, np2, NULL); 04514 exten-> return_target = np2; 04515 } 04516 04517 set_priorities(exten); 04518 attach_exten(&exten_list, exten); 04519 break; 04520 04521 case PV_GLOBALS: 04522 /* already done */ 04523 break; 04524 04525 case PV_CONTEXT: 04526 context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar); 04527 04528 /* contexts contain: ignorepat, includes, switches, eswitches, extensions, */ 04529 for (p2=p->u2.statements; p2; p2=p2->next) { 04530 pval *p3; 04531 char *s3; 04532 04533 switch (p2->type) { 04534 case PV_EXTENSION: 04535 exten = new_exten(); 04536 exten->name = strdup(p2->u1.str); 04537 exten->context = context; 04538 04539 if( (s3=strchr(exten->name, '/') ) != 0 ) 04540 { 04541 *s3 = 0; 04542 exten->cidmatch = s3+1; 04543 } 04544 04545 if ( p2->u3.hints ) 04546 exten->hints = strdup(p2->u3.hints); 04547 exten->regexten = p2->u4.regexten; 04548 if (gen_prios(exten, p->u1.str, p2->u2.statements, 0, context)) { 04549 return -1; 04550 } 04551 if (exten->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */ 04552 struct ael_priority *np2 = new_prio(); 04553 np2->type = AEL_APPCALL; 04554 np2->app = strdup("NoOp"); 04555 snprintf(buf,sizeof(buf),"End of Extension %s", exten->name); 04556 np2->appargs = strdup(buf); 04557 linkprio(exten, np2, NULL); 04558 exten-> return_target = np2; 04559 } 04560 /* is the last priority in the extension a label? Then add a trailing no-op */ 04561 if ( exten->plist_last && exten->plist_last->type == AEL_LABEL ) { 04562 struct ael_priority *np2 = new_prio(); 04563 np2->type = AEL_APPCALL; 04564 np2->app = strdup("NoOp"); 04565 snprintf(buf,sizeof(buf),"A NoOp to follow a trailing label %s", exten->plist_last->origin->u1.str); 04566 np2->appargs = strdup(buf); 04567 linkprio(exten, np2, NULL); 04568 } 04569 04570 set_priorities(exten); 04571 attach_exten(&exten_list, exten); 04572 break; 04573 04574 case PV_IGNOREPAT: 04575 ast_context_add_ignorepat2(context, p2->u1.str, registrar); 04576 break; 04577 04578 case PV_INCLUDES: 04579 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 04580 if ( p3->u2.arglist ) { 04581 snprintf(buf,sizeof(buf), "%s,%s,%s,%s,%s", 04582 p3->u1.str, 04583 p3->u2.arglist->u1.str, 04584 p3->u2.arglist->next->u1.str, 04585 p3->u2.arglist->next->next->u1.str, 04586 p3->u2.arglist->next->next->next->u1.str); 04587 ast_context_add_include2(context, buf, registrar); 04588 } else 04589 ast_context_add_include2(context, p3->u1.str, registrar); 04590 } 04591 break; 04592 04593 case PV_SWITCHES: 04594 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 04595 char *c = strchr(p3->u1.str, '/'); 04596 if (c) { 04597 *c = '\0'; 04598 c++; 04599 } else 04600 c = ""; 04601 04602 ast_context_add_switch2(context, p3->u1.str, c, 0, registrar); 04603 } 04604 break; 04605 04606 case PV_ESWITCHES: 04607 for (p3 = p2->u1.list; p3 ;p3=p3->next) { 04608 char *c = strchr(p3->u1.str, '/'); 04609 if (c) { 04610 *c = '\0'; 04611 c++; 04612 } else 04613 c = ""; 04614 04615 ast_context_add_switch2(context, p3->u1.str, c, 1, registrar); 04616 } 04617 break; 04618 default: 04619 break; 04620 } 04621 } 04622 04623 break; 04624 04625 default: 04626 /* huh? what? */ 04627 break; 04628 04629 } 04630 } 04631 04632 /* Create default "h" bubble context */ 04633 if (ast_custom_function_find("DIALPLAN_EXISTS") && ast_custom_function_find("STACK_PEEK")) { 04634 int i; 04635 const char *h_context = "ael-builtin-h-bubble"; 04636 struct ael_priority *np; 04637 struct { 04638 int priority; 04639 const char *app; 04640 const char *arg; 04641 } steps[] = { 04642 /* Start high, to avoid conflict with existing h extensions */ 04643 { 1, "Goto", "9991" }, 04644 /* Save the context, because after the StackPop, it disappears */ 04645 { 9991, "Set", "~~parentcxt~~=${STACK_PEEK(1,c,1)}" }, 04646 /* If we're not in a Gosub frame, exit */ 04647 { 9992, "GotoIf", "$[\"${~~parentcxt~~}\"=\"\"]?9996" }, 04648 /* Check for an "h" extension in that context */ 04649 { 9993, "GotoIf", "${DIALPLAN_EXISTS(${~~parentcxt~~},h,1)}?9994:9996" }, 04650 /* Pop off the stack frame to prevent an infinite loop */ 04651 { 9994, "StackPop", "" }, 04652 /* Finally, go there. */ 04653 { 9995, "Goto", "${~~parentcxt~~},h,1" }, 04654 /* Just an empty priority for jumping out early */ 04655 { 9996, "NoOp", "" } 04656 }; 04657 context = ast_context_find_or_create(local_contexts, local_table, h_context, registrar); 04658 if (context_used(exten_list, context)) { 04659 int found = 0; 04660 while (!found) { 04661 /* Pick a new context name that is not used. */ 04662 char h_context_template[] = "/tmp/ael-builtin-h-bubble-XXXXXX"; 04663 int fd = mkstemp(h_context_template); 04664 unlink(h_context_template); 04665 close(fd); 04666 context = ast_context_find_or_create(local_contexts, local_table, h_context_template + 5, registrar); 04667 found = !context_used(exten_list, context); 04668 } 04669 h_context = ast_get_context_name(context); 04670 } 04671 exten = new_exten(); 04672 exten->context = context; 04673 exten->name = strdup("h"); 04674 04675 for (i = 0; i < ARRAY_LEN(steps); i++) { 04676 np = new_prio(); 04677 np->type = AEL_APPCALL; 04678 np->priority_num = steps[i].priority; 04679 np->app = strdup(steps[i].app); 04680 np->appargs = strdup(steps[i].arg); 04681 linkprio(exten, np, NULL); 04682 } 04683 attach_exten(&exten_list, exten); 04684 04685 /* Include the default "h" bubble context in each macro context */ 04686 for (exten = exten_list; exten; exten = exten->next_exten) { 04687 /* All macros contain a "~~s~~" extension, and it's the first created. If 04688 * we perchance get a non-macro context, it's no big deal; the logic is 04689 * designed to exit out smoothly if not called from within a Gosub. */ 04690 if (!strcmp(exten->name, "~~s~~")) { 04691 ast_context_add_include2(exten->context, h_context, registrar); 04692 } 04693 } 04694 } 04695 04696 /* moved these from being done after a macro or extension were processed, 04697 to after all processing is done, for the sake of fixing gotos to labels inside cases... */ 04698 /* I guess this would be considered 2nd pass of compiler now... */ 04699 fix_gotos_in_extensions(exten_list); /* find and fix extension ref in gotos to labels that are in case statements */ 04700 add_extensions(exten_list); /* actually makes calls to create priorities in ast_contexts -- feeds dialplan to asterisk */ 04701 destroy_extensions(exten_list); /* all that remains is an empty husk, discard of it as is proper */ 04702 04703 return 0; 04704 }
static void attach_exten | ( | struct ael_extension ** | list, | |
struct ael_extension * | newmem | |||
) | [static] |
Definition at line 4356 of file pval.c.
References ael_extension::next_exten.
Referenced by ast_compile_ael2().
04357 { 04358 /* travel to the end of the list... */ 04359 struct ael_extension *lptr; 04360 if( !*list ) { 04361 *list = newmem; 04362 return; 04363 } 04364 lptr = *list; 04365 04366 while( lptr->next_exten ) { 04367 lptr = lptr->next_exten; 04368 } 04369 /* lptr should now pointing to the last element in the list; it has a null next_exten pointer */ 04370 lptr->next_exten = newmem; 04371 }
static void check_abstract_reference | ( | pval * | abstract_context | ) | [static] |
Definition at line 2336 of file pval.c.
References ast_log(), pval::endline, pval::filename, pval::list, LOG_WARNING, pval::next, PV_CONTEXT, PV_INCLUDES, pval::startline, pval::str, pval::type, pval::u1, and pval::u2.
Referenced by check_pval_item().
02337 { 02338 pval *i,*j; 02339 /* find some context includes that reference this context */ 02340 02341 02342 /* otherwise, print out a warning */ 02343 for (i=current_db; i; i=i->next) { 02344 if (i->type == PV_CONTEXT) { 02345 for (j=i->u2. statements; j; j=j->next) { 02346 if ( j->type == PV_INCLUDES ) { 02347 struct pval *p4; 02348 for (p4=j->u1.list; p4; p4=p4->next) { 02349 /* for each context pointed to, find it, then find a context/label that matches the 02350 target here! */ 02351 if ( !strcmp(p4->u1.str, abstract_context->u1.str) ) 02352 return; /* found a match! */ 02353 } 02354 } 02355 } 02356 } 02357 } 02358 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", 02359 abstract_context->filename, abstract_context->startline, abstract_context->endline, abstract_context->u1.str); 02360 warns++; 02361 }
Definition at line 2137 of file pval.c.
References ast_log(), pval::endline, pval::filename, LOG_WARNING, pval::next, pval::startline, pval::str, and pval::u1.
Referenced by check_pval_item().
02138 { 02139 #ifdef AAL_ARGCHECK 02140 struct argdesc *ad = app->args; 02141 pval *pa; 02142 int z; 02143 02144 for (pa = arglist; pa; pa=pa->next) { 02145 if (!ad) { 02146 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Extra argument %s not in application call to %s !\n", 02147 arglist->filename, arglist->startline, arglist->endline, pa->u1.str, app->name); 02148 warns++; 02149 return 1; 02150 } else { 02151 /* find the first entry in the ad list that will match */ 02152 do { 02153 if ( ad->dtype == ARGD_VARARG ) /* once we hit the VARARG, all bets are off. Discontinue the comparisons */ 02154 break; 02155 02156 z= option_matches( ad, pa, app); 02157 if (!z) { 02158 if ( !arglist ) 02159 arglist=appcall; 02160 02161 if (ad->type == ARGD_REQUIRED) { 02162 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", 02163 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); 02164 warns++; 02165 return 1; 02166 } 02167 } else if (z && ad->dtype == ARGD_OPTIONSET) { 02168 option_matches_j( ad, pa, app); 02169 } 02170 ad = ad->next; 02171 } while (ad && !z); 02172 } 02173 } 02174 /* any app nodes left, that are not optional? */ 02175 for ( ; ad; ad=ad->next) { 02176 if (ad->type == ARGD_REQUIRED && ad->dtype != ARGD_VARARG) { 02177 if ( !arglist ) 02178 arglist=appcall; 02179 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", 02180 arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); 02181 warns++; 02182 return 1; 02183 } 02184 } 02185 return 0; 02186 #else 02187 return 0; 02188 #endif 02189 }
static int check_break | ( | pval * | item | ) | [static] |
Definition at line 1045 of file pval.c.
References ast_log(), pval::dad, pval::endline, pval::filename, LOG_ERROR, PV_CASE, PV_CONTEXT, PV_DEFAULT, PV_FOR, PV_MACRO, PV_PATTERN, PV_WHILE, pval::startline, and pval::type.
Referenced by check_pval_item().
01046 { 01047 pval *p = item; 01048 01049 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ { 01050 /* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make 01051 no sense */ 01052 if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN 01053 || p->type == PV_WHILE || p->type == PV_FOR ) { 01054 return 1; 01055 } 01056 p = p->dad; 01057 } 01058 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'break' not in switch, for, or while statement!\n", 01059 item->filename, item->startline, item->endline); 01060 errs++; 01061 01062 return 0; 01063 }
static void check_context_names | ( | void | ) | [static] |
Definition at line 2317 of file pval.c.
References pval::abstract, ast_log(), pval::endline, pval::filename, LOG_WARNING, pval::next, PV_CONTEXT, PV_MACRO, pval::startline, pval::str, pval::type, pval::u1, and pval::u3.
Referenced by ael2_semantic_check().
02318 { 02319 pval *i,*j; 02320 for (i=current_db; i; i=i->next) { 02321 if (i->type == PV_CONTEXT || i->type == PV_MACRO) { 02322 for (j=i->next; j; j=j->next) { 02323 if ( j->type == PV_CONTEXT || j->type == PV_MACRO ) { 02324 if ( !strcmp(i->u1.str, j->u1.str) && !(i->u3.abstract&2) && !(j->u3.abstract&2) ) 02325 { 02326 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", 02327 i->filename, i->startline, i->endline, i->u1.str, j->filename, j->startline, j->endline); 02328 warns++; 02329 } 02330 } 02331 } 02332 } 02333 } 02334 }
static int check_continue | ( | pval * | item | ) | [static] |
Definition at line 1065 of file pval.c.
References ast_log(), pval::dad, pval::endline, pval::filename, LOG_ERROR, PV_CONTEXT, PV_FOR, PV_MACRO, PV_WHILE, pval::startline, and pval::type.
Referenced by check_pval_item().
01066 { 01067 pval *p = item; 01068 01069 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ { 01070 /* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make 01071 no sense */ 01072 if( p->type == PV_WHILE || p->type == PV_FOR ) { 01073 return 1; 01074 } 01075 p = p->dad; 01076 } 01077 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'continue' not in 'for' or 'while' statement!\n", 01078 item->filename, item->startline, item->endline); 01079 errs++; 01080 01081 return 0; 01082 }
static void check_day | ( | pval * | DAY | ) | [static] |
Definition at line 944 of file pval.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), pval::endline, pval::filename, LOG_WARNING, pval::startline, pval::str, and pval::u1.
Referenced by check_pval_item().
00945 { 00946 char *day; 00947 char *c; 00948 /* The following line is coincidence, really! */ 00949 int s, e; 00950 00951 day = ast_strdupa(DAY->u1.str); 00952 00953 /* Check for all days */ 00954 if (ast_strlen_zero(day) || !strcmp(day, "*")) { 00955 return; 00956 } 00957 /* Get start and ending days */ 00958 c = strchr(day, '-'); 00959 if (c) { 00960 *c = '\0'; 00961 c++; 00962 } 00963 /* Find the start */ 00964 if (sscanf(day, "%2d", &s) != 1) { 00965 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start day of month (%s) must be a number!\n", 00966 DAY->filename, DAY->startline, DAY->endline, day); 00967 warns++; 00968 } 00969 else if ((s < 1) || (s > 31)) { 00970 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", 00971 DAY->filename, DAY->startline, DAY->endline, day); 00972 warns++; 00973 } 00974 s--; 00975 if (c) { 00976 if (sscanf(c, "%2d", &e) != 1) { 00977 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end day of month (%s) must be a number!\n", 00978 DAY->filename, DAY->startline, DAY->endline, c); 00979 warns++; 00980 } 00981 else if ((e < 1) || (e > 31)) { 00982 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", 00983 DAY->filename, DAY->startline, DAY->endline, day); 00984 warns++; 00985 } 00986 e--; 00987 } else 00988 e = s; 00989 }
static void check_dow | ( | pval * | DOW | ) | [static] |
get_dow: Get day of week
Definition at line 905 of file pval.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), pval::endline, pval::filename, LOG_WARNING, pval::startline, pval::str, and pval::u1.
Referenced by check_pval_item().
00906 { 00907 char *dow; 00908 char *c; 00909 /* The following line is coincidence, really! */ 00910 int s, e; 00911 00912 dow = ast_strdupa(DOW->u1.str); 00913 00914 /* Check for all days */ 00915 if (ast_strlen_zero(dow) || !strcmp(dow, "*")) 00916 return; 00917 /* Get start and ending days */ 00918 c = strchr(dow, '-'); 00919 if (c) { 00920 *c = '\0'; 00921 c++; 00922 } else 00923 c = NULL; 00924 /* Find the start */ 00925 s = 0; 00926 while ((s < 7) && strcasecmp(dow, days[s])) s++; 00927 if (s >= 7) { 00928 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", 00929 DOW->filename, DOW->startline, DOW->endline, dow); 00930 warns++; 00931 } 00932 if (c) { 00933 e = 0; 00934 while ((e < 7) && strcasecmp(c, days[e])) e++; 00935 if (e >= 7) { 00936 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", 00937 DOW->filename, DOW->startline, DOW->endline, c); 00938 warns++; 00939 } 00940 } else 00941 e = s; 00942 }
static void check_expr2_input | ( | pval * | expr, | |
char * | str | |||
) | [static] |
Definition at line 808 of file pval.c.
References ast_log(), pval::endline, pval::filename, LOG_WARNING, and pval::startline.
Referenced by check_pval_item().
static void check_goto | ( | pval * | item | ) | [static] |
Definition at line 1232 of file pval.c.
References ast_log(), E_FINDLABEL, E_MATCH, pval::endline, pval::filename, find_context(), find_label_in_current_context(), find_label_in_current_db(), find_label_in_current_extension(), first, get_contxt(), get_extension_or_contxt(), in_context(), in_macro(), pval::list, localized_pbx_load_module(), LOG_ERROR, LOG_WARNING, pval::next, pbx_find_extension(), PV_INCLUDES, pbx_find_info::stacklen, pval::startline, pval::statements, pbx_find_info::status, STATUS_SUCCESS, pval::str, pval::type, pval::u1, and pval::u2.
Referenced by check_pval_item(), and find_pval_goto_item().
01233 { 01234 if (!item->u1.list) { 01235 return; 01236 } 01237 01238 /* check for the target of the goto-- does it exist? */ 01239 if ( !(item->u1.list)->next && !(item->u1.list)->u1.str ) { 01240 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: empty label reference found!\n", 01241 item->filename, item->startline, item->endline); 01242 errs++; 01243 } 01244 01245 /* just one item-- the label should be in the current extension */ 01246 if (!item->u1.list->next && !strstr(item->u1.list->u1.str,"${")) { 01247 struct pval *z = get_extension_or_contxt(item); 01248 struct pval *x = 0; 01249 if (z) 01250 x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), z); /* if in macro, use current context instead */ 01251 /* printf("Called find_label_in_current_extension with arg %s; current_extension is %x: %d\n", 01252 (char*)((item->u1.list)->u1.str), current_extension?current_extension:current_context, current_extension?current_extension->type:current_context->type); */ 01253 if (!x) { 01254 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s exists in the current extension!\n", 01255 item->filename, item->startline, item->endline, item->u1.list->u1.str); 01256 errs++; 01257 } 01258 else 01259 return; 01260 } 01261 01262 /* TWO items */ 01263 if (item->u1.list->next && !item->u1.list->next->next) { 01264 /* two items */ 01265 /* printf("Calling find_label_in_current_context with args %s, %s\n", 01266 (char*)((item->u1.list)->u1.str), (char *)item->u1.list->next->u1.str); */ 01267 if (!strstr((item->u1.list)->u1.str,"${") 01268 && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ { 01269 struct pval *z = get_contxt(item); 01270 struct pval *x = 0; 01271 01272 if (z) 01273 x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, z); 01274 01275 if (!x) { 01276 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", 01277 item->filename, item->startline, item->endline, item->u1.list->u1.str, item->u1.list->next->u1.str ); 01278 errs++; 01279 } 01280 else 01281 return; 01282 } 01283 } 01284 01285 /* All 3 items! */ 01286 if (item->u1.list->next && item->u1.list->next->next) { 01287 /* all three */ 01288 pval *first = item->u1.list; 01289 pval *second = item->u1.list->next; 01290 pval *third = item->u1.list->next->next; 01291 01292 /* printf("Calling find_label_in_current_db with args %s, %s, %s\n", 01293 (char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); */ 01294 if (!strstr((item->u1.list)->u1.str,"${") 01295 && !strstr(item->u1.list->next->u1.str,"${") 01296 && !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ { 01297 struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); 01298 if (!x) { 01299 struct pval *p3; 01300 struct pval *found = 0; 01301 struct pval *that_context = find_context(item->u1.list->u1.str); 01302 01303 /* the target of the goto could be in an included context!! Fancy that!! */ 01304 /* look for includes in the current context */ 01305 if (that_context) { 01306 for (p3=that_context->u2.statements; p3; p3=p3->next) { 01307 if (p3->type == PV_INCLUDES) { 01308 struct pval *p4; 01309 for (p4=p3->u1.list; p4; p4=p4->next) { 01310 /* for each context pointed to, find it, then find a context/label that matches the 01311 target here! */ 01312 char *incl_context = p4->u1.str; 01313 /* find a matching context name */ 01314 struct pval *that_other_context = find_context(incl_context); 01315 if (that_other_context) { 01316 struct pval *x3; 01317 x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context); 01318 if (x3) { 01319 found = x3; 01320 break; 01321 } 01322 } 01323 } 01324 } 01325 } 01326 if (!found) { 01327 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s|%s exists in the context %s or its inclusions!\n", 01328 item->filename, item->startline, item->endline, item->u1.list->next->u1.str, item->u1.list->next->next->u1.str, item->u1.list->u1.str ); 01329 errs++; 01330 } else { 01331 struct pval *mac = in_macro(item); /* is this goto inside a macro? */ 01332 if( mac ) { /* yes! */ 01333 struct pval *targ = in_context(found); 01334 if( mac != targ ) 01335 { 01336 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", 01337 item->filename, item->startline, item->endline); 01338 warns++; 01339 } 01340 } 01341 } 01342 } else { 01343 /* here is where code would go to check for target existence in extensions.conf files */ 01344 #ifdef STANDALONE 01345 struct pbx_find_info pfiq = {.stacklen = 0 }; 01346 extern int localized_pbx_load_module(void); 01347 /* if this is a standalone, we will need to make sure the 01348 localized load of extensions.conf is done */ 01349 if (!extensions_dot_conf_loaded) { 01350 localized_pbx_load_module(); 01351 extensions_dot_conf_loaded++; 01352 } 01353 01354 pbx_find_extension(NULL, NULL, &pfiq, first->u1.str, second->u1.str, atoi(third->u1.str), 01355 atoi(third->u1.str) ? NULL : third->u1.str, NULL, 01356 atoi(third->u1.str) ? E_MATCH : E_FINDLABEL); 01357 01358 if (pfiq.status != STATUS_SUCCESS) { 01359 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", 01360 item->filename, item->startline, item->endline, first->u1.str, second->u1.str, third->u1.str); 01361 warns++; 01362 } 01363 #else 01364 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: goto: Couldn't find goto target %s|%s|%s in the AEL code!\n", 01365 item->filename, item->startline, item->endline, first->u1.str, second->u1.str, third->u1.str); 01366 warns++; 01367 #endif 01368 } 01369 } else { 01370 struct pval *mac = in_macro(item); /* is this goto inside a macro? */ 01371 if( mac ) { /* yes! */ 01372 struct pval *targ = in_context(x); 01373 if( mac != targ ) 01374 { 01375 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", 01376 item->filename, item->startline, item->endline); 01377 warns++; 01378 } 01379 } 01380 } 01381 } 01382 } 01383 }
static void check_includes | ( | pval * | includes | ) | [static] |
Definition at line 818 of file pval.c.
References ast_log(), pval::endline, pval::filename, find_context(), pval::list, LOG_WARNING, pval::next, pval::startline, pval::str, and pval::u1.
Referenced by check_pval_item().
00819 { 00820 struct pval *p4; 00821 for (p4=includes->u1.list; p4; p4=p4->next) { 00822 /* for each context pointed to, find it, then find a context/label that matches the 00823 target here! */ 00824 char *incl_context = p4->u1.str; 00825 /* find a matching context name */ 00826 struct pval *that_other_context = find_context(incl_context); 00827 if (!that_other_context && strcmp(incl_context, "parkedcalls") != 0) { 00828 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The included context '%s' cannot be found.\n\ 00829 (You may ignore this warning if '%s' exists in extensions.conf, or is created by another module. I cannot check for those.)\n", 00830 includes->filename, includes->startline, includes->endline, incl_context, incl_context); 00831 warns++; 00832 } 00833 } 00834 }
static void check_label | ( | pval * | item | ) | [static] |
Definition at line 1113 of file pval.c.
References ast_log(), pval::dad, pval::endline, pval::filename, find_first_label_in_current_context(), LOG_ERROR, PV_EXTENSION, PV_MACRO, pval::startline, pval::str, pval::type, and pval::u1.
Referenced by check_pval_item().
01114 { 01115 struct pval *curr; 01116 struct pval *x; 01117 int alright = 0; 01118 01119 /* A label outside an extension just plain does not make sense! */ 01120 01121 curr = item; 01122 01123 while( curr ) { 01124 if( curr->type == PV_MACRO || curr->type == PV_EXTENSION ) { 01125 alright = 1; 01126 break; 01127 } 01128 curr = curr->dad; 01129 } 01130 if( !alright ) 01131 { 01132 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: Label %s is not within an extension or macro!\n", 01133 item->filename, item->startline, item->endline, item->u1.str); 01134 errs++; 01135 } 01136 01137 01138 /* basically, ensure that a label is not repeated in a context. Period. 01139 The method: well, for each label, find the first label in the context 01140 with the same name. If it's not the current label, then throw an error. */ 01141 01142 01143 /* printf("==== check_label: ====\n"); */ 01144 if( !current_extension ) 01145 curr = current_context; 01146 else 01147 curr = current_extension; 01148 01149 x = find_first_label_in_current_context((char *)item->u1.str, curr); 01150 /* printf("Hey, check_label found with item = %x, and x is %x, and currcont is %x, label name is %s\n", item,x, current_context, (char *)item->u1.str); */ 01151 if( x && x != item ) 01152 { 01153 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: Duplicate label %s! Previously defined at file %s, line %d.\n", 01154 item->filename, item->startline, item->endline, item->u1.str, x->filename, x->startline); 01155 errs++; 01156 } 01157 /* printf("<<<<< check_label: ====\n"); */ 01158 }
static void check_macro_returns | ( | pval * | macro | ) | [static] |
Definition at line 652 of file pval.c.
References ast_log(), calloc, pval::endcol, pval::endline, pval::filename, LOG_WARNING, pval::macro_statements, pval::next, PV_RETURN, pval::startcol, pval::startline, pval::str, strdup, pval::type, pval::u1, and pval::u3.
Referenced by check_pval_item().
00653 { 00654 pval *i; 00655 if (!macro->u3.macro_statements) 00656 { 00657 pval *z = calloc(1, sizeof(struct pval)); 00658 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The macro %s is empty! I will insert a return.\n", 00659 macro->filename, macro->startline, macro->endline, macro->u1.str); 00660 00661 z->type = PV_RETURN; 00662 z->startline = macro->startline; 00663 z->endline = macro->endline; 00664 z->startcol = macro->startcol; 00665 z->endcol = macro->endcol; 00666 z->filename = strdup(macro->filename); 00667 00668 macro->u3.macro_statements = z; 00669 return; 00670 } 00671 for (i=macro->u3.macro_statements; i; i=i->next) { 00672 /* if the last statement in the list is not return, then insert a return there */ 00673 if (i->next == NULL) { 00674 if (i->type != PV_RETURN) { 00675 pval *z = calloc(1, sizeof(struct pval)); 00676 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The macro %s does not end with a return; I will insert one.\n", 00677 macro->filename, macro->startline, macro->endline, macro->u1.str); 00678 00679 z->type = PV_RETURN; 00680 z->startline = macro->startline; 00681 z->endline = macro->endline; 00682 z->startcol = macro->startcol; 00683 z->endcol = macro->endcol; 00684 z->filename = strdup(macro->filename); 00685 00686 i->next = z; 00687 return; 00688 } 00689 } 00690 } 00691 return; 00692 }
static void check_month | ( | pval * | MON | ) | [static] |
Definition at line 1007 of file pval.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), pval::endline, pval::filename, LOG_WARNING, pval::startline, pval::str, and pval::u1.
Referenced by check_pval_item().
01008 { 01009 char *mon; 01010 char *c; 01011 /* The following line is coincidence, really! */ 01012 int s, e; 01013 01014 mon = ast_strdupa(MON->u1.str); 01015 01016 /* Check for all days */ 01017 if (ast_strlen_zero(mon) || !strcmp(mon, "*")) 01018 return ; 01019 /* Get start and ending days */ 01020 c = strchr(mon, '-'); 01021 if (c) { 01022 *c = '\0'; 01023 c++; 01024 } 01025 /* Find the start */ 01026 s = 0; 01027 while ((s < 12) && strcasecmp(mon, months[s])) s++; 01028 if (s >= 12) { 01029 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n", 01030 MON->filename, MON->startline, MON->endline, mon); 01031 warns++; 01032 } 01033 if (c) { 01034 e = 0; 01035 while ((e < 12) && strcasecmp(mon, months[e])) e++; 01036 if (e >= 12) { 01037 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n", 01038 MON->filename, MON->startline, MON->endline, c); 01039 warns++; 01040 } 01041 } else 01042 e = s; 01043 }
Definition at line 2872 of file pval.c.
References check_pval_item(), and pval::next.
Referenced by ael2_semantic_check(), and check_pval_item().
02873 { 02874 pval *i; 02875 02876 /* checks to do: 02877 1. Do goto's point to actual labels? 02878 2. Do macro calls reference a macro? 02879 3. Does the number of macro args match the definition? 02880 4. Is a macro call missing its & at the front? 02881 5. Application calls-- we could check syntax for existing applications, 02882 but I need some some sort of universal description bnf for a general 02883 sort of method for checking arguments, in number, maybe even type, at least. 02884 Don't want to hand code checks for hundreds of applications. 02885 */ 02886 02887 for (i=item; i; i=i->next) { 02888 check_pval_item(i,apps,in_globals); 02889 } 02890 }
Definition at line 2364 of file pval.c.
References pval::abstract, pval::arglist, ast_expr(), ast_expr_clear_extra_error_info(), ast_expr_register_extra_error_info(), ast_log(), check_abstract_reference(), check_app_args(), check_break(), check_continue(), check_day(), check_dow(), check_expr2_input(), check_goto(), check_includes(), check_label(), check_macro_returns(), check_month(), check_pval(), check_switch_expr(), check_timerange(), E_MATCH, pval::else_statements, pval::endcol, pval::endline, pval::filename, find_context(), find_macro(), find_pval_gotos(), pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, free, pval::list, localized_pbx_load_module(), LOG_ERROR, LOG_WARNING, pval::macro_statements, argapp::next, pval::next, pbx_find_extension(), PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTEXT, PV_CONTINUE, PV_DEFAULT, PV_ESWITCHES, PV_EXTENSION, PV_FOR, PV_GLOBALS, PV_GOTO, PV_IF, PV_IFTIME, PV_IGNOREPAT, PV_INCLUDES, PV_LABEL, PV_LOCALVARDEC, PV_MACRO, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_SWITCHES, PV_VARDEC, PV_WHILE, PV_WORD, pbx_find_info::stacklen, pval::startcol, pval::startline, pval::statements, pbx_find_info::status, STATUS_SUCCESS, pval::str, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.
Referenced by check_pval().
02365 { 02366 pval *lp; 02367 #ifdef AAL_ARGCHECK 02368 struct argapp *app, *found; 02369 #endif 02370 struct pval *macro_def; 02371 struct pval *app_def; 02372 02373 char errmsg[4096]; 02374 char *strp; 02375 02376 switch (item->type) { 02377 case PV_WORD: 02378 /* fields: item->u1.str == string associated with this (word). 02379 item->u2.arglist == pval list of 4 PV_WORD elements for time values (only in PV_INCLUDES) */ 02380 break; 02381 02382 case PV_MACRO: 02383 /* fields: item->u1.str == name of macro 02384 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 02385 item->u2.arglist->u1.str == argument 02386 item->u2.arglist->next == next arg 02387 02388 item->u3.macro_statements == pval list of statements in macro body. 02389 */ 02390 in_abstract_context = 0; 02391 current_context = item; 02392 current_extension = 0; 02393 02394 check_macro_returns(item); 02395 02396 for (lp=item->u2.arglist; lp; lp=lp->next) { 02397 02398 } 02399 check_pval(item->u3.macro_statements, apps,in_globals); 02400 break; 02401 02402 case PV_CONTEXT: 02403 /* fields: item->u1.str == name of context 02404 item->u2.statements == pval list of statements in context body 02405 item->u3.abstract == int 1 if an abstract keyword were present 02406 */ 02407 current_context = item; 02408 current_extension = 0; 02409 if ( item->u3.abstract ) { 02410 in_abstract_context = 1; 02411 check_abstract_reference(item); 02412 } else 02413 in_abstract_context = 0; 02414 check_pval(item->u2.statements, apps,in_globals); 02415 break; 02416 02417 case PV_MACRO_CALL: 02418 /* fields: item->u1.str == name of macro to call 02419 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 02420 item->u2.arglist->u1.str == argument 02421 item->u2.arglist->next == next arg 02422 */ 02423 #ifdef STANDALONE 02424 /* if this is a standalone, we will need to make sure the 02425 localized load of extensions.conf is done */ 02426 if (!extensions_dot_conf_loaded) { 02427 localized_pbx_load_module(); 02428 extensions_dot_conf_loaded++; 02429 } 02430 #endif 02431 macro_def = find_macro(item->u1.str); 02432 if (!macro_def) { 02433 #ifdef STANDALONE 02434 struct pbx_find_info pfiq = {.stacklen = 0 }; 02435 struct pbx_find_info pfiq2 = {.stacklen = 0 }; 02436 02437 /* look for the macro in the extensions.conf world */ 02438 pbx_find_extension(NULL, NULL, &pfiq, item->u1.str, "s", 1, NULL, NULL, E_MATCH); 02439 02440 if (pfiq.status != STATUS_SUCCESS) { 02441 char namebuf2[256]; 02442 snprintf(namebuf2, 256, "macro-%s", item->u1.str); 02443 02444 /* look for the macro in the extensions.conf world */ 02445 pbx_find_extension(NULL, NULL, &pfiq2, namebuf2, "s", 1, NULL, NULL, E_MATCH); 02446 02447 if (pfiq2.status == STATUS_SUCCESS) { 02448 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", 02449 item->filename, item->startline, item->endline, item->u1.str, item->u1.str); 02450 warns++; 02451 } else { 02452 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to non-existent %s! (Not even in the extensions.conf stuff!)\n", 02453 item->filename, item->startline, item->endline, item->u1.str); 02454 warns++; 02455 } 02456 } 02457 #else 02458 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to %s cannot be found in the AEL code!\n", 02459 item->filename, item->startline, item->endline, item->u1.str); 02460 warns++; 02461 02462 #endif 02463 #ifdef THIS_IS_1DOT4 02464 char namebuf2[256]; 02465 snprintf(namebuf2, 256, "macro-%s", item->u1.str); 02466 02467 /* look for the macro in the extensions.conf world */ 02468 pbx_find_extension(NULL, NULL, &pfiq, namebuf2, "s", 1, NULL, NULL, E_MATCH); 02469 02470 if (pfiq.status != STATUS_SUCCESS) { 02471 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", 02472 item->filename, item->startline, item->endline, item->u1.str); 02473 warns++; 02474 } 02475 02476 #endif 02477 02478 } else if (macro_def->type != PV_MACRO) { 02479 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: macro call to %s references a context, not a macro!\n", 02480 item->filename, item->startline, item->endline, item->u1.str); 02481 errs++; 02482 } else { 02483 /* macro_def is a MACRO, so do the args match in number? */ 02484 int hereargs = 0; 02485 int thereargs = 0; 02486 02487 for (lp=item->u2.arglist; lp; lp=lp->next) { 02488 hereargs++; 02489 } 02490 for (lp=macro_def->u2.arglist; lp; lp=lp->next) { 02491 thereargs++; 02492 } 02493 if (hereargs != thereargs ) { 02494 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", 02495 item->filename, item->startline, item->endline, item->u1.str, hereargs, thereargs); 02496 errs++; 02497 } 02498 } 02499 break; 02500 02501 case PV_APPLICATION_CALL: 02502 /* fields: item->u1.str == name of application to call 02503 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 02504 item->u2.arglist->u1.str == argument 02505 item->u2.arglist->next == next arg 02506 */ 02507 /* Need to check to see if the application is available! */ 02508 app_def = find_context(item->u1.str); 02509 if (app_def && app_def->type == PV_MACRO) { 02510 ast_log(LOG_ERROR,"Error: file %s, line %d-%d: application call to %s references an existing macro, but had no & preceding it!\n", 02511 item->filename, item->startline, item->endline, item->u1.str); 02512 errs++; 02513 } 02514 if (strcasecmp(item->u1.str,"GotoIf") == 0 02515 || strcasecmp(item->u1.str,"GotoIfTime") == 0 02516 || strcasecmp(item->u1.str,"while") == 0 02517 || strcasecmp(item->u1.str,"endwhile") == 0 02518 || strcasecmp(item->u1.str,"random") == 0 02519 || strcasecmp(item->u1.str,"gosub") == 0 02520 || strcasecmp(item->u1.str,"gosubif") == 0 02521 || strcasecmp(item->u1.str,"continuewhile") == 0 02522 || strcasecmp(item->u1.str,"endwhile") == 0 02523 || strcasecmp(item->u1.str,"execif") == 0 02524 || strcasecmp(item->u1.str,"execiftime") == 0 02525 || strcasecmp(item->u1.str,"exitwhile") == 0 02526 || strcasecmp(item->u1.str,"goto") == 0 02527 || strcasecmp(item->u1.str,"macro") == 0 02528 || strcasecmp(item->u1.str,"macroexclusive") == 0 02529 || strcasecmp(item->u1.str,"macroif") == 0 02530 || strcasecmp(item->u1.str,"stackpop") == 0 02531 || strcasecmp(item->u1.str,"execIf") == 0 ) { 02532 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", 02533 item->filename, item->startline, item->endline, item->u1.str); 02534 warns++; 02535 } 02536 if (strcasecmp(item->u1.str,"macroexit") == 0) { 02537 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: I am converting the MacroExit call here to a return statement.\n", 02538 item->filename, item->startline, item->endline); 02539 item->type = PV_RETURN; 02540 free(item->u1.str); 02541 item->u1.str = 0; 02542 } 02543 02544 #ifdef AAL_ARGCHECK 02545 found = 0; 02546 for (app=apps; app; app=app->next) { 02547 if (strcasecmp(app->name, item->u1.str) == 0) { 02548 found =app; 02549 break; 02550 } 02551 } 02552 if (!found) { 02553 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: application call to %s not listed in applist database!\n", 02554 item->filename, item->startline, item->endline, item->u1.str); 02555 warns++; 02556 } else 02557 check_app_args(item, item->u2.arglist, app); 02558 #endif 02559 break; 02560 02561 case PV_CASE: 02562 /* fields: item->u1.str == value of case 02563 item->u2.statements == pval list of statements under the case 02564 */ 02565 /* Make sure sequence of statements under case is terminated with goto, return, or break */ 02566 /* find the last statement */ 02567 check_pval(item->u2.statements, apps,in_globals); 02568 break; 02569 02570 case PV_PATTERN: 02571 /* fields: item->u1.str == value of case 02572 item->u2.statements == pval list of statements under the case 02573 */ 02574 /* Make sure sequence of statements under case is terminated with goto, return, or break */ 02575 /* find the last statement */ 02576 02577 check_pval(item->u2.statements, apps,in_globals); 02578 break; 02579 02580 case PV_DEFAULT: 02581 /* fields: 02582 item->u2.statements == pval list of statements under the case 02583 */ 02584 02585 check_pval(item->u2.statements, apps,in_globals); 02586 break; 02587 02588 case PV_CATCH: 02589 /* fields: item->u1.str == name of extension to catch 02590 item->u2.statements == pval list of statements in context body 02591 */ 02592 check_pval(item->u2.statements, apps,in_globals); 02593 break; 02594 02595 case PV_SWITCHES: 02596 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02597 */ 02598 check_pval(item->u1.list, apps,in_globals); 02599 break; 02600 02601 case PV_ESWITCHES: 02602 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02603 */ 02604 check_pval(item->u1.list, apps,in_globals); 02605 break; 02606 02607 case PV_INCLUDES: 02608 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 02609 */ 02610 check_pval(item->u1.list, apps,in_globals); 02611 check_includes(item); 02612 for (lp=item->u1.list; lp; lp=lp->next){ 02613 char *incl_context = lp->u1.str; 02614 struct pval *that_context = find_context(incl_context); 02615 02616 if ( lp->u2.arglist ) { 02617 check_timerange(lp->u2.arglist); 02618 check_dow(lp->u2.arglist->next); 02619 check_day(lp->u2.arglist->next->next); 02620 check_month(lp->u2.arglist->next->next->next); 02621 } 02622 02623 if (that_context) { 02624 find_pval_gotos(that_context->u2.statements,0); 02625 02626 } 02627 } 02628 break; 02629 02630 case PV_STATEMENTBLOCK: 02631 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 02632 */ 02633 check_pval(item->u1.list, apps,in_globals); 02634 break; 02635 02636 case PV_VARDEC: 02637 /* fields: item->u1.str == variable name 02638 item->u2.val == variable value to assign 02639 */ 02640 /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */ 02641 if( !in_globals ) { /* don't check stuff inside the globals context; no wrapping in $[ ] there... */ 02642 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); 02643 ast_expr_register_extra_error_info(errmsg); 02644 ast_expr(item->u2.val, expr_output, sizeof(expr_output),NULL); 02645 ast_expr_clear_extra_error_info(); 02646 if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) { 02647 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02648 item->filename, item->startline, item->endline, item->u2.val); 02649 warns++; 02650 } 02651 check_expr2_input(item,item->u2.val); 02652 } 02653 break; 02654 02655 case PV_LOCALVARDEC: 02656 /* fields: item->u1.str == variable name 02657 item->u2.val == variable value to assign 02658 */ 02659 /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */ 02660 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); 02661 ast_expr_register_extra_error_info(errmsg); 02662 ast_expr(item->u2.val, expr_output, sizeof(expr_output),NULL); 02663 ast_expr_clear_extra_error_info(); 02664 if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) { 02665 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02666 item->filename, item->startline, item->endline, item->u2.val); 02667 warns++; 02668 } 02669 check_expr2_input(item,item->u2.val); 02670 break; 02671 02672 case PV_GOTO: 02673 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 02674 item->u1.list->u1.str == where the data on a PV_WORD will always be. 02675 */ 02676 /* don't check goto's in abstract contexts */ 02677 if ( in_abstract_context ) 02678 break; 02679 02680 check_goto(item); 02681 break; 02682 02683 case PV_LABEL: 02684 /* fields: item->u1.str == label name 02685 */ 02686 if ( strspn(item->u1.str, "0123456789") == strlen(item->u1.str) ) { 02687 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: label '%s' is numeric, this is bad practice!\n", 02688 item->filename, item->startline, item->endline, item->u1.str); 02689 warns++; 02690 } 02691 02692 check_label(item); 02693 break; 02694 02695 case PV_FOR: 02696 /* fields: item->u1.for_init == a string containing the initalizer 02697 item->u2.for_test == a string containing the loop test 02698 item->u3.for_inc == a string containing the loop increment 02699 02700 item->u4.for_statements == a pval list of statements in the for () 02701 */ 02702 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); 02703 ast_expr_register_extra_error_info(errmsg); 02704 02705 strp = strchr(item->u1.for_init, '='); 02706 if (strp) { 02707 ast_expr(strp+1, expr_output, sizeof(expr_output),NULL); 02708 } 02709 ast_expr(item->u2.for_test, expr_output, sizeof(expr_output),NULL); 02710 strp = strchr(item->u3.for_inc, '='); 02711 if (strp) { 02712 ast_expr(strp+1, expr_output, sizeof(expr_output),NULL); 02713 } 02714 if ( strpbrk(item->u2.for_test,"~!-+<>=*/&^") && !strstr(item->u2.for_test,"${") ) { 02715 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02716 item->filename, item->startline, item->endline, item->u2.for_test); 02717 warns++; 02718 } 02719 if ( strpbrk(item->u3.for_inc,"~!-+<>=*/&^") && !strstr(item->u3.for_inc,"${") ) { 02720 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02721 item->filename, item->startline, item->endline, item->u3.for_inc); 02722 warns++; 02723 } 02724 check_expr2_input(item,item->u2.for_test); 02725 check_expr2_input(item,item->u3.for_inc); 02726 02727 ast_expr_clear_extra_error_info(); 02728 check_pval(item->u4.for_statements, apps,in_globals); 02729 break; 02730 02731 case PV_WHILE: 02732 /* fields: item->u1.str == the while conditional, as supplied by user 02733 02734 item->u2.statements == a pval list of statements in the while () 02735 */ 02736 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); 02737 ast_expr_register_extra_error_info(errmsg); 02738 ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL); 02739 ast_expr_clear_extra_error_info(); 02740 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02741 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", 02742 item->filename, item->startline, item->endline, item->u1.str); 02743 warns++; 02744 } 02745 check_expr2_input(item,item->u1.str); 02746 check_pval(item->u2.statements, apps,in_globals); 02747 break; 02748 02749 case PV_BREAK: 02750 /* fields: none 02751 */ 02752 check_break(item); 02753 break; 02754 02755 case PV_RETURN: 02756 /* fields: none 02757 */ 02758 break; 02759 02760 case PV_CONTINUE: 02761 /* fields: none 02762 */ 02763 check_continue(item); 02764 break; 02765 02766 case PV_RANDOM: 02767 /* fields: item->u1.str == the random number expression, as supplied by user 02768 02769 item->u2.statements == a pval list of statements in the if () 02770 item->u3.else_statements == a pval list of statements in the else 02771 (could be zero) 02772 */ 02773 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); 02774 ast_expr_register_extra_error_info(errmsg); 02775 ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL); 02776 ast_expr_clear_extra_error_info(); 02777 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02778 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: random expression '%s' has operators, but no variables. Interesting...\n", 02779 item->filename, item->startline, item->endline, item->u1.str); 02780 warns++; 02781 } 02782 check_expr2_input(item,item->u1.str); 02783 check_pval(item->u2.statements, apps,in_globals); 02784 if (item->u3.else_statements) { 02785 check_pval(item->u3.else_statements, apps,in_globals); 02786 } 02787 break; 02788 02789 case PV_IFTIME: 02790 /* fields: item->u1.list == the if time values, 4 of them, each in PV_WORD, linked list 02791 02792 item->u2.statements == a pval list of statements in the if () 02793 item->u3.else_statements == a pval list of statements in the else 02794 (could be zero) 02795 */ 02796 if ( item->u2.arglist ) { 02797 check_timerange(item->u1.list); 02798 check_dow(item->u1.list->next); 02799 check_day(item->u1.list->next->next); 02800 check_month(item->u1.list->next->next->next); 02801 } 02802 02803 check_pval(item->u2.statements, apps,in_globals); 02804 if (item->u3.else_statements) { 02805 check_pval(item->u3.else_statements, apps,in_globals); 02806 } 02807 break; 02808 02809 case PV_IF: 02810 /* fields: item->u1.str == the if conditional, as supplied by user 02811 02812 item->u2.statements == a pval list of statements in the if () 02813 item->u3.else_statements == a pval list of statements in the else 02814 (could be zero) 02815 */ 02816 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); 02817 ast_expr_register_extra_error_info(errmsg); 02818 ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL); 02819 ast_expr_clear_extra_error_info(); 02820 if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { 02821 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression '%s' has operators, but no variables. Interesting...\n", 02822 item->filename, item->startline, item->endline, item->u1.str); 02823 warns++; 02824 } 02825 check_expr2_input(item,item->u1.str); 02826 check_pval(item->u2.statements, apps,in_globals); 02827 if (item->u3.else_statements) { 02828 check_pval(item->u3.else_statements, apps,in_globals); 02829 } 02830 break; 02831 02832 case PV_SWITCH: 02833 /* fields: item->u1.str == the switch expression 02834 02835 item->u2.statements == a pval list of statements in the switch, 02836 (will be case statements, most likely!) 02837 */ 02838 /* we can check the switch expression, see if it matches any of the app variables... 02839 if it does, then, are all the possible cases accounted for? */ 02840 check_switch_expr(item, apps); 02841 check_pval(item->u2.statements, apps,in_globals); 02842 break; 02843 02844 case PV_EXTENSION: 02845 /* fields: item->u1.str == the extension name, label, whatever it's called 02846 02847 item->u2.statements == a pval list of statements in the extension 02848 item->u3.hints == a char * hint argument 02849 item->u4.regexten == an int boolean. non-zero says that regexten was specified 02850 */ 02851 current_extension = item ; 02852 02853 check_pval(item->u2.statements, apps,in_globals); 02854 break; 02855 02856 case PV_IGNOREPAT: 02857 /* fields: item->u1.str == the ignorepat data 02858 */ 02859 break; 02860 02861 case PV_GLOBALS: 02862 /* fields: item->u1.statements == pval list of statements, usually vardecs 02863 */ 02864 in_abstract_context = 0; 02865 check_pval(item->u1.statements, apps, 1); 02866 break; 02867 default: 02868 break; 02869 } 02870 }
Definition at line 2191 of file pval.c.
References ast_log(), ast_strdupa, calloc, pval::endcol, pval::endline, pval::filename, LOG_WARNING, pval::next, argapp::next, PV_APPLICATION_CALL, PV_CASE, PV_DEFAULT, PV_PATTERN, PV_STATEMENTBLOCK, pval::startcol, pval::startline, pval::statements, pval::str, strdup, pval::type, pval::u1, and pval::u2.
Referenced by check_pval_item().
02192 { 02193 #ifdef AAL_ARGCHECK 02194 /* get and clean the variable name */ 02195 char *buff1, *p; 02196 struct argapp *a,*a2; 02197 struct appsetvar *v,*v2; 02198 struct argchoice *c; 02199 pval *t; 02200 02201 p = item->u1.str; 02202 while (p && *p && (*p == ' ' || *p == '\t' || *p == '$' || *p == '{' ) ) 02203 p++; 02204 02205 buff1 = ast_strdupa(p); 02206 02207 while (strlen(buff1) > 0 && ( buff1[strlen(buff1)-1] == '}' || buff1[strlen(buff1)-1] == ' ' || buff1[strlen(buff1)-1] == '\t')) 02208 buff1[strlen(buff1)-1] = 0; 02209 /* buff1 now contains the variable name */ 02210 v = 0; 02211 for (a=apps; a; a=a->next) { 02212 for (v=a->setvars;v;v=v->next) { 02213 if (strcmp(v->name,buff1) == 0) { 02214 break; 02215 } 02216 } 02217 if ( v ) 02218 break; 02219 } 02220 if (v && v->vals) { 02221 /* we have a match, to a variable that has a set of determined values */ 02222 int def= 0; 02223 int pat = 0; 02224 int f1 = 0; 02225 02226 /* first of all, does this switch have a default case ? */ 02227 for (t=item->u2.statements; t; t=t->next) { 02228 if (t->type == PV_DEFAULT) { 02229 def =1; 02230 break; 02231 } 02232 if (t->type == PV_PATTERN) { 02233 pat++; 02234 } 02235 } 02236 if (def || pat) /* nothing to check. All cases accounted for! */ 02237 return; 02238 for (c=v->vals; c; c=c->next) { 02239 f1 = 0; 02240 for (t=item->u2.statements; t; t=t->next) { 02241 if (t->type == PV_CASE || t->type == PV_PATTERN) { 02242 if (!strcmp(t->u1.str,c->name)) { 02243 f1 = 1; 02244 break; 02245 } 02246 } 02247 } 02248 if (!f1) { 02249 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: switch with expression(%s) does not handle the case of %s !\n", 02250 item->filename, item->startline, item->endline, item->u1.str, c->name); 02251 warns++; 02252 } 02253 } 02254 /* next, is there an app call in the current exten, that would set this var? */ 02255 f1 = 0; 02256 t = current_extension->u2.statements; 02257 if ( t && t->type == PV_STATEMENTBLOCK ) 02258 t = t->u1.statements; 02259 for (; t && t != item; t=t->next) { 02260 if (t->type == PV_APPLICATION_CALL) { 02261 /* find the application that matches the u1.str */ 02262 for (a2=apps; a2; a2=a2->next) { 02263 if (strcasecmp(a2->name, t->u1.str)==0) { 02264 for (v2=a2->setvars; v2; v2=v2->next) { 02265 if (strcmp(v2->name, buff1) == 0) { 02266 /* found an app that sets the var */ 02267 f1 = 1; 02268 break; 02269 } 02270 } 02271 } 02272 if (f1) 02273 break; 02274 } 02275 } 02276 if (f1) 02277 break; 02278 } 02279 02280 /* see if it sets the var */ 02281 if (!f1) { 02282 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", 02283 item->filename, item->startline, item->endline, item->u1.str); 02284 warns++; 02285 } 02286 } 02287 #else 02288 pval *t,*tl=0,*p2; 02289 int def= 0; 02290 02291 /* first of all, does this switch have a default case ? */ 02292 for (t=item->u2.statements; t; t=t->next) { 02293 if (t->type == PV_DEFAULT) { 02294 def =1; 02295 break; 02296 } 02297 tl = t; 02298 } 02299 if (def) /* nothing to check. All cases accounted for! */ 02300 return; 02301 /* if no default, warn and insert a default case at the end */ 02302 p2 = tl->next = calloc(1, sizeof(struct pval)); 02303 02304 p2->type = PV_DEFAULT; 02305 p2->startline = tl->startline; 02306 p2->endline = tl->endline; 02307 p2->startcol = tl->startcol; 02308 p2->endcol = tl->endcol; 02309 p2->filename = strdup(tl->filename); 02310 ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: A default case was automatically added to the switch.\n", 02311 p2->filename, p2->startline, p2->endline); 02312 warns++; 02313 02314 #endif 02315 }
static void check_timerange | ( | pval * | p | ) | [static] |
Definition at line 837 of file pval.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), pval::endline, pval::filename, LOG_WARNING, pval::startline, pval::str, and pval::u1.
Referenced by check_pval_item().
00838 { 00839 char *times; 00840 char *e; 00841 int s1, s2; 00842 int e1, e2; 00843 00844 times = ast_strdupa(p->u1.str); 00845 00846 /* Star is all times */ 00847 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 00848 return; 00849 } 00850 /* Otherwise expect a range */ 00851 e = strchr(times, '-'); 00852 if (!e) { 00853 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", 00854 p->filename, p->startline, p->endline, times); 00855 warns++; 00856 return; 00857 } 00858 *e = '\0'; 00859 e++; 00860 while (*e && !isdigit(*e)) 00861 e++; 00862 if (!*e) { 00863 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The time range format (%s) is missing the end time!\n", 00864 p->filename, p->startline, p->endline, p->u1.str); 00865 warns++; 00866 } 00867 if (sscanf(times, "%2d:%2d", &s1, &s2) != 2) { 00868 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) isn't quite right!\n", 00869 p->filename, p->startline, p->endline, times); 00870 warns++; 00871 } 00872 if (sscanf(e, "%2d:%2d", &e1, &e2) != 2) { 00873 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) isn't quite right!\n", 00874 p->filename, p->startline, p->endline, times); 00875 warns++; 00876 } 00877 00878 s1 = s1 * 30 + s2/2; 00879 if ((s1 < 0) || (s1 >= 24*30)) { 00880 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) is out of range!\n", 00881 p->filename, p->startline, p->endline, times); 00882 warns++; 00883 } 00884 e1 = e1 * 30 + e2/2; 00885 if ((e1 < 0) || (e1 >= 24*30)) { 00886 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) is out of range!\n", 00887 p->filename, p->startline, p->endline, e); 00888 warns++; 00889 } 00890 return; 00891 }
int contains_switch | ( | pval * | item | ) |
Definition at line 3336 of file pval.c.
References find_switch_item(), and pval::next.
Referenced by find_switch_item(), and gen_prios().
03337 { 03338 pval *i; 03339 03340 for (i=item; i; i=i->next) { 03341 if (find_switch_item(i)) 03342 return 1; 03343 } 03344 return 0; 03345 }
static int context_used | ( | struct ael_extension * | exten_list, | |
struct ast_context * | context | |||
) | [static] |
Definition at line 4436 of file pval.c.
References ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ael_extension::context, exten, and ael_extension::next_exten.
Referenced by ast_compile_ael2().
04437 { 04438 struct ael_extension *exten; 04439 /* Check the simple elements first */ 04440 if (ast_walk_context_extensions(context, NULL) || ast_walk_context_includes(context, NULL) || ast_walk_context_ignorepats(context, NULL) || ast_walk_context_switches(context, NULL)) { 04441 return 1; 04442 } 04443 for (exten = exten_list; exten; exten = exten->next_exten) { 04444 if (exten->context == context) { 04445 return 1; 04446 } 04447 } 04448 return 0; 04449 }
void destroy_extensions | ( | struct ael_extension * | exten | ) |
Definition at line 2985 of file pval.c.
References ael_priority::app, ael_priority::appargs, free, ael_priority::goto_false, ael_priority::goto_true, ael_extension::hints, ael_extension::loop_break, ael_extension::loop_continue, ael_extension::name, ael_priority::next, ael_extension::next_exten, ael_priority::origin, ael_extension::plist, and ael_extension::plist_last.
Referenced by ast_compile_ael2().
02986 { 02987 struct ael_extension *ne, *nen; 02988 for (ne=exten; ne; ne=nen) { 02989 struct ael_priority *pe, *pen; 02990 02991 if (ne->name) 02992 free(ne->name); 02993 02994 /* cidmatch fields are allocated with name, and freed when 02995 the name field is freed. Don't do a free for this field, 02996 unless you LIKE to see a crash! */ 02997 02998 if (ne->hints) 02999 free(ne->hints); 03000 03001 for (pe=ne->plist; pe; pe=pen) { 03002 pen = pe->next; 03003 if (pe->app) 03004 free(pe->app); 03005 pe->app = 0; 03006 if (pe->appargs) 03007 free(pe->appargs); 03008 pe->appargs = 0; 03009 pe->origin = 0; 03010 pe->goto_true = 0; 03011 pe->goto_false = 0; 03012 free(pe); 03013 } 03014 nen = ne->next_exten; 03015 ne->next_exten = 0; 03016 ne->plist =0; 03017 ne->plist_last = 0; 03018 ne->next_exten = 0; 03019 ne->loop_break = 0; 03020 ne->loop_continue = 0; 03021 free(ne); 03022 } 03023 }
void destroy_pval | ( | pval * | item | ) |
Definition at line 4979 of file pval.c.
References destroy_pval_item(), and pval::next.
Referenced by destroy_pval_item(), pbx_load_module(), yydestruct(), and yyparse().
04980 { 04981 pval *i,*nxt; 04982 04983 for (i=item; i; i=nxt) { 04984 nxt = i->next; 04985 04986 destroy_pval_item(i); 04987 } 04988 }
void destroy_pval_item | ( | pval * | item | ) |
Definition at line 4711 of file pval.c.
References pval::arglist, ast_log(), destroy_pval(), pval::else_statements, pval::filename, pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, free, pval::hints, pval::list, LOG_WARNING, pval::macro_statements, PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTEXT, PV_CONTINUE, PV_DEFAULT, PV_ESWITCHES, PV_EXTENSION, PV_FOR, PV_GLOBALS, PV_GOTO, PV_IF, PV_IFTIME, PV_IGNOREPAT, PV_INCLUDES, PV_LABEL, PV_LOCALVARDEC, PV_MACRO, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_SWITCHES, PV_VARDEC, PV_WHILE, PV_WORD, pval::statements, pval::str, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.
Referenced by destroy_pval().
04712 { 04713 if (item == NULL) { 04714 ast_log(LOG_WARNING, "null item\n"); 04715 return; 04716 } 04717 04718 if (item->filename) 04719 free(item->filename); 04720 04721 switch (item->type) { 04722 case PV_WORD: 04723 /* fields: item->u1.str == string associated with this (word). */ 04724 if (item->u1.str ) 04725 free(item->u1.str); 04726 if ( item->u2.arglist ) 04727 destroy_pval(item->u2.arglist); 04728 break; 04729 04730 case PV_MACRO: 04731 /* fields: item->u1.str == name of macro 04732 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 04733 item->u2.arglist->u1.str == argument 04734 item->u2.arglist->next == next arg 04735 04736 item->u3.macro_statements == pval list of statements in macro body. 04737 */ 04738 destroy_pval(item->u2.arglist); 04739 if (item->u1.str ) 04740 free(item->u1.str); 04741 destroy_pval(item->u3.macro_statements); 04742 break; 04743 04744 case PV_CONTEXT: 04745 /* fields: item->u1.str == name of context 04746 item->u2.statements == pval list of statements in context body 04747 item->u3.abstract == int 1 if an abstract keyword were present 04748 */ 04749 if (item->u1.str) 04750 free(item->u1.str); 04751 destroy_pval(item->u2.statements); 04752 break; 04753 04754 case PV_MACRO_CALL: 04755 /* fields: item->u1.str == name of macro to call 04756 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 04757 item->u2.arglist->u1.str == argument 04758 item->u2.arglist->next == next arg 04759 */ 04760 if (item->u1.str) 04761 free(item->u1.str); 04762 destroy_pval(item->u2.arglist); 04763 break; 04764 04765 case PV_APPLICATION_CALL: 04766 /* fields: item->u1.str == name of application to call 04767 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 04768 item->u2.arglist->u1.str == argument 04769 item->u2.arglist->next == next arg 04770 */ 04771 if (item->u1.str) 04772 free(item->u1.str); 04773 destroy_pval(item->u2.arglist); 04774 break; 04775 04776 case PV_CASE: 04777 /* fields: item->u1.str == value of case 04778 item->u2.statements == pval list of statements under the case 04779 */ 04780 if (item->u1.str) 04781 free(item->u1.str); 04782 destroy_pval(item->u2.statements); 04783 break; 04784 04785 case PV_PATTERN: 04786 /* fields: item->u1.str == value of case 04787 item->u2.statements == pval list of statements under the case 04788 */ 04789 if (item->u1.str) 04790 free(item->u1.str); 04791 destroy_pval(item->u2.statements); 04792 break; 04793 04794 case PV_DEFAULT: 04795 /* fields: 04796 item->u2.statements == pval list of statements under the case 04797 */ 04798 destroy_pval(item->u2.statements); 04799 break; 04800 04801 case PV_CATCH: 04802 /* fields: item->u1.str == name of extension to catch 04803 item->u2.statements == pval list of statements in context body 04804 */ 04805 if (item->u1.str) 04806 free(item->u1.str); 04807 destroy_pval(item->u2.statements); 04808 break; 04809 04810 case PV_SWITCHES: 04811 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04812 */ 04813 destroy_pval(item->u1.list); 04814 break; 04815 04816 case PV_ESWITCHES: 04817 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04818 */ 04819 destroy_pval(item->u1.list); 04820 break; 04821 04822 case PV_INCLUDES: 04823 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 04824 item->u2.arglist == pval list of 4 PV_WORD elements for time values 04825 */ 04826 destroy_pval(item->u1.list); 04827 break; 04828 04829 case PV_STATEMENTBLOCK: 04830 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 04831 */ 04832 destroy_pval(item->u1.list); 04833 break; 04834 04835 case PV_LOCALVARDEC: 04836 case PV_VARDEC: 04837 /* fields: item->u1.str == variable name 04838 item->u2.val == variable value to assign 04839 */ 04840 if (item->u1.str) 04841 free(item->u1.str); 04842 if (item->u2.val) 04843 free(item->u2.val); 04844 break; 04845 04846 case PV_GOTO: 04847 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 04848 item->u1.list->u1.str == where the data on a PV_WORD will always be. 04849 */ 04850 04851 destroy_pval(item->u1.list); 04852 break; 04853 04854 case PV_LABEL: 04855 /* fields: item->u1.str == label name 04856 */ 04857 if (item->u1.str) 04858 free(item->u1.str); 04859 break; 04860 04861 case PV_FOR: 04862 /* fields: item->u1.for_init == a string containing the initalizer 04863 item->u2.for_test == a string containing the loop test 04864 item->u3.for_inc == a string containing the loop increment 04865 04866 item->u4.for_statements == a pval list of statements in the for () 04867 */ 04868 if (item->u1.for_init) 04869 free(item->u1.for_init); 04870 if (item->u2.for_test) 04871 free(item->u2.for_test); 04872 if (item->u3.for_inc) 04873 free(item->u3.for_inc); 04874 destroy_pval(item->u4.for_statements); 04875 break; 04876 04877 case PV_WHILE: 04878 /* fields: item->u1.str == the while conditional, as supplied by user 04879 04880 item->u2.statements == a pval list of statements in the while () 04881 */ 04882 if (item->u1.str) 04883 free(item->u1.str); 04884 destroy_pval(item->u2.statements); 04885 break; 04886 04887 case PV_BREAK: 04888 /* fields: none 04889 */ 04890 break; 04891 04892 case PV_RETURN: 04893 /* fields: none 04894 */ 04895 break; 04896 04897 case PV_CONTINUE: 04898 /* fields: none 04899 */ 04900 break; 04901 04902 case PV_IFTIME: 04903 /* fields: item->u1.list == the 4 time values, in PV_WORD structs, linked list 04904 04905 item->u2.statements == a pval list of statements in the if () 04906 item->u3.else_statements == a pval list of statements in the else 04907 (could be zero) 04908 */ 04909 destroy_pval(item->u1.list); 04910 destroy_pval(item->u2.statements); 04911 if (item->u3.else_statements) { 04912 destroy_pval(item->u3.else_statements); 04913 } 04914 break; 04915 04916 case PV_RANDOM: 04917 /* fields: item->u1.str == the random percentage, as supplied by user 04918 04919 item->u2.statements == a pval list of statements in the true part () 04920 item->u3.else_statements == a pval list of statements in the else 04921 (could be zero) 04922 fall thru to If */ 04923 case PV_IF: 04924 /* fields: item->u1.str == the if conditional, as supplied by user 04925 04926 item->u2.statements == a pval list of statements in the if () 04927 item->u3.else_statements == a pval list of statements in the else 04928 (could be zero) 04929 */ 04930 if (item->u1.str) 04931 free(item->u1.str); 04932 destroy_pval(item->u2.statements); 04933 if (item->u3.else_statements) { 04934 destroy_pval(item->u3.else_statements); 04935 } 04936 break; 04937 04938 case PV_SWITCH: 04939 /* fields: item->u1.str == the switch expression 04940 04941 item->u2.statements == a pval list of statements in the switch, 04942 (will be case statements, most likely!) 04943 */ 04944 if (item->u1.str) 04945 free(item->u1.str); 04946 destroy_pval(item->u2.statements); 04947 break; 04948 04949 case PV_EXTENSION: 04950 /* fields: item->u1.str == the extension name, label, whatever it's called 04951 04952 item->u2.statements == a pval list of statements in the extension 04953 item->u3.hints == a char * hint argument 04954 item->u4.regexten == an int boolean. non-zero says that regexten was specified 04955 */ 04956 if (item->u1.str) 04957 free(item->u1.str); 04958 if (item->u3.hints) 04959 free(item->u3.hints); 04960 destroy_pval(item->u2.statements); 04961 break; 04962 04963 case PV_IGNOREPAT: 04964 /* fields: item->u1.str == the ignorepat data 04965 */ 04966 if (item->u1.str) 04967 free(item->u1.str); 04968 break; 04969 04970 case PV_GLOBALS: 04971 /* fields: item->u1.statements == pval list of statements, usually vardecs 04972 */ 04973 destroy_pval(item->u1.statements); 04974 break; 04975 } 04976 free(item); 04977 }
static int extension_matches | ( | pval * | here, | |
const char * | exten, | |||
const char * | pattern | |||
) | [static] |
Definition at line 696 of file pval.c.
References ast_log(), pval::endline, pval::filename, LOG_ERROR, LOG_WARNING, and pval::startline.
Referenced by match_pval_item().
00697 { 00698 int err1; 00699 regex_t preg; 00700 00701 /* simple case, they match exactly, the pattern and exten name */ 00702 if (strcmp(pattern,exten) == 0) 00703 return 1; 00704 00705 if (pattern[0] == '_') { 00706 char reg1[2000]; 00707 const char *p; 00708 char *r = reg1; 00709 00710 if ( strlen(pattern)*5 >= 2000 ) /* safety valve */ { 00711 ast_log(LOG_ERROR,"Error: The pattern %s is way too big. Pattern matching cancelled.\n", 00712 pattern); 00713 return 0; 00714 } 00715 /* form a regular expression from the pattern, and then match it against exten */ 00716 *r++ = '^'; /* what if the extension is a pattern ?? */ 00717 *r++ = '_'; /* what if the extension is a pattern ?? */ 00718 *r++ = '?'; 00719 for (p=pattern+1; *p; p++) { 00720 switch ( *p ) { 00721 case 'X': 00722 *r++ = '['; 00723 *r++ = '0'; 00724 *r++ = '-'; 00725 *r++ = '9'; 00726 *r++ = 'X'; 00727 *r++ = ']'; 00728 break; 00729 00730 case 'Z': 00731 *r++ = '['; 00732 *r++ = '1'; 00733 *r++ = '-'; 00734 *r++ = '9'; 00735 *r++ = 'Z'; 00736 *r++ = ']'; 00737 break; 00738 00739 case 'N': 00740 *r++ = '['; 00741 *r++ = '2'; 00742 *r++ = '-'; 00743 *r++ = '9'; 00744 *r++ = 'N'; 00745 *r++ = ']'; 00746 break; 00747 00748 case '[': 00749 while ( *p && *p != ']' ) { 00750 *r++ = *p++; 00751 } 00752 *r++ = ']'; 00753 if ( *p != ']') { 00754 ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The extension pattern '%s' is missing a closing bracket \n", 00755 here->filename, here->startline, here->endline, pattern); 00756 } 00757 break; 00758 00759 case '.': 00760 case '!': 00761 *r++ = '.'; 00762 *r++ = '*'; 00763 break; 00764 case '*': 00765 *r++ = '\\'; 00766 *r++ = '*'; 00767 break; 00768 default: 00769 *r++ = *p; 00770 break; 00771 00772 } 00773 } 00774 *r++ = '$'; /* what if the extension is a pattern ?? */ 00775 *r++ = *p++; /* put in the closing null */ 00776 err1 = regcomp(&preg, reg1, REG_NOSUB|REG_EXTENDED); 00777 if ( err1 ) { 00778 char errmess[500]; 00779 regerror(err1,&preg,errmess,sizeof(errmess)); 00780 regfree(&preg); 00781 ast_log(LOG_WARNING, "Regcomp of %s failed, error code %d\n", 00782 reg1, err1); 00783 return 0; 00784 } 00785 err1 = regexec(&preg, exten, 0, 0, 0); 00786 regfree(&preg); 00787 00788 if ( err1 ) { 00789 /* ast_log(LOG_NOTICE,"*****************************[%d]Extension %s did not match %s(%s)\n", 00790 err1,exten, pattern, reg1); */ 00791 return 0; /* no match */ 00792 } else { 00793 /* ast_log(LOG_NOTICE,"*****************************Extension %s matched %s\n", 00794 exten, pattern); */ 00795 return 1; 00796 } 00797 00798 00799 } else { 00800 if ( strcmp(exten,pattern) == 0 ) { 00801 return 1; 00802 } else 00803 return 0; 00804 } 00805 }
struct pval* find_context | ( | char * | name | ) | [read] |
Definition at line 1960 of file pval.c.
References match_pval().
Referenced by ast_add_extension_nolock(), check_goto(), check_includes(), check_pval_item(), find_first_label_in_current_context(), find_label_in_current_context(), find_pval_goto_item(), get_goto_target(), and pbx_find_extension().
01961 { 01962 return_on_context_match = 1; 01963 count_labels = 0; 01964 match_context = name; 01965 match_exten = "*"; /* don't really need to set these, shouldn't be reached */ 01966 match_label = "*"; 01967 return match_pval(current_db); 01968 }
Definition at line 1846 of file pval.c.
References find_context(), pval::list, match_pval(), pval::next, PV_INCLUDES, pval::statements, pval::str, pval::type, pval::u1, and pval::u2.
Referenced by check_label().
01847 { 01848 /* printf(" --- Got args %s, %s\n", exten, label); */ 01849 struct pval *ret; 01850 struct pval *p3; 01851 01852 count_labels = 0; 01853 return_on_context_match = 0; 01854 match_context = "*"; 01855 match_exten = "*"; 01856 match_label = label; 01857 01858 ret = match_pval(curr_cont); 01859 if (ret) 01860 return ret; 01861 01862 /* the target of the goto could be in an included context!! Fancy that!! */ 01863 /* look for includes in the current context */ 01864 for (p3=curr_cont->u2.statements; p3; p3=p3->next) { 01865 if (p3->type == PV_INCLUDES) { 01866 struct pval *p4; 01867 for (p4=p3->u1.list; p4; p4=p4->next) { 01868 /* for each context pointed to, find it, then find a context/label that matches the 01869 target here! */ 01870 char *incl_context = p4->u1.str; 01871 /* find a matching context name */ 01872 struct pval *that_context = find_context(incl_context); 01873 if (that_context) { 01874 struct pval *x3; 01875 x3 = find_first_label_in_current_context(label, that_context); 01876 if (x3) { 01877 return x3; 01878 } 01879 } 01880 } 01881 } 01882 } 01883 return 0; 01884 }
struct pval * find_label_in_current_context | ( | char * | exten, | |
char * | label, | |||
pval * | curr_cont | |||
) | [static, read] |
Definition at line 1886 of file pval.c.
References find_context(), pval::list, match_pval(), pval::next, PV_INCLUDES, pval::statements, pval::str, pval::type, pval::u1, and pval::u2.
Referenced by check_goto(), and get_goto_target().
01887 { 01888 /* printf(" --- Got args %s, %s\n", exten, label); */ 01889 struct pval *ret; 01890 struct pval *p3; 01891 01892 count_labels = 0; 01893 return_on_context_match = 0; 01894 match_context = "*"; 01895 match_exten = exten; 01896 match_label = label; 01897 ret = match_pval(curr_cont->u2.statements); 01898 if (ret) 01899 return ret; 01900 01901 /* the target of the goto could be in an included context!! Fancy that!! */ 01902 /* look for includes in the current context */ 01903 for (p3=curr_cont->u2.statements; p3; p3=p3->next) { 01904 if (p3->type == PV_INCLUDES) { 01905 struct pval *p4; 01906 for (p4=p3->u1.list; p4; p4=p4->next) { 01907 /* for each context pointed to, find it, then find a context/label that matches the 01908 target here! */ 01909 char *incl_context = p4->u1.str; 01910 /* find a matching context name */ 01911 struct pval *that_context = find_context(incl_context); 01912 if (that_context) { 01913 struct pval *x3; 01914 x3 = find_label_in_current_context(exten, label, that_context); 01915 if (x3) { 01916 return x3; 01917 } 01918 } 01919 } 01920 } 01921 } 01922 return 0; 01923 }
static struct pval * find_label_in_current_db | ( | const char * | context, | |
const char * | exten, | |||
const char * | label | |||
) | [static, read] |
Definition at line 1936 of file pval.c.
References match_pval().
Referenced by check_goto(), and get_goto_target().
01937 { 01938 /* printf(" --- Got args %s, %s, %s\n", context, exten, label); */ 01939 count_labels = 0; 01940 return_on_context_match = 0; 01941 01942 match_context = context; 01943 match_exten = exten; 01944 match_label = label; 01945 01946 return match_pval(current_db); 01947 }
static struct pval * find_label_in_current_extension | ( | const char * | label, | |
pval * | curr_ext | |||
) | [static, read] |
Definition at line 1925 of file pval.c.
References match_pval().
Referenced by check_goto(), and get_goto_target().
01926 { 01927 /* printf(" --- Got args %s\n", label); */ 01928 count_labels = 0; 01929 return_on_context_match = 0; 01930 match_context = "*"; 01931 match_exten = "*"; 01932 match_label = label; 01933 return match_pval(curr_ext); 01934 }
struct pval* find_macro | ( | char * | name | ) | [read] |
Definition at line 1950 of file pval.c.
References match_pval().
Referenced by check_pval_item().
01951 { 01952 return_on_context_match = 1; 01953 count_labels = 0; 01954 match_context = name; 01955 match_exten = "*"; /* don't really need to set these, shouldn't be reached */ 01956 match_label = "*"; 01957 return match_pval(current_db); 01958 }
static void find_pval_goto_item | ( | pval * | item, | |
int | lev | |||
) | [static] |
Definition at line 1386 of file pval.c.
References ast_log(), check_goto(), pval::else_statements, find_context(), find_pval_gotos(), pval::for_statements, pval::list, LOG_ERROR, pval::macro_statements, pval::next, PV_CASE, PV_CATCH, PV_CONTEXT, PV_DEFAULT, PV_EXTENSION, PV_FOR, PV_GOTO, PV_IF, PV_IFTIME, PV_INCLUDES, PV_MACRO, PV_PATTERN, PV_RANDOM, PV_STATEMENTBLOCK, PV_SWITCH, PV_WHILE, pval::statements, pval::str, pval::type, pval::u1, pval::u2, pval::u3, and pval::u4.
Referenced by find_pval_gotos().
01387 { 01388 struct pval *p4; 01389 01390 if (lev>100) { 01391 ast_log(LOG_ERROR,"find_pval_goto in infinite loop! item_type: %u\n\n", item->type); 01392 return; 01393 } 01394 01395 switch ( item->type ) { 01396 case PV_MACRO: 01397 /* fields: item->u1.str == name of macro 01398 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 01399 item->u2.arglist->u1.str == argument 01400 item->u2.arglist->next == next arg 01401 01402 item->u3.macro_statements == pval list of statements in macro body. 01403 */ 01404 01405 /* printf("Descending into macro %s at line %d\n", item->u1.str, item->startline); */ 01406 find_pval_gotos(item->u3.macro_statements,lev+1); /* if we're just searching for a context, don't bother descending into them */ 01407 01408 break; 01409 01410 case PV_CONTEXT: 01411 /* fields: item->u1.str == name of context 01412 item->u2.statements == pval list of statements in context body 01413 item->u3.abstract == int 1 if an abstract keyword were present 01414 */ 01415 break; 01416 01417 case PV_CASE: 01418 /* fields: item->u1.str == value of case 01419 item->u2.statements == pval list of statements under the case 01420 */ 01421 /* printf("Descending into Case of %s\n", item->u1.str); */ 01422 find_pval_gotos(item->u2.statements,lev+1); 01423 break; 01424 01425 case PV_PATTERN: 01426 /* fields: item->u1.str == value of case 01427 item->u2.statements == pval list of statements under the case 01428 */ 01429 /* printf("Descending into Pattern of %s\n", item->u1.str); */ 01430 find_pval_gotos(item->u2.statements,lev+1); 01431 break; 01432 01433 case PV_DEFAULT: 01434 /* fields: 01435 item->u2.statements == pval list of statements under the case 01436 */ 01437 /* printf("Descending into default\n"); */ 01438 find_pval_gotos(item->u2.statements,lev+1); 01439 break; 01440 01441 case PV_CATCH: 01442 /* fields: item->u1.str == name of extension to catch 01443 item->u2.statements == pval list of statements in context body 01444 */ 01445 /* printf("Descending into catch of %s\n", item->u1.str); */ 01446 find_pval_gotos(item->u2.statements,lev+1); 01447 break; 01448 01449 case PV_STATEMENTBLOCK: 01450 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 01451 */ 01452 /* printf("Descending into statement block\n"); */ 01453 find_pval_gotos(item->u1.list,lev+1); 01454 break; 01455 01456 case PV_GOTO: 01457 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 01458 item->u1.list->u1.str == where the data on a PV_WORD will always be. 01459 */ 01460 check_goto(item); /* THE WHOLE FUNCTION OF THIS ENTIRE ROUTINE!!!! */ 01461 break; 01462 01463 case PV_INCLUDES: 01464 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 01465 */ 01466 for (p4=item->u1.list; p4; p4=p4->next) { 01467 /* for each context pointed to, find it, then find a context/label that matches the 01468 target here! */ 01469 char *incl_context = p4->u1.str; 01470 /* find a matching context name */ 01471 struct pval *that_context = find_context(incl_context); 01472 if (that_context && that_context->u2.statements) { 01473 /* printf("Descending into include of '%s' at line %d; that_context=%s, that_context type=%d\n", incl_context, item->startline, that_context->u1.str, that_context->type); */ 01474 find_pval_gotos(that_context->u2.statements,lev+1); /* keep working up the includes */ 01475 } 01476 } 01477 break; 01478 01479 case PV_FOR: 01480 /* fields: item->u1.for_init == a string containing the initalizer 01481 item->u2.for_test == a string containing the loop test 01482 item->u3.for_inc == a string containing the loop increment 01483 01484 item->u4.for_statements == a pval list of statements in the for () 01485 */ 01486 /* printf("Descending into for at line %d\n", item->startline); */ 01487 find_pval_gotos(item->u4.for_statements,lev+1); 01488 break; 01489 01490 case PV_WHILE: 01491 /* fields: item->u1.str == the while conditional, as supplied by user 01492 01493 item->u2.statements == a pval list of statements in the while () 01494 */ 01495 /* printf("Descending into while at line %d\n", item->startline); */ 01496 find_pval_gotos(item->u2.statements,lev+1); 01497 break; 01498 01499 case PV_RANDOM: 01500 /* fields: item->u1.str == the random number expression, as supplied by user 01501 01502 item->u2.statements == a pval list of statements in the if () 01503 item->u3.else_statements == a pval list of statements in the else 01504 (could be zero) 01505 fall thru to PV_IF */ 01506 01507 case PV_IFTIME: 01508 /* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list 01509 01510 item->u2.statements == a pval list of statements in the if () 01511 item->u3.else_statements == a pval list of statements in the else 01512 (could be zero) 01513 fall thru to PV_IF*/ 01514 case PV_IF: 01515 /* fields: item->u1.str == the if conditional, as supplied by user 01516 01517 item->u2.statements == a pval list of statements in the if () 01518 item->u3.else_statements == a pval list of statements in the else 01519 (could be zero) 01520 */ 01521 /* printf("Descending into random/iftime/if at line %d\n", item->startline); */ 01522 find_pval_gotos(item->u2.statements,lev+1); 01523 01524 if (item->u3.else_statements) { 01525 /* printf("Descending into random/iftime/if's ELSE at line %d\n", item->startline); */ 01526 find_pval_gotos(item->u3.else_statements,lev+1); 01527 } 01528 break; 01529 01530 case PV_SWITCH: 01531 /* fields: item->u1.str == the switch expression 01532 01533 item->u2.statements == a pval list of statements in the switch, 01534 (will be case statements, most likely!) 01535 */ 01536 /* printf("Descending into switch at line %d\n", item->startline); */ 01537 find_pval_gotos(item->u3.else_statements,lev+1); 01538 break; 01539 01540 case PV_EXTENSION: 01541 /* fields: item->u1.str == the extension name, label, whatever it's called 01542 01543 item->u2.statements == a pval list of statements in the extension 01544 item->u3.hints == a char * hint argument 01545 item->u4.regexten == an int boolean. non-zero says that regexten was specified 01546 */ 01547 01548 /* printf("Descending into extension %s at line %d\n", item->u1.str, item->startline); */ 01549 find_pval_gotos(item->u2.statements,lev+1); 01550 break; 01551 01552 default: 01553 break; 01554 } 01555 }
static void find_pval_gotos | ( | pval * | item, | |
int | lev | |||
) | [static] |
Definition at line 1557 of file pval.c.
References find_pval_goto_item(), and pval::next.
Referenced by check_pval_item(), and find_pval_goto_item().
01558 { 01559 pval *i; 01560 01561 for (i=item; i; i=i->next) { 01562 /* printf("About to call pval_goto_item, itemcount=%d, itemtype=%d\n", item_count, i->type); */ 01563 find_pval_goto_item(i, lev); 01564 } 01565 }
int find_switch_item | ( | pval * | item | ) |
Definition at line 3097 of file pval.c.
References contains_switch(), pval::else_statements, pval::for_statements, pval::list, pval::macro_statements, PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTEXT, PV_CONTINUE, PV_DEFAULT, PV_ESWITCHES, PV_EXTENSION, PV_FOR, PV_GLOBALS, PV_GOTO, PV_IF, PV_IFTIME, PV_IGNOREPAT, PV_INCLUDES, PV_LABEL, PV_LOCALVARDEC, PV_MACRO, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_SWITCHES, PV_VARDEC, PV_WHILE, PV_WORD, pval::statements, pval::type, pval::u1, pval::u2, pval::u3, and pval::u4.
Referenced by contains_switch().
03098 { 03099 switch ( item->type ) { 03100 case PV_LOCALVARDEC: 03101 /* fields: item->u1.str == string associated with this (word). */ 03102 break; 03103 03104 case PV_WORD: 03105 /* fields: item->u1.str == string associated with this (word). */ 03106 break; 03107 03108 case PV_MACRO: 03109 /* fields: item->u1.str == name of macro 03110 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 03111 item->u2.arglist->u1.str == argument 03112 item->u2.arglist->next == next arg 03113 03114 item->u3.macro_statements == pval list of statements in macro body. 03115 */ 03116 /* had better not see this */ 03117 if (contains_switch(item->u3.macro_statements)) 03118 return 1; 03119 break; 03120 03121 case PV_CONTEXT: 03122 /* fields: item->u1.str == name of context 03123 item->u2.statements == pval list of statements in context body 03124 item->u3.abstract == int 1 if an abstract keyword were present 03125 */ 03126 /* had better not see this */ 03127 if (contains_switch(item->u2.statements)) 03128 return 1; 03129 break; 03130 03131 case PV_MACRO_CALL: 03132 /* fields: item->u1.str == name of macro to call 03133 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 03134 item->u2.arglist->u1.str == argument 03135 item->u2.arglist->next == next arg 03136 */ 03137 break; 03138 03139 case PV_APPLICATION_CALL: 03140 /* fields: item->u1.str == name of application to call 03141 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 03142 item->u2.arglist->u1.str == argument 03143 item->u2.arglist->next == next arg 03144 */ 03145 break; 03146 03147 case PV_CASE: 03148 /* fields: item->u1.str == value of case 03149 item->u2.statements == pval list of statements under the case 03150 */ 03151 /* had better not see this */ 03152 if (contains_switch(item->u2.statements)) 03153 return 1; 03154 break; 03155 03156 case PV_PATTERN: 03157 /* fields: item->u1.str == value of case 03158 item->u2.statements == pval list of statements under the case 03159 */ 03160 /* had better not see this */ 03161 if (contains_switch(item->u2.statements)) 03162 return 1; 03163 break; 03164 03165 case PV_DEFAULT: 03166 /* fields: 03167 item->u2.statements == pval list of statements under the case 03168 */ 03169 /* had better not see this */ 03170 if (contains_switch(item->u2.statements)) 03171 return 1; 03172 break; 03173 03174 case PV_CATCH: 03175 /* fields: item->u1.str == name of extension to catch 03176 item->u2.statements == pval list of statements in context body 03177 */ 03178 /* had better not see this */ 03179 if (contains_switch(item->u2.statements)) 03180 return 1; 03181 break; 03182 03183 case PV_SWITCHES: 03184 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 03185 */ 03186 break; 03187 03188 case PV_ESWITCHES: 03189 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 03190 */ 03191 break; 03192 03193 case PV_INCLUDES: 03194 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 03195 item->u2.arglist == pval list of 4 PV_WORD elements for time values 03196 */ 03197 break; 03198 03199 case PV_STATEMENTBLOCK: 03200 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 03201 */ 03202 if (contains_switch(item->u1.list) ) 03203 return 1; 03204 break; 03205 03206 case PV_VARDEC: 03207 /* fields: item->u1.str == variable name 03208 item->u2.val == variable value to assign 03209 */ 03210 break; 03211 03212 case PV_GOTO: 03213 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 03214 item->u1.list->u1.str == where the data on a PV_WORD will always be. 03215 */ 03216 break; 03217 03218 case PV_LABEL: 03219 /* fields: item->u1.str == label name 03220 */ 03221 break; 03222 03223 case PV_FOR: 03224 /* fields: item->u1.for_init == a string containing the initalizer 03225 item->u2.for_test == a string containing the loop test 03226 item->u3.for_inc == a string containing the loop increment 03227 03228 item->u4.for_statements == a pval list of statements in the for () 03229 */ 03230 if (contains_switch(item->u4.for_statements)) 03231 return 1; 03232 break; 03233 03234 case PV_WHILE: 03235 /* fields: item->u1.str == the while conditional, as supplied by user 03236 03237 item->u2.statements == a pval list of statements in the while () 03238 */ 03239 if (contains_switch(item->u2.statements)) 03240 return 1; 03241 break; 03242 03243 case PV_BREAK: 03244 /* fields: none 03245 */ 03246 break; 03247 03248 case PV_RETURN: 03249 /* fields: none 03250 */ 03251 break; 03252 03253 case PV_CONTINUE: 03254 /* fields: none 03255 */ 03256 break; 03257 03258 case PV_IFTIME: 03259 /* fields: item->u1.list == there are 4 linked PV_WORDs here. 03260 03261 item->u2.statements == a pval list of statements in the if () 03262 item->u3.else_statements == a pval list of statements in the else 03263 (could be zero) 03264 */ 03265 if (contains_switch(item->u2.statements)) 03266 return 1; 03267 if ( item->u3.else_statements ) { 03268 if (contains_switch(item->u3.else_statements)) 03269 return 1; 03270 } 03271 break; 03272 03273 case PV_RANDOM: 03274 /* fields: item->u1.str == the random number expression, as supplied by user 03275 03276 item->u2.statements == a pval list of statements in the if () 03277 item->u3.else_statements == a pval list of statements in the else 03278 (could be zero) 03279 */ 03280 if (contains_switch(item->u2.statements)) 03281 return 1; 03282 if ( item->u3.else_statements ) { 03283 if (contains_switch(item->u3.else_statements)) 03284 return 1; 03285 } 03286 break; 03287 03288 case PV_IF: 03289 /* fields: item->u1.str == the if conditional, as supplied by user 03290 03291 item->u2.statements == a pval list of statements in the if () 03292 item->u3.else_statements == a pval list of statements in the else 03293 (could be zero) 03294 */ 03295 if (contains_switch(item->u2.statements)) 03296 return 1; 03297 if ( item->u3.else_statements ) { 03298 if (contains_switch(item->u3.else_statements)) 03299 return 1; 03300 } 03301 break; 03302 03303 case PV_SWITCH: 03304 /* fields: item->u1.str == the switch expression 03305 03306 item->u2.statements == a pval list of statements in the switch, 03307 (will be case statements, most likely!) 03308 */ 03309 return 1; /* JACKPOT */ 03310 break; 03311 03312 case PV_EXTENSION: 03313 /* fields: item->u1.str == the extension name, label, whatever it's called 03314 03315 item->u2.statements == a pval list of statements in the extension 03316 item->u3.hints == a char * hint argument 03317 item->u4.regexten == an int boolean. non-zero says that regexten was specified 03318 */ 03319 if (contains_switch(item->u2.statements)) 03320 return 1; 03321 break; 03322 03323 case PV_IGNOREPAT: 03324 /* fields: item->u1.str == the ignorepat data 03325 */ 03326 break; 03327 03328 case PV_GLOBALS: 03329 /* fields: item->u1.statements == pval list of statements, usually vardecs 03330 */ 03331 break; 03332 } 03333 return 0; 03334 }
static void fix_gotos_in_extensions | ( | struct ael_extension * | exten | ) | [static] |
Definition at line 4393 of file pval.c.
References ael_priority::appargs, pval::compiled_label, free, pval::goto_target, pval::goto_target_in_case, pval::list, ael_extension::name, pval::next, ael_priority::next, ael_extension::next_exten, ael_priority::origin, ael_extension::plist, PV_GOTO, pval::str, strdup, pval::type, pval::u1, pval::u2, and pval::u3.
Referenced by ast_compile_ael2().
04394 { 04395 struct ael_extension *e; 04396 for(e=exten;e;e=e->next_exten) { 04397 04398 struct ael_priority *p; 04399 for(p=e->plist;p;p=p->next) { 04400 04401 if( p->origin && p->origin->type == PV_GOTO && p->origin->u3.goto_target_in_case ) { 04402 04403 /* fix the extension of the goto target to the actual extension in the post-compiled dialplan */ 04404 04405 pval *target = p->origin->u2.goto_target; 04406 struct ael_extension *z = target->u3.compiled_label; 04407 pval *pv2 = p->origin; 04408 char buf1[500]; 04409 char *apparg_save = p->appargs; 04410 04411 p->appargs = 0; 04412 if (!pv2->u1.list->next) /* just one -- it won't hurt to repeat the extension */ { 04413 snprintf(buf1,sizeof(buf1),"%s,%s", z->name, pv2->u1.list->u1.str); 04414 p->appargs = strdup(buf1); 04415 04416 } else if (pv2->u1.list->next && !pv2->u1.list->next->next) /* two */ { 04417 snprintf(buf1,sizeof(buf1),"%s,%s", z->name, pv2->u1.list->next->u1.str); 04418 p->appargs = strdup(buf1); 04419 } else if (pv2->u1.list->next && pv2->u1.list->next->next) { 04420 snprintf(buf1,sizeof(buf1),"%s,%s,%s", pv2->u1.list->u1.str, 04421 z->name, 04422 pv2->u1.list->next->next->u1.str); 04423 p->appargs = strdup(buf1); 04424 } 04425 else 04426 printf("WHAT? The goto doesn't fall into one of three cases for GOTO????\n"); 04427 04428 if( apparg_save ) { 04429 free(apparg_save); 04430 } 04431 } 04432 } 04433 } 04434 }
static void gen_match_to_pattern | ( | char * | pattern, | |
char * | result | |||
) | [static] |
Definition at line 3068 of file pval.c.
Referenced by gen_prios().
03069 { 03070 /* the result will be a string that will be matched by pattern */ 03071 char *p=pattern, *t=result; 03072 while (*p) { 03073 if (*p == 'x' || *p == 'n' || *p == 'z' || *p == 'X' || *p == 'N' || *p == 'Z') 03074 *t++ = '9'; 03075 else if (*p == '[') { 03076 char *z = p+1; 03077 while (*z != ']') 03078 z++; 03079 if (*(z+1)== ']') 03080 z++; 03081 *t++=*(p+1); /* use the first char in the set */ 03082 p = z; 03083 } else { 03084 *t++ = *p; 03085 } 03086 p++; 03087 } 03088 *t++ = 0; /* cap it off */ 03089 }
static int gen_prios | ( | struct ael_extension * | exten, | |
char * | label, | |||
pval * | statement, | |||
struct ael_extension * | mother_exten, | |||
struct ast_context * | this_context | |||
) | [static] |
Definition at line 3348 of file pval.c.
References AEL_APPCALL, AEL_CONTROL1, AEL_FOR_CONTROL, AEL_IF_CONTROL, AEL_IFTIME_CONTROL, AEL_LABEL, AEL_RETURN, ael_priority::app, ael_priority::appargs, pval::arglist, ast_compat_app_set, BUF_SIZE, ael_extension::checked_switch, pval::compiled_label, contains_switch(), ael_extension::context, pval::else_statements, ael_priority::exten, first, pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, free, gen_match_to_pattern(), get_goto_target(), ael_priority::goto_false, pval::goto_target, pval::goto_target_in_case, ael_priority::goto_true, ael_extension::has_switch, ael_extension::is_switch, label_inside_case(), linkexten(), linkprio(), pval::list, ael_extension::loop_break, ael_extension::loop_continue, malloc, ael_extension::name, new_exten(), new_prio(), pval::next, ael_priority::origin, PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTINUE, PV_DEFAULT, PV_FOR, PV_GOTO, PV_IF, PV_IFTIME, PV_LABEL, PV_LOCALVARDEC, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_VARDEC, PV_WHILE, remove_spaces_before_equals(), ael_extension::return_needed, pval::statements, pval::str, strdup, pval::type, ael_priority::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.
Referenced by ast_compile_ael2().
03349 { 03350 pval *p,*p2,*p3; 03351 struct ael_priority *pr; 03352 struct ael_priority *for_init, *for_test, *for_inc, *for_loop, *for_end; 03353 struct ael_priority *while_test, *while_loop, *while_end; 03354 struct ael_priority *switch_set, *switch_test, *switch_end, *fall_thru, *switch_empty; 03355 struct ael_priority *if_test, *if_end, *if_skip, *if_false; 03356 #ifdef OLD_RAND_ACTION 03357 struct ael_priority *rand_test, *rand_end, *rand_skip; 03358 #endif 03359 char *buf1; 03360 char *buf2; 03361 char *new_label; 03362 char *strp, *strp2; 03363 int default_exists; 03364 int local_control_statement_count; 03365 int first; 03366 struct ael_priority *loop_break_save; 03367 struct ael_priority *loop_continue_save; 03368 struct ael_extension *switch_case,*switch_null; 03369 03370 if (!(buf1 = malloc(BUF_SIZE))) { 03371 return -1; 03372 } 03373 if (!(buf2 = malloc(BUF_SIZE))) { 03374 return -1; 03375 } 03376 if (!(new_label = malloc(BUF_SIZE))) { 03377 return -1; 03378 } 03379 03380 if ((mother_exten && !mother_exten->checked_switch) || (exten && !exten->checked_switch)) { 03381 if (contains_switch(statement)) { /* only run contains_switch if you haven't checked before */ 03382 if (mother_exten) { 03383 if (!mother_exten->has_switch) { 03384 for (first = 1; first >= 0; first--) { 03385 switch_set = new_prio(); 03386 switch_set->type = AEL_APPCALL; 03387 if (!ast_compat_app_set) { 03388 switch_set->app = strdup("MSet"); 03389 } else { 03390 switch_set->app = strdup("Set"); 03391 } 03392 /* Are we likely inside a gosub subroutine? */ 03393 if (!strcmp(mother_exten->name, "~~s~~") && first) { 03394 /* If we're not actually within a gosub, this will fail, but the 03395 * second time through, it will get set. If we are within gosub, 03396 * the second time through is redundant, but acceptable. */ 03397 switch_set->appargs = strdup("LOCAL(~~EXTEN~~)=${EXTEN}"); 03398 } else { 03399 switch_set->appargs = strdup("~~EXTEN~~=${EXTEN}"); 03400 first = 0; 03401 } 03402 linkprio(exten, switch_set, mother_exten); 03403 mother_exten->has_switch = 1; 03404 mother_exten->checked_switch = 1; 03405 if (exten) { 03406 exten->has_switch = 1; 03407 exten->checked_switch = 1; 03408 } 03409 } 03410 } 03411 } else if (exten) { 03412 if (!exten->has_switch) { 03413 for (first = 1; first >= 0; first--) { 03414 switch_set = new_prio(); 03415 switch_set->type = AEL_APPCALL; 03416 if (!ast_compat_app_set) { 03417 switch_set->app = strdup("MSet"); 03418 } else { 03419 switch_set->app = strdup("Set"); 03420 } 03421 /* Are we likely inside a gosub subroutine? */ 03422 if (!strcmp(exten->name, "~~s~~")) { 03423 /* If we're not actually within a gosub, this will fail, but the 03424 * second time through, it will get set. If we are within gosub, 03425 * the second time through is redundant, but acceptable. */ 03426 switch_set->appargs = strdup("LOCAL(~~EXTEN~~)=${EXTEN}"); 03427 } else { 03428 switch_set->appargs = strdup("~~EXTEN~~=${EXTEN}"); 03429 first = 0; 03430 } 03431 linkprio(exten, switch_set, mother_exten); 03432 exten->has_switch = 1; 03433 exten->checked_switch = 1; 03434 if (mother_exten) { 03435 mother_exten->has_switch = 1; 03436 mother_exten->checked_switch = 1; 03437 } 03438 } 03439 } 03440 } 03441 } else { 03442 if (mother_exten) { 03443 mother_exten->checked_switch = 1; 03444 } 03445 if (exten) { 03446 exten->checked_switch = 1; 03447 } 03448 } 03449 } 03450 for (p=statement; p; p=p->next) { 03451 switch (p->type) { 03452 case PV_VARDEC: 03453 pr = new_prio(); 03454 pr->type = AEL_APPCALL; 03455 snprintf(buf1, BUF_SIZE, "%s=$[%s]", p->u1.str, p->u2.val); 03456 if (!ast_compat_app_set) { 03457 pr->app = strdup("MSet"); 03458 } else { 03459 pr->app = strdup("Set"); 03460 } 03461 remove_spaces_before_equals(buf1); 03462 pr->appargs = strdup(buf1); 03463 pr->origin = p; 03464 linkprio(exten, pr, mother_exten); 03465 break; 03466 03467 case PV_LOCALVARDEC: 03468 pr = new_prio(); 03469 pr->type = AEL_APPCALL; 03470 snprintf(buf1, BUF_SIZE, "LOCAL(%s)=$[%s]", p->u1.str, p->u2.val); 03471 if (!ast_compat_app_set) { 03472 pr->app = strdup("MSet"); 03473 } else { 03474 pr->app = strdup("Set"); 03475 } 03476 remove_spaces_before_equals(buf1); 03477 pr->appargs = strdup(buf1); 03478 pr->origin = p; 03479 linkprio(exten, pr, mother_exten); 03480 break; 03481 03482 case PV_GOTO: 03483 pr = new_prio(); 03484 pr->type = AEL_APPCALL; 03485 p->u2.goto_target = get_goto_target(p); 03486 if( p->u2.goto_target ) { 03487 p->u3.goto_target_in_case = label_inside_case(p->u2.goto_target); 03488 } 03489 03490 if (!p->u1.list->next) /* just one */ { 03491 pr->app = strdup("Goto"); 03492 if (!mother_exten) 03493 pr->appargs = strdup(p->u1.list->u1.str); 03494 else { /* for the case of simple within-extension gotos in case/pattern/default statement blocks: */ 03495 snprintf(buf1, BUF_SIZE, "%s,%s", mother_exten->name, p->u1.list->u1.str); 03496 pr->appargs = strdup(buf1); 03497 } 03498 03499 } else if (p->u1.list->next && !p->u1.list->next->next) /* two */ { 03500 snprintf(buf1, BUF_SIZE, "%s,%s", p->u1.list->u1.str, p->u1.list->next->u1.str); 03501 pr->app = strdup("Goto"); 03502 pr->appargs = strdup(buf1); 03503 } else if (p->u1.list->next && p->u1.list->next->next) { 03504 snprintf(buf1, BUF_SIZE, "%s,%s,%s", p->u1.list->u1.str, 03505 p->u1.list->next->u1.str, 03506 p->u1.list->next->next->u1.str); 03507 pr->app = strdup("Goto"); 03508 pr->appargs = strdup(buf1); 03509 } 03510 pr->origin = p; 03511 linkprio(exten, pr, mother_exten); 03512 break; 03513 03514 case PV_LABEL: 03515 pr = new_prio(); 03516 pr->type = AEL_LABEL; 03517 pr->origin = p; 03518 p->u3.compiled_label = exten; 03519 linkprio(exten, pr, mother_exten); 03520 break; 03521 03522 case PV_FOR: 03523 control_statement_count++; 03524 loop_break_save = exten->loop_break; /* save them, then restore before leaving */ 03525 loop_continue_save = exten->loop_continue; 03526 snprintf(new_label, BUF_SIZE, "for_%s_%d", label, control_statement_count); 03527 for_init = new_prio(); 03528 for_inc = new_prio(); 03529 for_test = new_prio(); 03530 for_loop = new_prio(); 03531 for_end = new_prio(); 03532 for_init->type = AEL_APPCALL; 03533 for_inc->type = AEL_APPCALL; 03534 for_test->type = AEL_FOR_CONTROL; 03535 for_test->goto_false = for_end; 03536 for_loop->type = AEL_CONTROL1; /* simple goto */ 03537 for_end->type = AEL_APPCALL; 03538 if (!ast_compat_app_set) { 03539 for_init->app = strdup("MSet"); 03540 } else { 03541 for_init->app = strdup("Set"); 03542 } 03543 03544 strcpy(buf2,p->u1.for_init); 03545 remove_spaces_before_equals(buf2); 03546 strp = strchr(buf2, '='); 03547 if (strp) { 03548 strp2 = strchr(p->u1.for_init, '='); 03549 *(strp+1) = 0; 03550 strcat(buf2,"$["); 03551 strncat(buf2,strp2+1, BUF_SIZE-strlen(strp2+1)-2); 03552 strcat(buf2,"]"); 03553 for_init->appargs = strdup(buf2); 03554 } else { 03555 strp2 = p->u1.for_init; 03556 while (*strp2 && isspace(*strp2)) 03557 strp2++; 03558 if (*strp2 == '&') { /* itsa macro call */ 03559 char *strp3 = strp2+1; 03560 while (*strp3 && isspace(*strp3)) 03561 strp3++; 03562 strcpy(buf2, strp3); 03563 strp3 = strchr(buf2,'('); 03564 if (strp3) { 03565 *strp3 = '|'; 03566 } 03567 while ((strp3=strchr(buf2,','))) { 03568 *strp3 = '|'; 03569 } 03570 strp3 = strrchr(buf2, ')'); 03571 if (strp3) 03572 *strp3 = 0; /* remove the closing paren */ 03573 03574 for_init->appargs = strdup(buf2); 03575 free(for_init->app); 03576 for_init->app = strdup("Macro"); 03577 } else { /* must be a regular app call */ 03578 char *strp3; 03579 strcpy(buf2, strp2); 03580 strp3 = strchr(buf2,'('); 03581 if (strp3) { 03582 *strp3 = 0; 03583 free(for_init->app); 03584 for_init->app = strdup(buf2); 03585 for_init->appargs = strdup(strp3+1); 03586 strp3 = strrchr(for_init->appargs, ')'); 03587 if (strp3) 03588 *strp3 = 0; /* remove the closing paren */ 03589 } 03590 } 03591 } 03592 03593 strcpy(buf2,p->u3.for_inc); 03594 remove_spaces_before_equals(buf2); 03595 strp = strchr(buf2, '='); 03596 if (strp) { /* there's an = in this part; that means an assignment. set it up */ 03597 strp2 = strchr(p->u3.for_inc, '='); 03598 *(strp+1) = 0; 03599 strcat(buf2,"$["); 03600 strncat(buf2,strp2+1, BUF_SIZE-strlen(strp2+1)-2); 03601 strcat(buf2,"]"); 03602 for_inc->appargs = strdup(buf2); 03603 if (!ast_compat_app_set) { 03604 for_inc->app = strdup("MSet"); 03605 } else { 03606 for_inc->app = strdup("Set"); 03607 } 03608 } else { 03609 strp2 = p->u3.for_inc; 03610 while (*strp2 && isspace(*strp2)) 03611 strp2++; 03612 if (*strp2 == '&') { /* itsa macro call */ 03613 char *strp3 = strp2+1; 03614 while (*strp3 && isspace(*strp3)) 03615 strp3++; 03616 strcpy(buf2, strp3); 03617 strp3 = strchr(buf2,'('); 03618 if (strp3) { 03619 *strp3 = ','; 03620 } 03621 strp3 = strrchr(buf2, ')'); 03622 if (strp3) 03623 *strp3 = 0; /* remove the closing paren */ 03624 03625 for_inc->appargs = strdup(buf2); 03626 03627 for_inc->app = strdup("Macro"); 03628 } else { /* must be a regular app call */ 03629 char *strp3; 03630 strcpy(buf2, strp2); 03631 strp3 = strchr(buf2,'('); 03632 if (strp3) { 03633 *strp3 = 0; 03634 for_inc->app = strdup(buf2); 03635 for_inc->appargs = strdup(strp3+1); 03636 strp3 = strrchr(for_inc->appargs, ')'); 03637 if (strp3) 03638 *strp3 = 0; /* remove the closing paren */ 03639 } 03640 } 03641 } 03642 snprintf(buf1, BUF_SIZE, "$[%s]",p->u2.for_test); 03643 for_test->app = 0; 03644 for_test->appargs = strdup(buf1); 03645 for_loop->goto_true = for_test; 03646 snprintf(buf1, BUF_SIZE, "Finish for_%s_%d", label, control_statement_count); 03647 for_end->app = strdup("NoOp"); 03648 for_end->appargs = strdup(buf1); 03649 /* link & load! */ 03650 linkprio(exten, for_init, mother_exten); 03651 linkprio(exten, for_test, mother_exten); 03652 03653 /* now, put the body of the for loop here */ 03654 exten->loop_break = for_end; 03655 exten->loop_continue = for_inc; 03656 03657 if (gen_prios(exten, new_label, p->u4.for_statements, mother_exten, this_context)) { /* this will link in all the statements here */ 03658 return -1; 03659 } 03660 03661 linkprio(exten, for_inc, mother_exten); 03662 linkprio(exten, for_loop, mother_exten); 03663 linkprio(exten, for_end, mother_exten); 03664 03665 03666 exten->loop_break = loop_break_save; 03667 exten->loop_continue = loop_continue_save; 03668 for_loop->origin = p; 03669 break; 03670 03671 case PV_WHILE: 03672 control_statement_count++; 03673 loop_break_save = exten->loop_break; /* save them, then restore before leaving */ 03674 loop_continue_save = exten->loop_continue; 03675 snprintf(new_label, BUF_SIZE, "while_%s_%d", label, control_statement_count); 03676 while_test = new_prio(); 03677 while_loop = new_prio(); 03678 while_end = new_prio(); 03679 while_test->type = AEL_FOR_CONTROL; 03680 while_test->goto_false = while_end; 03681 while_loop->type = AEL_CONTROL1; /* simple goto */ 03682 while_end->type = AEL_APPCALL; 03683 snprintf(buf1, BUF_SIZE, "$[%s]",p->u1.str); 03684 while_test->app = 0; 03685 while_test->appargs = strdup(buf1); 03686 while_loop->goto_true = while_test; 03687 snprintf(buf1, BUF_SIZE, "Finish while_%s_%d", label, control_statement_count); 03688 while_end->app = strdup("NoOp"); 03689 while_end->appargs = strdup(buf1); 03690 03691 linkprio(exten, while_test, mother_exten); 03692 03693 /* now, put the body of the for loop here */ 03694 exten->loop_break = while_end; 03695 exten->loop_continue = while_test; 03696 03697 if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the while body statements here */ 03698 return -1; 03699 } 03700 03701 linkprio(exten, while_loop, mother_exten); 03702 linkprio(exten, while_end, mother_exten); 03703 03704 03705 exten->loop_break = loop_break_save; 03706 exten->loop_continue = loop_continue_save; 03707 while_loop->origin = p; 03708 break; 03709 03710 case PV_SWITCH: 03711 control_statement_count++; 03712 local_control_statement_count = control_statement_count; 03713 loop_break_save = exten->loop_break; /* save them, then restore before leaving */ 03714 loop_continue_save = exten->loop_continue; 03715 snprintf(new_label, BUF_SIZE, "sw_%s_%d", label, control_statement_count); 03716 switch_test = new_prio(); 03717 switch_end = new_prio(); 03718 switch_test->type = AEL_APPCALL; 03719 switch_end->type = AEL_APPCALL; 03720 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", control_statement_count, p->u1.str); 03721 switch_test->app = strdup("Goto"); 03722 switch_test->appargs = strdup(buf1); 03723 snprintf(buf1, BUF_SIZE, "Finish switch_%s_%d", label, control_statement_count); 03724 switch_end->app = strdup("NoOp"); 03725 switch_end->appargs = strdup(buf1); 03726 switch_end->origin = p; 03727 switch_end->exten = exten; 03728 03729 linkprio(exten, switch_test, mother_exten); 03730 linkprio(exten, switch_end, mother_exten); 03731 03732 exten->loop_break = switch_end; 03733 exten->loop_continue = 0; 03734 default_exists = 0; 03735 03736 for (p2=p->u2.statements; p2; p2=p2->next) { 03737 /* now, for each case/default put the body of the for loop here */ 03738 if (p2->type == PV_CASE) { 03739 /* ok, generate a extension and link it in */ 03740 switch_case = new_exten(); 03741 if (mother_exten && mother_exten->checked_switch) { 03742 switch_case->has_switch = mother_exten->has_switch; 03743 switch_case->checked_switch = mother_exten->checked_switch; 03744 } 03745 if (exten && exten->checked_switch) { 03746 switch_case->has_switch = exten->has_switch; 03747 switch_case->checked_switch = exten->checked_switch; 03748 } 03749 switch_case->context = this_context; 03750 switch_case->is_switch = 1; 03751 /* the break/continue locations are inherited from parent */ 03752 switch_case->loop_break = exten->loop_break; 03753 switch_case->loop_continue = exten->loop_continue; 03754 03755 linkexten(exten,switch_case); 03756 snprintf(buf1, BUF_SIZE, "sw_%d_%s", local_control_statement_count, p2->u1.str); 03757 switch_case->name = strdup(buf1); 03758 snprintf(new_label, BUF_SIZE, "sw_%s_%s_%d", label, p2->u1.str, local_control_statement_count); 03759 03760 if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the case body statements here */ 03761 return -1; 03762 } 03763 03764 /* here is where we write code to "fall thru" to the next case... if there is one... */ 03765 for (p3=p2->u2.statements; p3; p3=p3->next) { 03766 if (!p3->next) 03767 break; 03768 } 03769 /* p3 now points the last statement... */ 03770 if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN) ) { 03771 /* is there a following CASE/PATTERN/DEFAULT? */ 03772 if (p2->next && p2->next->type == PV_CASE) { 03773 fall_thru = new_prio(); 03774 fall_thru->type = AEL_APPCALL; 03775 fall_thru->app = strdup("Goto"); 03776 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, p2->next->u1.str); 03777 fall_thru->appargs = strdup(buf1); 03778 linkprio(switch_case, fall_thru, mother_exten); 03779 } else if (p2->next && p2->next->type == PV_PATTERN) { 03780 fall_thru = new_prio(); 03781 fall_thru->type = AEL_APPCALL; 03782 fall_thru->app = strdup("Goto"); 03783 gen_match_to_pattern(p2->next->u1.str, buf2); 03784 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, buf2); 03785 fall_thru->appargs = strdup(buf1); 03786 linkprio(switch_case, fall_thru, mother_exten); 03787 } else if (p2->next && p2->next->type == PV_DEFAULT) { 03788 fall_thru = new_prio(); 03789 fall_thru->type = AEL_APPCALL; 03790 fall_thru->app = strdup("Goto"); 03791 snprintf(buf1, BUF_SIZE, "sw_%d_.,10", local_control_statement_count); 03792 fall_thru->appargs = strdup(buf1); 03793 linkprio(switch_case, fall_thru, mother_exten); 03794 } else if (!p2->next) { 03795 fall_thru = new_prio(); 03796 fall_thru->type = AEL_CONTROL1; 03797 fall_thru->goto_true = switch_end; 03798 fall_thru->app = strdup("Goto"); 03799 linkprio(switch_case, fall_thru, mother_exten); 03800 } 03801 } 03802 if (switch_case->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */ 03803 char buf[2000]; 03804 struct ael_priority *np2 = new_prio(); 03805 np2->type = AEL_APPCALL; 03806 np2->app = strdup("NoOp"); 03807 snprintf(buf, BUF_SIZE, "End of Extension %s", switch_case->name); 03808 np2->appargs = strdup(buf); 03809 linkprio(switch_case, np2, mother_exten); 03810 switch_case-> return_target = np2; 03811 } 03812 } else if (p2->type == PV_PATTERN) { 03813 /* ok, generate a extension and link it in */ 03814 switch_case = new_exten(); 03815 if (mother_exten && mother_exten->checked_switch) { 03816 switch_case->has_switch = mother_exten->has_switch; 03817 switch_case->checked_switch = mother_exten->checked_switch; 03818 } 03819 if (exten && exten->checked_switch) { 03820 switch_case->has_switch = exten->has_switch; 03821 switch_case->checked_switch = exten->checked_switch; 03822 } 03823 switch_case->context = this_context; 03824 switch_case->is_switch = 1; 03825 /* the break/continue locations are inherited from parent */ 03826 switch_case->loop_break = exten->loop_break; 03827 switch_case->loop_continue = exten->loop_continue; 03828 03829 linkexten(exten,switch_case); 03830 snprintf(buf1, BUF_SIZE, "_sw_%d_%s", local_control_statement_count, p2->u1.str); 03831 switch_case->name = strdup(buf1); 03832 snprintf(new_label, BUF_SIZE, "sw_%s_%s_%d", label, p2->u1.str, local_control_statement_count); 03833 03834 if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the while body statements here */ 03835 return -1; 03836 } 03837 /* here is where we write code to "fall thru" to the next case... if there is one... */ 03838 for (p3=p2->u2.statements; p3; p3=p3->next) { 03839 if (!p3->next) 03840 break; 03841 } 03842 /* p3 now points the last statement... */ 03843 if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) { 03844 /* is there a following CASE/PATTERN/DEFAULT? */ 03845 if (p2->next && p2->next->type == PV_CASE) { 03846 fall_thru = new_prio(); 03847 fall_thru->type = AEL_APPCALL; 03848 fall_thru->app = strdup("Goto"); 03849 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, p2->next->u1.str); 03850 fall_thru->appargs = strdup(buf1); 03851 linkprio(switch_case, fall_thru, mother_exten); 03852 } else if (p2->next && p2->next->type == PV_PATTERN) { 03853 fall_thru = new_prio(); 03854 fall_thru->type = AEL_APPCALL; 03855 fall_thru->app = strdup("Goto"); 03856 gen_match_to_pattern(p2->next->u1.str, buf2); 03857 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, buf2); 03858 fall_thru->appargs = strdup(buf1); 03859 linkprio(switch_case, fall_thru, mother_exten); 03860 } else if (p2->next && p2->next->type == PV_DEFAULT) { 03861 fall_thru = new_prio(); 03862 fall_thru->type = AEL_APPCALL; 03863 fall_thru->app = strdup("Goto"); 03864 snprintf(buf1, BUF_SIZE, "sw_%d_.,10", local_control_statement_count); 03865 fall_thru->appargs = strdup(buf1); 03866 linkprio(switch_case, fall_thru, mother_exten); 03867 } else if (!p2->next) { 03868 fall_thru = new_prio(); 03869 fall_thru->type = AEL_CONTROL1; 03870 fall_thru->goto_true = switch_end; 03871 fall_thru->app = strdup("Goto"); 03872 linkprio(switch_case, fall_thru, mother_exten); 03873 } 03874 } 03875 if (switch_case->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */ 03876 char buf[2000]; 03877 struct ael_priority *np2 = new_prio(); 03878 np2->type = AEL_APPCALL; 03879 np2->app = strdup("NoOp"); 03880 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); 03881 np2->appargs = strdup(buf); 03882 linkprio(switch_case, np2, mother_exten); 03883 switch_case-> return_target = np2; 03884 } 03885 } else if (p2->type == PV_DEFAULT) { 03886 /* ok, generate a extension and link it in */ 03887 switch_case = new_exten(); 03888 if (mother_exten && mother_exten->checked_switch) { 03889 switch_case->has_switch = mother_exten->has_switch; 03890 switch_case->checked_switch = mother_exten->checked_switch; 03891 } 03892 if (exten && exten->checked_switch) { 03893 switch_case->has_switch = exten->has_switch; 03894 switch_case->checked_switch = exten->checked_switch; 03895 } 03896 switch_case->context = this_context; 03897 switch_case->is_switch = 1; 03898 03899 /* new: the default case intros a pattern with ., which covers ALMOST everything. 03900 but it doesn't cover a NULL pattern. So, we'll define a null extension to match 03901 that goto's the default extension. */ 03902 03903 default_exists++; 03904 switch_null = new_exten(); 03905 if (mother_exten && mother_exten->checked_switch) { 03906 switch_null->has_switch = mother_exten->has_switch; 03907 switch_null->checked_switch = mother_exten->checked_switch; 03908 } 03909 if (exten && exten->checked_switch) { 03910 switch_null->has_switch = exten->has_switch; 03911 switch_null->checked_switch = exten->checked_switch; 03912 } 03913 switch_null->context = this_context; 03914 switch_null->is_switch = 1; 03915 switch_empty = new_prio(); 03916 snprintf(buf1, BUF_SIZE, "sw_%d_.,10", local_control_statement_count); 03917 switch_empty->app = strdup("Goto"); 03918 switch_empty->appargs = strdup(buf1); 03919 linkprio(switch_null, switch_empty, mother_exten); 03920 snprintf(buf1, BUF_SIZE, "sw_%d_", local_control_statement_count); 03921 switch_null->name = strdup(buf1); 03922 switch_null->loop_break = exten->loop_break; 03923 switch_null->loop_continue = exten->loop_continue; 03924 linkexten(exten,switch_null); 03925 03926 /* the break/continue locations are inherited from parent */ 03927 switch_case->loop_break = exten->loop_break; 03928 switch_case->loop_continue = exten->loop_continue; 03929 linkexten(exten,switch_case); 03930 snprintf(buf1, BUF_SIZE, "_sw_%d_.", local_control_statement_count); 03931 switch_case->name = strdup(buf1); 03932 03933 snprintf(new_label, BUF_SIZE, "sw_%s_default_%d", label, local_control_statement_count); 03934 03935 if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the default: body statements here */ 03936 return -1; 03937 } 03938 03939 /* here is where we write code to "fall thru" to the next case... if there is one... */ 03940 for (p3=p2->u2.statements; p3; p3=p3->next) { 03941 if (!p3->next) 03942 break; 03943 } 03944 /* p3 now points the last statement... */ 03945 if (!p3 || (p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) { 03946 /* is there a following CASE/PATTERN/DEFAULT? */ 03947 if (p2->next && p2->next->type == PV_CASE) { 03948 fall_thru = new_prio(); 03949 fall_thru->type = AEL_APPCALL; 03950 fall_thru->app = strdup("Goto"); 03951 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, p2->next->u1.str); 03952 fall_thru->appargs = strdup(buf1); 03953 linkprio(switch_case, fall_thru, mother_exten); 03954 } else if (p2->next && p2->next->type == PV_PATTERN) { 03955 fall_thru = new_prio(); 03956 fall_thru->type = AEL_APPCALL; 03957 fall_thru->app = strdup("Goto"); 03958 gen_match_to_pattern(p2->next->u1.str, buf2); 03959 snprintf(buf1, BUF_SIZE, "sw_%d_%s,10", local_control_statement_count, buf2); 03960 fall_thru->appargs = strdup(buf1); 03961 linkprio(switch_case, fall_thru, mother_exten); 03962 } else if (p2->next && p2->next->type == PV_DEFAULT) { 03963 fall_thru = new_prio(); 03964 fall_thru->type = AEL_APPCALL; 03965 fall_thru->app = strdup("Goto"); 03966 snprintf(buf1, BUF_SIZE, "sw_%d_.,10", local_control_statement_count); 03967 fall_thru->appargs = strdup(buf1); 03968 linkprio(switch_case, fall_thru, mother_exten); 03969 } else if (!p2->next) { 03970 fall_thru = new_prio(); 03971 fall_thru->type = AEL_CONTROL1; 03972 fall_thru->goto_true = switch_end; 03973 fall_thru->app = strdup("Goto"); 03974 linkprio(switch_case, fall_thru, mother_exten); 03975 } 03976 } 03977 if (switch_case->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */ 03978 char buf[2000]; 03979 struct ael_priority *np2 = new_prio(); 03980 np2->type = AEL_APPCALL; 03981 np2->app = strdup("NoOp"); 03982 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); 03983 np2->appargs = strdup(buf); 03984 linkprio(switch_case, np2, mother_exten); 03985 switch_case-> return_target = np2; 03986 } 03987 } else { 03988 /* what could it be??? */ 03989 } 03990 } 03991 03992 exten->loop_break = loop_break_save; 03993 exten->loop_continue = loop_continue_save; 03994 switch_test->origin = p; 03995 switch_end->origin = p; 03996 break; 03997 03998 case PV_MACRO_CALL: 03999 pr = new_prio(); 04000 pr->type = AEL_APPCALL; 04001 snprintf(buf1, BUF_SIZE, "%s,~~s~~,1", p->u1.str); 04002 first = 1; 04003 for (p2 = p->u2.arglist; p2; p2 = p2->next) { 04004 if (first) 04005 { 04006 strcat(buf1,"("); 04007 first = 0; 04008 } 04009 else 04010 strcat(buf1,","); 04011 strcat(buf1,p2->u1.str); 04012 } 04013 if (!first) 04014 strcat(buf1,")"); 04015 04016 pr->app = strdup("Gosub"); 04017 pr->appargs = strdup(buf1); 04018 pr->origin = p; 04019 linkprio(exten, pr, mother_exten); 04020 break; 04021 04022 case PV_APPLICATION_CALL: 04023 pr = new_prio(); 04024 pr->type = AEL_APPCALL; 04025 buf1[0] = 0; 04026 for (p2 = p->u2.arglist; p2; p2 = p2->next) { 04027 if (p2 != p->u2.arglist ) 04028 strcat(buf1,","); 04029 strcat(buf1,p2->u1.str); 04030 } 04031 pr->app = strdup(p->u1.str); 04032 pr->appargs = strdup(buf1); 04033 pr->origin = p; 04034 linkprio(exten, pr, mother_exten); 04035 break; 04036 04037 case PV_BREAK: 04038 pr = new_prio(); 04039 pr->type = AEL_CONTROL1; /* simple goto */ 04040 pr->goto_true = exten->loop_break; 04041 pr->origin = p; 04042 linkprio(exten, pr, mother_exten); 04043 break; 04044 04045 case PV_RETURN: /* hmmmm */ 04046 pr = new_prio(); 04047 pr->type = AEL_RETURN; /* simple Return */ 04048 /* exten->return_needed++; */ 04049 pr->app = strdup("Return"); 04050 pr->appargs = strdup(""); 04051 pr->origin = p; 04052 linkprio(exten, pr, mother_exten); 04053 break; 04054 04055 case PV_CONTINUE: 04056 pr = new_prio(); 04057 pr->type = AEL_CONTROL1; /* simple goto */ 04058 pr->goto_true = exten->loop_continue; 04059 pr->origin = p; 04060 linkprio(exten, pr, mother_exten); 04061 break; 04062 04063 case PV_IFTIME: 04064 control_statement_count++; 04065 snprintf(new_label, BUF_SIZE, "iftime_%s_%d", label, control_statement_count); 04066 04067 if_test = new_prio(); 04068 if_test->type = AEL_IFTIME_CONTROL; 04069 snprintf(buf1, BUF_SIZE, "%s,%s,%s,%s", 04070 p->u1.list->u1.str, 04071 p->u1.list->next->u1.str, 04072 p->u1.list->next->next->u1.str, 04073 p->u1.list->next->next->next->u1.str); 04074 if_test->app = 0; 04075 if_test->appargs = strdup(buf1); 04076 if_test->origin = p; 04077 04078 if_end = new_prio(); 04079 if_end->type = AEL_APPCALL; 04080 snprintf(buf1, BUF_SIZE, "Finish iftime_%s_%d", label, control_statement_count); 04081 if_end->app = strdup("NoOp"); 04082 if_end->appargs = strdup(buf1); 04083 04084 if (p->u3.else_statements) { 04085 if_skip = new_prio(); 04086 if_skip->type = AEL_CONTROL1; /* simple goto */ 04087 if_skip->goto_true = if_end; 04088 if_skip->origin = p; 04089 04090 } else { 04091 if_skip = 0; 04092 04093 if_test->goto_false = if_end; 04094 } 04095 04096 if_false = new_prio(); 04097 if_false->type = AEL_CONTROL1; 04098 if (p->u3.else_statements) { 04099 if_false->goto_true = if_skip; /* +1 */ 04100 } else { 04101 if_false->goto_true = if_end; 04102 } 04103 04104 /* link & load! */ 04105 linkprio(exten, if_test, mother_exten); 04106 linkprio(exten, if_false, mother_exten); 04107 04108 /* now, put the body of the if here */ 04109 04110 if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the statements here */ 04111 return -1; 04112 } 04113 04114 if (p->u3.else_statements) { 04115 linkprio(exten, if_skip, mother_exten); 04116 if (gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context)) { /* this will link in all the statements here */ 04117 return -1; 04118 } 04119 } 04120 04121 linkprio(exten, if_end, mother_exten); 04122 04123 break; 04124 04125 case PV_RANDOM: 04126 case PV_IF: 04127 control_statement_count++; 04128 snprintf(new_label, BUF_SIZE, "if_%s_%d", label, control_statement_count); 04129 04130 if_test = new_prio(); 04131 if_end = new_prio(); 04132 if_test->type = AEL_IF_CONTROL; 04133 if_end->type = AEL_APPCALL; 04134 if ( p->type == PV_RANDOM ) 04135 snprintf(buf1, BUF_SIZE, "$[${RAND(0,99)} < (%s)]", p->u1.str); 04136 else 04137 snprintf(buf1, BUF_SIZE, "$[%s]", p->u1.str); 04138 if_test->app = 0; 04139 if_test->appargs = strdup(buf1); 04140 snprintf(buf1, BUF_SIZE, "Finish if_%s_%d", label, control_statement_count); 04141 if_end->app = strdup("NoOp"); 04142 if_end->appargs = strdup(buf1); 04143 if_test->origin = p; 04144 04145 if (p->u3.else_statements) { 04146 if_skip = new_prio(); 04147 if_skip->type = AEL_CONTROL1; /* simple goto */ 04148 if_skip->goto_true = if_end; 04149 if_test->goto_false = if_skip;; 04150 } else { 04151 if_skip = 0; 04152 if_test->goto_false = if_end;; 04153 } 04154 04155 /* link & load! */ 04156 linkprio(exten, if_test, mother_exten); 04157 04158 /* now, put the body of the if here */ 04159 04160 if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the statements here */ 04161 return -1; 04162 } 04163 04164 if (p->u3.else_statements) { 04165 linkprio(exten, if_skip, mother_exten); 04166 if (gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context)) { /* this will link in all the statements here */ 04167 return -1; 04168 } 04169 } 04170 04171 linkprio(exten, if_end, mother_exten); 04172 04173 break; 04174 04175 case PV_STATEMENTBLOCK: 04176 if (gen_prios(exten, label, p->u1.list, mother_exten, this_context)) { /* recurse into the block */ 04177 return -1; 04178 } 04179 break; 04180 04181 case PV_CATCH: 04182 control_statement_count++; 04183 /* generate an extension with name of catch, put all catch stats 04184 into this exten! */ 04185 switch_case = new_exten(); 04186 if (mother_exten && mother_exten->checked_switch) { 04187 switch_case->has_switch = mother_exten->has_switch; 04188 switch_case->checked_switch = mother_exten->checked_switch; 04189 } 04190 if (exten && exten->checked_switch) { 04191 switch_case->has_switch = exten->has_switch; 04192 switch_case->checked_switch = exten->checked_switch; 04193 } 04194 04195 switch_case->context = this_context; 04196 linkexten(exten,switch_case); 04197 switch_case->name = strdup(p->u1.str); 04198 snprintf(new_label, BUF_SIZE, "catch_%s_%d",p->u1.str, control_statement_count); 04199 04200 if (gen_prios(switch_case, new_label, p->u2.statements, mother_exten,this_context)) { /* this will link in all the catch body statements here */ 04201 return -1; 04202 } 04203 if (switch_case->return_needed) { /* returns now generate a Return() app call, no longer a goto to the end of the exten */ 04204 char buf[2000]; 04205 struct ael_priority *np2 = new_prio(); 04206 np2->type = AEL_APPCALL; 04207 np2->app = strdup("NoOp"); 04208 snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); 04209 np2->appargs = strdup(buf); 04210 linkprio(switch_case, np2, mother_exten); 04211 switch_case-> return_target = np2; 04212 } 04213 04214 break; 04215 default: 04216 break; 04217 } 04218 } 04219 free(buf1); 04220 free(buf2); 04221 free(new_label); 04222 return 0; 04223 }
Definition at line 4383 of file pval.c.
References pval::dad, PV_CONTEXT, PV_MACRO, and pval::type.
Referenced by check_goto(), and get_goto_target().
04384 { 04385 while( p && p->type != PV_CONTEXT && p->type != PV_MACRO ) { 04386 04387 p = p->dad; 04388 } 04389 04390 return p; 04391 }
Definition at line 4373 of file pval.c.
References pval::dad, PV_CONTEXT, PV_EXTENSION, PV_MACRO, and pval::type.
Referenced by check_goto(), and get_goto_target().
04374 { 04375 while( p && p->type != PV_EXTENSION && p->type != PV_CONTEXT && p->type != PV_MACRO ) { 04376 04377 p = p->dad; 04378 } 04379 04380 return p; 04381 }
Definition at line 1160 of file pval.c.
References find_context(), find_label_in_current_context(), find_label_in_current_db(), find_label_in_current_extension(), first, get_contxt(), get_extension_or_contxt(), pval::list, pval::next, PV_INCLUDES, pval::statements, pval::str, pval::type, pval::u1, and pval::u2.
Referenced by gen_prios().
01161 { 01162 /* just one item-- the label should be in the current extension */ 01163 pval *curr_ext = get_extension_or_contxt(item); /* containing exten, or macro */ 01164 pval *curr_cont; 01165 01166 if (!item->u1.list) { 01167 return NULL; 01168 } 01169 01170 if (!item->u1.list->next && !strstr((item->u1.list)->u1.str,"${")) { 01171 struct pval *x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), curr_ext); 01172 return x; 01173 } 01174 01175 curr_cont = get_contxt(item); 01176 01177 /* TWO items */ 01178 if (item->u1.list->next && !item->u1.list->next->next) { 01179 if (!strstr((item->u1.list)->u1.str,"${") 01180 && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ { 01181 struct pval *x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, curr_cont); 01182 return x; 01183 } 01184 } 01185 01186 /* All 3 items! */ 01187 if (item->u1.list->next && item->u1.list->next->next) { 01188 /* all three */ 01189 pval *first = item->u1.list; 01190 pval *second = item->u1.list->next; 01191 pval *third = item->u1.list->next->next; 01192 01193 if (!strstr((item->u1.list)->u1.str,"${") 01194 && !strstr(item->u1.list->next->u1.str,"${") 01195 && !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ { 01196 struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); 01197 if (!x) { 01198 01199 struct pval *p3; 01200 struct pval *that_context = find_context(item->u1.list->u1.str); 01201 01202 /* the target of the goto could be in an included context!! Fancy that!! */ 01203 /* look for includes in the current context */ 01204 if (that_context) { 01205 for (p3=that_context->u2.statements; p3; p3=p3->next) { 01206 if (p3->type == PV_INCLUDES) { 01207 struct pval *p4; 01208 for (p4=p3->u1.list; p4; p4=p4->next) { 01209 /* for each context pointed to, find it, then find a context/label that matches the 01210 target here! */ 01211 char *incl_context = p4->u1.str; 01212 /* find a matching context name */ 01213 struct pval *that_other_context = find_context(incl_context); 01214 if (that_other_context) { 01215 struct pval *x3; 01216 x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context); 01217 if (x3) { 01218 return x3; 01219 } 01220 } 01221 } 01222 } 01223 } 01224 } 01225 } 01226 return x; 01227 } 01228 } 01229 return NULL; 01230 }
Definition at line 1097 of file pval.c.
References pval::dad, PV_CONTEXT, PV_MACRO, and pval::type.
Referenced by check_goto().
Definition at line 1084 of file pval.c.
References pval::dad, PV_MACRO, and pval::type.
Referenced by check_goto().
int is_empty | ( | char * | arg | ) |
int is_float | ( | char * | arg | ) |
int is_int | ( | char * | arg | ) |
static int label_inside_case | ( | pval * | label | ) | [static] |
Definition at line 3025 of file pval.c.
References pval::dad, PV_CASE, PV_CONTEXT, PV_DEFAULT, PV_MACRO, PV_PATTERN, and pval::type.
Referenced by gen_prios().
03026 { 03027 pval *p = label; 03028 03029 while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ { 03030 if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN ) { 03031 return 1; 03032 } 03033 03034 p = p->dad; 03035 } 03036 return 0; 03037 }
static void linkexten | ( | struct ael_extension * | exten, | |
struct ael_extension * | add | |||
) | [static] |
Definition at line 3039 of file pval.c.
References ael_extension::next_exten.
Referenced by gen_prios().
03040 { 03041 add->next_exten = exten->next_exten; /* this will reverse the order. Big deal. */ 03042 exten->next_exten = add; 03043 }
void linkprio | ( | struct ael_extension * | exten, | |
struct ael_priority * | prio, | |||
struct ael_extension * | mother_exten | |||
) |
Definition at line 2943 of file pval.c.
References ael_priority::appargs, ael_priority::exten, free, ael_extension::has_switch, malloc, ael_priority::next, ael_extension::plist, and ael_extension::plist_last.
Referenced by ast_compile_ael2(), and gen_prios().
02944 { 02945 char *p1, *p2; 02946 02947 if (!exten->plist) { 02948 exten->plist = prio; 02949 exten->plist_last = prio; 02950 } else { 02951 exten->plist_last->next = prio; 02952 exten->plist_last = prio; 02953 } 02954 if( !prio->exten ) 02955 prio->exten = exten; /* don't override the switch value */ 02956 /* The following code will cause all priorities within an extension 02957 to have ${EXTEN} or ${EXTEN: replaced with ~~EXTEN~~, which is 02958 set just before the first switch in an exten. The switches 02959 will muck up the original ${EXTEN} value, so we save it away 02960 and the user accesses this copy instead. */ 02961 if (prio->appargs && ((mother_exten && mother_exten->has_switch) || exten->has_switch) ) { 02962 while ((p1 = strstr(prio->appargs, "${EXTEN}"))) { 02963 p2 = malloc(strlen(prio->appargs)+5); 02964 *p1 = 0; 02965 strcpy(p2, prio->appargs); 02966 strcat(p2, "${~~EXTEN~~}"); 02967 if (*(p1+8)) 02968 strcat(p2, p1+8); 02969 free(prio->appargs); 02970 prio->appargs = p2; 02971 } 02972 while ((p1 = strstr(prio->appargs, "${EXTEN:"))) { 02973 p2 = malloc(strlen(prio->appargs)+5); 02974 *p1 = 0; 02975 strcpy(p2, prio->appargs); 02976 strcat(p2, "${~~EXTEN~~:"); 02977 if (*(p1+8)) 02978 strcat(p2, p1+8); 02979 free(prio->appargs); 02980 prio->appargs = p2; 02981 } 02982 } 02983 }
Definition at line 5926 of file pval.c.
References pval::next, pval::prev, and pval::u1_last.
Referenced by pvalAppCallAddArg(), pvalCasePatDefAddStatement(), pvalContextAddStatement(), pvalESwitchesAddSwitch(), pvalGlobalsAddStatement(), pvalIncludesAddInclude(), pvalIncludesAddIncludeWithTimeConstraints(), pvalMacroAddArg(), pvalMacroAddStatement(), pvalMacroCallAddArg(), pvalStatementBlockAddStatement(), pvalSwitchAddCase(), pvalSwitchesAddSwitch(), pvalTopLevAddObject(), and yyparse().
05927 { 05928 if (!head) 05929 return tail; 05930 if (tail) { 05931 if (!head->next) { 05932 head->next = tail; 05933 } else { 05934 head->u1_last->next = tail; 05935 } 05936 head->u1_last = tail; 05937 tail->prev = head; /* the dad link only points to containers */ 05938 } 05939 return head; 05940 }
int localized_pbx_load_module | ( | void | ) |
Definition at line 1818 of file pval.c.
References match_pval_item(), and pval::next.
Referenced by find_context(), find_first_label_in_current_context(), find_label_in_current_context(), find_label_in_current_db(), find_label_in_current_extension(), find_macro(), and match_pval_item().
01819 { 01820 pval *i; 01821 01822 for (i=item; i; i=i->next) { 01823 pval *x; 01824 /* printf(" -- match pval: item %d\n", i->type); */ 01825 01826 if ((x = match_pval_item(i))) { 01827 /* printf("match_pval: returning x=%x\n", (int)x); */ 01828 return x; /* cut the search short */ 01829 } 01830 } 01831 return 0; 01832 }
Definition at line 1570 of file pval.c.
References pval::else_statements, extension_matches(), pval::for_statements, pval::list, pval::macro_statements, match_pval(), pval::next, PV_CASE, PV_CATCH, PV_CONTEXT, PV_DEFAULT, PV_EXTENSION, PV_FOR, PV_IF, PV_IFTIME, PV_LABEL, PV_MACRO, PV_PATTERN, PV_RANDOM, PV_STATEMENTBLOCK, PV_SWITCH, PV_WHILE, pval::statements, pval::str, pval::type, pval::u1, pval::u2, pval::u3, and pval::u4.
Referenced by match_pval().
01571 { 01572 pval *x; 01573 01574 switch ( item->type ) { 01575 case PV_MACRO: 01576 /* fields: item->u1.str == name of macro 01577 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 01578 item->u2.arglist->u1.str == argument 01579 item->u2.arglist->next == next arg 01580 01581 item->u3.macro_statements == pval list of statements in macro body. 01582 */ 01583 /* printf(" matching in MACRO %s, match_context=%s; retoncontmtch=%d; \n", item->u1.str, match_context, return_on_context_match); */ 01584 if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) { 01585 01586 /* printf("MACRO: match context is: %s\n", match_context); */ 01587 01588 if (return_on_context_match && !strcmp(item->u1.str, match_context)) /* if we're just searching for a context, don't bother descending into them */ { 01589 /* printf("Returning on matching macro %s\n", match_context); */ 01590 return item; 01591 } 01592 01593 01594 if (!return_on_context_match) { 01595 /* printf("Descending into matching macro %s/%s\n", match_context, item->u1.str); */ 01596 if ((x=match_pval(item->u3.macro_statements))) { 01597 /* printf("Responded with pval match %x\n", x); */ 01598 return x; 01599 } 01600 } 01601 } else { 01602 /* printf("Skipping context/macro %s\n", item->u1.str); */ 01603 } 01604 01605 break; 01606 01607 case PV_CONTEXT: 01608 /* fields: item->u1.str == name of context 01609 item->u2.statements == pval list of statements in context body 01610 item->u3.abstract == int 1 if an abstract keyword were present 01611 */ 01612 /* printf(" matching in CONTEXT\n"); */ 01613 if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) { 01614 if (return_on_context_match && !strcmp(item->u1.str, match_context)) { 01615 /* printf("Returning on matching context %s\n", match_context); */ 01616 /* printf("non-CONTEXT: Responded with pval match %x\n", x); */ 01617 return item; 01618 } 01619 01620 if (!return_on_context_match ) { 01621 /* printf("Descending into matching context %s\n", match_context); */ 01622 if ((x=match_pval(item->u2.statements))) /* if we're just searching for a context, don't bother descending into them */ { 01623 /* printf("CONTEXT: Responded with pval match %x\n", x); */ 01624 return x; 01625 } 01626 } 01627 } else { 01628 /* printf("Skipping context/macro %s\n", item->u1.str); */ 01629 } 01630 break; 01631 01632 case PV_CASE: 01633 /* fields: item->u1.str == value of case 01634 item->u2.statements == pval list of statements under the case 01635 */ 01636 /* printf(" matching in CASE\n"); */ 01637 if ((x=match_pval(item->u2.statements))) { 01638 /* printf("CASE: Responded with pval match %x\n", x); */ 01639 return x; 01640 } 01641 break; 01642 01643 case PV_PATTERN: 01644 /* fields: item->u1.str == value of case 01645 item->u2.statements == pval list of statements under the case 01646 */ 01647 /* printf(" matching in PATTERN\n"); */ 01648 if ((x=match_pval(item->u2.statements))) { 01649 /* printf("PATTERN: Responded with pval match %x\n", x); */ 01650 return x; 01651 } 01652 break; 01653 01654 case PV_DEFAULT: 01655 /* fields: 01656 item->u2.statements == pval list of statements under the case 01657 */ 01658 /* printf(" matching in DEFAULT\n"); */ 01659 if ((x=match_pval(item->u2.statements))) { 01660 /* printf("DEFAULT: Responded with pval match %x\n", x); */ 01661 return x; 01662 } 01663 break; 01664 01665 case PV_CATCH: 01666 /* fields: item->u1.str == name of extension to catch 01667 item->u2.statements == pval list of statements in context body 01668 */ 01669 /* printf(" matching in CATCH\n"); */ 01670 if ((x=match_pval(item->u2.statements))) { 01671 /* printf("CATCH: Responded with pval match %x\n", x); */ 01672 return x; 01673 } 01674 break; 01675 01676 case PV_STATEMENTBLOCK: 01677 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 01678 */ 01679 /* printf(" matching in STATEMENTBLOCK\n"); */ 01680 if ((x=match_pval(item->u1.list))) { 01681 /* printf("STATEMENTBLOCK: Responded with pval match %x\n", x); */ 01682 return x; 01683 } 01684 break; 01685 01686 case PV_LABEL: 01687 /* fields: item->u1.str == label name 01688 */ 01689 /* printf("PV_LABEL %s (cont=%s, exten=%s\n", 01690 item->u1.str, current_context->u1.str, (current_extension?current_extension->u1.str:"<macro>"));*/ 01691 01692 if (count_labels) { 01693 if (!strcmp(match_label, item->u1.str)) { 01694 label_count++; 01695 last_matched_label = item; 01696 } 01697 01698 } else { 01699 if (!strcmp(match_label, item->u1.str)) { 01700 /* printf("LABEL: Responded with pval match %x\n", x); */ 01701 return item; 01702 } 01703 } 01704 break; 01705 01706 case PV_FOR: 01707 /* fields: item->u1.for_init == a string containing the initalizer 01708 item->u2.for_test == a string containing the loop test 01709 item->u3.for_inc == a string containing the loop increment 01710 01711 item->u4.for_statements == a pval list of statements in the for () 01712 */ 01713 /* printf(" matching in FOR\n"); */ 01714 if ((x=match_pval(item->u4.for_statements))) { 01715 /* printf("FOR: Responded with pval match %x\n", x);*/ 01716 return x; 01717 } 01718 break; 01719 01720 case PV_WHILE: 01721 /* fields: item->u1.str == the while conditional, as supplied by user 01722 01723 item->u2.statements == a pval list of statements in the while () 01724 */ 01725 /* printf(" matching in WHILE\n"); */ 01726 if ((x=match_pval(item->u2.statements))) { 01727 /* printf("WHILE: Responded with pval match %x\n", x); */ 01728 return x; 01729 } 01730 break; 01731 01732 case PV_RANDOM: 01733 /* fields: item->u1.str == the random number expression, as supplied by user 01734 01735 item->u2.statements == a pval list of statements in the if () 01736 item->u3.else_statements == a pval list of statements in the else 01737 (could be zero) 01738 fall thru to PV_IF */ 01739 01740 case PV_IFTIME: 01741 /* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list 01742 01743 item->u2.statements == a pval list of statements in the if () 01744 item->u3.else_statements == a pval list of statements in the else 01745 (could be zero) 01746 fall thru to PV_IF*/ 01747 case PV_IF: 01748 /* fields: item->u1.str == the if conditional, as supplied by user 01749 01750 item->u2.statements == a pval list of statements in the if () 01751 item->u3.else_statements == a pval list of statements in the else 01752 (could be zero) 01753 */ 01754 /* printf(" matching in IF/IFTIME/RANDOM\n"); */ 01755 if ((x=match_pval(item->u2.statements))) { 01756 return x; 01757 } 01758 if (item->u3.else_statements) { 01759 if ((x=match_pval(item->u3.else_statements))) { 01760 /* printf("IF/IFTIME/RANDOM: Responded with pval match %x\n", x); */ 01761 return x; 01762 } 01763 } 01764 break; 01765 01766 case PV_SWITCH: 01767 /* fields: item->u1.str == the switch expression 01768 01769 item->u2.statements == a pval list of statements in the switch, 01770 (will be case statements, most likely!) 01771 */ 01772 /* printf(" matching in SWITCH\n"); */ 01773 if ((x=match_pval(item->u2.statements))) { 01774 /* printf("SWITCH: Responded with pval match %x\n", x); */ 01775 return x; 01776 } 01777 break; 01778 01779 case PV_EXTENSION: 01780 /* fields: item->u1.str == the extension name, label, whatever it's called 01781 01782 item->u2.statements == a pval list of statements in the extension 01783 item->u3.hints == a char * hint argument 01784 item->u4.regexten == an int boolean. non-zero says that regexten was specified 01785 */ 01786 /* printf(" matching in EXTENSION\n"); */ 01787 if (!strcmp(match_exten,"*") || extension_matches(item, match_exten, item->u1.str) ) { 01788 /* printf("Descending into matching exten %s => %s\n", match_exten, item->u1.str); */ 01789 if (strcmp(match_label,"1") == 0) { 01790 if (item->u2.statements) { 01791 struct pval *p5 = item->u2.statements; 01792 while (p5 && p5->type == PV_LABEL) /* find the first non-label statement in this context. If it exists, there's a "1" */ 01793 p5 = p5->next; 01794 if (p5) 01795 return p5; 01796 else 01797 return 0; 01798 } 01799 else 01800 return 0; 01801 } 01802 01803 if ((x=match_pval(item->u2.statements))) { 01804 /* printf("EXTENSION: Responded with pval match %x\n", x); */ 01805 return x; 01806 } 01807 } else { 01808 /* printf("Skipping exten %s\n", item->u1.str); */ 01809 } 01810 break; 01811 default: 01812 /* printf(" matching in default = %d\n", item->type); */ 01813 break; 01814 } 01815 return 0; 01816 }
struct ael_extension* new_exten | ( | void | ) | [read] |
Definition at line 2937 of file pval.c.
References calloc.
Referenced by ast_compile_ael2(), and gen_prios().
02938 { 02939 struct ael_extension *x = (struct ael_extension *)calloc(sizeof(struct ael_extension),1); 02940 return x; 02941 }
struct ael_priority* new_prio | ( | void | ) | [read] |
Definition at line 2931 of file pval.c.
References calloc.
Referenced by ast_compile_ael2(), and gen_prios().
02932 { 02933 struct ael_priority *x = (struct ael_priority *)calloc(sizeof(struct ael_priority),1); 02934 return x; 02935 }
static void print_pval | ( | FILE * | fin, | |
pval * | item, | |||
int | depth | |||
) | [static] |
Definition at line 117 of file pval.c.
References pval::abstract, pval::arglist, pval::else_statements, pval::for_inc, pval::for_init, pval::for_statements, pval::for_test, pval::hints, pval::list, pval::macro_statements, pval::next, print_pval_list(), PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTEXT, PV_CONTINUE, PV_DEFAULT, PV_ESWITCHES, PV_EXTENSION, PV_FOR, PV_GLOBALS, PV_GOTO, PV_IF, PV_IFTIME, PV_IGNOREPAT, PV_INCLUDES, PV_LABEL, PV_LOCALVARDEC, PV_MACRO, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_SWITCHES, PV_VARDEC, PV_WHILE, PV_WORD, pval::regexten, pval::statements, pval::str, pval::type, pval::u1, pval::u2, pval::u3, pval::u4, and pval::val.
Referenced by print_pval_list().
00118 { 00119 int i; 00120 pval *lp; 00121 00122 for (i=0; i<depth; i++) { 00123 fprintf(fin, "\t"); /* depth == indentation */ 00124 } 00125 00126 switch ( item->type ) { 00127 case PV_WORD: 00128 fprintf(fin,"%s;\n", item->u1.str); /* usually, words are encapsulated in something else */ 00129 break; 00130 00131 case PV_MACRO: 00132 fprintf(fin,"macro %s(", item->u1.str); 00133 for (lp=item->u2.arglist; lp; lp=lp->next) { 00134 if (lp != item->u2.arglist ) 00135 fprintf(fin,", "); 00136 fprintf(fin,"%s", lp->u1.str); 00137 } 00138 fprintf(fin,") {\n"); 00139 print_pval_list(fin,item->u3.macro_statements,depth+1); 00140 for (i=0; i<depth; i++) { 00141 fprintf(fin,"\t"); /* depth == indentation */ 00142 } 00143 fprintf(fin,"};\n\n"); 00144 break; 00145 00146 case PV_CONTEXT: 00147 if ( item->u3.abstract ) 00148 fprintf(fin,"abstract context %s {\n", item->u1.str); 00149 else 00150 fprintf(fin,"context %s {\n", item->u1.str); 00151 print_pval_list(fin,item->u2.statements,depth+1); 00152 for (i=0; i<depth; i++) { 00153 fprintf(fin,"\t"); /* depth == indentation */ 00154 } 00155 fprintf(fin,"};\n\n"); 00156 break; 00157 00158 case PV_MACRO_CALL: 00159 fprintf(fin,"&%s(", item->u1.str); 00160 for (lp=item->u2.arglist; lp; lp=lp->next) { 00161 if ( lp != item->u2.arglist ) 00162 fprintf(fin,", "); 00163 fprintf(fin,"%s", lp->u1.str); 00164 } 00165 fprintf(fin,");\n"); 00166 break; 00167 00168 case PV_APPLICATION_CALL: 00169 fprintf(fin,"%s(", item->u1.str); 00170 for (lp=item->u2.arglist; lp; lp=lp->next) { 00171 if ( lp != item->u2.arglist ) 00172 fprintf(fin,","); 00173 fprintf(fin,"%s", lp->u1.str); 00174 } 00175 fprintf(fin,");\n"); 00176 break; 00177 00178 case PV_CASE: 00179 fprintf(fin,"case %s:\n", item->u1.str); 00180 print_pval_list(fin,item->u2.statements, depth+1); 00181 break; 00182 00183 case PV_PATTERN: 00184 fprintf(fin,"pattern %s:\n", item->u1.str); 00185 print_pval_list(fin,item->u2.statements, depth+1); 00186 break; 00187 00188 case PV_DEFAULT: 00189 fprintf(fin,"default:\n"); 00190 print_pval_list(fin,item->u2.statements, depth+1); 00191 break; 00192 00193 case PV_CATCH: 00194 fprintf(fin,"catch %s {\n", item->u1.str); 00195 print_pval_list(fin,item->u2.statements, depth+1); 00196 for (i=0; i<depth; i++) { 00197 fprintf(fin,"\t"); /* depth == indentation */ 00198 } 00199 fprintf(fin,"};\n"); 00200 break; 00201 00202 case PV_SWITCHES: 00203 fprintf(fin,"switches {\n"); 00204 print_pval_list(fin,item->u1.list,depth+1); 00205 for (i=0; i<depth; i++) { 00206 fprintf(fin,"\t"); /* depth == indentation */ 00207 } 00208 fprintf(fin,"};\n"); 00209 break; 00210 00211 case PV_ESWITCHES: 00212 fprintf(fin,"eswitches {\n"); 00213 print_pval_list(fin,item->u1.list,depth+1); 00214 for (i=0; i<depth; i++) { 00215 fprintf(fin,"\t"); /* depth == indentation */ 00216 } 00217 fprintf(fin,"};\n"); 00218 break; 00219 00220 case PV_INCLUDES: 00221 fprintf(fin,"includes {\n"); 00222 for (lp=item->u1.list; lp; lp=lp->next) { 00223 for (i=0; i<depth+1; i++) { 00224 fprintf(fin,"\t"); /* depth == indentation */ 00225 } 00226 fprintf(fin,"%s", lp->u1.str); /* usually, words are encapsulated in something else */ 00227 if (lp->u2.arglist) 00228 fprintf(fin,"|%s|%s|%s|%s", 00229 lp->u2.arglist->u1.str, 00230 lp->u2.arglist->next->u1.str, 00231 lp->u2.arglist->next->next->u1.str, 00232 lp->u2.arglist->next->next->next->u1.str 00233 ); 00234 fprintf(fin,";\n"); /* usually, words are encapsulated in something else */ 00235 } 00236 00237 for (i=0; i<depth; i++) { 00238 fprintf(fin,"\t"); /* depth == indentation */ 00239 } 00240 fprintf(fin,"};\n"); 00241 break; 00242 00243 case PV_STATEMENTBLOCK: 00244 fprintf(fin,"{\n"); 00245 print_pval_list(fin,item->u1.list, depth+1); 00246 for (i=0; i<depth; i++) { 00247 fprintf(fin,"\t"); /* depth == indentation */ 00248 } 00249 fprintf(fin,"}\n"); 00250 break; 00251 00252 case PV_VARDEC: 00253 fprintf(fin,"%s=%s;\n", item->u1.str, item->u2.val); 00254 break; 00255 00256 case PV_LOCALVARDEC: 00257 fprintf(fin,"local %s=%s;\n", item->u1.str, item->u2.val); 00258 break; 00259 00260 case PV_GOTO: 00261 fprintf(fin,"goto %s", item->u1.list->u1.str); 00262 if ( item->u1.list->next ) 00263 fprintf(fin,",%s", item->u1.list->next->u1.str); 00264 if ( item->u1.list->next && item->u1.list->next->next ) 00265 fprintf(fin,",%s", item->u1.list->next->next->u1.str); 00266 fprintf(fin,"\n"); 00267 break; 00268 00269 case PV_LABEL: 00270 fprintf(fin,"%s:\n", item->u1.str); 00271 break; 00272 00273 case PV_FOR: 00274 fprintf(fin,"for (%s; %s; %s)\n", item->u1.for_init, item->u2.for_test, item->u3.for_inc); 00275 print_pval_list(fin,item->u4.for_statements,depth+1); 00276 break; 00277 00278 case PV_WHILE: 00279 fprintf(fin,"while (%s)\n", item->u1.str); 00280 print_pval_list(fin,item->u2.statements,depth+1); 00281 break; 00282 00283 case PV_BREAK: 00284 fprintf(fin,"break;\n"); 00285 break; 00286 00287 case PV_RETURN: 00288 fprintf(fin,"return;\n"); 00289 break; 00290 00291 case PV_CONTINUE: 00292 fprintf(fin,"continue;\n"); 00293 break; 00294 00295 case PV_RANDOM: 00296 case PV_IFTIME: 00297 case PV_IF: 00298 if ( item->type == PV_IFTIME ) { 00299 00300 fprintf(fin,"ifTime ( %s|%s|%s|%s )\n", 00301 item->u1.list->u1.str, 00302 item->u1.list->next->u1.str, 00303 item->u1.list->next->next->u1.str, 00304 item->u1.list->next->next->next->u1.str 00305 ); 00306 } else if ( item->type == PV_RANDOM ) { 00307 fprintf(fin,"random ( %s )\n", item->u1.str ); 00308 } else 00309 fprintf(fin,"if ( %s )\n", item->u1.str); 00310 if ( item->u2.statements && item->u2.statements->next ) { 00311 for (i=0; i<depth; i++) { 00312 fprintf(fin,"\t"); /* depth == indentation */ 00313 } 00314 fprintf(fin,"{\n"); 00315 print_pval_list(fin,item->u2.statements,depth+1); 00316 for (i=0; i<depth; i++) { 00317 fprintf(fin,"\t"); /* depth == indentation */ 00318 } 00319 if ( item->u3.else_statements ) 00320 fprintf(fin,"}\n"); 00321 else 00322 fprintf(fin,"};\n"); 00323 } else if (item->u2.statements ) { 00324 print_pval_list(fin,item->u2.statements,depth+1); 00325 } else { 00326 if (item->u3.else_statements ) 00327 fprintf(fin, " {} "); 00328 else 00329 fprintf(fin, " {}; "); 00330 } 00331 if ( item->u3.else_statements ) { 00332 for (i=0; i<depth; i++) { 00333 fprintf(fin,"\t"); /* depth == indentation */ 00334 } 00335 fprintf(fin,"else\n"); 00336 print_pval_list(fin,item->u3.else_statements, depth); 00337 } 00338 break; 00339 00340 case PV_SWITCH: 00341 fprintf(fin,"switch( %s ) {\n", item->u1.str); 00342 print_pval_list(fin,item->u2.statements,depth+1); 00343 for (i=0; i<depth; i++) { 00344 fprintf(fin,"\t"); /* depth == indentation */ 00345 } 00346 fprintf(fin,"}\n"); 00347 break; 00348 00349 case PV_EXTENSION: 00350 if ( item->u4.regexten ) 00351 fprintf(fin, "regexten "); 00352 if ( item->u3.hints ) 00353 fprintf(fin,"hints(%s) ", item->u3.hints); 00354 00355 fprintf(fin,"%s => ", item->u1.str); 00356 print_pval_list(fin,item->u2.statements,depth+1); 00357 fprintf(fin,"\n"); 00358 break; 00359 00360 case PV_IGNOREPAT: 00361 fprintf(fin,"ignorepat => %s;\n", item->u1.str); 00362 break; 00363 00364 case PV_GLOBALS: 00365 fprintf(fin,"globals {\n"); 00366 print_pval_list(fin,item->u1.statements,depth+1); 00367 for (i=0; i<depth; i++) { 00368 fprintf(fin,"\t"); /* depth == indentation */ 00369 } 00370 fprintf(fin,"}\n"); 00371 break; 00372 } 00373 }
static void print_pval_list | ( | FILE * | fin, | |
pval * | item, | |||
int | depth | |||
) | [static] |
Definition at line 375 of file pval.c.
References pval::next, and print_pval().
Referenced by ael2_print(), and print_pval().
00376 { 00377 pval *i; 00378 00379 for (i=item; i; i=i->next) { 00380 print_pval(fin, i, depth); 00381 } 00382 }
Definition at line 5304 of file pval.c.
References pval::arglist, linku1(), PV_APPLICATION_CALL, pvalCheckType(), and pval::u2.
05305 { 05306 if (!pvalCheckType(p, "pvalAppCallAddArg", PV_APPLICATION_CALL)) 05307 return; 05308 if (!p->u2.arglist) 05309 p->u2.arglist = arg; 05310 else 05311 linku1(p->u2.arglist, arg); 05312 }
char* pvalAppCallGetAppName | ( | pval * | p | ) |
Definition at line 5290 of file pval.c.
References PV_APPLICATION_CALL, pvalCheckType(), pval::str, and pval::u1.
05291 { 05292 if (!pvalCheckType(p, "pvalAppCallGetAppName", PV_APPLICATION_CALL)) 05293 return 0; 05294 return p->u1.str; 05295 }
void pvalAppCallSetAppName | ( | pval * | p, | |
char * | name | |||
) |
Definition at line 5283 of file pval.c.
References PV_APPLICATION_CALL, pvalCheckType(), pval::str, and pval::u1.
05284 { 05285 if (!pvalCheckType(p, "pvalAppCallSetAppName", PV_APPLICATION_CALL)) 05286 return; 05287 p->u1.str = name; 05288 }
Definition at line 5297 of file pval.c.
References pval::arglist, PV_APPLICATION_CALL, pvalCheckType(), and pval::u2.
05298 { 05299 if (!pvalCheckType(p, "pvalAppCallSetArglist", PV_APPLICATION_CALL)) 05300 return; 05301 p->u2.arglist = arglist; 05302 }
Definition at line 5314 of file pval.c.
References pval::arglist, pval::next, PV_APPLICATION_CALL, pvalCheckType(), and pval::u2.
05315 { 05316 if (!pvalCheckType(p, "pvalAppCallWalkArgs", PV_APPLICATION_CALL)) 05317 return 0; 05318 if (!(*args)) 05319 *args = p->u2.arglist; 05320 else { 05321 *args = (*args)->next; 05322 } 05323 return *args; 05324 }
Definition at line 5339 of file pval.c.
References pval::arglist, linku1(), pval::statements, and pval::u2.
05340 { 05341 if (!p->u2.arglist) 05342 p->u2.statements = statement; 05343 else 05344 linku1(p->u2.statements, statement); 05345 }
Definition at line 5347 of file pval.c.
References pval::next, pval::statements, and pval::u2.
05348 { 05349 if (!(*statement)) 05350 *statement = p->u2.statements; 05351 else { 05352 *statement = (*statement)->next; 05353 } 05354 return *statement; 05355 }
char* pvalCasePatGetVal | ( | pval * | p | ) |
void pvalCasePatSetVal | ( | pval * | p, | |
char * | val | |||
) |
Definition at line 5327 of file pval.c.
References PV_APPLICATION_CALL, pvalCheckType(), pval::str, and pval::u1.
05328 { 05329 if (!pvalCheckType(p, "pvalAppCallWalkArgs", PV_APPLICATION_CALL)) 05330 return; 05331 p->u1.str = val; 05332 }
char* pvalCatchGetExtName | ( | pval * | p | ) |
Definition at line 5365 of file pval.c.
References PV_CATCH, pvalCheckType(), pval::str, and pval::u1.
05366 { 05367 if (!pvalCheckType(p, "pvalCatchGetExtName", PV_CATCH)) 05368 return 0; 05369 return p->u1.str; 05370 }
Definition at line 5379 of file pval.c.
References PV_CATCH, pvalCheckType(), pval::statements, and pval::u2.
05380 { 05381 if (!pvalCheckType(p, "pvalCatchGetStatement", PV_CATCH)) 05382 return 0; 05383 return p->u2.statements; 05384 }
void pvalCatchSetExtName | ( | pval * | p, | |
char * | name | |||
) |
Definition at line 5372 of file pval.c.
References PV_CATCH, pvalCheckType(), pval::statements, and pval::u2.
05373 { 05374 if (!pvalCheckType(p, "pvalCatchSetStatement", PV_CATCH)) 05375 return; 05376 p->u2.statements = statement; 05377 }
Definition at line 5070 of file pval.c.
References ast_log(), LOG_ERROR, and pval::type.
Referenced by pvalAppCallAddArg(), pvalAppCallGetAppName(), pvalAppCallSetAppName(), pvalAppCallSetArglist(), pvalAppCallWalkArgs(), pvalCasePatSetVal(), pvalCatchGetExtName(), pvalCatchGetStatement(), pvalCatchSetExtName(), pvalCatchSetStatement(), pvalContextAddStatement(), pvalContextGetAbstract(), pvalContextGetName(), pvalContextSetAbstract(), pvalContextSetName(), pvalContextUnsetAbstract(), pvalContextWalkStatements(), pvalESwitchesAddSwitch(), pvalESwitchesWalkNames(), pvalExtenGetHints(), pvalExtenGetName(), pvalExtenGetRegexten(), pvalExtenGetStatement(), pvalExtenSetHints(), pvalExtenSetName(), pvalExtenSetRegexten(), pvalExtenSetStatement(), pvalExtenUnSetRegexten(), pvalForGetInc(), pvalForGetInit(), pvalForGetStatement(), pvalForGetTest(), pvalForSetInc(), pvalForSetInit(), pvalForSetStatement(), pvalForSetTest(), pvalGlobalsWalkStatements(), pvalGotoGetTarget(), pvalGotoSetTarget(), pvalIfGetCondition(), pvalIfSetCondition(), pvalIfTimeGetCondition(), pvalIfTimeSetCondition(), pvalIgnorePatGetPattern(), pvalIgnorePatSetPattern(), pvalIncludeGetTimeConstraints(), pvalIncludesAddInclude(), pvalIncludesAddIncludeWithTimeConstraints(), pvalIncludesWalk(), pvalLabelGetName(), pvalLabelSetName(), pvalMacroAddArg(), pvalMacroAddStatement(), pvalMacroCallAddArg(), pvalMacroCallGetMacroName(), pvalMacroCallSetArglist(), pvalMacroCallSetMacroName(), pvalMacroCallWalkArgs(), pvalMacroGetName(), pvalMacroSetArglist(), pvalMacroSetName(), pvalMacroWalkArgs(), pvalMacroWalkStatements(), pvalRandomGetCondition(), pvalRandomSetCondition(), pvalStatementBlockAddStatement(), pvalStatementBlockWalkStatements(), pvalSwitchAddCase(), pvalSwitchesAddSwitch(), pvalSwitchesWalkNames(), pvalSwitchGetTestexpr(), pvalSwitchSetTestexpr(), pvalSwitchWalkCases(), pvalVarDecGetValue(), pvalVarDecGetVarname(), pvalVarDecSetValue(), pvalVarDecSetVarname(), pvalWordGetString(), and pvalWordSetString().
Definition at line 5755 of file pval.c.
References pval::else_statements, and pval::u3.
05756 { 05757 return p->u3.else_statements; 05758 }
Definition at line 5750 of file pval.c.
References pval::statements, and pval::u2.
05751 { 05752 return p->u2.statements; 05753 }
Definition at line 5745 of file pval.c.
References pval::else_statements, and pval::u3.
05746 { 05747 p->u3.else_statements = statement; 05748 }
Definition at line 5740 of file pval.c.
References pval::statements, and pval::u2.
05741 { 05742 p->u2.statements = statement; 05743 }
Definition at line 5216 of file pval.c.
References linku1(), PV_CONTEXT, pvalCheckType(), pval::statements, and pval::u2.
05217 { 05218 if (!pvalCheckType(p, "pvalContextAddStatement", PV_CONTEXT)) 05219 return; 05220 if (!p->u2.statements) 05221 p->u2.statements = statement; 05222 else 05223 linku1(p->u2.statements, statement); 05224 }
int pvalContextGetAbstract | ( | pval * | p | ) |
Definition at line 5207 of file pval.c.
References pval::abstract, PV_CONTEXT, pvalCheckType(), and pval::u3.
05208 { 05209 if (!pvalCheckType(p, "pvalContextGetAbstract", PV_CONTEXT)) 05210 return 0; 05211 return p->u3.abstract; 05212 }
char* pvalContextGetName | ( | pval * | p | ) |
Definition at line 5186 of file pval.c.
References PV_CONTEXT, pvalCheckType(), pval::str, and pval::u1.
05187 { 05188 if (!pvalCheckType(p, "pvalContextGetName", PV_CONTEXT)) 05189 return 0; 05190 return p->u1.str; 05191 }
void pvalContextSetAbstract | ( | pval * | p | ) |
Definition at line 5193 of file pval.c.
References pval::abstract, PV_CONTEXT, pvalCheckType(), and pval::u3.
05194 { 05195 if (!pvalCheckType(p, "pvalContextSetAbstract", PV_CONTEXT)) 05196 return; 05197 p->u3.abstract = 1; 05198 }
void pvalContextSetName | ( | pval * | p, | |
char * | name | |||
) |
Definition at line 5179 of file pval.c.
References PV_CONTEXT, pvalCheckType(), pval::str, and pval::u1.
05180 { 05181 if (!pvalCheckType(p, "pvalContextSetName", PV_CONTEXT)) 05182 return; 05183 p->u1.str = name; 05184 }
void pvalContextUnsetAbstract | ( | pval * | p | ) |
Definition at line 5200 of file pval.c.
References pval::abstract, PV_CONTEXT, pvalCheckType(), and pval::u3.
05201 { 05202 if (!pvalCheckType(p, "pvalContextUnsetAbstract", PV_CONTEXT)) 05203 return; 05204 p->u3.abstract = 0; 05205 }
Definition at line 5226 of file pval.c.
References pval::next, PV_CONTEXT, pvalCheckType(), pval::statements, and pval::u2.
05227 { 05228 if (!pvalCheckType(p, "pvalContextWalkStatements", PV_CONTEXT)) 05229 return 0; 05230 if (!(*statements)) 05231 *statements = p->u2.statements; 05232 else { 05233 *statements = (*statements)->next; 05234 } 05235 return *statements; 05236 }
Definition at line 5081 of file pval.c.
References calloc, and pval::type.
Referenced by pvalESwitchesAddSwitch(), pvalGotoSetTarget(), pvalIfTimeSetCondition(), pvalIncludesAddInclude(), pvalIncludesAddIncludeWithTimeConstraints(), and pvalSwitchesAddSwitch().
void pvalESwitchesAddSwitch | ( | pval * | p, | |
char * | name | |||
) |
Definition at line 5409 of file pval.c.
References linku1(), pval::list, PV_ESWITCHES, PV_WORD, pvalCheckType(), pvalCreateNode(), pval::str, and pval::u1.
05410 { 05411 pval *s; 05412 if (!pvalCheckType(p, "pvalESwitchesAddSwitch", PV_ESWITCHES)) 05413 return; 05414 s = pvalCreateNode(PV_WORD); 05415 s->u1.str = name; 05416 p->u1.list = linku1(p->u1.list, s); 05417 }
Definition at line 5419 of file pval.c.
References pval::list, pval::next, PV_ESWITCHES, pvalCheckType(), pval::str, and pval::u1.
05420 { 05421 if (!pvalCheckType(p, "pvalESwitchesWalkNames", PV_ESWITCHES)) 05422 return 0; 05423 if (!(*next_item)) 05424 *next_item = p->u1.list; 05425 else { 05426 *next_item = (*next_item)->next; 05427 } 05428 return (*next_item)->u1.str; 05429 }
char* pvalExtenGetHints | ( | pval * | p | ) |
Definition at line 5841 of file pval.c.
References pval::hints, PV_EXTENSION, pvalCheckType(), and pval::u3.
05842 { 05843 if (!pvalCheckType(p, "pvalExtenGetHints", PV_EXTENSION)) 05844 return 0; 05845 return p->u3.hints; 05846 }
char* pvalExtenGetName | ( | pval * | p | ) |
Definition at line 5806 of file pval.c.
References PV_EXTENSION, pvalCheckType(), pval::str, and pval::u1.
05807 { 05808 if (!pvalCheckType(p, "pvalExtenGetName", PV_EXTENSION)) 05809 return 0; 05810 return p->u1.str; 05811 }
int pvalExtenGetRegexten | ( | pval * | p | ) |
Definition at line 5827 of file pval.c.
References PV_EXTENSION, pvalCheckType(), pval::regexten, and pval::u4.
05828 { 05829 if (!pvalCheckType(p, "pvalExtenGetRegexten", PV_EXTENSION)) 05830 return 0; 05831 return p->u4.regexten; 05832 }
Definition at line 5855 of file pval.c.
References PV_EXTENSION, pvalCheckType(), pval::statements, and pval::u2.
05856 { 05857 if (!pvalCheckType(p, "pvalExtenGetStatement", PV_EXTENSION)) 05858 return 0; 05859 return p->u2.statements; 05860 }
void pvalExtenSetHints | ( | pval * | p, | |
char * | hints | |||
) |
Definition at line 5834 of file pval.c.
References pval::hints, PV_EXTENSION, pvalCheckType(), and pval::u3.
05835 { 05836 if (!pvalCheckType(p, "pvalExtenSetHints", PV_EXTENSION)) 05837 return; 05838 p->u3.hints = hints; 05839 }
void pvalExtenSetName | ( | pval * | p, | |
char * | name | |||
) |
Definition at line 5799 of file pval.c.
References PV_EXTENSION, pvalCheckType(), pval::str, and pval::u1.
05800 { 05801 if (!pvalCheckType(p, "pvalExtenSetName", PV_EXTENSION)) 05802 return; 05803 p->u1.str = name; 05804 }
void pvalExtenSetRegexten | ( | pval * | p | ) |
Definition at line 5813 of file pval.c.
References PV_EXTENSION, pvalCheckType(), pval::regexten, and pval::u4.
05814 { 05815 if (!pvalCheckType(p, "pvalExtenSetRegexten", PV_EXTENSION)) 05816 return; 05817 p->u4.regexten = 1; 05818 }
Definition at line 5848 of file pval.c.
References PV_EXTENSION, pvalCheckType(), pval::statements, and pval::u2.
05849 { 05850 if (!pvalCheckType(p, "pvalExtenSetStatement", PV_EXTENSION)) 05851 return; 05852 p->u2.statements = statement; 05853 }
void pvalExtenUnSetRegexten | ( | pval * | p | ) |
Definition at line 5820 of file pval.c.
References PV_EXTENSION, pvalCheckType(), pval::regexten, and pval::u4.
05821 { 05822 if (!pvalCheckType(p, "pvalExtenUnSetRegexten", PV_EXTENSION)) 05823 return; 05824 p->u4.regexten = 0; 05825 }
char* pvalForGetInc | ( | pval * | p | ) |
Definition at line 5667 of file pval.c.
References pval::for_inc, PV_FOR, pvalCheckType(), and pval::u3.
05668 { 05669 if (!pvalCheckType(p, "pvalForGetInc", PV_FOR)) 05670 return 0; 05671 return p->u3.for_inc; 05672 }
char* pvalForGetInit | ( | pval * | p | ) |
Definition at line 5653 of file pval.c.
References pval::for_init, PV_FOR, pvalCheckType(), and pval::u1.
05654 { 05655 if (!pvalCheckType(p, "pvalForGetInit", PV_FOR)) 05656 return 0; 05657 return p->u1.for_init; 05658 }
Definition at line 5674 of file pval.c.
References pval::for_statements, PV_FOR, pvalCheckType(), and pval::u4.
05675 { 05676 if (!pvalCheckType(p, "pvalForGetStatement", PV_FOR)) 05677 return 0; 05678 return p->u4.for_statements; 05679 }
char* pvalForGetTest | ( | pval * | p | ) |
Definition at line 5660 of file pval.c.
References pval::for_test, PV_FOR, pvalCheckType(), and pval::u2.
05661 { 05662 if (!pvalCheckType(p, "pvalForGetTest", PV_FOR)) 05663 return 0; 05664 return p->u2.for_test; 05665 }
void pvalForSetInc | ( | pval * | p, | |
char * | inc | |||
) |
Definition at line 5639 of file pval.c.
References pval::for_inc, PV_FOR, pvalCheckType(), and pval::u3.
05640 { 05641 if (!pvalCheckType(p, "pvalForSetInc", PV_FOR)) 05642 return; 05643 p->u3.for_inc = inc; 05644 }
void pvalForSetInit | ( | pval * | p, | |
char * | init | |||
) |
Definition at line 5625 of file pval.c.
References pval::for_init, PV_FOR, pvalCheckType(), and pval::u1.
05626 { 05627 if (!pvalCheckType(p, "pvalForSetInit", PV_FOR)) 05628 return; 05629 p->u1.for_init = init; 05630 }
Definition at line 5646 of file pval.c.
References pval::for_statements, PV_FOR, pvalCheckType(), and pval::u4.
05647 { 05648 if (!pvalCheckType(p, "pvalForSetStatement", PV_FOR)) 05649 return; 05650 p->u4.for_statements = statement; 05651 }
void pvalForSetTest | ( | pval * | p, | |
char * | test | |||
) |
Definition at line 5632 of file pval.c.
References pval::for_test, PV_FOR, pvalCheckType(), and pval::u2.
05633 { 05634 if (!pvalCheckType(p, "pvalForSetTest", PV_FOR)) 05635 return; 05636 p->u2.for_test = test; 05637 }
Definition at line 5878 of file pval.c.
References ast_log(), linku1(), LOG_ERROR, PV_GLOBALS, pval::statements, pval::type, and pval::u1.
05879 { 05880 if (p->type != PV_GLOBALS) { 05881 ast_log(LOG_ERROR, "pvalGlobalsAddStatement called where first arg is not a Globals!\n"); 05882 } else { 05883 if (!p->u1.statements) { 05884 p->u1.statements = statement; 05885 } else { 05886 p->u1.statements = linku1(p->u1.statements,statement); 05887 } 05888 } 05889 }
Definition at line 5891 of file pval.c.
References pval::next, PV_GLOBALS, and pvalCheckType().
05892 { 05893 if (!pvalCheckType(p, "pvalGlobalsWalkStatements", PV_GLOBALS)) 05894 return 0; 05895 if (!*next_statement) { 05896 *next_statement = p; 05897 return p; 05898 } else { 05899 *next_statement = (*next_statement)->next; 05900 return (*next_statement)->next; 05901 } 05902 }
void pvalGotoGetTarget | ( | pval * | p, | |
char ** | context, | |||
char ** | exten, | |||
char ** | label | |||
) |
Definition at line 5583 of file pval.c.
References pval::list, pval::next, PV_GOTO, pvalCheckType(), pval::str, and pval::u1.
05584 { 05585 if (!pvalCheckType(p, "pvalGotoGetTarget", PV_GOTO)) 05586 return; 05587 if (p->u1.list && p->u1.list->next && p->u1.list->next->next) { 05588 *context = p->u1.list->u1.str; 05589 *exten = p->u1.list->next->u1.str; 05590 *label = p->u1.list->next->next->u1.str; 05591 05592 } else if (p->u1.list && p->u1.list->next ) { 05593 *exten = p->u1.list->u1.str; 05594 *label = p->u1.list->next->u1.str; 05595 *context = 0; 05596 05597 } else if (p->u1.list) { 05598 *label = p->u1.list->u1.str; 05599 *context = 0; 05600 *exten = 0; 05601 05602 } else { 05603 *context = 0; 05604 *exten = 0; 05605 *label = 0; 05606 } 05607 }
void pvalGotoSetTarget | ( | pval * | p, | |
char * | context, | |||
char * | exten, | |||
char * | label | |||
) |
Definition at line 5547 of file pval.c.
References ext, pval::list, pval::next, PV_GOTO, PV_WORD, pvalCheckType(), pvalCreateNode(), pval::str, and pval::u1.
05548 { 05549 pval *con, *ext, *pri; 05550 05551 if (!pvalCheckType(p, "pvalGotoSetTarget", PV_GOTO)) 05552 return; 05553 if (context && strlen(context)) { 05554 con = pvalCreateNode(PV_WORD); 05555 ext = pvalCreateNode(PV_WORD); 05556 pri = pvalCreateNode(PV_WORD); 05557 05558 con->u1.str = context; 05559 ext->u1.str = exten; 05560 pri->u1.str = label; 05561 05562 con->next = ext; 05563 ext->next = pri; 05564 p->u1.list = con; 05565 } else if (exten && strlen(exten)) { 05566 ext = pvalCreateNode(PV_WORD); 05567 pri = pvalCreateNode(PV_WORD); 05568 05569 ext->u1.str = exten; 05570 pri->u1.str = label; 05571 05572 ext->next = pri; 05573 p->u1.list = ext; 05574 } else { 05575 pri = pvalCreateNode(PV_WORD); 05576 05577 pri->u1.str = label; 05578 05579 p->u1.list = pri; 05580 } 05581 }
char* pvalIfGetCondition | ( | pval * | p | ) |
Definition at line 5690 of file pval.c.
References PV_IFTIME, pvalCheckType(), pval::str, and pval::u1.
05691 { 05692 if (!pvalCheckType(p, "pvalIfGetCondition", PV_IFTIME)) 05693 return 0; 05694 return p->u1.str; 05695 }
void pvalIfSetCondition | ( | pval * | p, | |
char * | expr | |||
) |
Definition at line 5683 of file pval.c.
References PV_IF, pvalCheckType(), pval::str, and pval::u1.
05684 { 05685 if (!pvalCheckType(p, "pvalIfSetCondition", PV_IF)) 05686 return; 05687 p->u1.str = expr; 05688 }
void pvalIfTimeGetCondition | ( | pval * | p, | |
char ** | hour_range, | |||
char ** | dow_range, | |||
char ** | dom_range, | |||
char ** | month_range | |||
) |
Definition at line 5716 of file pval.c.
References pval::list, pval::next, PV_IFTIME, pvalCheckType(), pval::str, and pval::u1.
void pvalIfTimeSetCondition | ( | pval * | p, | |
char * | hour_range, | |||
char * | dow_range, | |||
char * | dom_range, | |||
char * | mon_range | |||
) |
Definition at line 5697 of file pval.c.
References pval::list, pval::next, PV_IFTIME, PV_WORD, pvalCheckType(), pvalCreateNode(), pvalWordSetString(), and pval::u1.
05697 : 24-hour format begin-end|dow range|dom range|month range */ 05698 { 05699 pval *hr = pvalCreateNode(PV_WORD); 05700 pval *dow = pvalCreateNode(PV_WORD); 05701 pval *dom = pvalCreateNode(PV_WORD); 05702 pval *mon = pvalCreateNode(PV_WORD); 05703 if (!pvalCheckType(p, "pvalIfTimeSetCondition", PV_IFTIME)) 05704 return; 05705 pvalWordSetString(hr, hour_range); 05706 pvalWordSetString(dow, dow_range); 05707 pvalWordSetString(dom, dom_range); 05708 pvalWordSetString(mon, mon_range); 05709 dom->next = mon; 05710 dow->next = dom; 05711 hr->next = dow; 05712 p->u1.list = hr; 05713 }
char* pvalIgnorePatGetPattern | ( | pval * | p | ) |
Definition at line 5870 of file pval.c.
References PV_IGNOREPAT, pvalCheckType(), pval::str, and pval::u1.
05871 { 05872 if (!pvalCheckType(p, "pvalIgnorePatGetPattern", PV_IGNOREPAT)) 05873 return 0; 05874 return p->u1.str; 05875 }
void pvalIgnorePatSetPattern | ( | pval * | p, | |
char * | pat | |||
) |
Definition at line 5863 of file pval.c.
References PV_IGNOREPAT, pvalCheckType(), pval::str, and pval::u1.
05864 { 05865 if (!pvalCheckType(p, "pvalIgnorePatSetPattern", PV_IGNOREPAT)) 05866 return; 05867 p->u1.str = pat; 05868 }
void pvalIncludeGetTimeConstraints | ( | pval * | p, | |
char ** | hour_range, | |||
char ** | dom_range, | |||
char ** | dow_range, | |||
char ** | month_range | |||
) |
Definition at line 5470 of file pval.c.
References pval::arglist, pval::next, PV_WORD, pvalCheckType(), pval::str, pval::u1, and pval::u2.
05471 { 05472 if (!pvalCheckType(p, "pvalIncludeGetTimeConstraints", PV_WORD)) 05473 return; 05474 if (p->u2.arglist) { 05475 *hour_range = p->u2.arglist->u1.str; 05476 *dom_range = p->u2.arglist->next->u1.str; 05477 *dow_range = p->u2.arglist->next->next->u1.str; 05478 *month_range = p->u2.arglist->next->next->next->u1.str; 05479 } else { 05480 *hour_range = 0; 05481 *dom_range = 0; 05482 *dow_range = 0; 05483 *month_range = 0; 05484 } 05485 }
void pvalIncludesAddInclude | ( | pval * | p, | |
const char * | include | |||
) |
Definition at line 5432 of file pval.c.
References linku1(), pval::list, PV_INCLUDES, PV_WORD, pvalCheckType(), pvalCreateNode(), pval::str, and pval::u1.
05433 { 05434 pval *s; 05435 if (!pvalCheckType(p, "pvalIncludesAddSwitch", PV_INCLUDES)) 05436 return; 05437 s = pvalCreateNode(PV_WORD); 05438 s->u1.str = (char *)include; 05439 p->u1.list = linku1(p->u1.list, s); 05440 }
void pvalIncludesAddIncludeWithTimeConstraints | ( | pval * | p, | |
const char * | include, | |||
char * | hour_range, | |||
char * | dom_range, | |||
char * | dow_range, | |||
char * | month_range | |||
) |
Definition at line 5443 of file pval.c.
References pval::arglist, linku1(), pval::list, pval::next, PV_INCLUDES, PV_WORD, pvalCheckType(), pvalCreateNode(), pval::str, pval::u1, and pval::u2.
05444 { 05445 pval *hr = pvalCreateNode(PV_WORD); 05446 pval *dom = pvalCreateNode(PV_WORD); 05447 pval *dow = pvalCreateNode(PV_WORD); 05448 pval *mon = pvalCreateNode(PV_WORD); 05449 pval *s = pvalCreateNode(PV_WORD); 05450 05451 if (!pvalCheckType(p, "pvalIncludeAddIncludeWithTimeConstraints", PV_INCLUDES)) 05452 return; 05453 05454 s->u1.str = (char *)include; 05455 p->u1.list = linku1(p->u1.list, s); 05456 05457 hr->u1.str = hour_range; 05458 dom->u1.str = dom_range; 05459 dow->u1.str = dow_range; 05460 mon->u1.str = month_range; 05461 05462 s->u2.arglist = hr; 05463 05464 hr->next = dom; 05465 dom->next = dow; 05466 dow->next = mon; 05467 mon->next = 0; 05468 }
Definition at line 5487 of file pval.c.
References pval::list, pval::next, PV_INCLUDES, pvalCheckType(), pval::str, and pval::u1.
05488 { 05489 if (!pvalCheckType(p, "pvalIncludesWalk", PV_INCLUDES)) 05490 return 0; 05491 if (!(*next_item)) 05492 *next_item = p->u1.list; 05493 else { 05494 *next_item = (*next_item)->next; 05495 } 05496 return (*next_item)->u1.str; 05497 }
char* pvalLabelGetName | ( | pval * | p | ) |
Definition at line 5617 of file pval.c.
References PV_LABEL, pvalCheckType(), pval::str, and pval::u1.
05618 { 05619 if (!pvalCheckType(p, "pvalLabelGetName", PV_LABEL)) 05620 return 0; 05621 return p->u1.str; 05622 }
void pvalLabelSetName | ( | pval * | p, | |
char * | name | |||
) |
Definition at line 5130 of file pval.c.
References pval::arglist, linku1(), PV_MACRO, pvalCheckType(), and pval::u2.
Definition at line 5153 of file pval.c.
References linku1(), pval::macro_statements, PV_MACRO, pvalCheckType(), and pval::u3.
05154 { 05155 if (!pvalCheckType(p, "pvalMacroAddStatement", PV_MACRO)) 05156 return; 05157 if (!p->u3.macro_statements) 05158 p->u3.macro_statements = statement; 05159 else 05160 linku1(p->u3.macro_statements, statement); 05161 05162 05163 }
Definition at line 5260 of file pval.c.
References pval::arglist, linku1(), PV_MACRO_CALL, pvalCheckType(), and pval::u2.
05261 { 05262 if (!pvalCheckType(p, "pvalMacroCallGetAddArg", PV_MACRO_CALL)) 05263 return; 05264 if (!p->u2.arglist) 05265 p->u2.arglist = arg; 05266 else 05267 linku1(p->u2.arglist, arg); 05268 }
char* pvalMacroCallGetMacroName | ( | pval * | p | ) |
Definition at line 5246 of file pval.c.
References PV_MACRO_CALL, pvalCheckType(), pval::str, and pval::u1.
05247 { 05248 if (!pvalCheckType(p, "pvalMacroCallGetMacroName", PV_MACRO_CALL)) 05249 return 0; 05250 return p->u1.str; 05251 }
Definition at line 5253 of file pval.c.
References pval::arglist, PV_MACRO_CALL, pvalCheckType(), and pval::u2.
05254 { 05255 if (!pvalCheckType(p, "pvalMacroCallSetArglist", PV_MACRO_CALL)) 05256 return; 05257 p->u2.arglist = arglist; 05258 }
void pvalMacroCallSetMacroName | ( | pval * | p, | |
char * | name | |||
) |
Definition at line 5239 of file pval.c.
References PV_MACRO_CALL, pvalCheckType(), pval::str, and pval::u1.
05240 { 05241 if (!pvalCheckType(p, "pvalMacroCallSetMacroName", PV_MACRO_CALL)) 05242 return; 05243 p->u1.str = name; 05244 }
Definition at line 5270 of file pval.c.
References pval::arglist, pval::next, PV_MACRO_CALL, pvalCheckType(), and pval::u2.
05271 { 05272 if (!pvalCheckType(p, "pvalMacroCallWalkArgs", PV_MACRO_CALL)) 05273 return 0; 05274 if (!(*args)) 05275 *args = p->u2.arglist; 05276 else { 05277 *args = (*args)->next; 05278 } 05279 return *args; 05280 }
char* pvalMacroGetName | ( | pval * | p | ) |
Definition at line 5116 of file pval.c.
References PV_MACRO, pvalCheckType(), pval::str, and pval::u1.
05117 { 05118 if (!pvalCheckType(p, "pvalMacroGetName", PV_MACRO)) 05119 return 0; 05120 return p->u1.str; 05121 }
Definition at line 5123 of file pval.c.
References pval::arglist, PV_MACRO, pvalCheckType(), and pval::u2.
05124 { 05125 if (!pvalCheckType(p, "pvalMacroSetArglist", PV_MACRO)) 05126 return; 05127 p->u2.arglist = arglist; 05128 }
void pvalMacroSetName | ( | pval * | p, | |
char * | name | |||
) |
Definition at line 5141 of file pval.c.
References pval::arglist, pval::next, PV_MACRO, pvalCheckType(), and pval::u2.
05142 { 05143 if (!pvalCheckType(p, "pvalMacroWalkArgs", PV_MACRO)) 05144 return 0; 05145 if (!(*arg)) 05146 *arg = p->u2.arglist; 05147 else { 05148 *arg = (*arg)->next; 05149 } 05150 return *arg; 05151 }
Definition at line 5165 of file pval.c.
References pval::macro_statements, pval::next, PV_MACRO, pvalCheckType(), and pval::u3.
05166 { 05167 if (!pvalCheckType(p, "pvalMacroWalkStatements", PV_MACRO)) 05168 return 0; 05169 if (!(*next_statement)) 05170 *next_statement = p->u3.macro_statements; 05171 else { 05172 *next_statement = (*next_statement)->next; 05173 } 05174 return *next_statement; 05175 }
Definition at line 5088 of file pval.c.
References pval::type.
05089 { 05090 return p->type; 05091 }
char* pvalRandomGetCondition | ( | pval * | p | ) |
Definition at line 5733 of file pval.c.
References PV_RANDOM, pvalCheckType(), pval::str, and pval::u1.
05734 { 05735 if (!pvalCheckType(p, "pvalRandomGetCondition", PV_RANDOM)) 05736 return 0; 05737 return p->u1.str; 05738 }
void pvalRandomSetCondition | ( | pval * | p, | |
char * | percent | |||
) |
Definition at line 5726 of file pval.c.
References PV_RANDOM, pvalCheckType(), pval::str, and pval::u1.
05727 { 05728 if (!pvalCheckType(p, "pvalRandomSetCondition", PV_RANDOM)) 05729 return; 05730 p->u1.str = percent; 05731 }
Definition at line 5500 of file pval.c.
References linku1(), pval::list, PV_STATEMENTBLOCK, pvalCheckType(), and pval::u1.
05501 { 05502 if (!pvalCheckType(p, "pvalStatementBlockAddStatement", PV_STATEMENTBLOCK)) 05503 return; 05504 p->u1.list = linku1(p->u1.list, statement); 05505 }
Definition at line 5507 of file pval.c.
References pval::list, pval::next, PV_STATEMENTBLOCK, pvalCheckType(), and pval::u1.
05508 { 05509 if (!pvalCheckType(p, "pvalStatementBlockWalkStatements", PV_STATEMENTBLOCK)) 05510 return 0; 05511 if (!(*next_statement)) 05512 *next_statement = p->u1.list; 05513 else { 05514 *next_statement = (*next_statement)->next; 05515 } 05516 return *next_statement; 05517 }
Definition at line 5774 of file pval.c.
References linku1(), PV_CASE, PV_SWITCH, pvalCheckType(), pval::statements, and pval::u2.
05775 { 05776 if (!pvalCheckType(p, "pvalSwitchAddCase", PV_SWITCH)) 05777 return; 05778 if (!pvalCheckType(Case, "pvalSwitchAddCase", PV_CASE)) 05779 return; 05780 if (!p->u2.statements) 05781 p->u2.statements = Case; 05782 else 05783 linku1(p->u2.statements, Case); 05784 }
void pvalSwitchesAddSwitch | ( | pval * | p, | |
char * | name | |||
) |
Definition at line 5387 of file pval.c.
References linku1(), pval::list, PV_SWITCHES, PV_WORD, pvalCheckType(), pvalCreateNode(), pval::str, and pval::u1.
05388 { 05389 pval *s; 05390 if (!pvalCheckType(p, "pvalSwitchesAddSwitch", PV_SWITCHES)) 05391 return; 05392 s = pvalCreateNode(PV_WORD); 05393 s->u1.str = name; 05394 p->u1.list = linku1(p->u1.list, s); 05395 }
Definition at line 5397 of file pval.c.
References pval::list, pval::next, PV_SWITCHES, pvalCheckType(), pval::str, and pval::u1.
05398 { 05399 if (!pvalCheckType(p, "pvalSwitchesWalkNames", PV_SWITCHES)) 05400 return 0; 05401 if (!(*next_item)) 05402 *next_item = p->u1.list; 05403 else { 05404 *next_item = (*next_item)->next; 05405 } 05406 return (*next_item)->u1.str; 05407 }
char* pvalSwitchGetTestexpr | ( | pval * | p | ) |
Definition at line 5767 of file pval.c.
References PV_SWITCH, pvalCheckType(), pval::str, and pval::u1.
05768 { 05769 if (!pvalCheckType(p, "pvalSwitchGetTestexpr", PV_SWITCH)) 05770 return 0; 05771 return p->u1.str; 05772 }
void pvalSwitchSetTestexpr | ( | pval * | p, | |
char * | expr | |||
) |
Definition at line 5760 of file pval.c.
References PV_SWITCH, pvalCheckType(), pval::str, and pval::u1.
05761 { 05762 if (!pvalCheckType(p, "pvalSwitchSetTestexpr", PV_SWITCH)) 05763 return; 05764 p->u1.str = expr; 05765 }
Definition at line 5786 of file pval.c.
References pval::next, PV_SWITCH, pvalCheckType(), pval::statements, and pval::u2.
05787 { 05788 if (!pvalCheckType(p, "pvalSwitchWalkCases", PV_SWITCH)) 05789 return 0; 05790 if (!(*next_case)) 05791 *next_case = p->u2.statements; 05792 else { 05793 *next_case = (*next_case)->next; 05794 } 05795 return *next_case; 05796 }
Definition at line 5914 of file pval.c.
References pval::next.
char* pvalVarDecGetValue | ( | pval * | p | ) |
Definition at line 5540 of file pval.c.
References PV_VARDEC, pvalCheckType(), pval::u2, and pval::val.
05541 { 05542 if (!pvalCheckType(p, "pvalVarDecGetValue", PV_VARDEC)) 05543 return 0; 05544 return p->u2.val; 05545 }
char* pvalVarDecGetVarname | ( | pval * | p | ) |
Definition at line 5533 of file pval.c.
References PV_VARDEC, pvalCheckType(), pval::str, and pval::u1.
05534 { 05535 if (!pvalCheckType(p, "pvalVarDecGetVarname", PV_VARDEC)) 05536 return 0; 05537 return p->u1.str; 05538 }
void pvalVarDecSetValue | ( | pval * | p, | |
char * | value | |||
) |
void pvalVarDecSetVarname | ( | pval * | p, | |
char * | name | |||
) |
char* pvalWordGetString | ( | pval * | p | ) |
Definition at line 5101 of file pval.c.
References PV_WORD, pvalCheckType(), pval::str, and pval::u1.
05102 { 05103 if (!pvalCheckType(p, "pvalWordGetString", PV_WORD)) 05104 return 0; 05105 return p->u1.str; 05106 }
void pvalWordSetString | ( | pval * | p, | |
char * | str | |||
) |
Definition at line 5094 of file pval.c.
References PV_WORD, pvalCheckType(), pval::str, and pval::u1.
Referenced by pvalIfTimeSetCondition().
05095 { 05096 if (!pvalCheckType(p, "pvalWordSetString", PV_WORD)) 05097 return; 05098 p->u1.str = str; 05099 }
static void remove_spaces_before_equals | ( | char * | str | ) | [static] |
Definition at line 3045 of file pval.c.
Referenced by ast_compile_ael2(), and gen_prios().
void set_priorities | ( | struct ael_extension * | exten | ) |
Definition at line 4225 of file pval.c.
References ael_extension::is_switch, ael_priority::next, ael_extension::next_exten, ael_priority::origin, ael_extension::plist, ael_priority::priority_num, PV_LABEL, ael_extension::regexten, and pval::type.
Referenced by ast_compile_ael2().
04226 { 04227 int i; 04228 struct ael_priority *pr; 04229 do { 04230 if (exten->is_switch) 04231 i = 10; 04232 else if (exten->regexten) 04233 i=2; 04234 else 04235 i=1; 04236 04237 for (pr=exten->plist; pr; pr=pr->next) { 04238 pr->priority_num = i; 04239 04240 if (!pr->origin || (pr->origin && pr->origin->type != PV_LABEL) ) /* Labels don't show up in the dialplan, 04241 but we want them to point to the right 04242 priority, which would be the next line 04243 after the label; */ 04244 i++; 04245 } 04246 04247 exten = exten->next_exten; 04248 } while ( exten ); 04249 }
void traverse_pval_item_template | ( | pval * | item, | |
int | depth | |||
) |
Definition at line 402 of file pval.c.
References pval::arglist, pval::else_statements, pval::for_statements, pval::list, pval::macro_statements, pval::next, PV_APPLICATION_CALL, PV_BREAK, PV_CASE, PV_CATCH, PV_CONTEXT, PV_CONTINUE, PV_DEFAULT, PV_ESWITCHES, PV_EXTENSION, PV_FOR, PV_GLOBALS, PV_GOTO, PV_IF, PV_IFTIME, PV_IGNOREPAT, PV_INCLUDES, PV_LABEL, PV_LOCALVARDEC, PV_MACRO, PV_MACRO_CALL, PV_PATTERN, PV_RANDOM, PV_RETURN, PV_STATEMENTBLOCK, PV_SWITCH, PV_SWITCHES, PV_VARDEC, PV_WHILE, PV_WORD, pval::statements, pval::type, pval::u1, pval::u2, pval::u3, and pval::u4.
Referenced by traverse_pval_template().
00404 { 00405 pval *lp; 00406 00407 switch ( item->type ) { 00408 case PV_WORD: 00409 /* fields: item->u1.str == string associated with this (word). */ 00410 break; 00411 00412 case PV_MACRO: 00413 /* fields: item->u1.str == name of macro 00414 item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user 00415 item->u2.arglist->u1.str == argument 00416 item->u2.arglist->next == next arg 00417 00418 item->u3.macro_statements == pval list of statements in macro body. 00419 */ 00420 for (lp=item->u2.arglist; lp; lp=lp->next) { 00421 00422 } 00423 traverse_pval_item_template(item->u3.macro_statements,depth+1); 00424 break; 00425 00426 case PV_CONTEXT: 00427 /* fields: item->u1.str == name of context 00428 item->u2.statements == pval list of statements in context body 00429 item->u3.abstract == int 1 if an abstract keyword were present 00430 */ 00431 traverse_pval_item_template(item->u2.statements,depth+1); 00432 break; 00433 00434 case PV_MACRO_CALL: 00435 /* fields: item->u1.str == name of macro to call 00436 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 00437 item->u2.arglist->u1.str == argument 00438 item->u2.arglist->next == next arg 00439 */ 00440 for (lp=item->u2.arglist; lp; lp=lp->next) { 00441 } 00442 break; 00443 00444 case PV_APPLICATION_CALL: 00445 /* fields: item->u1.str == name of application to call 00446 item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user 00447 item->u2.arglist->u1.str == argument 00448 item->u2.arglist->next == next arg 00449 */ 00450 for (lp=item->u2.arglist; lp; lp=lp->next) { 00451 } 00452 break; 00453 00454 case PV_CASE: 00455 /* fields: item->u1.str == value of case 00456 item->u2.statements == pval list of statements under the case 00457 */ 00458 traverse_pval_item_template(item->u2.statements,depth+1); 00459 break; 00460 00461 case PV_PATTERN: 00462 /* fields: item->u1.str == value of case 00463 item->u2.statements == pval list of statements under the case 00464 */ 00465 traverse_pval_item_template(item->u2.statements,depth+1); 00466 break; 00467 00468 case PV_DEFAULT: 00469 /* fields: 00470 item->u2.statements == pval list of statements under the case 00471 */ 00472 traverse_pval_item_template(item->u2.statements,depth+1); 00473 break; 00474 00475 case PV_CATCH: 00476 /* fields: item->u1.str == name of extension to catch 00477 item->u2.statements == pval list of statements in context body 00478 */ 00479 traverse_pval_item_template(item->u2.statements,depth+1); 00480 break; 00481 00482 case PV_SWITCHES: 00483 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 00484 */ 00485 traverse_pval_item_template(item->u1.list,depth+1); 00486 break; 00487 00488 case PV_ESWITCHES: 00489 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 00490 */ 00491 traverse_pval_item_template(item->u1.list,depth+1); 00492 break; 00493 00494 case PV_INCLUDES: 00495 /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list 00496 item->u2.arglist == pval list of 4 PV_WORD elements for time values 00497 */ 00498 traverse_pval_item_template(item->u1.list,depth+1); 00499 traverse_pval_item_template(item->u2.arglist,depth+1); 00500 break; 00501 00502 case PV_STATEMENTBLOCK: 00503 /* fields: item->u1.list == pval list of statements in block, one per entry in the list 00504 */ 00505 traverse_pval_item_template(item->u1.list,depth+1); 00506 break; 00507 00508 case PV_LOCALVARDEC: 00509 case PV_VARDEC: 00510 /* fields: item->u1.str == variable name 00511 item->u2.val == variable value to assign 00512 */ 00513 break; 00514 00515 case PV_GOTO: 00516 /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. 00517 item->u1.list->u1.str == where the data on a PV_WORD will always be. 00518 */ 00519 00520 if ( item->u1.list->next ) 00521 ; 00522 if ( item->u1.list->next && item->u1.list->next->next ) 00523 ; 00524 00525 break; 00526 00527 case PV_LABEL: 00528 /* fields: item->u1.str == label name 00529 */ 00530 break; 00531 00532 case PV_FOR: 00533 /* fields: item->u1.for_init == a string containing the initalizer 00534 item->u2.for_test == a string containing the loop test 00535 item->u3.for_inc == a string containing the loop increment 00536 00537 item->u4.for_statements == a pval list of statements in the for () 00538 */ 00539 traverse_pval_item_template(item->u4.for_statements,depth+1); 00540 break; 00541 00542 case PV_WHILE: 00543 /* fields: item->u1.str == the while conditional, as supplied by user 00544 00545 item->u2.statements == a pval list of statements in the while () 00546 */ 00547 traverse_pval_item_template(item->u2.statements,depth+1); 00548 break; 00549 00550 case PV_BREAK: 00551 /* fields: none 00552 */ 00553 break; 00554 00555 case PV_RETURN: 00556 /* fields: none 00557 */ 00558 break; 00559 00560 case PV_CONTINUE: 00561 /* fields: none 00562 */ 00563 break; 00564 00565 case PV_IFTIME: 00566 /* fields: item->u1.list == there are 4 linked PV_WORDs here. 00567 00568 item->u2.statements == a pval list of statements in the if () 00569 item->u3.else_statements == a pval list of statements in the else 00570 (could be zero) 00571 */ 00572 traverse_pval_item_template(item->u2.statements,depth+1); 00573 if ( item->u3.else_statements ) { 00574 traverse_pval_item_template(item->u3.else_statements,depth+1); 00575 } 00576 break; 00577 00578 case PV_RANDOM: 00579 /* fields: item->u1.str == the random number expression, as supplied by user 00580 00581 item->u2.statements == a pval list of statements in the if () 00582 item->u3.else_statements == a pval list of statements in the else 00583 (could be zero) 00584 */ 00585 traverse_pval_item_template(item->u2.statements,depth+1); 00586 if ( item->u3.else_statements ) { 00587 traverse_pval_item_template(item->u3.else_statements,depth+1); 00588 } 00589 break; 00590 00591 case PV_IF: 00592 /* fields: item->u1.str == the if conditional, as supplied by user 00593 00594 item->u2.statements == a pval list of statements in the if () 00595 item->u3.else_statements == a pval list of statements in the else 00596 (could be zero) 00597 */ 00598 traverse_pval_item_template(item->u2.statements,depth+1); 00599 if ( item->u3.else_statements ) { 00600 traverse_pval_item_template(item->u3.else_statements,depth+1); 00601 } 00602 break; 00603 00604 case PV_SWITCH: 00605 /* fields: item->u1.str == the switch expression 00606 00607 item->u2.statements == a pval list of statements in the switch, 00608 (will be case statements, most likely!) 00609 */ 00610 traverse_pval_item_template(item->u2.statements,depth+1); 00611 break; 00612 00613 case PV_EXTENSION: 00614 /* fields: item->u1.str == the extension name, label, whatever it's called 00615 00616 item->u2.statements == a pval list of statements in the extension 00617 item->u3.hints == a char * hint argument 00618 item->u4.regexten == an int boolean. non-zero says that regexten was specified 00619 */ 00620 traverse_pval_item_template(item->u2.statements,depth+1); 00621 break; 00622 00623 case PV_IGNOREPAT: 00624 /* fields: item->u1.str == the ignorepat data 00625 */ 00626 break; 00627 00628 case PV_GLOBALS: 00629 /* fields: item->u1.statements == pval list of statements, usually vardecs 00630 */ 00631 traverse_pval_item_template(item->u1.statements,depth+1); 00632 break; 00633 } 00634 }
void traverse_pval_template | ( | pval * | item, | |
int | depth | |||
) |
Definition at line 636 of file pval.c.
References pval::next, and traverse_pval_item_template().
00638 { 00639 pval *i; 00640 00641 for (i=item; i; i=i->next) { 00642 traverse_pval_item_template(i, depth); 00643 } 00644 }
int control_statement_count = 0 [static] |
int count_labels [static] |
pval* current_context [static] |
pval* current_db [static] |
pval* current_extension [static] |
int errs [static] |
Definition at line 67 of file pval.c.
Referenced by pbx_load_module().
char expr_output[2096] [static] |
int in_abstract_context [static] |
int label_count [static] |
pval* last_matched_label [static] |
const char* match_context [static] |
const char* match_exten [static] |
const char* match_label [static] |
int return_on_context_match [static] |