- Timestamp:
- Dec 26, 2006, 1:05:26 AM (17 years ago)
- Branches:
- master, barnowl_perlaim, debian, release-1.10, release-1.4, release-1.5, release-1.6, release-1.7, release-1.8, release-1.9
- Children:
- 446aa2b
- Parents:
- 20eb22c
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
filter.c
rb699e9b rcb769bb 19 19 int owl_filter_init(owl_filter *f, char *name, int argc, char **argv) 20 20 { 21 int i, j, error;22 owl_filterelement *fe;23 char *regexstr;24 owl_list list;25 26 21 f->name=owl_strdup(name); 27 22 f->polarity=0; 28 23 f->color=OWL_COLOR_DEFAULT; 29 24 f->cachedmsgid=-1; 30 owl_list_create(&(f->fes)); 31 25 32 26 /* first take arguments that have to come first */ 33 27 /* set the color */ … … 41 35 argv+=2; 42 36 } 43 44 /* then deal with the expression */ 45 for (i=0; i<argc; i++) { 46 error=0; 47 fe=owl_malloc(sizeof(owl_filterelement)); 48 49 /* all the 0 argument possibilities */ 50 if (!strcmp(argv[i], "(")) { 51 owl_filterelement_create_openbrace(fe); 52 } else if (!strcmp(argv[i], ")")) { 53 owl_filterelement_create_closebrace(fe); 54 } else if (!strcasecmp(argv[i], "and")) { 55 owl_filterelement_create_and(fe); 56 } else if (!strcasecmp(argv[i], "or")) { 57 owl_filterelement_create_or(fe); 58 } else if (!strcasecmp(argv[i], "not")) { 59 owl_filterelement_create_not(fe); 60 } else if (!strcasecmp(argv[i], "true")) { 61 owl_filterelement_create_true(fe); 62 } else if (!strcasecmp(argv[i], "false")) { 63 owl_filterelement_create_false(fe); 64 65 } else if (i==argc-1) { /* we need more than one arg at this point */ 66 error=1; 67 } else { 68 if (!strcasecmp(argv[i], "filter")) { 69 owl_filterelement_create_filter(fe, argv[i+1]); 70 i++; 71 } else if (!strcasecmp(argv[i], "perl")) { 72 owl_filterelement_create_perl(fe, argv[i+1]); 73 i++; 74 } else { 75 regexstr=owl_text_substitute(argv[i+1], "%me%", owl_zephyr_get_sender()); 76 owl_filterelement_create_re(fe, argv[i], regexstr); 77 owl_free(regexstr); 78 i++; 79 } 80 } 81 82 if (!error) { 83 owl_list_append_element(&(f->fes), fe); 84 } else { 85 owl_free(fe); 86 owl_filter_free(f); 87 return(-1); 88 } 89 } 90 91 /* Are we trying to use the filter we're creating? Bad. */ 92 owl_list_create(&list); 93 _owl_filter_get_subfilter_names(f, &list); 94 j=owl_list_get_size(&list); 95 for (i=0; i<j; i++) { 96 if (!strcasecmp(name, owl_list_get_element(&list, i))) { 97 owl_function_error("Filter loop."); 98 owl_filter_free(f); 99 owl_list_free_all(&list, owl_free); 100 return(-1); 101 } 102 } 103 owl_list_free_all(&list, owl_free); 104 105 /* Now check for more subtle recursion. */ 37 38 if(!(f->root = owl_filter_parse_expression(argc, argv, NULL))) 39 return(-1); 40 41 /* Now check for recursion. */ 106 42 if (owl_filter_is_toodeep(f)) { 107 43 owl_function_error("Filter loop or exceeds recursion depth"); … … 109 45 return(-1); 110 46 } 111 47 112 48 return(0); 49 } 50 51 52 /* A primitive expression is one without any toplevel ``and'' or ``or''s*/ 53 54 static owl_filterelement * owl_filter_parse_primitive_expression(int argc, char **argv, int *next) 55 { 56 if(!argc) return NULL; 57 58 owl_filterelement * fe = owl_malloc(sizeof(owl_filterelement)); 59 owl_filterelement *op; 60 61 owl_filterelement_create(fe); 62 int i = 0, skip; 63 64 if(!strcasecmp(argv[i], "(")) { 65 i++; 66 op = owl_filter_parse_expression(argc-i, argv+i, &skip); 67 if(!op) goto err; 68 i += skip; 69 if(strcasecmp(argv[i++], ")")) goto err; 70 owl_filterelement_create_group(fe, op); 71 } else if(!strcasecmp(argv[i], "not")) { 72 i++; 73 op = owl_filter_parse_primitive_expression(argc-i, argv+i, &skip); 74 if(!op) goto err; 75 i += skip; 76 owl_filterelement_create_not(fe, op); 77 } else if(!strcasecmp(argv[i], "true")) { 78 i++; 79 owl_filterelement_create_true(fe); 80 } else if(!strcasecmp(argv[i], "false")) { 81 i++; 82 owl_filterelement_create_false(fe); 83 } else { 84 if(argc == 1) goto err; 85 if(!strcasecmp(*argv, "filter")) { 86 owl_filterelement_create_filter(fe, *(argv+1)); 87 } else if(!strcasecmp(*argv, "perl")) { 88 owl_filterelement_create_perl(fe, *(argv+1)); 89 } else { 90 owl_filterelement_create_re(fe, *argv, *(argv+1)); 91 } 92 i += 2; 93 } 94 95 if(next) { 96 *next = i; 97 } else if(i != argc) { 98 goto err; 99 } 100 return fe; 101 err: 102 owl_filterelement_free(fe); 103 owl_free(fe); 104 return NULL; 105 } 106 107 owl_filterelement * owl_filter_parse_expression(int argc, char **argv, int *next) 108 { 109 int i = 0, skip; 110 owl_filterelement * op1 = NULL, * op2 = NULL; 111 112 op1 = owl_filter_parse_primitive_expression(argc-i, argv+i, &skip); 113 i += skip; 114 if(!op1) goto err; 115 116 while(i < argc) { 117 if(strcasecmp(argv[i], "and") && 118 strcasecmp(argv[i], "or")) break; 119 op2 = owl_filter_parse_primitive_expression(argc-i-1, argv+i+1, &skip); 120 if(!op2) goto err; 121 owl_filterelement * tmp = owl_malloc(sizeof(owl_filterelement)); 122 if(!strcasecmp(argv[i], "and")) { 123 owl_filterelement_create_and(tmp, op1, op2); 124 } else { 125 owl_filterelement_create_or(tmp, op1, op2); 126 } 127 op1 = tmp; 128 op2 = NULL; 129 i += skip+1; 130 } 131 132 if(next) { 133 *next = i; 134 } else if(i != argc) { 135 goto err; 136 } 137 return op1; 138 err: 139 if(op1) { 140 owl_filterelement_free(op1); 141 owl_free(op1); 142 } 143 return NULL; 113 144 } 114 145 … … 153 184 int owl_filter_message_match(owl_filter *f, owl_message *m) 154 185 { 155 int i, j, tmp; 156 owl_list work_fes, *fes; 157 owl_filterelement *fe; 158 char *field, *match; 159 160 /* create the working list of expression elements */ 161 fes=&(f->fes); 162 owl_list_create(&work_fes); 163 j=owl_list_get_size(fes); 164 for (i=0; i<j; i++) { 165 owl_list_append_element(&work_fes, owl_list_get_element(fes, i)); 166 } 167 168 /* first go thru and evaluate all RE elements to true or false */ 169 match=""; 170 for (i=0; i<j; i++) { 171 fe=owl_list_get_element(&work_fes, i); 172 if (!owl_filterelement_is_re(fe)) continue; 173 field=owl_filterelement_get_field(fe); 174 if (!strcasecmp(field, "class")) { 175 match=owl_message_get_class(m); 176 } else if (!strcasecmp(field, "instance")) { 177 match=owl_message_get_instance(m); 178 } else if (!strcasecmp(field, "sender")) { 179 match=owl_message_get_sender(m); 180 } else if (!strcasecmp(field, "recipient")) { 181 match=owl_message_get_recipient(m); 182 } else if (!strcasecmp(field, "body")) { 183 match=owl_message_get_body(m); 184 } else if (!strcasecmp(field, "opcode")) { 185 match=owl_message_get_opcode(m); 186 } else if (!strcasecmp(field, "realm")) { 187 match=owl_message_get_realm(m); 188 } else if (!strcasecmp(field, "type")) { 189 match=owl_message_get_type(m); 190 } else if (!strcasecmp(field, "hostname")) { 191 match=owl_message_get_hostname(m); 192 } else if (!strcasecmp(field, "direction")) { 193 if (owl_message_is_direction_out(m)) { 194 match="out"; 195 } else if (owl_message_is_direction_in(m)) { 196 match="in"; 197 } else if (owl_message_is_direction_none(m)) { 198 match="none"; 199 } else { 200 match=""; 201 } 202 } else if (!strcasecmp(field, "login")) { 203 if (owl_message_is_login(m)) { 204 match="login"; 205 } else if (owl_message_is_logout(m)) { 206 match="logout"; 207 } else { 208 match="none"; 209 } 210 } else { 211 match = owl_message_get_attribute_value(m,field); 212 if(match == NULL) match = ""; 213 } 214 215 tmp=owl_regex_compare(owl_filterelement_get_re(fe), match); 216 if (!tmp) { 217 owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g)); 218 } else { 219 owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g)); 220 } 221 } 222 223 /* now subfilters and perl functions */ 224 for (i=0; i<j; i++) { 225 owl_filter *subfilter; 226 227 fe=owl_list_get_element(&work_fes, i); 228 229 if (owl_filterelement_is_filter(fe)) { 230 231 subfilter=owl_global_get_filter(&g, owl_filterelement_get_filtername(fe)); 232 if (!subfilter) { 233 /* the filter does not exist, maybe because it was deleted. 234 * Default to not matching 235 */ 236 owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g)); 237 } else if (owl_filter_message_match(subfilter, m)) { 238 owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g)); 239 } else { 240 owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g)); 241 } 242 243 } else if (owl_filterelement_is_perl(fe)) { 244 char *subname, *perlrv; 245 int tf=0; 246 247 subname = owl_filterelement_get_filtername(fe); 248 if (!owl_perlconfig_is_function(subname)) { 249 owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g)); 250 continue; 251 } 252 perlrv = owl_perlconfig_call_with_message(subname, m); 253 if (perlrv) { 254 if (0 == strcmp(perlrv, "1")) { 255 tf=1; 256 } 257 owl_free(perlrv); 258 } 259 if (tf) { 260 owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g)); 261 } else { 262 owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g)); 263 } 264 } 265 } 266 267 /* call the recrsive helper */ 268 i=_owl_filter_message_match_recurse(f, m, &work_fes, 0, owl_list_get_size(&(f->fes))-1); 269 270 /* now there will be only one TRUE / FALSE, find it among the NULL's */ 271 tmp=0; 272 for (i=0; i<j; i++) { 273 fe=owl_list_get_element(&work_fes, i); 274 if (owl_filterelement_is_null(fe)) continue; 275 if (owl_filterelement_is_true(fe)) { 276 tmp=1; 277 break; 278 } 279 if (owl_filterelement_is_false(fe)) { 280 tmp=0; 281 break; 282 } 283 } 284 285 /* reverse the answer if negative polarity is in use */ 286 if (f->polarity) tmp=!tmp; 287 288 owl_list_free_simple(&work_fes); 289 return(tmp); 290 } 291 292 int _owl_filter_message_match_recurse(owl_filter *f, owl_message *m, owl_list *fes, int start, int end) 293 { 294 int a=0, b=0, i, x, y, z, score, ret, type; 295 owl_filterelement *fe, *tmpfe=NULL; 296 297 /* Deal with parens first. */ 298 for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) { 299 /* Find first open paren and matching close paren, store in x, y */ 300 score=x=y=0; 301 for (i=start; i<=end; i++) { 302 fe=owl_list_get_element(fes, i); 303 if (owl_filterelement_is_openbrace(fe)) { 304 if (score==0) x=i; 305 score++; 306 } else if (owl_filterelement_is_closebrace(fe)) { 307 score--; 308 if (score<0) { 309 /* unblanaced parens */ 310 return(-1); 311 } else if (score==0) { 312 y=i; /* this is the matching close paren */ 313 break; 314 } 315 } 316 } 317 if (score>0) { 318 /* unblanaced parens */ 319 return(-1); 320 } 321 322 /* Simply the parens by removing them and evaluating what was in between */ 323 if (y>0) { 324 /* null out the parens */ 325 owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g)); 326 owl_list_replace_element(fes, y, owl_global_get_filterelement_null(&g)); 327 328 /* evaluate expression in between */ 329 ret=_owl_filter_message_match_recurse(f, m, fes, x+1, y-1); 330 if (ret<0) return(-1); 331 332 /* there may be more, so we continue */ 333 continue; 334 } else { 335 /* otherwise we're done with this part */ 336 break; 337 } 338 } 339 if (i==OWL_FILTER_MAX_DEPTH) { 340 /* hit the saftey limit, consider it invalid */ 341 return(-1); 342 } 343 344 /* Find AND / OR / NOT. 345 * For binary expressions (AND/OR): 346 * "type" is 1 347 * "x" will index first val, "y" the operator and "z" the second val 348 * For unary expressions (NOT): 349 * "type" is 2 350 * "x" will index the operator, "y" the value 351 * "score" tallys how many expression elements have been found so far 352 */ 353 for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) { 354 type=score=x=y=z=0; 355 for (i=start; i<=end; i++) { 356 fe=owl_list_get_element(fes, i); 357 if (owl_filterelement_is_null(fe)) continue; 358 if (score==0) { 359 if (owl_filterelement_is_value(fe)) { 360 x=i; 361 score=1; 362 type=1; 363 } else if (owl_filterelement_is_not(fe)) { 364 x=i; 365 score=1; 366 type=2; 367 } 368 } else if (score==1) { 369 if (type==1) { 370 if (owl_filterelement_is_and(fe) || owl_filterelement_is_or(fe)) { 371 score=2; 372 y=i; 373 } else { 374 /* it's not a valid binary expression */ 375 x=y=z=score=0; 376 } 377 } else if (type==2) { 378 if (owl_filterelement_is_value(fe)) { 379 /* valid unary expression, we're done */ 380 y=i; 381 break; 382 } 383 } 384 } else if (score==2) { 385 if (owl_filterelement_is_value(fe)) { 386 /* valid binary expression, we're done */ 387 z=i; 388 break; 389 } else { 390 x=y=z=score=0; 391 } 392 } 393 } 394 395 /* simplify AND / OR */ 396 if ((type==1) && (z>0)) { 397 fe=owl_list_get_element(fes, x); 398 if (owl_filterelement_is_true(fe)) { 399 a=1; 400 } else if (owl_filterelement_is_false(fe)) { 401 a=0; 402 } 403 404 fe=owl_list_get_element(fes, z); 405 if (owl_filterelement_is_true(fe)) { 406 b=1; 407 } else if (owl_filterelement_is_false(fe)) { 408 b=0; 409 } 410 411 fe=owl_list_get_element(fes, y); 412 if (owl_filterelement_is_and(fe)) { 413 if (a && b) { 414 tmpfe=owl_global_get_filterelement_true(&g); 415 } else { 416 tmpfe=owl_global_get_filterelement_false(&g); 417 } 418 } else if (owl_filterelement_is_or(fe)) { 419 if (a || b) { 420 tmpfe=owl_global_get_filterelement_true(&g); 421 } else { 422 tmpfe=owl_global_get_filterelement_false(&g); 423 } 424 } 425 owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g)); 426 owl_list_replace_element(fes, y, tmpfe); 427 owl_list_replace_element(fes, z, owl_global_get_filterelement_null(&g)); 428 } else if ((type==2) && (y>0)) { 429 /* simplify NOT */ 430 fe=owl_list_get_element(fes, y); 431 owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g)); 432 if (owl_filterelement_is_false(fe)) { 433 owl_list_replace_element(fes, y, owl_global_get_filterelement_true(&g)); 434 } else { 435 owl_list_replace_element(fes, y, owl_global_get_filterelement_false(&g)); 436 } 437 } else { 438 break; 439 } 440 } 441 return(0); 442 443 } 186 if(!f->root) return 0; 187 int ret = owl_filterelement_match(f->root, m); 188 if(f->polarity) ret = !ret; 189 return ret; 190 } 191 444 192 445 193 void owl_filter_print(owl_filter *f, char *out) 446 194 { 447 int i, j; 448 owl_filterelement *fe; 449 char *tmp; 450 451 strcpy(out, owl_filter_get_name(f)); 452 strcat(out, ": "); 453 454 if (f->color!=OWL_COLOR_DEFAULT) { 455 strcat(out, "-c "); 456 strcat(out, owl_util_color_to_string(f->color)); 457 strcat(out, " "); 458 } 459 460 j=owl_list_get_size(&(f->fes)); 461 for (i=0; i<j; i++) { 462 fe=owl_list_get_element(&(f->fes), i); 463 tmp=owl_filterelement_to_string(fe); 464 strcat(out, tmp); 465 owl_free(tmp); 466 } 195 strcpy(out, ""); 196 if(!f->root) return; 197 owl_filterelement_print(f->root, out); 467 198 strcat(out, "\n"); 468 199 } … … 480 211 } 481 212 482 /* Private483 * 'list' should already be allocated and initialized484 * This function places into list the string names of all filters485 * used in the filter expression for 'f'.486 * Caller must do a full free on 'list', including elements.487 */488 void _owl_filter_get_subfilter_names(owl_filter *f, owl_list *list)489 {490 int i, j;491 owl_filterelement *fe;492 493 j=owl_list_get_size(&(f->fes));494 for (i=0; i<j; i++) {495 fe=owl_list_get_element(&(f->fes), i);496 if (owl_filterelement_is_filter(fe)) {497 owl_list_append_element(list, owl_strdup(owl_filterelement_get_filtername(fe)));498 }499 }500 }501 213 502 214 int owl_filter_is_toodeep(owl_filter *f) 503 215 { 504 owl_list seen, tocheck, tmp; 505 int i, j, x, y; 506 owl_filter *subfilter; 507 508 owl_list_create(&seen); 509 owl_list_create(&tocheck); 510 owl_list_create(&tmp); 511 512 /* seed 'tocheck' with the first set of filters */ 513 _owl_filter_get_subfilter_names(f, &tmp); 514 j=owl_list_get_size(&tmp); 515 for (i=0; i<j; i++) { 516 owl_util_list_add_unique_string(&tocheck, owl_list_get_element(&tmp, i)); 517 } 518 owl_list_free_all(&tmp, owl_free); 519 owl_list_create(&tmp); 520 521 /* add this list to the 'seen' list */ 522 owl_list_append_element(&seen, owl_strdup(owl_filter_get_name(f))); 523 524 for (i=0; i<OWL_FILTER_MAXRECURSE; i++) { 525 /* if anything in 'tocheck' is in 'seen' we have a loop */ 526 if (owl_util_common_strings_in_lists(&tocheck, &seen)) { 527 owl_list_free_all(&tmp, owl_free); 528 owl_list_free_all(&tocheck, owl_free); 529 owl_list_free_all(&seen, owl_free); 530 return(1); 531 } 532 533 /* if there's nothing to check, we're done */ 534 y=owl_list_get_size(&tocheck); 535 if (y==0) { 536 owl_list_free_all(&tmp, owl_free); 537 owl_list_free_all(&tocheck, owl_free); 538 owl_list_free_all(&seen, owl_free); 539 return(0); 540 } 541 542 /* add everything in 'tocheck' to the 'seen' list */ 543 /* y=owl_list_get_size(&tocheck); */ 544 for (x=0; x<y; x++) { 545 owl_list_append_element(&seen, owl_strdup(owl_list_get_element(&tocheck, x))); 546 } 547 548 /* make a new list into 'tmp' with the children of 'tocheck' */ 549 /* y=owl_list_get_size(&tocheck); */ 550 for (x=0; x<y; x++) { 551 subfilter=owl_global_get_filter(&g, owl_list_get_element(&tocheck, x)); 552 if (!subfilter) return(0); 553 _owl_filter_get_subfilter_names(subfilter, &tmp); 554 } 555 556 /* clean out 'tocheck' */ 557 owl_list_free_all(&tocheck, owl_free); 558 owl_list_create(&tocheck); 559 560 /* put 'tmp' into 'tocheck' */ 561 y=owl_list_get_size(&tmp); 562 for (x=0; x<y; x++) { 563 owl_util_list_add_unique_string(&tocheck, owl_list_get_element(&tmp, x)); 564 } 565 566 /* clean out 'tmp' */ 567 owl_list_free_all(&tmp, owl_free); 568 owl_list_create(&tmp); 569 } 570 571 owl_list_free_all(&tmp, owl_free); 572 owl_list_free_all(&tocheck, owl_free); 573 owl_list_free_all(&seen, owl_free); 574 575 return(1); 216 return owl_filterelement_is_toodeep(f, f->root); 576 217 } 577 218 578 219 void owl_filter_free(owl_filter *f) 579 220 { 580 void (*func)();581 582 func=&owl_filterelement_free;583 221 if(f->root) { 222 owl_filterelement_free(f->root); 223 owl_free(f->root); 224 } 584 225 if (f->name) owl_free(f->name); 585 owl_list_free_all(&(f->fes), func); 586 } 226 } 227 228 /**************************************************************************/ 229 /************************* REGRESSION TESTS *******************************/ 230 /**************************************************************************/ 231 232 #ifdef OWL_INCLUDE_REG_TESTS 233 234 int owl_filter_test_string(char * filt, owl_message *m, int shouldmatch) /* noproto */ { 235 owl_filter f; 236 int ok; 237 int failed = 0; 238 if(owl_filter_init_fromstring(&f, "test-filter", filt)) { 239 printf("\tFAIL: parse %s\n", filt); 240 failed = 1; 241 goto out; 242 } 243 ok = owl_filter_message_match(&f, m); 244 if((shouldmatch && !ok) || (!shouldmatch && ok)) { 245 printf("\tFAIL: match %s (got %d, expected %d)\n", filt, ok, shouldmatch); 246 failed = 1; 247 } 248 out: 249 owl_filter_free(&f); 250 if(!failed) { 251 printf("\tok : %s %s\n", shouldmatch ? "matches" : "doesn't match", filt); 252 } 253 return failed; 254 } 255 256 257 #include "test.h" 258 259 260 int owl_filter_regtest(void) { 261 owl_list_create(&(g.filterlist)); 262 int numfailed=0; 263 owl_message m; 264 owl_message_init(&m); 265 owl_message_set_type_zephyr(&m); 266 owl_message_set_direction_in(&m); 267 owl_message_set_class(&m, "owl"); 268 owl_message_set_instance(&m, "tester"); 269 owl_message_set_sender(&m, "owl-user"); 270 owl_message_set_recipient(&m, "joe"); 271 owl_message_set_attribute(&m, "foo", "bar"); 272 273 #define TEST_FILTER(f, e) numfailed += owl_filter_test_string(f, &m, e) 274 275 276 TEST_FILTER("true", 1); 277 TEST_FILTER("false", 0); 278 TEST_FILTER("( true )", 1); 279 TEST_FILTER("not false", 1); 280 TEST_FILTER("( true ) or ( false )", 1); 281 TEST_FILTER("true and false", 0); 282 TEST_FILTER("( true or true ) or ( ( false ) )", 1); 283 284 TEST_FILTER("class owl", 1); 285 TEST_FILTER("class ^owl$", 1); 286 TEST_FILTER("instance test", 1); 287 TEST_FILTER("instance ^test$", 0); 288 TEST_FILTER("instance ^tester$", 1); 289 290 TEST_FILTER("foo bar", 1); 291 TEST_FILTER("class owl and instance tester", 1); 292 TEST_FILTER("type ^zephyr$ and direction ^in$ and ( class ^owl$ or instance ^owl$ )", 1); 293 294 // Order of operations and precedence 295 TEST_FILTER("not true or false", 0); 296 TEST_FILTER("true or true and false", 0); 297 TEST_FILTER("true and true and false or true", 1); 298 TEST_FILTER("false and false or true", 1); 299 TEST_FILTER("true and false or false", 0); 300 301 owl_filter f1, f2, f3, f4; 302 303 owl_filter_init_fromstring(&f1, "f1", "class owl"); 304 owl_global_add_filter(&g, &f1); 305 TEST_FILTER("filter f1", 1); 306 307 // Test recursion prevention 308 FAIL_UNLESS("self reference", owl_filter_init_fromstring(&f2, "test", "filter test")); 309 310 // mutual recursion 311 owl_filter_init_fromstring(&f3, "f3", "filter f4"); 312 owl_global_add_filter(&g, &f3); 313 FAIL_UNLESS("mutual recursion", owl_filter_init_fromstring(&f4, "f4", "filter f3")); 314 315 return 0; 316 } 317 318 319 #endif /* OWL_INCLUDE_REG_TESTS */
Note: See TracChangeset
for help on using the changeset viewer.