2 * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 #include <sys/types.h>
27 #include "event-parse.h"
28 #include "event-utils.h"
33 static struct format_field comm
= {
37 static struct format_field cpu
= {
42 struct event_list
*next
;
43 struct event_format
*event
;
46 static void show_error(char *error_buf
, const char *fmt
, ...)
48 unsigned long long index
;
54 input
= pevent_get_input_buf();
55 index
= pevent_get_input_buf_ptr();
56 len
= input
? strlen(input
) : 0;
59 strcpy(error_buf
, input
);
60 error_buf
[len
] = '\n';
61 for (i
= 1; i
< len
&& i
< index
; i
++)
62 error_buf
[len
+i
] = ' ';
63 error_buf
[len
+ i
] = '^';
64 error_buf
[len
+ i
+ 1] = '\n';
69 vsnprintf(error_buf
+ len
, PEVENT_FILTER_ERROR_BUFSZ
- len
, fmt
, ap
);
73 static void free_token(char *token
)
75 pevent_free_token(token
);
78 static enum event_type
read_token(char **tok
)
85 type
= pevent_read_token(&token
);
86 } while (type
== EVENT_NEWLINE
|| type
== EVENT_SPACE
);
88 /* If token is = or ! check to see if the next char is ~ */
90 (strcmp(token
, "=") == 0 || strcmp(token
, "!") == 0) &&
91 pevent_peek_char() == '~') {
98 sprintf(*tok
, "%c%c", *token
, '~');
100 /* Now remove the '~' from the buffer */
101 pevent_read_token(&token
);
109 static int filter_cmp(const void *a
, const void *b
)
111 const struct filter_type
*ea
= a
;
112 const struct filter_type
*eb
= b
;
114 if (ea
->event_id
< eb
->event_id
)
117 if (ea
->event_id
> eb
->event_id
)
123 static struct filter_type
*
124 find_filter_type(struct event_filter
*filter
, int id
)
126 struct filter_type
*filter_type
;
127 struct filter_type key
;
131 filter_type
= bsearch(&key
, filter
->event_filters
,
133 sizeof(*filter
->event_filters
),
139 static struct filter_type
*
140 add_filter_type(struct event_filter
*filter
, int id
)
142 struct filter_type
*filter_type
;
145 filter_type
= find_filter_type(filter
, id
);
149 filter_type
= realloc(filter
->event_filters
,
150 sizeof(*filter
->event_filters
) *
151 (filter
->filters
+ 1));
155 filter
->event_filters
= filter_type
;
157 for (i
= 0; i
< filter
->filters
; i
++) {
158 if (filter
->event_filters
[i
].event_id
> id
)
162 if (i
< filter
->filters
)
163 memmove(&filter
->event_filters
[i
+1],
164 &filter
->event_filters
[i
],
165 sizeof(*filter
->event_filters
) *
166 (filter
->filters
- i
));
168 filter_type
= &filter
->event_filters
[i
];
169 filter_type
->event_id
= id
;
170 filter_type
->event
= pevent_find_event(filter
->pevent
, id
);
171 filter_type
->filter
= NULL
;
179 * pevent_filter_alloc - create a new event filter
180 * @pevent: The pevent that this filter is associated with
182 struct event_filter
*pevent_filter_alloc(struct pevent
*pevent
)
184 struct event_filter
*filter
;
186 filter
= malloc(sizeof(*filter
));
190 memset(filter
, 0, sizeof(*filter
));
191 filter
->pevent
= pevent
;
197 static struct filter_arg
*allocate_arg(void)
199 return calloc(1, sizeof(struct filter_arg
));
202 static void free_arg(struct filter_arg
*arg
)
208 case FILTER_ARG_NONE
:
209 case FILTER_ARG_BOOLEAN
:
213 free_arg(arg
->num
.left
);
214 free_arg(arg
->num
.right
);
218 free_arg(arg
->exp
.left
);
219 free_arg(arg
->exp
.right
);
224 regfree(&arg
->str
.reg
);
225 free(arg
->str
.buffer
);
228 case FILTER_ARG_VALUE
:
229 if (arg
->value
.type
== FILTER_STRING
||
230 arg
->value
.type
== FILTER_CHAR
)
231 free(arg
->value
.str
);
235 free_arg(arg
->op
.left
);
236 free_arg(arg
->op
.right
);
244 static int add_event(struct event_list
**events
,
245 struct event_format
*event
)
247 struct event_list
*list
;
249 list
= malloc(sizeof(*list
));
253 list
->next
= *events
;
259 static int event_match(struct event_format
*event
,
260 regex_t
*sreg
, regex_t
*ereg
)
263 return !regexec(sreg
, event
->system
, 0, NULL
, 0) &&
264 !regexec(ereg
, event
->name
, 0, NULL
, 0);
267 return !regexec(ereg
, event
->system
, 0, NULL
, 0) ||
268 !regexec(ereg
, event
->name
, 0, NULL
, 0);
271 static enum pevent_errno
272 find_event(struct pevent
*pevent
, struct event_list
**events
,
273 char *sys_name
, char *event_name
)
275 struct event_format
*event
;
285 /* if no name is given, then swap sys and name */
286 event_name
= sys_name
;
290 ret
= asprintf(®
, "^%s$", event_name
);
292 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
294 ret
= regcomp(&ereg
, reg
, REG_ICASE
|REG_NOSUB
);
298 return PEVENT_ERRNO__INVALID_EVENT_NAME
;
301 ret
= asprintf(®
, "^%s$", sys_name
);
304 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
307 ret
= regcomp(&sreg
, reg
, REG_ICASE
|REG_NOSUB
);
311 return PEVENT_ERRNO__INVALID_EVENT_NAME
;
315 for (i
= 0; i
< pevent
->nr_events
; i
++) {
316 event
= pevent
->events
[i
];
317 if (event_match(event
, sys_name
? &sreg
: NULL
, &ereg
)) {
319 if (add_event(events
, event
) < 0) {
331 return PEVENT_ERRNO__EVENT_NOT_FOUND
;
333 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
338 static void free_events(struct event_list
*events
)
340 struct event_list
*event
;
344 events
= events
->next
;
349 static enum pevent_errno
350 create_arg_item(struct event_format
*event
, const char *token
,
351 enum event_type type
, struct filter_arg
**parg
, char *error_str
)
353 struct format_field
*field
;
354 struct filter_arg
*arg
;
356 arg
= allocate_arg();
358 show_error(error_str
, "failed to allocate filter arg");
359 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
366 arg
->type
= FILTER_ARG_VALUE
;
368 type
== EVENT_DQUOTE
? FILTER_STRING
: FILTER_CHAR
;
369 arg
->value
.str
= strdup(token
);
370 if (!arg
->value
.str
) {
372 show_error(error_str
, "failed to allocate string filter arg");
373 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
377 /* if it is a number, then convert it */
378 if (isdigit(token
[0])) {
379 arg
->type
= FILTER_ARG_VALUE
;
380 arg
->value
.type
= FILTER_NUMBER
;
381 arg
->value
.val
= strtoull(token
, NULL
, 0);
384 /* Consider this a field */
385 field
= pevent_find_any_field(event
, token
);
387 /* If token is 'COMM' or 'CPU' then it is special */
388 if (strcmp(token
, COMM
) == 0) {
390 } else if (strcmp(token
, CPU
) == 0) {
393 /* not a field, Make it false */
394 arg
->type
= FILTER_ARG_BOOLEAN
;
395 arg
->boolean
.value
= FILTER_FALSE
;
399 arg
->type
= FILTER_ARG_FIELD
;
400 arg
->field
.field
= field
;
404 show_error(error_str
, "expected a value but found %s", token
);
405 return PEVENT_ERRNO__UNEXPECTED_TYPE
;
411 static struct filter_arg
*
412 create_arg_op(enum filter_op_type btype
)
414 struct filter_arg
*arg
;
416 arg
= allocate_arg();
420 arg
->type
= FILTER_ARG_OP
;
421 arg
->op
.type
= btype
;
426 static struct filter_arg
*
427 create_arg_exp(enum filter_exp_type etype
)
429 struct filter_arg
*arg
;
431 arg
= allocate_arg();
435 arg
->type
= FILTER_ARG_EXP
;
436 arg
->exp
.type
= etype
;
441 static struct filter_arg
*
442 create_arg_cmp(enum filter_cmp_type ctype
)
444 struct filter_arg
*arg
;
446 arg
= allocate_arg();
450 /* Use NUM and change if necessary */
451 arg
->type
= FILTER_ARG_NUM
;
452 arg
->num
.type
= ctype
;
457 static enum pevent_errno
458 add_right(struct filter_arg
*op
, struct filter_arg
*arg
, char *error_str
)
460 struct filter_arg
*left
;
482 * The arg must be num, str, or field
485 case FILTER_ARG_VALUE
:
486 case FILTER_ARG_FIELD
:
489 show_error(error_str
, "Illegal rvalue");
490 return PEVENT_ERRNO__ILLEGAL_RVALUE
;
494 * Depending on the type, we may need to
495 * convert this to a string or regex.
497 switch (arg
->value
.type
) {
500 * A char should be converted to number if
501 * the string is 1 byte, and the compare
504 if (strlen(arg
->value
.str
) == 1 &&
505 op
->num
.type
!= FILTER_CMP_REGEX
&&
506 op
->num
.type
!= FILTER_CMP_NOT_REGEX
) {
507 arg
->value
.type
= FILTER_NUMBER
;
513 /* convert op to a string arg */
514 op_type
= op
->num
.type
;
516 str
= arg
->value
.str
;
518 /* reset the op for the new field */
519 memset(op
, 0, sizeof(*op
));
522 * If left arg was a field not found then
523 * NULL the entire op.
525 if (left
->type
== FILTER_ARG_BOOLEAN
) {
528 op
->type
= FILTER_ARG_BOOLEAN
;
529 op
->boolean
.value
= FILTER_FALSE
;
533 /* Left arg must be a field */
534 if (left
->type
!= FILTER_ARG_FIELD
) {
535 show_error(error_str
,
536 "Illegal lvalue for string comparison");
537 return PEVENT_ERRNO__ILLEGAL_LVALUE
;
540 /* Make sure this is a valid string compare */
543 op_type
= FILTER_CMP_MATCH
;
546 op_type
= FILTER_CMP_NOT_MATCH
;
549 case FILTER_CMP_REGEX
:
550 case FILTER_CMP_NOT_REGEX
:
551 ret
= regcomp(&op
->str
.reg
, str
, REG_ICASE
|REG_NOSUB
);
553 show_error(error_str
,
554 "RegEx '%s' did not compute",
556 return PEVENT_ERRNO__INVALID_REGEX
;
560 show_error(error_str
,
561 "Illegal comparison for string");
562 return PEVENT_ERRNO__ILLEGAL_STRING_CMP
;
565 op
->type
= FILTER_ARG_STR
;
566 op
->str
.type
= op_type
;
567 op
->str
.field
= left
->field
.field
;
568 op
->str
.val
= strdup(str
);
570 show_error(error_str
, "Failed to allocate string filter");
571 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
574 * Need a buffer to copy data for tests
576 op
->str
.buffer
= malloc(op
->str
.field
->size
+ 1);
577 if (!op
->str
.buffer
) {
578 show_error(error_str
, "Failed to allocate string filter");
579 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
581 /* Null terminate this buffer */
582 op
->str
.buffer
[op
->str
.field
->size
] = 0;
584 /* We no longer have left or right args */
593 switch (op
->num
.type
) {
594 case FILTER_CMP_REGEX
:
595 case FILTER_CMP_NOT_REGEX
:
596 show_error(error_str
,
597 "Op not allowed with integers");
598 return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP
;
604 /* numeric compare */
618 show_error(error_str
, "Syntax error");
619 return PEVENT_ERRNO__SYNTAX_ERROR
;
622 static struct filter_arg
*
623 rotate_op_right(struct filter_arg
*a
, struct filter_arg
*b
)
625 struct filter_arg
*arg
;
632 static enum pevent_errno
add_left(struct filter_arg
*op
, struct filter_arg
*arg
)
636 if (arg
->type
== FILTER_ARG_OP
)
637 arg
= rotate_op_right(arg
, op
);
645 if (arg
->type
== FILTER_ARG_OP
)
646 arg
= rotate_op_right(arg
, op
);
648 /* left arg of compares must be a field */
649 if (arg
->type
!= FILTER_ARG_FIELD
&&
650 arg
->type
!= FILTER_ARG_BOOLEAN
)
651 return PEVENT_ERRNO__INVALID_ARG_TYPE
;
655 return PEVENT_ERRNO__INVALID_ARG_TYPE
;
668 static enum op_type
process_op(const char *token
,
669 enum filter_op_type
*btype
,
670 enum filter_cmp_type
*ctype
,
671 enum filter_exp_type
*etype
)
673 *btype
= FILTER_OP_NOT
;
674 *etype
= FILTER_EXP_NONE
;
675 *ctype
= FILTER_CMP_NONE
;
677 if (strcmp(token
, "&&") == 0)
678 *btype
= FILTER_OP_AND
;
679 else if (strcmp(token
, "||") == 0)
680 *btype
= FILTER_OP_OR
;
681 else if (strcmp(token
, "!") == 0)
684 if (*btype
!= FILTER_OP_NOT
)
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
;
711 if (*etype
!= FILTER_EXP_NONE
)
714 /* Check for compares */
715 if (strcmp(token
, "==") == 0)
716 *ctype
= FILTER_CMP_EQ
;
717 else if (strcmp(token
, "!=") == 0)
718 *ctype
= FILTER_CMP_NE
;
719 else if (strcmp(token
, "<") == 0)
720 *ctype
= FILTER_CMP_LT
;
721 else if (strcmp(token
, ">") == 0)
722 *ctype
= FILTER_CMP_GT
;
723 else if (strcmp(token
, "<=") == 0)
724 *ctype
= FILTER_CMP_LE
;
725 else if (strcmp(token
, ">=") == 0)
726 *ctype
= FILTER_CMP_GE
;
727 else if (strcmp(token
, "=~") == 0)
728 *ctype
= FILTER_CMP_REGEX
;
729 else if (strcmp(token
, "!~") == 0)
730 *ctype
= FILTER_CMP_NOT_REGEX
;
737 static int check_op_done(struct filter_arg
*arg
)
741 return arg
->exp
.right
!= NULL
;
744 return arg
->op
.right
!= NULL
;
747 return arg
->num
.right
!= NULL
;
750 /* A string conversion is always done */
753 case FILTER_ARG_BOOLEAN
:
754 /* field not found, is ok */
768 static enum pevent_errno
769 reparent_op_arg(struct filter_arg
*parent
, struct filter_arg
*old_child
,
770 struct filter_arg
*arg
, char *error_str
)
772 struct filter_arg
*other_child
;
773 struct filter_arg
**ptr
;
775 if (parent
->type
!= FILTER_ARG_OP
&&
776 arg
->type
!= FILTER_ARG_OP
) {
777 show_error(error_str
, "can not reparent other than OP");
778 return PEVENT_ERRNO__REPARENT_NOT_OP
;
781 /* Get the sibling */
782 if (old_child
->op
.right
== arg
) {
783 ptr
= &old_child
->op
.right
;
784 other_child
= old_child
->op
.left
;
785 } else if (old_child
->op
.left
== arg
) {
786 ptr
= &old_child
->op
.left
;
787 other_child
= old_child
->op
.right
;
789 show_error(error_str
, "Error in reparent op, find other child");
790 return PEVENT_ERRNO__REPARENT_FAILED
;
793 /* Detach arg from old_child */
797 if (parent
== old_child
) {
798 free_arg(other_child
);
800 /* Free arg without recussion */
805 if (parent
->op
.right
== old_child
)
806 ptr
= &parent
->op
.right
;
807 else if (parent
->op
.left
== old_child
)
808 ptr
= &parent
->op
.left
;
810 show_error(error_str
, "Error in reparent op");
811 return PEVENT_ERRNO__REPARENT_FAILED
;
820 /* Returns either filter_vals (success) or pevent_errno (failfure) */
821 static int test_arg(struct filter_arg
*parent
, struct filter_arg
*arg
,
829 case FILTER_ARG_BOOLEAN
:
830 return FILTER_VAL_FALSE
+ arg
->boolean
.value
;
834 case FILTER_ARG_VALUE
:
835 case FILTER_ARG_FIELD
:
836 return FILTER_VAL_NORM
;
839 lval
= test_arg(arg
, arg
->exp
.left
, error_str
);
840 if (lval
!= FILTER_VAL_NORM
)
842 rval
= test_arg(arg
, arg
->exp
.right
, error_str
);
843 if (rval
!= FILTER_VAL_NORM
)
845 return FILTER_VAL_NORM
;
848 lval
= test_arg(arg
, arg
->num
.left
, error_str
);
849 if (lval
!= FILTER_VAL_NORM
)
851 rval
= test_arg(arg
, arg
->num
.right
, error_str
);
852 if (rval
!= FILTER_VAL_NORM
)
854 return FILTER_VAL_NORM
;
857 if (arg
->op
.type
!= FILTER_OP_NOT
) {
858 lval
= test_arg(arg
, arg
->op
.left
, error_str
);
860 case FILTER_VAL_NORM
:
862 case FILTER_VAL_TRUE
:
863 if (arg
->op
.type
== FILTER_OP_OR
)
864 return FILTER_VAL_TRUE
;
865 rval
= test_arg(arg
, arg
->op
.right
, error_str
);
866 if (rval
!= FILTER_VAL_NORM
)
869 return reparent_op_arg(parent
, arg
, arg
->op
.right
,
872 case FILTER_VAL_FALSE
:
873 if (arg
->op
.type
== FILTER_OP_AND
)
874 return FILTER_VAL_FALSE
;
875 rval
= test_arg(arg
, arg
->op
.right
, error_str
);
876 if (rval
!= FILTER_VAL_NORM
)
879 return reparent_op_arg(parent
, arg
, arg
->op
.right
,
887 rval
= test_arg(arg
, arg
->op
.right
, error_str
);
889 case FILTER_VAL_NORM
:
893 case FILTER_VAL_TRUE
:
894 if (arg
->op
.type
== FILTER_OP_OR
)
895 return FILTER_VAL_TRUE
;
896 if (arg
->op
.type
== FILTER_OP_NOT
)
897 return FILTER_VAL_FALSE
;
899 return reparent_op_arg(parent
, arg
, arg
->op
.left
,
902 case FILTER_VAL_FALSE
:
903 if (arg
->op
.type
== FILTER_OP_AND
)
904 return FILTER_VAL_FALSE
;
905 if (arg
->op
.type
== FILTER_OP_NOT
)
906 return FILTER_VAL_TRUE
;
908 return reparent_op_arg(parent
, arg
, arg
->op
.left
,
914 show_error(error_str
, "bad arg in filter tree");
915 return PEVENT_ERRNO__BAD_FILTER_ARG
;
917 return FILTER_VAL_NORM
;
920 /* Remove any unknown event fields */
921 static int collapse_tree(struct filter_arg
*arg
,
922 struct filter_arg
**arg_collapsed
, char *error_str
)
926 ret
= test_arg(arg
, arg
, error_str
);
928 case FILTER_VAL_NORM
:
931 case FILTER_VAL_TRUE
:
932 case FILTER_VAL_FALSE
:
934 arg
= allocate_arg();
936 arg
->type
= FILTER_ARG_BOOLEAN
;
937 arg
->boolean
.value
= ret
== FILTER_VAL_TRUE
;
939 show_error(error_str
, "Failed to allocate filter arg");
940 ret
= PEVENT_ERRNO__MEM_ALLOC_FAILED
;
945 /* test_arg() already set the error_str */
951 *arg_collapsed
= arg
;
955 static enum pevent_errno
956 process_filter(struct event_format
*event
, struct filter_arg
**parg
,
957 char *error_str
, int not)
959 enum event_type type
;
961 struct filter_arg
*current_op
= NULL
;
962 struct filter_arg
*current_exp
= NULL
;
963 struct filter_arg
*left_item
= NULL
;
964 struct filter_arg
*arg
= NULL
;
965 enum op_type op_type
;
966 enum filter_op_type btype
;
967 enum filter_exp_type etype
;
968 enum filter_cmp_type ctype
;
969 enum pevent_errno ret
;
975 type
= read_token(&token
);
980 ret
= create_arg_item(event
, token
, type
, &arg
, error_str
);
985 else if (current_exp
) {
986 ret
= add_right(current_exp
, arg
, error_str
);
990 /* Not's only one one expression */
1005 if (*token
== ',') {
1006 show_error(error_str
, "Illegal token ','");
1007 ret
= PEVENT_ERRNO__ILLEGAL_TOKEN
;
1011 if (*token
== '(') {
1013 show_error(error_str
,
1014 "Open paren can not come after item");
1015 ret
= PEVENT_ERRNO__INVALID_PAREN
;
1019 show_error(error_str
,
1020 "Open paren can not come after expression");
1021 ret
= PEVENT_ERRNO__INVALID_PAREN
;
1025 ret
= process_filter(event
, &arg
, error_str
, 0);
1026 if (ret
!= PEVENT_ERRNO__UNBALANCED_PAREN
) {
1028 show_error(error_str
,
1029 "Unbalanced number of '('");
1030 ret
= PEVENT_ERRNO__UNBALANCED_PAREN
;
1036 /* A not wants just one expression */
1045 ret
= add_right(current_op
, arg
, error_str
);
1053 if (!current_op
&& !current_exp
)
1056 /* Make sure everything is finished at this level */
1057 if (current_exp
&& !check_op_done(current_exp
))
1059 if (current_op
&& !check_op_done(current_op
))
1065 *parg
= current_exp
;
1067 return PEVENT_ERRNO__UNBALANCED_PAREN
;
1072 op_type
= process_op(token
, &btype
, &ctype
, &etype
);
1074 /* All expect a left arg except for NOT */
1077 /* Logic ops need a left expression */
1078 if (!current_exp
&& !current_op
)
1082 /* logic only processes ops and exp */
1092 show_error(error_str
,
1093 "Unknown op token %s", token
);
1094 ret
= PEVENT_ERRNO__UNKNOWN_TOKEN
;
1101 arg
= create_arg_op(btype
);
1105 ret
= add_left(arg
, current_op
);
1107 ret
= add_left(arg
, current_exp
);
1113 arg
= create_arg_op(btype
);
1117 ret
= add_right(current_op
, arg
, error_str
);
1121 ret
= process_filter(event
, &arg
, error_str
, 1);
1124 ret
= add_right(current_exp
, arg
, error_str
);
1131 if (op_type
== OP_EXP
)
1132 arg
= create_arg_exp(etype
);
1134 arg
= create_arg_cmp(ctype
);
1139 ret
= add_right(current_op
, arg
, error_str
);
1142 ret
= add_left(arg
, left_item
);
1163 } while (type
!= EVENT_NONE
);
1165 if (!current_op
&& !current_exp
)
1169 current_op
= current_exp
;
1171 ret
= collapse_tree(current_op
, parg
, error_str
);
1172 /* collapse_tree() may free current_op, and updates parg accordingly */
1181 show_error(error_str
, "failed to allocate filter arg");
1182 ret
= PEVENT_ERRNO__MEM_ALLOC_FAILED
;
1185 show_error(error_str
, "Syntax error");
1186 ret
= PEVENT_ERRNO__SYNTAX_ERROR
;
1188 free_arg(current_op
);
1189 free_arg(current_exp
);
1195 static enum pevent_errno
1196 process_event(struct event_format
*event
, const char *filter_str
,
1197 struct filter_arg
**parg
, char *error_str
)
1201 pevent_buffer_init(filter_str
, strlen(filter_str
));
1203 ret
= process_filter(event
, parg
, error_str
, 0);
1207 /* If parg is NULL, then make it into FALSE */
1209 *parg
= allocate_arg();
1211 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
1213 (*parg
)->type
= FILTER_ARG_BOOLEAN
;
1214 (*parg
)->boolean
.value
= FILTER_FALSE
;
1220 static enum pevent_errno
1221 filter_event(struct event_filter
*filter
, struct event_format
*event
,
1222 const char *filter_str
, char *error_str
)
1224 struct filter_type
*filter_type
;
1225 struct filter_arg
*arg
;
1226 enum pevent_errno ret
;
1229 ret
= process_event(event
, filter_str
, &arg
, error_str
);
1234 /* just add a TRUE arg */
1235 arg
= allocate_arg();
1237 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
1239 arg
->type
= FILTER_ARG_BOOLEAN
;
1240 arg
->boolean
.value
= FILTER_TRUE
;
1243 filter_type
= add_filter_type(filter
, event
->id
);
1244 if (filter_type
== NULL
)
1245 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
1247 if (filter_type
->filter
)
1248 free_arg(filter_type
->filter
);
1249 filter_type
->filter
= arg
;
1254 static void filter_init_error_buf(struct event_filter
*filter
)
1256 /* clear buffer to reset show error */
1257 pevent_buffer_init("", 0);
1258 filter
->error_buffer
[0] = '\0';
1262 * pevent_filter_add_filter_str - add a new filter
1263 * @filter: the event filter to add to
1264 * @filter_str: the filter string that contains the filter
1266 * Returns 0 if the filter was successfully added or a
1267 * negative error code. Use pevent_filter_strerror() to see
1268 * actual error message in case of error.
1270 enum pevent_errno
pevent_filter_add_filter_str(struct event_filter
*filter
,
1271 const char *filter_str
)
1273 struct pevent
*pevent
= filter
->pevent
;
1274 struct event_list
*event
;
1275 struct event_list
*events
= NULL
;
1276 const char *filter_start
;
1277 const char *next_event
;
1279 char *event_name
= NULL
;
1280 char *sys_name
= NULL
;
1282 enum pevent_errno rtn
= 0; /* PEVENT_ERRNO__SUCCESS */
1286 filter_init_error_buf(filter
);
1288 filter_start
= strchr(filter_str
, ':');
1290 len
= filter_start
- filter_str
;
1292 len
= strlen(filter_str
);
1295 next_event
= strchr(filter_str
, ',');
1297 (!filter_start
|| next_event
< filter_start
))
1298 len
= next_event
- filter_str
;
1299 else if (filter_start
)
1300 len
= filter_start
- filter_str
;
1302 len
= strlen(filter_str
);
1304 this_event
= malloc(len
+ 1);
1305 if (this_event
== NULL
) {
1306 /* This can only happen when events is NULL, but still */
1307 free_events(events
);
1308 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
1310 memcpy(this_event
, filter_str
, len
);
1311 this_event
[len
] = 0;
1316 filter_str
= next_event
;
1318 sys_name
= strtok_r(this_event
, "/", &sp
);
1319 event_name
= strtok_r(NULL
, "/", &sp
);
1322 /* This can only happen when events is NULL, but still */
1323 free_events(events
);
1325 return PEVENT_ERRNO__FILTER_NOT_FOUND
;
1328 /* Find this event */
1329 ret
= find_event(pevent
, &events
, strim(sys_name
), strim(event_name
));
1331 free_events(events
);
1336 } while (filter_str
);
1342 /* filter starts here */
1343 for (event
= events
; event
; event
= event
->next
) {
1344 ret
= filter_event(filter
, event
->event
, filter_start
,
1345 filter
->error_buffer
);
1346 /* Failures are returned if a parse error happened */
1350 if (ret
>= 0 && pevent
->test_filters
) {
1352 test
= pevent_filter_make_string(filter
, event
->event
->id
);
1354 printf(" '%s: %s'\n", event
->event
->name
, test
);
1360 free_events(events
);
1362 if (rtn
>= 0 && pevent
->test_filters
)
1368 static void free_filter_type(struct filter_type
*filter_type
)
1370 free_arg(filter_type
->filter
);
1374 * pevent_filter_strerror - fill error message in a buffer
1375 * @filter: the event filter contains error
1376 * @err: the error code
1377 * @buf: the buffer to be filled in
1378 * @buflen: the size of the buffer
1380 * Returns 0 if message was filled successfully, -1 if error
1382 int pevent_filter_strerror(struct event_filter
*filter
, enum pevent_errno err
,
1383 char *buf
, size_t buflen
)
1385 if (err
<= __PEVENT_ERRNO__START
|| err
>= __PEVENT_ERRNO__END
)
1388 if (strlen(filter
->error_buffer
) > 0) {
1389 size_t len
= snprintf(buf
, buflen
, "%s", filter
->error_buffer
);
1396 return pevent_strerror(filter
->pevent
, err
, buf
, buflen
);
1400 * pevent_filter_remove_event - remove a filter for an event
1401 * @filter: the event filter to remove from
1402 * @event_id: the event to remove a filter for
1404 * Removes the filter saved for an event defined by @event_id
1407 * Returns 1: if an event was removed
1408 * 0: if the event was not found
1410 int pevent_filter_remove_event(struct event_filter
*filter
,
1413 struct filter_type
*filter_type
;
1416 if (!filter
->filters
)
1419 filter_type
= find_filter_type(filter
, event_id
);
1424 free_filter_type(filter_type
);
1426 /* The filter_type points into the event_filters array */
1427 len
= (unsigned long)(filter
->event_filters
+ filter
->filters
) -
1428 (unsigned long)(filter_type
+ 1);
1430 memmove(filter_type
, filter_type
+ 1, len
);
1433 memset(&filter
->event_filters
[filter
->filters
], 0,
1434 sizeof(*filter_type
));
1440 * pevent_filter_reset - clear all filters in a filter
1441 * @filter: the event filter to reset
1443 * Removes all filters from a filter and resets it.
1445 void pevent_filter_reset(struct event_filter
*filter
)
1449 for (i
= 0; i
< filter
->filters
; i
++)
1450 free_filter_type(&filter
->event_filters
[i
]);
1452 free(filter
->event_filters
);
1453 filter
->filters
= 0;
1454 filter
->event_filters
= NULL
;
1457 void pevent_filter_free(struct event_filter
*filter
)
1459 pevent_unref(filter
->pevent
);
1461 pevent_filter_reset(filter
);
1466 static char *arg_to_str(struct event_filter
*filter
, struct filter_arg
*arg
);
1468 static int copy_filter_type(struct event_filter
*filter
,
1469 struct event_filter
*source
,
1470 struct filter_type
*filter_type
)
1472 struct filter_arg
*arg
;
1473 struct event_format
*event
;
1478 /* Can't assume that the pevent's are the same */
1479 sys
= filter_type
->event
->system
;
1480 name
= filter_type
->event
->name
;
1481 event
= pevent_find_event_by_name(filter
->pevent
, sys
, name
);
1485 str
= arg_to_str(source
, filter_type
->filter
);
1489 if (strcmp(str
, "TRUE") == 0 || strcmp(str
, "FALSE") == 0) {
1490 /* Add trivial event */
1491 arg
= allocate_arg();
1495 arg
->type
= FILTER_ARG_BOOLEAN
;
1496 if (strcmp(str
, "TRUE") == 0)
1497 arg
->boolean
.value
= 1;
1499 arg
->boolean
.value
= 0;
1501 filter_type
= add_filter_type(filter
, event
->id
);
1502 if (filter_type
== NULL
)
1505 filter_type
->filter
= arg
;
1511 filter_event(filter
, event
, str
, NULL
);
1518 * pevent_filter_copy - copy a filter using another filter
1519 * @dest - the filter to copy to
1520 * @source - the filter to copy from
1522 * Returns 0 on success and -1 if not all filters were copied
1524 int pevent_filter_copy(struct event_filter
*dest
, struct event_filter
*source
)
1529 pevent_filter_reset(dest
);
1531 for (i
= 0; i
< source
->filters
; i
++) {
1532 if (copy_filter_type(dest
, source
, &source
->event_filters
[i
]))
1540 * pevent_update_trivial - update the trivial filters with the given filter
1541 * @dest - the filter to update
1542 * @source - the filter as the source of the update
1543 * @type - the type of trivial filter to update.
1545 * Scan dest for trivial events matching @type to replace with the source.
1547 * Returns 0 on success and -1 if there was a problem updating, but
1548 * events may have still been updated on error.
1550 int pevent_update_trivial(struct event_filter
*dest
, struct event_filter
*source
,
1551 enum filter_trivial_type type
)
1553 struct pevent
*src_pevent
;
1554 struct pevent
*dest_pevent
;
1555 struct event_format
*event
;
1556 struct filter_type
*filter_type
;
1557 struct filter_arg
*arg
;
1561 src_pevent
= source
->pevent
;
1562 dest_pevent
= dest
->pevent
;
1564 /* Do nothing if either of the filters has nothing to filter */
1565 if (!dest
->filters
|| !source
->filters
)
1568 for (i
= 0; i
< dest
->filters
; i
++) {
1569 filter_type
= &dest
->event_filters
[i
];
1570 arg
= filter_type
->filter
;
1571 if (arg
->type
!= FILTER_ARG_BOOLEAN
)
1573 if ((arg
->boolean
.value
&& type
== FILTER_TRIVIAL_FALSE
) ||
1574 (!arg
->boolean
.value
&& type
== FILTER_TRIVIAL_TRUE
))
1577 event
= filter_type
->event
;
1579 if (src_pevent
!= dest_pevent
) {
1581 event
= pevent_find_event_by_name(src_pevent
,
1588 str
= pevent_filter_make_string(source
, event
->id
);
1592 /* Don't bother if the filter is trivial too */
1593 if (strcmp(str
, "TRUE") != 0 && strcmp(str
, "FALSE") != 0)
1594 filter_event(dest
, event
, str
, NULL
);
1601 * pevent_filter_clear_trivial - clear TRUE and FALSE filters
1602 * @filter: the filter to remove trivial filters from
1603 * @type: remove only true, false, or both
1605 * Removes filters that only contain a TRUE or FALES boolean arg.
1607 * Returns 0 on success and -1 if there was a problem.
1609 int pevent_filter_clear_trivial(struct event_filter
*filter
,
1610 enum filter_trivial_type type
)
1612 struct filter_type
*filter_type
;
1617 if (!filter
->filters
)
1621 * Two steps, first get all ids with trivial filters.
1622 * then remove those ids.
1624 for (i
= 0; i
< filter
->filters
; i
++) {
1627 filter_type
= &filter
->event_filters
[i
];
1628 if (filter_type
->filter
->type
!= FILTER_ARG_BOOLEAN
)
1631 case FILTER_TRIVIAL_FALSE
:
1632 if (filter_type
->filter
->boolean
.value
)
1635 case FILTER_TRIVIAL_TRUE
:
1636 if (!filter_type
->filter
->boolean
.value
)
1642 new_ids
= realloc(ids
, sizeof(*ids
) * (count
+ 1));
1649 ids
[count
++] = filter_type
->event_id
;
1655 for (i
= 0; i
< count
; i
++)
1656 pevent_filter_remove_event(filter
, ids
[i
]);
1663 * pevent_filter_event_has_trivial - return true event contains trivial filter
1664 * @filter: the filter with the information
1665 * @event_id: the id of the event to test
1666 * @type: trivial type to test for (TRUE, FALSE, EITHER)
1668 * Returns 1 if the event contains a matching trivial type
1671 int pevent_filter_event_has_trivial(struct event_filter
*filter
,
1673 enum filter_trivial_type type
)
1675 struct filter_type
*filter_type
;
1677 if (!filter
->filters
)
1680 filter_type
= find_filter_type(filter
, event_id
);
1685 if (filter_type
->filter
->type
!= FILTER_ARG_BOOLEAN
)
1689 case FILTER_TRIVIAL_FALSE
:
1690 return !filter_type
->filter
->boolean
.value
;
1692 case FILTER_TRIVIAL_TRUE
:
1693 return filter_type
->filter
->boolean
.value
;
1699 static int test_filter(struct event_format
*event
, struct filter_arg
*arg
,
1700 struct pevent_record
*record
, enum pevent_errno
*err
);
1703 get_comm(struct event_format
*event
, struct pevent_record
*record
)
1708 pid
= pevent_data_pid(event
->pevent
, record
);
1709 comm
= pevent_data_comm_from_pid(event
->pevent
, pid
);
1713 static unsigned long long
1714 get_value(struct event_format
*event
,
1715 struct format_field
*field
, struct pevent_record
*record
)
1717 unsigned long long val
;
1719 /* Handle our dummy "comm" field */
1720 if (field
== &comm
) {
1723 name
= get_comm(event
, record
);
1724 return (unsigned long)name
;
1727 /* Handle our dummy "cpu" field */
1731 pevent_read_number_field(field
, record
->data
, &val
);
1733 if (!(field
->flags
& FIELD_IS_SIGNED
))
1736 switch (field
->size
) {
1744 return (long long)val
;
1749 static unsigned long long
1750 get_arg_value(struct event_format
*event
, struct filter_arg
*arg
,
1751 struct pevent_record
*record
, enum pevent_errno
*err
);
1753 static unsigned long long
1754 get_exp_value(struct event_format
*event
, struct filter_arg
*arg
,
1755 struct pevent_record
*record
, enum pevent_errno
*err
)
1757 unsigned long long lval
, rval
;
1759 lval
= get_arg_value(event
, arg
->exp
.left
, record
, err
);
1760 rval
= get_arg_value(event
, arg
->exp
.right
, record
, err
);
1764 * There was an error, no need to process anymore.
1769 switch (arg
->exp
.type
) {
1770 case FILTER_EXP_ADD
:
1773 case FILTER_EXP_SUB
:
1776 case FILTER_EXP_MUL
:
1779 case FILTER_EXP_DIV
:
1782 case FILTER_EXP_MOD
:
1785 case FILTER_EXP_RSHIFT
:
1786 return lval
>> rval
;
1788 case FILTER_EXP_LSHIFT
:
1789 return lval
<< rval
;
1791 case FILTER_EXP_AND
:
1797 case FILTER_EXP_XOR
:
1800 case FILTER_EXP_NOT
:
1803 *err
= PEVENT_ERRNO__INVALID_EXP_TYPE
;
1808 static unsigned long long
1809 get_arg_value(struct event_format
*event
, struct filter_arg
*arg
,
1810 struct pevent_record
*record
, enum pevent_errno
*err
)
1812 switch (arg
->type
) {
1813 case FILTER_ARG_FIELD
:
1814 return get_value(event
, arg
->field
.field
, record
);
1816 case FILTER_ARG_VALUE
:
1817 if (arg
->value
.type
!= FILTER_NUMBER
) {
1819 *err
= PEVENT_ERRNO__NOT_A_NUMBER
;
1821 return arg
->value
.val
;
1823 case FILTER_ARG_EXP
:
1824 return get_exp_value(event
, arg
, record
, err
);
1828 *err
= PEVENT_ERRNO__INVALID_ARG_TYPE
;
1833 static int test_num(struct event_format
*event
, struct filter_arg
*arg
,
1834 struct pevent_record
*record
, enum pevent_errno
*err
)
1836 unsigned long long lval
, rval
;
1838 lval
= get_arg_value(event
, arg
->num
.left
, record
, err
);
1839 rval
= get_arg_value(event
, arg
->num
.right
, record
, err
);
1843 * There was an error, no need to process anymore.
1848 switch (arg
->num
.type
) {
1850 return lval
== rval
;
1853 return lval
!= rval
;
1862 return lval
>= rval
;
1865 return lval
<= rval
;
1869 *err
= PEVENT_ERRNO__ILLEGAL_INTEGER_CMP
;
1874 static const char *get_field_str(struct filter_arg
*arg
, struct pevent_record
*record
)
1876 struct event_format
*event
;
1877 struct pevent
*pevent
;
1878 unsigned long long addr
;
1879 const char *val
= NULL
;
1883 /* If the field is not a string convert it */
1884 if (arg
->str
.field
->flags
& FIELD_IS_STRING
) {
1885 val
= record
->data
+ arg
->str
.field
->offset
;
1886 size
= arg
->str
.field
->size
;
1888 if (arg
->str
.field
->flags
& FIELD_IS_DYNAMIC
) {
1889 addr
= *(unsigned int *)val
;
1890 val
= record
->data
+ (addr
& 0xffff);
1895 * We need to copy the data since we can't be sure the field
1896 * is null terminated.
1898 if (*(val
+ size
- 1)) {
1900 memcpy(arg
->str
.buffer
, val
, arg
->str
.field
->size
);
1901 /* the buffer is already NULL terminated */
1902 val
= arg
->str
.buffer
;
1906 event
= arg
->str
.field
->event
;
1907 pevent
= event
->pevent
;
1908 addr
= get_value(event
, arg
->str
.field
, record
);
1910 if (arg
->str
.field
->flags
& (FIELD_IS_POINTER
| FIELD_IS_LONG
))
1911 /* convert to a kernel symbol */
1912 val
= pevent_find_function(pevent
, addr
);
1915 /* just use the hex of the string name */
1916 snprintf(hex
, 64, "0x%llx", addr
);
1924 static int test_str(struct event_format
*event
, struct filter_arg
*arg
,
1925 struct pevent_record
*record
, enum pevent_errno
*err
)
1929 if (arg
->str
.field
== &comm
)
1930 val
= get_comm(event
, record
);
1932 val
= get_field_str(arg
, record
);
1934 switch (arg
->str
.type
) {
1935 case FILTER_CMP_MATCH
:
1936 return strcmp(val
, arg
->str
.val
) == 0;
1938 case FILTER_CMP_NOT_MATCH
:
1939 return strcmp(val
, arg
->str
.val
) != 0;
1941 case FILTER_CMP_REGEX
:
1942 /* Returns zero on match */
1943 return !regexec(&arg
->str
.reg
, val
, 0, NULL
, 0);
1945 case FILTER_CMP_NOT_REGEX
:
1946 return regexec(&arg
->str
.reg
, val
, 0, NULL
, 0);
1950 *err
= PEVENT_ERRNO__ILLEGAL_STRING_CMP
;
1955 static int test_op(struct event_format
*event
, struct filter_arg
*arg
,
1956 struct pevent_record
*record
, enum pevent_errno
*err
)
1958 switch (arg
->op
.type
) {
1960 return test_filter(event
, arg
->op
.left
, record
, err
) &&
1961 test_filter(event
, arg
->op
.right
, record
, err
);
1964 return test_filter(event
, arg
->op
.left
, record
, err
) ||
1965 test_filter(event
, arg
->op
.right
, record
, err
);
1968 return !test_filter(event
, arg
->op
.right
, record
, err
);
1972 *err
= PEVENT_ERRNO__INVALID_OP_TYPE
;
1977 static int test_filter(struct event_format
*event
, struct filter_arg
*arg
,
1978 struct pevent_record
*record
, enum pevent_errno
*err
)
1982 * There was an error, no need to process anymore.
1987 switch (arg
->type
) {
1988 case FILTER_ARG_BOOLEAN
:
1990 return arg
->boolean
.value
;
1993 return test_op(event
, arg
, record
, err
);
1995 case FILTER_ARG_NUM
:
1996 return test_num(event
, arg
, record
, err
);
1998 case FILTER_ARG_STR
:
1999 return test_str(event
, arg
, record
, err
);
2001 case FILTER_ARG_EXP
:
2002 case FILTER_ARG_VALUE
:
2003 case FILTER_ARG_FIELD
:
2005 * Expressions, fields and values evaluate
2006 * to true if they return non zero
2008 return !!get_arg_value(event
, arg
, record
, err
);
2012 *err
= PEVENT_ERRNO__INVALID_ARG_TYPE
;
2018 * pevent_event_filtered - return true if event has filter
2019 * @filter: filter struct with filter information
2020 * @event_id: event id to test if filter exists
2022 * Returns 1 if filter found for @event_id
2025 int pevent_event_filtered(struct event_filter
*filter
, int event_id
)
2027 struct filter_type
*filter_type
;
2029 if (!filter
->filters
)
2032 filter_type
= find_filter_type(filter
, event_id
);
2034 return filter_type
? 1 : 0;
2038 * pevent_filter_match - test if a record matches a filter
2039 * @filter: filter struct with filter information
2040 * @record: the record to test against the filter
2042 * Returns: match result or error code (prefixed with PEVENT_ERRNO__)
2043 * FILTER_MATCH - filter found for event and @record matches
2044 * FILTER_MISS - filter found for event and @record does not match
2045 * FILTER_NOT_FOUND - no filter found for @record's event
2046 * NO_FILTER - if no filters exist
2047 * otherwise - error occurred during test
2049 enum pevent_errno
pevent_filter_match(struct event_filter
*filter
,
2050 struct pevent_record
*record
)
2052 struct pevent
*pevent
= filter
->pevent
;
2053 struct filter_type
*filter_type
;
2056 enum pevent_errno err
= 0;
2058 filter_init_error_buf(filter
);
2060 if (!filter
->filters
)
2061 return PEVENT_ERRNO__NO_FILTER
;
2063 event_id
= pevent_data_type(pevent
, record
);
2065 filter_type
= find_filter_type(filter
, event_id
);
2067 return PEVENT_ERRNO__FILTER_NOT_FOUND
;
2069 ret
= test_filter(filter_type
->event
, filter_type
->filter
, record
, &err
);
2073 return ret
? PEVENT_ERRNO__FILTER_MATCH
: PEVENT_ERRNO__FILTER_MISS
;
2076 static char *op_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2086 switch (arg
->op
.type
) {
2094 left
= arg_to_str(filter
, arg
->op
.left
);
2095 right
= arg_to_str(filter
, arg
->op
.right
);
2096 if (!left
|| !right
)
2099 /* Try to consolidate boolean values */
2100 if (strcmp(left
, "TRUE") == 0)
2102 else if (strcmp(left
, "FALSE") == 0)
2105 if (strcmp(right
, "TRUE") == 0)
2107 else if (strcmp(right
, "FALSE") == 0)
2110 if (left_val
>= 0) {
2111 if ((arg
->op
.type
== FILTER_OP_AND
&& !left_val
) ||
2112 (arg
->op
.type
== FILTER_OP_OR
&& left_val
)) {
2113 /* Just return left value */
2118 if (right_val
>= 0) {
2119 /* just evaluate this. */
2121 switch (arg
->op
.type
) {
2123 val
= left_val
&& right_val
;
2126 val
= left_val
|| right_val
;
2131 asprintf(&str
, val
? "TRUE" : "FALSE");
2135 if (right_val
>= 0) {
2136 if ((arg
->op
.type
== FILTER_OP_AND
&& !right_val
) ||
2137 (arg
->op
.type
== FILTER_OP_OR
&& right_val
)) {
2138 /* Just return right value */
2143 /* The right value is meaningless */
2149 asprintf(&str
, "(%s) %s (%s)", left
, op
, right
);
2154 right
= arg_to_str(filter
, arg
->op
.right
);
2158 /* See if we can consolidate */
2159 if (strcmp(right
, "TRUE") == 0)
2161 else if (strcmp(right
, "FALSE") == 0)
2163 if (right_val
>= 0) {
2164 /* just return the opposite */
2165 asprintf(&str
, right_val
? "FALSE" : "TRUE");
2168 asprintf(&str
, "%s(%s)", op
, right
);
2180 static char *val_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2184 asprintf(&str
, "%lld", arg
->value
.val
);
2189 static char *field_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2191 return strdup(arg
->field
.field
->name
);
2194 static char *exp_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2201 lstr
= arg_to_str(filter
, arg
->exp
.left
);
2202 rstr
= arg_to_str(filter
, arg
->exp
.right
);
2206 switch (arg
->exp
.type
) {
2207 case FILTER_EXP_ADD
:
2210 case FILTER_EXP_SUB
:
2213 case FILTER_EXP_MUL
:
2216 case FILTER_EXP_DIV
:
2219 case FILTER_EXP_MOD
:
2222 case FILTER_EXP_RSHIFT
:
2225 case FILTER_EXP_LSHIFT
:
2228 case FILTER_EXP_AND
:
2234 case FILTER_EXP_XOR
:
2238 op
= "[ERROR IN EXPRESSION TYPE]";
2242 asprintf(&str
, "%s %s %s", lstr
, op
, rstr
);
2250 static char *num_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2257 lstr
= arg_to_str(filter
, arg
->num
.left
);
2258 rstr
= arg_to_str(filter
, arg
->num
.right
);
2262 switch (arg
->num
.type
) {
2286 asprintf(&str
, "%s %s %s", lstr
, op
, rstr
);
2300 static char *str_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2305 switch (arg
->str
.type
) {
2306 case FILTER_CMP_MATCH
:
2309 case FILTER_CMP_NOT_MATCH
:
2313 case FILTER_CMP_REGEX
:
2317 case FILTER_CMP_NOT_REGEX
:
2321 asprintf(&str
, "%s %s \"%s\"",
2322 arg
->str
.field
->name
, op
, arg
->str
.val
);
2332 static char *arg_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2336 switch (arg
->type
) {
2337 case FILTER_ARG_BOOLEAN
:
2338 asprintf(&str
, arg
->boolean
.value
? "TRUE" : "FALSE");
2342 return op_to_str(filter
, arg
);
2344 case FILTER_ARG_NUM
:
2345 return num_to_str(filter
, arg
);
2347 case FILTER_ARG_STR
:
2348 return str_to_str(filter
, arg
);
2350 case FILTER_ARG_VALUE
:
2351 return val_to_str(filter
, arg
);
2353 case FILTER_ARG_FIELD
:
2354 return field_to_str(filter
, arg
);
2356 case FILTER_ARG_EXP
:
2357 return exp_to_str(filter
, arg
);
2367 * pevent_filter_make_string - return a string showing the filter
2368 * @filter: filter struct with filter information
2369 * @event_id: the event id to return the filter string with
2371 * Returns a string that displays the filter contents.
2372 * This string must be freed with free(str).
2373 * NULL is returned if no filter is found or allocation failed.
2376 pevent_filter_make_string(struct event_filter
*filter
, int event_id
)
2378 struct filter_type
*filter_type
;
2380 if (!filter
->filters
)
2383 filter_type
= find_filter_type(filter
, event_id
);
2388 return arg_to_str(filter
, filter_type
->filter
);
2392 * pevent_filter_compare - compare two filters and return if they are the same
2393 * @filter1: Filter to compare with @filter2
2394 * @filter2: Filter to compare with @filter1
2397 * 1 if the two filters hold the same content.
2400 int pevent_filter_compare(struct event_filter
*filter1
, struct event_filter
*filter2
)
2402 struct filter_type
*filter_type1
;
2403 struct filter_type
*filter_type2
;
2408 /* Do the easy checks first */
2409 if (filter1
->filters
!= filter2
->filters
)
2411 if (!filter1
->filters
&& !filter2
->filters
)
2415 * Now take a look at each of the events to see if they have the same
2418 for (i
= 0; i
< filter1
->filters
; i
++) {
2419 filter_type1
= &filter1
->event_filters
[i
];
2420 filter_type2
= find_filter_type(filter2
, filter_type1
->event_id
);
2423 if (filter_type1
->filter
->type
!= filter_type2
->filter
->type
)
2425 switch (filter_type1
->filter
->type
) {
2426 case FILTER_TRIVIAL_FALSE
:
2427 case FILTER_TRIVIAL_TRUE
:
2428 /* trivial types just need the type compared */
2433 /* The best way to compare complex filters is with strings */
2434 str1
= arg_to_str(filter1
, filter_type1
->filter
);
2435 str2
= arg_to_str(filter2
, filter_type2
->filter
);
2437 result
= strcmp(str1
, str2
) != 0;
2439 /* bail out if allocation fails */
2448 if (i
< filter1
->filters
)