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