aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-02-22 21:30:09 -0500
committerSteven Rostedt <rostedt@goodmis.org>2010-02-22 21:30:09 -0500
commitad3eec12fc6035b49177f09d15b2f9fb466fe1fa (patch)
tree428b0b08a5dc19c0248c6207bcf23cbbbb373c14
parent855f4eeaa3dd370145c737ad8303c5b5abc029ea (diff)
parse-events: Restructure advanced filter to handle arithmetic
Have fields be compared to each other and have mathmatic algorithms applied. Now we can do: funcgraph_exit : rettime - calltime > 1000000 Or sched_wakeup : pid == common_pid Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--parse-events.h41
-rw-r--r--parse-filter.c779
2 files changed, 620 insertions, 200 deletions
diff --git a/parse-events.h b/parse-events.h
index bccb9ee..f87d85c 100644
--- a/parse-events.h
+++ b/parse-events.h
@@ -524,20 +524,55 @@ enum filter_cmp_type {
524 FILTER_CMP_NOT_REGEX, 524 FILTER_CMP_NOT_REGEX,
525}; 525};
526 526
527enum filter_exp_type {
528 FILTER_EXP_NONE,
529 FILTER_EXP_ADD,
530 FILTER_EXP_SUB,
531 FILTER_EXP_MUL,
532 FILTER_EXP_DIV,
533 FILTER_EXP_MOD,
534 FILTER_EXP_RSHIFT,
535 FILTER_EXP_LSHIFT,
536 FILTER_EXP_AND,
537 FILTER_EXP_OR,
538 FILTER_EXP_XOR,
539 FILTER_EXP_NOT,
540};
541
527enum filter_arg_type { 542enum filter_arg_type {
528 FILTER_ARG_NONE, 543 FILTER_ARG_NONE,
529 FILTER_ARG_BOOLEAN, 544 FILTER_ARG_BOOLEAN,
545 FILTER_ARG_VALUE,
546 FILTER_ARG_FIELD,
530 FILTER_ARG_OP, 547 FILTER_ARG_OP,
548 FILTER_ARG_EXP,
531 FILTER_ARG_NUM, 549 FILTER_ARG_NUM,
532 FILTER_ARG_STR, 550 FILTER_ARG_STR,
533}; 551};
534 552
553enum filter_value_type {
554 FILTER_NUMBER,
555 FILTER_STRING
556};
557
535struct fliter_arg; 558struct fliter_arg;
536 559
537struct filter_arg_boolean { 560struct filter_arg_boolean {
538 enum filter_boolean_type value; 561 enum filter_boolean_type value;
539}; 562};
540 563
564struct filter_arg_field {
565 struct format_field *field;
566};
567
568struct filter_arg_value {
569 enum filter_value_type type;
570 union {
571 char *str;
572 unsigned long long val;
573 };
574};
575
541struct filter_arg_op { 576struct filter_arg_op {
542 enum filter_op_type type; 577 enum filter_op_type type;
543 struct filter_arg *left; 578 struct filter_arg *left;
@@ -546,8 +581,8 @@ struct filter_arg_op {
546 581
547struct filter_arg_num { 582struct filter_arg_num {
548 enum filter_cmp_type type; 583 enum filter_cmp_type type;
549 struct format_field *field; 584 struct filter_arg *left;
550 unsigned long long val; 585 struct filter_arg *right;
551}; 586};
552 587
553struct filter_arg_str { 588struct filter_arg_str {
@@ -562,6 +597,8 @@ struct filter_arg {
562 enum filter_arg_type type; 597 enum filter_arg_type type;
563 union { 598 union {
564 struct filter_arg_boolean bool; 599 struct filter_arg_boolean bool;
600 struct filter_arg_field field;
601 struct filter_arg_value value;
565 struct filter_arg_op op; 602 struct filter_arg_op op;
566 struct filter_arg_num num; 603 struct filter_arg_num num;
567 struct filter_arg_str str; 604 struct filter_arg_str str;
diff --git a/parse-filter.c b/parse-filter.c
index 816582d..0890589 100644
--- a/parse-filter.c
+++ b/parse-filter.c
@@ -297,99 +297,35 @@ static void free_events(struct event_list *events)
297 } 297 }
298} 298}
299 299
300static int process_valid_field(struct filter_arg *arg,
301 struct format_field *field,
302 enum filter_cmp_type op_type,
303 enum event_type type,
304 char *val,
305 char **error_str)
306{
307 int ret;
308
309 switch (type) {
310
311 case EVENT_SQUOTE:
312 /* treat this as a character if string is of length 1? */
313 if (strlen(val) == 1)
314 goto as_int;
315 /* fall through */
316
317 case EVENT_DQUOTE:
318 /* right now only allow match */
319 switch (op_type) {
320 case FILTER_CMP_EQ:
321 op_type = FILTER_CMP_MATCH;
322 break;
323 case FILTER_CMP_NE:
324 op_type = FILTER_CMP_NOT_MATCH;
325 break;
326
327 case FILTER_CMP_REGEX:
328 case FILTER_CMP_NOT_REGEX:
329 ret = regcomp(&arg->str.reg, val, REG_ICASE|REG_NOSUB);
330 if (ret)
331 return -1;
332 break;
333
334 default:
335 show_error(error_str,
336 "Op not allowed with string");
337 return -1;
338 }
339 arg->type = FILTER_ARG_STR;
340 arg->str.field = field;
341 arg->str.type = op_type;
342 arg->str.val = strdup(val);
343 if (!arg->str.val)
344 die("Can't allocate arg value");
345
346 /* Need a buffer to copy data int for tests */
347 arg->str.buffer = malloc_or_die(arg->str.field->size + 1);
348 /* Null terminate this buffer */
349 arg->str.buffer[arg->str.field->size] = 0;
350
351 break;
352 case EVENT_ITEM:
353 as_int:
354 switch (op_type) {
355 case FILTER_CMP_REGEX:
356 case FILTER_CMP_NOT_REGEX:
357 show_error(error_str,
358 "Op not allowed with integers");
359 return -1;
360 default:
361 break;
362 }
363 arg->type = FILTER_ARG_NUM;
364 arg->num.field = field;
365 arg->num.type = op_type;
366 arg->num.val = strtoll(val, NULL, 0);
367 break;
368
369 default:
370 /* Can't happen */
371 return -1;
372 }
373
374 return 0;
375}
376
377static enum event_type 300static enum event_type
378process_filter(struct event_format *event, struct filter_arg **parg, 301process_filter(struct event_format *event, struct filter_arg **parg,
379 char **tok, char **error_str, int cont); 302 enum event_type type, char **tok, char **error_str);
380 303
381static enum event_type 304static enum event_type
382process_paren(struct event_format *event, struct filter_arg **parg, 305process_paren(struct event_format *event, struct filter_arg **parg,
383 char **tok, char **error_str, int cont); 306 char **tok, char **error_str);
384 307
385static enum event_type 308static enum event_type
386process_not(struct event_format *event, struct filter_arg **parg, 309process_not(struct event_format *event, struct filter_arg **parg,
387 char **tok, char **error_str, int cont); 310 char **tok, char **error_str);
311
312static enum event_type
313process_op_token(struct event_format *event, struct filter_arg *larg,
314 struct filter_arg **parg, enum event_type type, char **tok,
315 char **error_str);
388 316
389static enum event_type 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/*
322 * Output: tok, parg
323 */
324static enum event_type
390process_token(struct event_format *event, struct filter_arg **parg, 325process_token(struct event_format *event, struct filter_arg **parg,
391 char **tok, char **error_str, int cont) 326 char **tok, char **error_str, int cont)
392{ 327{
328 struct filter_arg *arg;
393 enum event_type type; 329 enum event_type type;
394 char *token; 330 char *token;
395 331
@@ -399,168 +335,450 @@ process_token(struct event_format *event, struct filter_arg **parg,
399 type = read_token(&token); 335 type = read_token(&token);
400 336
401 if (type == EVENT_ITEM) { 337 if (type == EVENT_ITEM) {
402 type = process_filter(event, parg, &token, error_str, cont); 338 type = process_filter(event, parg, type, &token, error_str);
403 339
404 } else if (type == EVENT_DELIM && strcmp(token, "(") == 0) { 340 } else if (type == EVENT_DELIM && strcmp(token, "(") == 0) {
405 free_token(token); 341 free_token(token);
406 type = process_paren(event, parg, &token, error_str, cont); 342 type = process_paren(event, parg, &token, error_str);
407 343
408 } else if (type == EVENT_OP && strcmp(token, "!") == 0) { 344 } else if (type == EVENT_OP && strcmp(token, "!") == 0) {
409 type = process_not(event, parg, &token, error_str, cont); 345 type = process_not(event, parg, &token, error_str);
346 } else {
347 if (type == EVENT_NONE)
348 show_error(error_str, "unexpected end of filter");
349 else
350 show_error(error_str, "unexpected token '%s'", token);
351 type = EVENT_ERROR;
352 }
353
354 *tok = token;
355 while (cont && type != EVENT_ERROR) {
356 if (type != EVENT_OP)
357 break;
358 /* continue */
359 arg = *parg;
360 *parg = NULL;
361 type = process_op_token(event, arg, parg, type, tok, error_str);
410 } 362 }
411 363
412 if (type == EVENT_ERROR) { 364 if (type == EVENT_ERROR) {
413 free_token(token);
414 free_arg(*parg); 365 free_arg(*parg);
415 *parg = NULL; 366 *parg = NULL;
416 return EVENT_ERROR; 367 return EVENT_ERROR;
417 } 368 }
418 369
419 *tok = token;
420 return type; 370 return type;
421} 371}
422 372
373/*
374 * Input: tok
375 * Output: parg, tok
376 */
423static enum event_type 377static enum event_type
424process_op(struct event_format *event, struct filter_arg *larg, 378process_bool(struct event_format *event, struct filter_arg *larg,
425 struct filter_arg **parg, char **tok, char **error_str) 379 struct filter_arg **parg, char **tok, char **error_str)
426{ 380{
427 enum event_type type; 381 struct filter_arg *rarg;
428 struct filter_arg *arg; 382 struct filter_arg *arg;
383 enum event_type type;
384 enum filter_op_type btype;
385
386 /* Can only be called with '&&' or '||' */
387 btype = strcmp(*tok, "&&") == 0 ?
388 FILTER_OP_AND : FILTER_OP_OR;
389
390 type = process_token(event, &rarg, tok, error_str, 0);
391 if (type == EVENT_ERROR) {
392 free_arg(larg);
393 *parg = NULL;
394 return type;
395 }
396
397 /*
398 * 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
400 * condition.
401 */
402 if (!larg || !rarg) {
403 if (btype == FILTER_OP_AND ||
404 (!larg && !rarg)) {
405 free_arg(larg);
406 free_arg(rarg);
407 *parg = NULL;
408 return type;
409 }
410 *parg = larg ? larg : rarg;
411 return type;
412 }
429 413
430 arg = allocate_arg(); 414 arg = allocate_arg();
431 arg->type = FILTER_ARG_OP; 415 arg->type = FILTER_ARG_OP;
416 arg->op.type = btype;
432 arg->op.left = larg; 417 arg->op.left = larg;
418 arg->op.right = rarg;
433 419
434 /* Can only be called with '&&' or '||' */ 420 *parg = arg;
435 arg->op.type = strcmp(*tok, "&&") == 0 ?
436 FILTER_OP_AND : FILTER_OP_OR;
437 421
438 free_token(*tok); 422 return type;
423}
439 424
440 type = process_token(event, &arg->op.right, tok, error_str, 1); 425/*
441 if (type == EVENT_ERROR) 426 * Input: tok
427 * Output: parg
428 */
429static enum event_type
430process_value_token(struct event_format *event, struct filter_arg **parg,
431 enum event_type type, char **tok, char **error_str)
432{
433 struct format_field *field;
434 struct filter_arg *arg;
435 char *token;
436
437 token = *tok;
438 *tok = NULL;
439
440 arg = allocate_arg();
441
442 switch (type) {
443
444 case EVENT_SQUOTE:
445 case EVENT_DQUOTE:
446 arg->type = FILTER_ARG_VALUE;
447 arg->value.type = FILTER_STRING;
448 arg->value.str = token;
449 break;
450 case EVENT_ITEM:
451 /* if it is a number, then convert it */
452 if (isdigit(token[0])) {
453 arg->type = FILTER_ARG_VALUE;
454 arg->value.type = FILTER_NUMBER;
455 arg->value.val = strtoll(token, NULL, 0);
456 free_token(token);
457 break;
458 }
459 /* Consider this a field */
460 field = pevent_find_any_field(event, token);
461 free_token(token);
462 if (!field) {
463 /* not a field, so NULL it up */
464 free_arg(arg);
465 arg = NULL;
466 break;
467 }
468
469 arg->type = FILTER_ARG_FIELD;
470 arg->field.field = field;
471 break;
472 default:
442 free_arg(arg); 473 free_arg(arg);
474 show_error(error_str, "expected a value but found %s",
475 token);
476 free_token(token);
477 return EVENT_ERROR;
478 }
443 479
444 *parg = arg; 480 *parg = arg;
481 return type;
482}
445 483
484/*
485 * Output: parg
486 */
487static enum event_type
488process_value(struct event_format *event, struct filter_arg **parg,
489 char **error_str)
490{
491 enum event_type type;
492 char *token;
493
494 type = read_token(&token);
495 type = process_value_token(event, parg, type, &token, error_str);
496 free_token(token);
446 return type; 497 return type;
447} 498}
448 499
500/*
501 * Output: parg, tok
502 */
449static enum event_type 503static enum event_type
450process_filter(struct event_format *event, struct filter_arg **parg, 504process_cmp(struct event_format *event, enum filter_cmp_type op_type,
451 char **tok, char **error_str, int cont) 505 struct filter_arg *larg, struct filter_arg **parg,
506 char **tok, char **error_str)
452{ 507{
453 struct format_field *field;
454 enum filter_cmp_type etype;
455 struct filter_arg *arg; 508 struct filter_arg *arg;
509 struct filter_arg *rarg;
456 enum event_type type; 510 enum event_type type;
457 char *field_name;
458 char *token;
459 char *op;
460 int ret; 511 int ret;
461 512
462 *parg = NULL; 513 *parg = NULL;
463 514
464 field_name = *tok; 515 type = process_value(event, &rarg, error_str);
465 *tok = NULL; 516 if (type == EVENT_ERROR)
517 return type;
466 518
467 type = read_token(&token); 519 arg = allocate_arg();
468 if (type != EVENT_OP) { 520 /*
469 if (type == EVENT_NONE) 521 * If either arg is NULL if right was field not found.
522 * Then make the entire expression NULL. (will turn to FALSE)
523 */
524 if (!larg || !rarg) {
525 free_arg(larg);
526 free_arg(rarg);
527 free_arg(arg);
528 arg = NULL;
529 goto cont;
530 }
531
532 switch (type) {
533 case EVENT_SQUOTE:
534 /* treat this as a character if string is of length 1? */
535 if (strlen(rarg->str.val) == 1) {
536 switch (op_type) {
537 case FILTER_CMP_REGEX:
538 case FILTER_CMP_NOT_REGEX:
539 /* regex can't be used with ints */
540 break;
541 default:
542 goto as_int;
543 }
544 }
545 /* fall through */
546 case EVENT_DQUOTE:
547 arg->type = FILTER_ARG_STR;
548
549 if (larg->type != FILTER_ARG_FIELD) {
550 free(larg);
551 free(rarg);
470 show_error(error_str, 552 show_error(error_str,
471 "Expected OP but found end of filter after %s", 553 "Illegal lval for string comparison");
472 field_name); 554 free_arg(arg);
473 else 555 return EVENT_ERROR;
556 }
557
558 arg->str.field = larg->field.field;
559 free_arg(larg);
560
561 /* free the rarg, and use its token */
562 arg->str.val = rarg->value.str;
563 rarg->value.str = NULL;
564 free_arg(rarg);
565
566 /* Make sure this is a valid string compare */
567 switch (op_type) {
568 case FILTER_CMP_EQ:
569 op_type = FILTER_CMP_MATCH;
570 break;
571 case FILTER_CMP_NE:
572 op_type = FILTER_CMP_NOT_MATCH;
573 break;
574
575 case FILTER_CMP_REGEX:
576 case FILTER_CMP_NOT_REGEX:
577 ret = regcomp(&arg->str.reg, arg->str.val, REG_ICASE|REG_NOSUB);
578 if (ret) {
579 show_error(error_str,
580 "RegEx '%s' did not compute",
581 arg->str.val);
582 free_arg(arg);
583 return EVENT_ERROR;
584 }
585 break;
586 default:
474 show_error(error_str, 587 show_error(error_str,
475 "Expected OP but found %s after %s", 588 "Illegal comparison for string");
476 token, field_name); 589 free_arg(arg);
477 free_token(field_name); 590 return EVENT_ERROR;
591 }
592
593 arg->str.type = op_type;
594
595 /*
596 * Need a buffer to copy data int for tests */
597 arg->str.buffer = malloc_or_die(arg->str.field->size + 1);
598 /* Null terminate this buffer */
599 arg->str.buffer[arg->str.field->size] = 0;
600
601 break;
602 default:
603 as_int:
604 switch (op_type) {
605 case FILTER_CMP_REGEX:
606 case FILTER_CMP_NOT_REGEX:
607 show_error(error_str,
608 "Op not allowed with integers");
609 free_arg(arg);
610 return EVENT_ERROR;
611 default:
612 break;
613 }
614 /* numeric compare */
615 arg->type = FILTER_ARG_NUM;
616 arg->num.type = op_type;
617 arg->num.left = larg;
618 arg->num.right = rarg;
619 break;
620 }
621 cont:
622 *parg = arg;
623 return read_token(tok);
624}
625
626/*
627 * Output: parg, tok
628 */
629static enum event_type
630process_exp(struct event_format *event, enum filter_exp_type etype,
631 struct filter_arg *larg, struct filter_arg **parg,
632 char **tok, char **error_str)
633{
634 struct filter_arg *rarg;
635 struct filter_arg *arg;
636 enum event_type type;
637
638 type = process_value(event, &rarg, error_str);
639 if (type == EVENT_ERROR)
640 return type;
641
642 /* larg can be NULL if a field did not match */
643 if (!larg) {
644 /* syntax is correct, just return NULL */
645 arg = NULL;
646 free_arg(rarg);
647 goto cont;
648 }
649
650 arg = allocate_arg();
651 arg->type = FILTER_ARG_EXP;
652 arg->op.type = etype;
653 arg->op.left = larg;
654 arg->op.right = rarg;
655
656 cont:
657 /* still need a cmp */
658 return process_op(event, arg, parg, tok, error_str);
659}
660
661/*
662 * Input: tok
663 * Output: parg, tok
664 */
665static enum event_type
666process_op_token(struct event_format *event, struct filter_arg *larg,
667 struct filter_arg **parg, enum event_type type, char **tok,
668 char **error_str)
669{
670 enum filter_cmp_type ctype;
671 enum filter_exp_type etype = FILTER_EXP_NONE;
672 char *token;
673
674 token = *tok;
675 *parg = NULL;
676
677 if (type != EVENT_OP) {
678 *parg = larg;
679 return type;
680 }
681
682 if (strcmp(token, "&&") == 0 || strcmp(token, "||") == 0) {
683 /* handle boolean cases */
684 return process_bool(event, larg, parg, tok, error_str);
685 }
686
687 /* Check for value expressions */
688 if (strcmp(token, "+") == 0) {
689 etype = FILTER_EXP_ADD;
690 } else if (strcmp(token, "-") == 0) {
691 etype = FILTER_EXP_SUB;
692 } else if (strcmp(token, "*") == 0) {
693 etype = FILTER_EXP_MUL;
694 } else if (strcmp(token, "/") == 0) {
695 etype = FILTER_EXP_DIV;
696 } else if (strcmp(token, "%") == 0) {
697 etype = FILTER_EXP_MOD;
698 } else if (strcmp(token, ">>") == 0) {
699 etype = FILTER_EXP_RSHIFT;
700 } else if (strcmp(token, "<<") == 0) {
701 etype = FILTER_EXP_LSHIFT;
702 } else if (strcmp(token, "&") == 0) {
703 etype = FILTER_EXP_AND;
704 } else if (strcmp(token, "|") == 0) {
705 etype = FILTER_EXP_OR;
706 } else if (strcmp(token, "^") == 0) {
707 etype = FILTER_EXP_XOR;
708 } else if (strcmp(token, "~") == 0)
709 etype = FILTER_EXP_NOT;
710
711 if (etype != FILTER_EXP_NONE) {
478 free_token(token); 712 free_token(token);
479 return EVENT_ERROR; 713 return process_exp(event, etype, larg, parg, tok, error_str);
480 } 714 }
481 715
482 if (strcmp(token, "==") == 0) { 716 if (strcmp(token, "==") == 0) {
483 etype = FILTER_CMP_EQ; 717 ctype = FILTER_CMP_EQ;
484 } else if (strcmp(token, "!=") == 0) { 718 } else if (strcmp(token, "!=") == 0) {
485 etype = FILTER_CMP_NE; 719 ctype = FILTER_CMP_NE;
486 } else if (strcmp(token, "<") == 0) { 720 } else if (strcmp(token, "<") == 0) {
487 etype = FILTER_CMP_LT; 721 ctype = FILTER_CMP_LT;
488 } else if (strcmp(token, ">") == 0) { 722 } else if (strcmp(token, ">") == 0) {
489 etype = FILTER_CMP_GT; 723 ctype = FILTER_CMP_GT;
490 } else if (strcmp(token, "<=") == 0) { 724 } else if (strcmp(token, "<=") == 0) {
491 etype = FILTER_CMP_LE; 725 ctype = FILTER_CMP_LE;
492 } else if (strcmp(token, ">=") == 0) { 726 } else if (strcmp(token, ">=") == 0) {
493 etype = FILTER_CMP_GE; 727 ctype = FILTER_CMP_GE;
494 } else if (strcmp(token, "=~") == 0) { 728 } else if (strcmp(token, "=~") == 0) {
495 etype = FILTER_CMP_REGEX; 729 ctype = FILTER_CMP_REGEX;
496 } else if (strcmp(token, "!~") == 0) { 730 } else if (strcmp(token, "!~") == 0) {
497 etype = FILTER_CMP_NOT_REGEX; 731 ctype = FILTER_CMP_NOT_REGEX;
498 } else { 732 } else {
499 show_error(error_str, 733 show_error(error_str,
500 "Unknown op '%s' after '%s'", 734 "Unknown op '%s'", token);
501 token, field_name);
502 free_token(field_name);
503 free_token(token); 735 free_token(token);
504 return EVENT_ERROR; 736 return EVENT_ERROR;
505 } 737 }
506 op = token;
507 738
508 type = read_token(&token); 739 free_token(token);
509 if (type != EVENT_ITEM && type != EVENT_SQUOTE && type != EVENT_DQUOTE) { 740 *tok = NULL;
510 show_error(error_str, 741 return process_cmp(event, ctype, larg, parg, tok, error_str);
511 "Expected an item after '%s %s' instead of %s", 742}
512 field_name, op, token);
513 free_token(field_name);
514 free_token(op);
515 free_token(token);
516 return EVENT_ERROR;
517 }
518 free_token(op);
519 743
520 field = pevent_find_any_field(event, field_name); 744static enum event_type
521 free_token(field_name); 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;
522 749
523 arg = allocate_arg(); 750 *tok = NULL;
751 type = read_token(tok);
752 type = process_op_token(event, larg, parg, type, tok, error_str);
524 753
525 if (field) { 754 return type;
526 ret = process_valid_field(arg, field, etype, type, token, error_str); 755}
527 if (ret < 0) {
528 free_arg(arg);
529 return EVENT_ERROR;
530 }
531 } else {
532 /*
533 * When an event does not contain a field in the
534 * filter, just make it false.
535 */
536 arg->type = FILTER_ARG_BOOLEAN;
537 arg->bool.value = FILTER_FALSE;
538 }
539 756
540 free_token(token); 757static enum event_type
758process_filter(struct event_format *event, struct filter_arg **parg,
759 enum event_type type, char **tok, char **error_str)
760{
761 struct filter_arg *larg = NULL;
541 762
542 type = read_token(tok); 763 *parg = NULL;
543 764
544 if (cont && type == EVENT_OP && 765 type = process_value_token(event, &larg, type, tok, error_str);
545 (strcmp(*tok, "&&") == 0 || strcmp(*tok, "||") == 0)) { 766 free_token(*tok);
546 /* continue */; 767 *tok = NULL;
547 type = process_op(event, arg, parg, tok, error_str);
548 } else
549 *parg = arg;
550 768
551 return type; 769 return process_op(event, larg, parg, tok, error_str);
552} 770}
553 771
554static enum event_type 772static enum event_type
555process_paren(struct event_format *event, struct filter_arg **parg, 773process_paren(struct event_format *event, struct filter_arg **parg,
556 char **tok, char **error_str, int cont) 774 char **tok, char **error_str)
557{ 775{
558 struct filter_arg *arg; 776 struct filter_arg *arg;
559 enum event_type type; 777 enum event_type type;
560 778
561 *parg = NULL; 779 *parg = NULL;
562 780
563 type = process_token(event, &arg, tok, error_str, 1); 781 type = process_token(event, &arg, tok, error_str, 0);
564 if (type == EVENT_ERROR) { 782 if (type == EVENT_ERROR) {
565 free_arg(arg); 783 free_arg(arg);
566 return type; 784 return type;
@@ -578,22 +796,16 @@ process_paren(struct event_format *event, struct filter_arg **parg,
578 return EVENT_ERROR; 796 return EVENT_ERROR;
579 } 797 }
580 free_token(*tok); 798 free_token(*tok);
799 *tok = NULL;
581 800
582 type = read_token(tok); 801 *parg = arg;
583
584 if (cont && type == EVENT_OP &&
585 (strcmp(*tok, "&&") == 0 || strcmp(*tok, "||") == 0)) {
586 /* continue */;
587 type = process_op(event, arg, parg, tok, error_str);
588 } else
589 *parg = arg;
590 802
591 return type; 803 return read_token(tok);
592} 804}
593 805
594static enum event_type 806static enum event_type
595process_not(struct event_format *event, struct filter_arg **parg, 807process_not(struct event_format *event, struct filter_arg **parg,
596 char **tok, char **error_str, int cont) 808 char **tok, char **error_str)
597{ 809{
598 struct filter_arg *arg; 810 struct filter_arg *arg;
599 enum event_type type; 811 enum event_type type;
@@ -611,13 +823,14 @@ process_not(struct event_format *event, struct filter_arg **parg,
611 *tok = NULL; 823 *tok = NULL;
612 return EVENT_ERROR; 824 return EVENT_ERROR;
613 } 825 }
826 /* If the bool value is NULL, then make this into TRUE */
827 if (!arg->op.right) {
828 arg->type = FILTER_ARG_BOOLEAN;
829 arg->bool.value = FILTER_TRUE;
830 }
614 831
615 if (cont && type == EVENT_OP && 832 free_token(*tok);
616 (strcmp(*tok, "&&") == 0 || strcmp(*tok, "||") == 0)) { 833 *tok = NULL;
617 /* continue */;
618 type = process_op(event, arg, parg, tok, error_str);
619 } else
620 *parg = arg;
621 834
622 return type; 835 return type;
623} 836}
@@ -645,6 +858,14 @@ process_event(struct event_format *event, const char *filter_str,
645 *parg = NULL; 858 *parg = NULL;
646 return -1; 859 return -1;
647 } 860 }
861
862 /* If parg is NULL, then make it into FALSE */
863 if (!*parg) {
864 *parg = allocate_arg();
865 (*parg)->type = FILTER_ARG_BOOLEAN;
866 (*parg)->bool.value = FILTER_FALSE;
867 }
868
648 return 0; 869 return 0;
649} 870}
650 871
@@ -931,7 +1152,6 @@ int pevent_filter_copy(struct event_filter *dest, struct event_filter *source)
931 * Returns 0 on success and -1 if there was a problem updating, but 1152 * Returns 0 on success and -1 if there was a problem updating, but
932 * events may have still been updated on error. 1153 * events may have still been updated on error.
933 */ 1154 */
934
935int pevent_update_trivial(struct event_filter *dest, struct event_filter *source, 1155int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
936 enum filter_trivial_type type) 1156 enum filter_trivial_type type)
937{ 1157{
@@ -1099,31 +1319,102 @@ get_value(struct format_field *field, struct record *record)
1099 return val; 1319 return val;
1100} 1320}
1101 1321
1322static unsigned long long
1323get_arg_value(struct event_format *event, struct filter_arg *arg, struct record *record);
1324
1325static unsigned long long
1326get_exp_value(struct event_format *event, struct filter_arg *arg, struct record *record)
1327{
1328 unsigned long long lval, rval;
1329
1330 lval = get_arg_value(event, arg->op.left, record);
1331 rval = get_arg_value(event, arg->op.right, record);
1332
1333 switch (arg->op.type) {
1334 case FILTER_EXP_ADD:
1335 return lval + rval;
1336
1337 case FILTER_EXP_SUB:
1338 return lval - rval;
1339
1340 case FILTER_EXP_MUL:
1341 return lval * rval;
1342
1343 case FILTER_EXP_DIV:
1344 return lval / rval;
1345
1346 case FILTER_EXP_MOD:
1347 return lval % rval;
1348
1349 case FILTER_EXP_RSHIFT:
1350 return lval >> rval;
1351
1352 case FILTER_EXP_LSHIFT:
1353 return lval << rval;
1354
1355 case FILTER_EXP_AND:
1356 return lval & rval;
1357
1358 case FILTER_EXP_OR:
1359 return lval | rval;
1360
1361 case FILTER_EXP_XOR:
1362 return lval ^ rval;
1363
1364 case FILTER_EXP_NOT:
1365 default:
1366 die("error in exp");
1367 }
1368 return 0;
1369}
1370
1371static unsigned long long
1372get_arg_value(struct event_format *event, struct filter_arg *arg, struct record *record)
1373{
1374 switch (arg->type) {
1375 case FILTER_ARG_FIELD:
1376 return get_value(arg->field.field, record);
1377
1378 case FILTER_ARG_VALUE:
1379 if (arg->value.type != FILTER_NUMBER)
1380 die("must have number field!");
1381 return arg->value.val;
1382
1383 case FILTER_ARG_EXP:
1384 return get_exp_value(event, arg, record);
1385
1386 default:
1387 die("oops in filter");
1388 }
1389 return 0;
1390}
1391
1102static int test_num(struct event_format *event, 1392static int test_num(struct event_format *event,
1103 struct filter_arg *arg, struct record *record) 1393 struct filter_arg *arg, struct record *record)
1104{ 1394{
1105 unsigned long long val; 1395 unsigned long long lval, rval;
1106 1396
1107 val = get_value(arg->num.field, record); 1397 lval = get_arg_value(event, arg->num.left, record);
1398 rval = get_arg_value(event, arg->num.right, record);
1108 1399
1109 switch (arg->num.type) { 1400 switch (arg->num.type) {
1110 case FILTER_CMP_EQ: 1401 case FILTER_CMP_EQ:
1111 return val == arg->num.val; 1402 return lval == rval;
1112 1403
1113 case FILTER_CMP_NE: 1404 case FILTER_CMP_NE:
1114 return val != arg->num.val; 1405 return lval != rval;
1115 1406
1116 case FILTER_CMP_GT: 1407 case FILTER_CMP_GT:
1117 return val > arg->num.val; 1408 return lval > rval;
1118 1409
1119 case FILTER_CMP_LT: 1410 case FILTER_CMP_LT:
1120 return val < arg->num.val; 1411 return lval < rval;
1121 1412
1122 case FILTER_CMP_GE: 1413 case FILTER_CMP_GE:
1123 return val >= arg->num.val; 1414 return lval >= rval;
1124 1415
1125 case FILTER_CMP_LE: 1416 case FILTER_CMP_LE:
1126 return val <= arg->num.val; 1417 return lval <= rval;
1127 1418
1128 default: 1419 default:
1129 /* ?? */ 1420 /* ?? */
@@ -1208,7 +1499,17 @@ static int test_filter(struct event_format *event,
1208 case FILTER_ARG_STR: 1499 case FILTER_ARG_STR:
1209 return test_str(event, arg, record); 1500 return test_str(event, arg, record);
1210 1501
1502 case FILTER_ARG_EXP:
1503 case FILTER_ARG_VALUE:
1504 case FILTER_ARG_FIELD:
1505 /*
1506 * Expressions, fields and values evaluate
1507 * to true if they return non zero
1508 */
1509 return !!get_arg_value(event, arg, record);
1510
1211 default: 1511 default:
1512 die("oops!");
1212 /* ?? */ 1513 /* ?? */
1213 return 0; 1514 return 0;
1214 } 1515 }
@@ -1385,12 +1686,88 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
1385 return str; 1686 return str;
1386} 1687}
1387 1688
1689static char *val_to_str(struct event_filter *filter, struct filter_arg *arg)
1690{
1691 char *str;
1692
1693 str = malloc_or_die(30);
1694
1695 snprintf(str, 30, "%lld", arg->value.val);
1696
1697 return str;
1698}
1699
1700static char *field_to_str(struct event_filter *filter, struct filter_arg *arg)
1701{
1702 return strdup(arg->field.field->name);
1703}
1704
1705static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
1706{
1707 char *lstr;
1708 char *rstr;
1709 char *op;
1710 char *str;
1711 int len;
1712
1713 lstr = arg_to_str(filter, arg->op.left);
1714 rstr = arg_to_str(filter, arg->op.right);
1715
1716 switch (arg->op.type) {
1717 case FILTER_EXP_ADD:
1718 op = "+";
1719 break;
1720 case FILTER_EXP_SUB:
1721 op = "-";
1722 break;
1723 case FILTER_EXP_MUL:
1724 op = "*";
1725 break;
1726 case FILTER_EXP_DIV:
1727 op = "/";
1728 break;
1729 case FILTER_EXP_MOD:
1730 op = "%";
1731 break;
1732 case FILTER_EXP_RSHIFT:
1733 op = ">>";
1734 break;
1735 case FILTER_EXP_LSHIFT:
1736 op = "<<";
1737 break;
1738 case FILTER_EXP_AND:
1739 op = "&";
1740 break;
1741 case FILTER_EXP_OR:
1742 op = "|";
1743 break;
1744 case FILTER_EXP_XOR:
1745 op = "^";
1746 break;
1747 default:
1748 die("oops in exp");
1749 }
1750
1751 len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
1752 str = malloc_or_die(len);
1753 snprintf(str, len, "%s %s %s", lstr, op, rstr);
1754 free(lstr);
1755 free(rstr);
1756
1757 return str;
1758}
1759
1388static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) 1760static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
1389{ 1761{
1762 char *lstr;
1763 char *rstr;
1390 char *str = NULL; 1764 char *str = NULL;
1391 char *op = NULL; 1765 char *op = NULL;
1392 int len; 1766 int len;
1393 1767
1768 lstr = arg_to_str(filter, arg->num.left);
1769 rstr = arg_to_str(filter, arg->num.right);
1770
1394 switch (arg->num.type) { 1771 switch (arg->num.type) {
1395 case FILTER_CMP_EQ: 1772 case FILTER_CMP_EQ:
1396 op = "=="; 1773 op = "==";
@@ -1415,22 +1792,19 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
1415 if (!op) 1792 if (!op)
1416 op = "<="; 1793 op = "<=";
1417 1794
1418 len = strlen(arg->num.field->name) + strlen(op) + 30; 1795 len = strlen(lstr) + strlen(op) + strlen(rstr) + 4;
1419 str = malloc_or_die(len); 1796 str = malloc_or_die(len);
1420 if (arg->num.field->flags & FIELD_IS_SIGNED) 1797 sprintf(str, "%s %s %s", lstr, op, rstr);
1421 snprintf(str, len, "%s %s %lld", 1798
1422 arg->num.field->name,
1423 op, arg->num.val);
1424 else
1425 snprintf(str, len, "%s %s %llu",
1426 arg->num.field->name,
1427 op, arg->num.val);
1428 break; 1799 break;
1429 1800
1430 default: 1801 default:
1431 /* ?? */ 1802 /* ?? */
1432 break; 1803 break;
1433 } 1804 }
1805
1806 free(lstr);
1807 free(rstr);
1434 return str; 1808 return str;
1435} 1809}
1436 1810
@@ -1493,6 +1867,15 @@ static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
1493 case FILTER_ARG_STR: 1867 case FILTER_ARG_STR:
1494 return str_to_str(filter, arg); 1868 return str_to_str(filter, arg);
1495 1869
1870 case FILTER_ARG_VALUE:
1871 return val_to_str(filter, arg);
1872
1873 case FILTER_ARG_FIELD:
1874 return field_to_str(filter, arg);
1875
1876 case FILTER_ARG_EXP:
1877 return exp_to_str(filter, arg);
1878
1496 default: 1879 default:
1497 /* ?? */ 1880 /* ?? */
1498 return NULL; 1881 return NULL;