diff options
Diffstat (limited to 'parse-filter.c')
| -rw-r--r-- | parse-filter.c | 257 |
1 files changed, 187 insertions, 70 deletions
diff --git a/parse-filter.c b/parse-filter.c index 0890589..973a702 100644 --- a/parse-filter.c +++ b/parse-filter.c | |||
| @@ -298,10 +298,6 @@ static void free_events(struct event_list *events) | |||
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | static enum event_type | 300 | static enum event_type |
| 301 | process_filter(struct event_format *event, struct filter_arg **parg, | ||
| 302 | enum event_type type, char **tok, char **error_str); | ||
| 303 | |||
| 304 | static enum event_type | ||
| 305 | process_paren(struct event_format *event, struct filter_arg **parg, | 301 | process_paren(struct event_format *event, struct filter_arg **parg, |
| 306 | char **tok, char **error_str); | 302 | char **tok, char **error_str); |
| 307 | 303 | ||
| @@ -310,22 +306,26 @@ process_not(struct event_format *event, struct filter_arg **parg, | |||
| 310 | char **tok, char **error_str); | 306 | char **tok, char **error_str); |
| 311 | 307 | ||
| 312 | static enum event_type | 308 | static enum event_type |
| 309 | process_value_token(struct event_format *event, struct filter_arg **parg, | ||
| 310 | enum event_type type, char **tok, char **error_str); | ||
| 311 | |||
| 312 | static enum event_type | ||
| 313 | process_op_token(struct event_format *event, struct filter_arg *larg, | 313 | process_op_token(struct event_format *event, struct filter_arg *larg, |
| 314 | struct filter_arg **parg, enum event_type type, char **tok, | 314 | struct filter_arg **parg, enum event_type type, char **tok, |
| 315 | char **error_str); | 315 | char **error_str); |
| 316 | 316 | ||
| 317 | static enum event_type | ||
| 318 | process_op(struct event_format *event, struct filter_arg *larg, | ||
| 319 | struct filter_arg **parg, char **tok, char **error_str); | ||
| 320 | |||
| 321 | /* | 317 | /* |
| 318 | * process_token | ||
| 319 | * Called when a new expression is found. Processes an op, or | ||
| 320 | * ends early if a ')' is found. | ||
| 321 | * | ||
| 322 | * Output: tok, parg | 322 | * Output: tok, parg |
| 323 | */ | 323 | */ |
| 324 | static enum event_type | 324 | static enum event_type |
| 325 | process_token(struct event_format *event, struct filter_arg **parg, | 325 | process_token(struct event_format *event, struct filter_arg **parg, |
| 326 | char **tok, char **error_str, int cont) | 326 | char **tok, char **error_str) |
| 327 | { | 327 | { |
| 328 | struct filter_arg *arg; | 328 | struct filter_arg *arg = NULL; |
| 329 | enum event_type type; | 329 | enum event_type type; |
| 330 | char *token; | 330 | char *token; |
| 331 | 331 | ||
| @@ -334,37 +334,109 @@ process_token(struct event_format *event, struct filter_arg **parg, | |||
| 334 | 334 | ||
| 335 | type = read_token(&token); | 335 | type = read_token(&token); |
| 336 | 336 | ||
| 337 | if (type == EVENT_ITEM) { | 337 | /* |
| 338 | type = process_filter(event, parg, type, &token, error_str); | 338 | * This is a start of a new expresion. We expect to find |
| 339 | * a item or a parenthesis. | ||
| 340 | */ | ||
| 341 | switch (type) { | ||
| 342 | case EVENT_SQUOTE: | ||
| 343 | case EVENT_DQUOTE: | ||
| 344 | case EVENT_ITEM: | ||
| 345 | type = process_value_token(event, &arg, type, &token, error_str); | ||
| 346 | if (type == EVENT_ERROR) { | ||
| 347 | free_token(token); | ||
| 348 | return type; | ||
| 349 | } | ||
| 350 | type = read_token(&token); | ||
| 351 | break; | ||
| 352 | case EVENT_DELIM: | ||
| 353 | if (strcmp(token, "(") != 0) | ||
| 354 | break; | ||
| 339 | 355 | ||
| 340 | } else if (type == EVENT_DELIM && strcmp(token, "(") == 0) { | ||
| 341 | free_token(token); | 356 | free_token(token); |
| 342 | type = process_paren(event, parg, &token, error_str); | 357 | type = process_paren(event, &arg, &token, error_str); |
| 358 | if (type == EVENT_NONE) { | ||
| 359 | *tok = token; | ||
| 360 | *parg = arg; | ||
| 361 | return type; | ||
| 362 | } | ||
| 363 | if (arg) { | ||
| 364 | /* | ||
| 365 | * If the parenthesis was a full expression, | ||
| 366 | * then just return it. Otherwise, we may still | ||
| 367 | * need to find an op. | ||
| 368 | */ | ||
| 369 | switch (arg->type) { | ||
| 370 | case FILTER_ARG_OP: | ||
| 371 | case FILTER_ARG_NUM: | ||
| 372 | case FILTER_ARG_STR: | ||
| 373 | *tok = token; | ||
| 374 | *parg = arg; | ||
| 375 | return type; | ||
| 376 | default: | ||
| 377 | break; | ||
| 378 | } | ||
| 379 | } | ||
| 380 | break; | ||
| 343 | 381 | ||
| 344 | } else if (type == EVENT_OP && strcmp(token, "!") == 0) { | 382 | case EVENT_OP: |
| 345 | type = process_not(event, parg, &token, error_str); | 383 | if (strcmp(token, "!") != 0) |
| 346 | } else { | 384 | break; |
| 347 | if (type == EVENT_NONE) | 385 | |
| 348 | show_error(error_str, "unexpected end of filter"); | 386 | /* |
| 349 | else | 387 | * A not is its own filter, it just negates, |
| 350 | show_error(error_str, "unexpected token '%s'", token); | 388 | * process it by itself. |
| 351 | type = EVENT_ERROR; | 389 | */ |
| 390 | *tok = token; | ||
| 391 | type = process_not(event, parg, tok, error_str); | ||
| 392 | return type; | ||
| 393 | |||
| 394 | default: | ||
| 395 | break; | ||
| 352 | } | 396 | } |
| 353 | 397 | ||
| 354 | *tok = token; | 398 | for (;;) { |
| 355 | while (cont && type != EVENT_ERROR) { | 399 | if (type == EVENT_NONE) { |
| 356 | if (type != EVENT_OP) | 400 | show_error(error_str, "unexpected end of filter"); |
| 357 | break; | 401 | type = EVENT_ERROR; |
| 358 | /* continue */ | 402 | |
| 359 | arg = *parg; | 403 | } else if (type == EVENT_DELIM && strcmp(token, ")") == 0) { |
| 404 | /* Parenthesis call this and may return at anytime. */ | ||
| 405 | *tok = token; | ||
| 406 | *parg = arg; | ||
| 407 | return type; | ||
| 408 | |||
| 409 | } else if (type != EVENT_OP) { | ||
| 410 | show_error(error_str, "Expected an OP but found %s", token); | ||
| 411 | type = EVENT_ERROR; | ||
| 412 | } | ||
| 413 | |||
| 414 | if (type == EVENT_ERROR) { | ||
| 415 | free_token(token); | ||
| 416 | return type; | ||
| 417 | } | ||
| 418 | |||
| 419 | *tok = token; | ||
| 360 | *parg = NULL; | 420 | *parg = NULL; |
| 361 | type = process_op_token(event, arg, parg, type, tok, error_str); | 421 | type = process_op_token(event, arg, parg, type, tok, error_str); |
| 362 | } | ||
| 363 | 422 | ||
| 364 | if (type == EVENT_ERROR) { | 423 | if (type == EVENT_ERROR) { |
| 365 | free_arg(*parg); | 424 | free_arg(*parg); |
| 366 | *parg = NULL; | 425 | *parg = NULL; |
| 367 | return EVENT_ERROR; | 426 | return EVENT_ERROR; |
| 427 | } | ||
| 428 | |||
| 429 | if (!(*parg) || (*parg)->type != FILTER_ARG_EXP) | ||
| 430 | break; | ||
| 431 | |||
| 432 | /* | ||
| 433 | * This op was an expression (value return) | ||
| 434 | * It's not fine by itself, there had better be an OP | ||
| 435 | * after it. | ||
| 436 | */ | ||
| 437 | token = *tok; | ||
| 438 | *tok = NULL; | ||
| 439 | arg = *parg; | ||
| 368 | } | 440 | } |
| 369 | 441 | ||
| 370 | return type; | 442 | return type; |
| @@ -387,7 +459,7 @@ process_bool(struct event_format *event, struct filter_arg *larg, | |||
| 387 | btype = strcmp(*tok, "&&") == 0 ? | 459 | btype = strcmp(*tok, "&&") == 0 ? |
| 388 | FILTER_OP_AND : FILTER_OP_OR; | 460 | FILTER_OP_AND : FILTER_OP_OR; |
| 389 | 461 | ||
| 390 | type = process_token(event, &rarg, tok, error_str, 0); | 462 | type = process_token(event, &rarg, tok, error_str); |
| 391 | if (type == EVENT_ERROR) { | 463 | if (type == EVENT_ERROR) { |
| 392 | free_arg(larg); | 464 | free_arg(larg); |
| 393 | *parg = NULL; | 465 | *parg = NULL; |
| @@ -396,7 +468,7 @@ process_bool(struct event_format *event, struct filter_arg *larg, | |||
| 396 | 468 | ||
| 397 | /* | 469 | /* |
| 398 | * If larg or rarg is null then if this is AND, the whole expression | 470 | * If larg or rarg is null then if this is AND, the whole expression |
| 399 | * becomes NULL, elso if this is an OR, then we use the non NULL | 471 | * becomes NULL, else if this is an OR, then we use the non NULL |
| 400 | * condition. | 472 | * condition. |
| 401 | */ | 473 | */ |
| 402 | if (!larg || !rarg) { | 474 | if (!larg || !rarg) { |
| @@ -417,9 +489,18 @@ process_bool(struct event_format *event, struct filter_arg *larg, | |||
| 417 | arg->op.left = larg; | 489 | arg->op.left = larg; |
| 418 | arg->op.right = rarg; | 490 | arg->op.right = rarg; |
| 419 | 491 | ||
| 420 | *parg = arg; | ||
| 421 | 492 | ||
| 422 | return type; | 493 | /* |
| 494 | * If the next token is also a boolean expression, then | ||
| 495 | * make the next boolean the parent.. | ||
| 496 | */ | ||
| 497 | if (type != EVENT_OP || | ||
| 498 | (strcmp(*tok, "&&") != 0 && strcmp(*tok, "||") != 0)) { | ||
| 499 | *parg = arg; | ||
| 500 | return type; | ||
| 501 | } | ||
| 502 | |||
| 503 | return process_bool(event, arg, parg, tok, error_str); | ||
| 423 | } | 504 | } |
| 424 | 505 | ||
| 425 | /* | 506 | /* |
| @@ -482,22 +563,50 @@ process_value_token(struct event_format *event, struct filter_arg **parg, | |||
| 482 | } | 563 | } |
| 483 | 564 | ||
| 484 | /* | 565 | /* |
| 485 | * Output: parg | 566 | * Output: parg, tok |
| 486 | */ | 567 | */ |
| 487 | static enum event_type | 568 | static enum event_type |
| 488 | process_value(struct event_format *event, struct filter_arg **parg, | 569 | process_value(struct event_format *event, struct filter_arg **parg, |
| 489 | char **error_str) | 570 | enum event_type *orig_type, char **tok, char **error_str) |
| 490 | { | 571 | { |
| 491 | enum event_type type; | 572 | enum event_type type; |
| 492 | char *token; | 573 | char *token; |
| 493 | 574 | ||
| 575 | *tok = NULL; | ||
| 494 | type = read_token(&token); | 576 | type = read_token(&token); |
| 495 | type = process_value_token(event, parg, type, &token, error_str); | 577 | *orig_type = type; |
| 496 | free_token(token); | 578 | if (type == EVENT_DELIM && strcmp(token, "(") == 0) { |
| 579 | type = process_paren(event, parg, &token, error_str); | ||
| 580 | /* Must be a expression or value */ | ||
| 581 | if (type == EVENT_ERROR || !(*parg)) { | ||
| 582 | free_token(token); | ||
| 583 | return type; | ||
| 584 | } | ||
| 585 | switch ((*parg)->type) { | ||
| 586 | case FILTER_ARG_BOOLEAN: | ||
| 587 | case FILTER_ARG_VALUE: | ||
| 588 | case FILTER_ARG_FIELD: | ||
| 589 | case FILTER_ARG_EXP: | ||
| 590 | break; | ||
| 591 | default: | ||
| 592 | show_error(error_str, "expected a value"); | ||
| 593 | free_token(token); | ||
| 594 | return EVENT_ERROR; | ||
| 595 | } | ||
| 596 | } else { | ||
| 597 | type = process_value_token(event, parg, type, &token, error_str); | ||
| 598 | free_token(token); | ||
| 599 | if (type == EVENT_ERROR) | ||
| 600 | return type; | ||
| 601 | type = read_token(&token); | ||
| 602 | } | ||
| 603 | |||
| 604 | *tok = token; | ||
| 497 | return type; | 605 | return type; |
| 498 | } | 606 | } |
| 499 | 607 | ||
| 500 | /* | 608 | /* |
| 609 | * Input: larg | ||
| 501 | * Output: parg, tok | 610 | * Output: parg, tok |
| 502 | */ | 611 | */ |
| 503 | static enum event_type | 612 | static enum event_type |
| @@ -507,18 +616,21 @@ process_cmp(struct event_format *event, enum filter_cmp_type op_type, | |||
| 507 | { | 616 | { |
| 508 | struct filter_arg *arg; | 617 | struct filter_arg *arg; |
| 509 | struct filter_arg *rarg; | 618 | struct filter_arg *rarg; |
| 619 | enum event_type orig_type; | ||
| 510 | enum event_type type; | 620 | enum event_type type; |
| 511 | int ret; | 621 | int ret; |
| 512 | 622 | ||
| 513 | *parg = NULL; | 623 | *parg = NULL; |
| 514 | 624 | ||
| 515 | type = process_value(event, &rarg, error_str); | 625 | type = process_value(event, &rarg, &orig_type, tok, error_str); |
| 516 | if (type == EVENT_ERROR) | 626 | if (type == EVENT_ERROR) { |
| 627 | free_arg(rarg); | ||
| 517 | return type; | 628 | return type; |
| 629 | } | ||
| 518 | 630 | ||
| 519 | arg = allocate_arg(); | 631 | arg = allocate_arg(); |
| 520 | /* | 632 | /* |
| 521 | * If either arg is NULL if right was field not found. | 633 | * If either arg is NULL or right was field not found. |
| 522 | * Then make the entire expression NULL. (will turn to FALSE) | 634 | * Then make the entire expression NULL. (will turn to FALSE) |
| 523 | */ | 635 | */ |
| 524 | if (!larg || !rarg) { | 636 | if (!larg || !rarg) { |
| @@ -529,7 +641,7 @@ process_cmp(struct event_format *event, enum filter_cmp_type op_type, | |||
| 529 | goto cont; | 641 | goto cont; |
| 530 | } | 642 | } |
| 531 | 643 | ||
| 532 | switch (type) { | 644 | switch (orig_type) { |
| 533 | case EVENT_SQUOTE: | 645 | case EVENT_SQUOTE: |
| 534 | /* treat this as a character if string is of length 1? */ | 646 | /* treat this as a character if string is of length 1? */ |
| 535 | if (strlen(rarg->str.val) == 1) { | 647 | if (strlen(rarg->str.val) == 1) { |
| @@ -620,10 +732,11 @@ process_cmp(struct event_format *event, enum filter_cmp_type op_type, | |||
| 620 | } | 732 | } |
| 621 | cont: | 733 | cont: |
| 622 | *parg = arg; | 734 | *parg = arg; |
| 623 | return read_token(tok); | 735 | return type; |
| 624 | } | 736 | } |
| 625 | 737 | ||
| 626 | /* | 738 | /* |
| 739 | * Input: larg | ||
| 627 | * Output: parg, tok | 740 | * Output: parg, tok |
| 628 | */ | 741 | */ |
| 629 | static enum event_type | 742 | static enum event_type |
| @@ -633,11 +746,14 @@ process_exp(struct event_format *event, enum filter_exp_type etype, | |||
| 633 | { | 746 | { |
| 634 | struct filter_arg *rarg; | 747 | struct filter_arg *rarg; |
| 635 | struct filter_arg *arg; | 748 | struct filter_arg *arg; |
| 749 | enum event_type orig_type; | ||
| 636 | enum event_type type; | 750 | enum event_type type; |
| 637 | 751 | ||
| 638 | type = process_value(event, &rarg, error_str); | 752 | type = process_value(event, &rarg, &orig_type, tok, error_str); |
| 639 | if (type == EVENT_ERROR) | 753 | if (type == EVENT_ERROR) { |
| 754 | free_arg(rarg); | ||
| 640 | return type; | 755 | return type; |
| 756 | } | ||
| 641 | 757 | ||
| 642 | /* larg can be NULL if a field did not match */ | 758 | /* larg can be NULL if a field did not match */ |
| 643 | if (!larg) { | 759 | if (!larg) { |
| @@ -655,7 +771,8 @@ process_exp(struct event_format *event, enum filter_exp_type etype, | |||
| 655 | 771 | ||
| 656 | cont: | 772 | cont: |
| 657 | /* still need a cmp */ | 773 | /* still need a cmp */ |
| 658 | return process_op(event, arg, parg, tok, error_str); | 774 | type = process_op_token(event, arg, parg, type, tok, error_str); |
| 775 | return type; | ||
| 659 | } | 776 | } |
| 660 | 777 | ||
| 661 | /* | 778 | /* |
| @@ -742,31 +859,25 @@ process_op_token(struct event_format *event, struct filter_arg *larg, | |||
| 742 | } | 859 | } |
| 743 | 860 | ||
| 744 | static enum event_type | 861 | static enum event_type |
| 745 | process_op(struct event_format *event, struct filter_arg *larg, | ||
| 746 | struct filter_arg **parg, char **tok, char **error_str) | ||
| 747 | { | ||
| 748 | enum event_type type; | ||
| 749 | |||
| 750 | *tok = NULL; | ||
| 751 | type = read_token(tok); | ||
| 752 | type = process_op_token(event, larg, parg, type, tok, error_str); | ||
| 753 | |||
| 754 | return type; | ||
| 755 | } | ||
| 756 | |||
| 757 | static enum event_type | ||
| 758 | process_filter(struct event_format *event, struct filter_arg **parg, | 862 | process_filter(struct event_format *event, struct filter_arg **parg, |
| 759 | enum event_type type, char **tok, char **error_str) | 863 | char **tok, char **error_str) |
| 760 | { | 864 | { |
| 761 | struct filter_arg *larg = NULL; | 865 | struct filter_arg *larg = NULL; |
| 866 | enum event_type type; | ||
| 762 | 867 | ||
| 763 | *parg = NULL; | 868 | *parg = NULL; |
| 764 | |||
| 765 | type = process_value_token(event, &larg, type, tok, error_str); | ||
| 766 | free_token(*tok); | ||
| 767 | *tok = NULL; | 869 | *tok = NULL; |
| 768 | 870 | ||
| 769 | return process_op(event, larg, parg, tok, error_str); | 871 | type = process_token(event, parg, tok, error_str); |
| 872 | |||
| 873 | if (type == EVENT_OP && | ||
| 874 | (strcmp(*tok, "&&") == 0 || strcmp(*tok, "||") == 0)) { | ||
| 875 | larg = *parg; | ||
| 876 | *parg = NULL; | ||
| 877 | type = process_bool(event, larg, parg, tok, error_str); | ||
| 878 | } | ||
| 879 | |||
| 880 | return type; | ||
| 770 | } | 881 | } |
| 771 | 882 | ||
| 772 | static enum event_type | 883 | static enum event_type |
| @@ -778,11 +889,17 @@ process_paren(struct event_format *event, struct filter_arg **parg, | |||
| 778 | 889 | ||
| 779 | *parg = NULL; | 890 | *parg = NULL; |
| 780 | 891 | ||
| 781 | type = process_token(event, &arg, tok, error_str, 0); | 892 | type = process_token(event, &arg, tok, error_str); |
| 782 | if (type == EVENT_ERROR) { | 893 | if (type == EVENT_ERROR) { |
| 783 | free_arg(arg); | 894 | free_arg(arg); |
| 784 | return type; | 895 | return type; |
| 785 | } | 896 | } |
| 897 | |||
| 898 | if (type == EVENT_OP && | ||
| 899 | (strcmp(*tok, "&&") == 0 || strcmp(*tok, "||") == 0)) { | ||
| 900 | type = process_bool(event, arg, parg, tok, error_str); | ||
| 901 | } | ||
| 902 | |||
| 786 | if (type != EVENT_DELIM || strcmp(*tok, ")") != 0) { | 903 | if (type != EVENT_DELIM || strcmp(*tok, ")") != 0) { |
| 787 | if (*tok) | 904 | if (*tok) |
| 788 | show_error(error_str, | 905 | show_error(error_str, |
| @@ -815,7 +932,7 @@ process_not(struct event_format *event, struct filter_arg **parg, | |||
| 815 | arg->op.type = FILTER_OP_NOT; | 932 | arg->op.type = FILTER_OP_NOT; |
| 816 | 933 | ||
| 817 | arg->op.left = NULL; | 934 | arg->op.left = NULL; |
| 818 | type = process_token(event, &arg->op.right, tok, error_str, 0); | 935 | type = process_token(event, &arg->op.right, tok, error_str); |
| 819 | if (type == EVENT_ERROR) { | 936 | if (type == EVENT_ERROR) { |
| 820 | free_arg(arg); | 937 | free_arg(arg); |
| 821 | *parg = NULL; | 938 | *parg = NULL; |
| @@ -844,7 +961,7 @@ process_event(struct event_format *event, const char *filter_str, | |||
| 844 | 961 | ||
| 845 | pevent_buffer_init(filter_str, strlen(filter_str)); | 962 | pevent_buffer_init(filter_str, strlen(filter_str)); |
| 846 | 963 | ||
| 847 | type = process_token(event, parg, &token, error_str, 1); | 964 | type = process_filter(event, parg, &token, error_str); |
| 848 | 965 | ||
| 849 | if (type == EVENT_ERROR) | 966 | if (type == EVENT_ERROR) |
| 850 | return -1; | 967 | return -1; |
