aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-04-01 17:07:27 -0400
committerSteven Rostedt <rostedt@goodmis.org>2010-04-01 22:37:30 -0400
commitd5dfeec080a394f59a9d82452aa50f6bbb2a085a (patch)
treed11cdb1b2bd95c35195d39e9a1fbce157015a098
parent73effebdbe6b887ed2683f15175a65dda9cddfbf (diff)
parse-events: Fix parenthesis parsing of filters
The parenthesis filter parsing was a bit broken and needed a rewrite. This redesigns the filter parsing to be a bit more sane when it comes to parenthesis. It lets the parenthesis be treated as what they resolve to be. Funny, the example used by kernelshark failed because of this bug: "next_prio < 100 && (prev_prio > 100 && prev_pid != 0)" Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--parse-events.h2
-rw-r--r--parse-filter.c257
-rw-r--r--trace-input.c1
3 files changed, 188 insertions, 72 deletions
diff --git a/parse-events.h b/parse-events.h
index d79f4e0..0c6a330 100644
--- a/parse-events.h
+++ b/parse-events.h
@@ -573,8 +573,8 @@ enum filter_arg_type {
573 FILTER_ARG_BOOLEAN, 573 FILTER_ARG_BOOLEAN,
574 FILTER_ARG_VALUE, 574 FILTER_ARG_VALUE,
575 FILTER_ARG_FIELD, 575 FILTER_ARG_FIELD,
576 FILTER_ARG_OP,
577 FILTER_ARG_EXP, 576 FILTER_ARG_EXP,
577 FILTER_ARG_OP,
578 FILTER_ARG_NUM, 578 FILTER_ARG_NUM,
579 FILTER_ARG_STR, 579 FILTER_ARG_STR,
580}; 580};
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
300static enum event_type 300static enum event_type
301process_filter(struct event_format *event, struct filter_arg **parg,
302 enum event_type type, char **tok, char **error_str);
303
304static enum event_type
305process_paren(struct event_format *event, struct filter_arg **parg, 301process_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
312static enum event_type 308static enum event_type
309process_value_token(struct event_format *event, struct filter_arg **parg,
310 enum event_type type, char **tok, char **error_str);
311
312static enum event_type
313process_op_token(struct event_format *event, struct filter_arg *larg, 313process_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
317static enum event_type
318process_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 */
324static enum event_type 324static enum event_type
325process_token(struct event_format *event, struct filter_arg **parg, 325process_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 */
487static enum event_type 568static enum event_type
488process_value(struct event_format *event, struct filter_arg **parg, 569process_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 */
503static enum event_type 612static 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 */
629static enum event_type 742static 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
744static enum event_type 861static enum event_type
745process_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
757static enum event_type
758process_filter(struct event_format *event, struct filter_arg **parg, 862process_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
772static enum event_type 883static 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;
diff --git a/trace-input.c b/trace-input.c
index c70dc6b..9b0e509 100644
--- a/trace-input.c
+++ b/trace-input.c
@@ -712,7 +712,6 @@ static int update_page_info(struct tracecmd_input *handle, int cpu)
712 handle->cpu_data[cpu].page_size = flags & COMMIT_MASK; 712 handle->cpu_data[cpu].page_size = flags & COMMIT_MASK;
713 713
714 if (flags & MISSING_EVENTS) { 714 if (flags & MISSING_EVENTS) {
715 breakpoint();
716 if (flags & MISSING_STORED) { 715 if (flags & MISSING_STORED) {
717 ptr += handle->cpu_data[cpu].page_size; 716 ptr += handle->cpu_data[cpu].page_size;
718 switch (pevent->header_page_size_size) { 717 switch (pevent->header_page_size_size) {