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"
32 static struct format_field comm
= {
37 struct event_list
*next
;
38 struct event_format
*event
;
41 static void show_error(char *error_buf
, const char *fmt
, ...)
43 unsigned long long index
;
49 input
= pevent_get_input_buf();
50 index
= pevent_get_input_buf_ptr();
51 len
= input
? strlen(input
) : 0;
54 strcpy(error_buf
, input
);
55 error_buf
[len
] = '\n';
56 for (i
= 1; i
< len
&& i
< index
; i
++)
57 error_buf
[len
+i
] = ' ';
58 error_buf
[len
+ i
] = '^';
59 error_buf
[len
+ i
+ 1] = '\n';
64 vsnprintf(error_buf
+ len
, PEVENT_FILTER_ERROR_BUFSZ
- len
, fmt
, ap
);
68 static void free_token(char *token
)
70 pevent_free_token(token
);
73 static enum event_type
read_token(char **tok
)
80 type
= pevent_read_token(&token
);
81 } while (type
== EVENT_NEWLINE
|| type
== EVENT_SPACE
);
83 /* If token is = or ! check to see if the next char is ~ */
85 (strcmp(token
, "=") == 0 || strcmp(token
, "!") == 0) &&
86 pevent_peek_char() == '~') {
93 sprintf(*tok
, "%c%c", *token
, '~');
95 /* Now remove the '~' from the buffer */
96 pevent_read_token(&token
);
104 static int filter_cmp(const void *a
, const void *b
)
106 const struct filter_type
*ea
= a
;
107 const struct filter_type
*eb
= b
;
109 if (ea
->event_id
< eb
->event_id
)
112 if (ea
->event_id
> eb
->event_id
)
118 static struct filter_type
*
119 find_filter_type(struct event_filter
*filter
, int id
)
121 struct filter_type
*filter_type
;
122 struct filter_type key
;
126 filter_type
= bsearch(&key
, filter
->event_filters
,
128 sizeof(*filter
->event_filters
),
134 static struct filter_type
*
135 add_filter_type(struct event_filter
*filter
, int id
)
137 struct filter_type
*filter_type
;
140 filter_type
= find_filter_type(filter
, id
);
144 filter_type
= realloc(filter
->event_filters
,
145 sizeof(*filter
->event_filters
) *
146 (filter
->filters
+ 1));
150 filter
->event_filters
= filter_type
;
152 for (i
= 0; i
< filter
->filters
; i
++) {
153 if (filter
->event_filters
[i
].event_id
> id
)
157 if (i
< filter
->filters
)
158 memmove(&filter
->event_filters
[i
+1],
159 &filter
->event_filters
[i
],
160 sizeof(*filter
->event_filters
) *
161 (filter
->filters
- i
));
163 filter_type
= &filter
->event_filters
[i
];
164 filter_type
->event_id
= id
;
165 filter_type
->event
= pevent_find_event(filter
->pevent
, id
);
166 filter_type
->filter
= NULL
;
174 * pevent_filter_alloc - create a new event filter
175 * @pevent: The pevent that this filter is associated with
177 struct event_filter
*pevent_filter_alloc(struct pevent
*pevent
)
179 struct event_filter
*filter
;
181 filter
= malloc(sizeof(*filter
));
185 memset(filter
, 0, sizeof(*filter
));
186 filter
->pevent
= pevent
;
192 static struct filter_arg
*allocate_arg(void)
194 return calloc(1, sizeof(struct filter_arg
));
197 static void free_arg(struct filter_arg
*arg
)
203 case FILTER_ARG_NONE
:
204 case FILTER_ARG_BOOLEAN
:
208 free_arg(arg
->num
.left
);
209 free_arg(arg
->num
.right
);
213 free_arg(arg
->exp
.left
);
214 free_arg(arg
->exp
.right
);
219 regfree(&arg
->str
.reg
);
220 free(arg
->str
.buffer
);
223 case FILTER_ARG_VALUE
:
224 if (arg
->value
.type
== FILTER_STRING
||
225 arg
->value
.type
== FILTER_CHAR
)
226 free(arg
->value
.str
);
230 free_arg(arg
->op
.left
);
231 free_arg(arg
->op
.right
);
239 static int add_event(struct event_list
**events
,
240 struct event_format
*event
)
242 struct event_list
*list
;
244 list
= malloc(sizeof(*list
));
248 list
->next
= *events
;
254 static int event_match(struct event_format
*event
,
255 regex_t
*sreg
, regex_t
*ereg
)
258 return !regexec(sreg
, event
->system
, 0, NULL
, 0) &&
259 !regexec(ereg
, event
->name
, 0, NULL
, 0);
262 return !regexec(ereg
, event
->system
, 0, NULL
, 0) ||
263 !regexec(ereg
, event
->name
, 0, NULL
, 0);
266 static enum pevent_errno
267 find_event(struct pevent
*pevent
, struct event_list
**events
,
268 char *sys_name
, char *event_name
)
270 struct event_format
*event
;
280 /* if no name is given, then swap sys and name */
281 event_name
= sys_name
;
285 reg
= malloc(strlen(event_name
) + 3);
287 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
289 sprintf(reg
, "^%s$", event_name
);
291 ret
= regcomp(&ereg
, reg
, REG_ICASE
|REG_NOSUB
);
295 return PEVENT_ERRNO__INVALID_EVENT_NAME
;
298 reg
= malloc(strlen(sys_name
) + 3);
301 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
304 sprintf(reg
, "^%s$", sys_name
);
305 ret
= regcomp(&sreg
, reg
, REG_ICASE
|REG_NOSUB
);
309 return PEVENT_ERRNO__INVALID_EVENT_NAME
;
313 for (i
= 0; i
< pevent
->nr_events
; i
++) {
314 event
= pevent
->events
[i
];
315 if (event_match(event
, sys_name
? &sreg
: NULL
, &ereg
)) {
317 if (add_event(events
, event
) < 0) {
329 return PEVENT_ERRNO__EVENT_NOT_FOUND
;
331 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
336 static void free_events(struct event_list
*events
)
338 struct event_list
*event
;
342 events
= events
->next
;
347 static enum pevent_errno
348 create_arg_item(struct event_format
*event
, const char *token
,
349 enum event_type type
, struct filter_arg
**parg
, char *error_str
)
351 struct format_field
*field
;
352 struct filter_arg
*arg
;
354 arg
= allocate_arg();
356 show_error(error_str
, "failed to allocate filter arg");
357 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
364 arg
->type
= FILTER_ARG_VALUE
;
366 type
== EVENT_DQUOTE
? FILTER_STRING
: FILTER_CHAR
;
367 arg
->value
.str
= strdup(token
);
368 if (!arg
->value
.str
) {
370 show_error(error_str
, "failed to allocate string filter arg");
371 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
375 /* if it is a number, then convert it */
376 if (isdigit(token
[0])) {
377 arg
->type
= FILTER_ARG_VALUE
;
378 arg
->value
.type
= FILTER_NUMBER
;
379 arg
->value
.val
= strtoull(token
, NULL
, 0);
382 /* Consider this a field */
383 field
= pevent_find_any_field(event
, token
);
385 if (strcmp(token
, COMM
) != 0) {
386 /* not a field, Make it false */
387 arg
->type
= FILTER_ARG_BOOLEAN
;
388 arg
->boolean
.value
= FILTER_FALSE
;
391 /* If token is 'COMM' then it is special */
394 arg
->type
= FILTER_ARG_FIELD
;
395 arg
->field
.field
= field
;
399 show_error(error_str
, "expected a value but found %s", token
);
400 return PEVENT_ERRNO__UNEXPECTED_TYPE
;
406 static struct filter_arg
*
407 create_arg_op(enum filter_op_type btype
)
409 struct filter_arg
*arg
;
411 arg
= allocate_arg();
415 arg
->type
= FILTER_ARG_OP
;
416 arg
->op
.type
= btype
;
421 static struct filter_arg
*
422 create_arg_exp(enum filter_exp_type etype
)
424 struct filter_arg
*arg
;
426 arg
= allocate_arg();
430 arg
->type
= FILTER_ARG_EXP
;
431 arg
->op
.type
= etype
;
436 static struct filter_arg
*
437 create_arg_cmp(enum filter_exp_type etype
)
439 struct filter_arg
*arg
;
441 arg
= allocate_arg();
445 /* Use NUM and change if necessary */
446 arg
->type
= FILTER_ARG_NUM
;
447 arg
->op
.type
= etype
;
452 static enum pevent_errno
453 add_right(struct filter_arg
*op
, struct filter_arg
*arg
, char *error_str
)
455 struct filter_arg
*left
;
477 * The arg must be num, str, or field
480 case FILTER_ARG_VALUE
:
481 case FILTER_ARG_FIELD
:
484 show_error(error_str
, "Illegal rvalue");
485 return PEVENT_ERRNO__ILLEGAL_RVALUE
;
489 * Depending on the type, we may need to
490 * convert this to a string or regex.
492 switch (arg
->value
.type
) {
495 * A char should be converted to number if
496 * the string is 1 byte, and the compare
499 if (strlen(arg
->value
.str
) == 1 &&
500 op
->num
.type
!= FILTER_CMP_REGEX
&&
501 op
->num
.type
!= FILTER_CMP_NOT_REGEX
) {
502 arg
->value
.type
= FILTER_NUMBER
;
508 /* convert op to a string arg */
509 op_type
= op
->num
.type
;
511 str
= arg
->value
.str
;
513 /* reset the op for the new field */
514 memset(op
, 0, sizeof(*op
));
517 * If left arg was a field not found then
518 * NULL the entire op.
520 if (left
->type
== FILTER_ARG_BOOLEAN
) {
523 op
->type
= FILTER_ARG_BOOLEAN
;
524 op
->boolean
.value
= FILTER_FALSE
;
528 /* Left arg must be a field */
529 if (left
->type
!= FILTER_ARG_FIELD
) {
530 show_error(error_str
,
531 "Illegal lvalue for string comparison");
532 return PEVENT_ERRNO__ILLEGAL_LVALUE
;
535 /* Make sure this is a valid string compare */
538 op_type
= FILTER_CMP_MATCH
;
541 op_type
= FILTER_CMP_NOT_MATCH
;
544 case FILTER_CMP_REGEX
:
545 case FILTER_CMP_NOT_REGEX
:
546 ret
= regcomp(&op
->str
.reg
, str
, REG_ICASE
|REG_NOSUB
);
548 show_error(error_str
,
549 "RegEx '%s' did not compute",
551 return PEVENT_ERRNO__INVALID_REGEX
;
555 show_error(error_str
,
556 "Illegal comparison for string");
557 return PEVENT_ERRNO__ILLEGAL_STRING_CMP
;
560 op
->type
= FILTER_ARG_STR
;
561 op
->str
.type
= op_type
;
562 op
->str
.field
= left
->field
.field
;
563 op
->str
.val
= strdup(str
);
565 show_error(error_str
, "Failed to allocate string filter");
566 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
569 * Need a buffer to copy data for tests
571 op
->str
.buffer
= malloc(op
->str
.field
->size
+ 1);
572 if (!op
->str
.buffer
) {
573 show_error(error_str
, "Failed to allocate string filter");
574 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
576 /* Null terminate this buffer */
577 op
->str
.buffer
[op
->str
.field
->size
] = 0;
579 /* We no longer have left or right args */
588 switch (op
->num
.type
) {
589 case FILTER_CMP_REGEX
:
590 case FILTER_CMP_NOT_REGEX
:
591 show_error(error_str
,
592 "Op not allowed with integers");
593 return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP
;
599 /* numeric compare */
613 show_error(error_str
, "Syntax error");
614 return PEVENT_ERRNO__SYNTAX_ERROR
;
617 static struct filter_arg
*
618 rotate_op_right(struct filter_arg
*a
, struct filter_arg
*b
)
620 struct filter_arg
*arg
;
627 static enum pevent_errno
add_left(struct filter_arg
*op
, struct filter_arg
*arg
)
631 if (arg
->type
== FILTER_ARG_OP
)
632 arg
= rotate_op_right(arg
, op
);
640 if (arg
->type
== FILTER_ARG_OP
)
641 arg
= rotate_op_right(arg
, op
);
643 /* left arg of compares must be a field */
644 if (arg
->type
!= FILTER_ARG_FIELD
&&
645 arg
->type
!= FILTER_ARG_BOOLEAN
)
646 return PEVENT_ERRNO__INVALID_ARG_TYPE
;
650 return PEVENT_ERRNO__INVALID_ARG_TYPE
;
663 static enum op_type
process_op(const char *token
,
664 enum filter_op_type
*btype
,
665 enum filter_cmp_type
*ctype
,
666 enum filter_exp_type
*etype
)
668 *btype
= FILTER_OP_NOT
;
669 *etype
= FILTER_EXP_NONE
;
670 *ctype
= FILTER_CMP_NONE
;
672 if (strcmp(token
, "&&") == 0)
673 *btype
= FILTER_OP_AND
;
674 else if (strcmp(token
, "||") == 0)
675 *btype
= FILTER_OP_OR
;
676 else if (strcmp(token
, "!") == 0)
679 if (*btype
!= FILTER_OP_NOT
)
682 /* Check for value expressions */
683 if (strcmp(token
, "+") == 0) {
684 *etype
= FILTER_EXP_ADD
;
685 } else if (strcmp(token
, "-") == 0) {
686 *etype
= FILTER_EXP_SUB
;
687 } else if (strcmp(token
, "*") == 0) {
688 *etype
= FILTER_EXP_MUL
;
689 } else if (strcmp(token
, "/") == 0) {
690 *etype
= FILTER_EXP_DIV
;
691 } else if (strcmp(token
, "%") == 0) {
692 *etype
= FILTER_EXP_MOD
;
693 } else if (strcmp(token
, ">>") == 0) {
694 *etype
= FILTER_EXP_RSHIFT
;
695 } else if (strcmp(token
, "<<") == 0) {
696 *etype
= FILTER_EXP_LSHIFT
;
697 } else if (strcmp(token
, "&") == 0) {
698 *etype
= FILTER_EXP_AND
;
699 } else if (strcmp(token
, "|") == 0) {
700 *etype
= FILTER_EXP_OR
;
701 } else if (strcmp(token
, "^") == 0) {
702 *etype
= FILTER_EXP_XOR
;
703 } else if (strcmp(token
, "~") == 0)
704 *etype
= FILTER_EXP_NOT
;
706 if (*etype
!= FILTER_EXP_NONE
)
709 /* Check for compares */
710 if (strcmp(token
, "==") == 0)
711 *ctype
= FILTER_CMP_EQ
;
712 else if (strcmp(token
, "!=") == 0)
713 *ctype
= FILTER_CMP_NE
;
714 else if (strcmp(token
, "<") == 0)
715 *ctype
= FILTER_CMP_LT
;
716 else if (strcmp(token
, ">") == 0)
717 *ctype
= FILTER_CMP_GT
;
718 else if (strcmp(token
, "<=") == 0)
719 *ctype
= FILTER_CMP_LE
;
720 else if (strcmp(token
, ">=") == 0)
721 *ctype
= FILTER_CMP_GE
;
722 else if (strcmp(token
, "=~") == 0)
723 *ctype
= FILTER_CMP_REGEX
;
724 else if (strcmp(token
, "!~") == 0)
725 *ctype
= FILTER_CMP_NOT_REGEX
;
732 static int check_op_done(struct filter_arg
*arg
)
736 return arg
->exp
.right
!= NULL
;
739 return arg
->op
.right
!= NULL
;
742 return arg
->num
.right
!= NULL
;
745 /* A string conversion is always done */
748 case FILTER_ARG_BOOLEAN
:
749 /* field not found, is ok */
763 static enum pevent_errno
764 reparent_op_arg(struct filter_arg
*parent
, struct filter_arg
*old_child
,
765 struct filter_arg
*arg
, char *error_str
)
767 struct filter_arg
*other_child
;
768 struct filter_arg
**ptr
;
770 if (parent
->type
!= FILTER_ARG_OP
&&
771 arg
->type
!= FILTER_ARG_OP
) {
772 show_error(error_str
, "can not reparent other than OP");
773 return PEVENT_ERRNO__REPARENT_NOT_OP
;
776 /* Get the sibling */
777 if (old_child
->op
.right
== arg
) {
778 ptr
= &old_child
->op
.right
;
779 other_child
= old_child
->op
.left
;
780 } else if (old_child
->op
.left
== arg
) {
781 ptr
= &old_child
->op
.left
;
782 other_child
= old_child
->op
.right
;
784 show_error(error_str
, "Error in reparent op, find other child");
785 return PEVENT_ERRNO__REPARENT_FAILED
;
788 /* Detach arg from old_child */
792 if (parent
== old_child
) {
793 free_arg(other_child
);
795 /* Free arg without recussion */
800 if (parent
->op
.right
== old_child
)
801 ptr
= &parent
->op
.right
;
802 else if (parent
->op
.left
== old_child
)
803 ptr
= &parent
->op
.left
;
805 show_error(error_str
, "Error in reparent op");
806 return PEVENT_ERRNO__REPARENT_FAILED
;
815 /* Returns either filter_vals (success) or pevent_errno (failfure) */
816 static int test_arg(struct filter_arg
*parent
, struct filter_arg
*arg
,
824 case FILTER_ARG_BOOLEAN
:
825 return FILTER_VAL_FALSE
+ arg
->boolean
.value
;
829 case FILTER_ARG_VALUE
:
830 case FILTER_ARG_FIELD
:
831 return FILTER_VAL_NORM
;
834 lval
= test_arg(arg
, arg
->exp
.left
, error_str
);
835 if (lval
!= FILTER_VAL_NORM
)
837 rval
= test_arg(arg
, arg
->exp
.right
, error_str
);
838 if (rval
!= FILTER_VAL_NORM
)
840 return FILTER_VAL_NORM
;
843 lval
= test_arg(arg
, arg
->num
.left
, error_str
);
844 if (lval
!= FILTER_VAL_NORM
)
846 rval
= test_arg(arg
, arg
->num
.right
, error_str
);
847 if (rval
!= FILTER_VAL_NORM
)
849 return FILTER_VAL_NORM
;
852 if (arg
->op
.type
!= FILTER_OP_NOT
) {
853 lval
= test_arg(arg
, arg
->op
.left
, error_str
);
855 case FILTER_VAL_NORM
:
857 case FILTER_VAL_TRUE
:
858 if (arg
->op
.type
== FILTER_OP_OR
)
859 return FILTER_VAL_TRUE
;
860 rval
= test_arg(arg
, arg
->op
.right
, error_str
);
861 if (rval
!= FILTER_VAL_NORM
)
864 return reparent_op_arg(parent
, arg
, arg
->op
.right
,
867 case FILTER_VAL_FALSE
:
868 if (arg
->op
.type
== FILTER_OP_AND
)
869 return FILTER_VAL_FALSE
;
870 rval
= test_arg(arg
, arg
->op
.right
, error_str
);
871 if (rval
!= FILTER_VAL_NORM
)
874 return reparent_op_arg(parent
, arg
, arg
->op
.right
,
882 rval
= test_arg(arg
, arg
->op
.right
, error_str
);
884 case FILTER_VAL_NORM
:
888 case FILTER_VAL_TRUE
:
889 if (arg
->op
.type
== FILTER_OP_OR
)
890 return FILTER_VAL_TRUE
;
891 if (arg
->op
.type
== FILTER_OP_NOT
)
892 return FILTER_VAL_FALSE
;
894 return reparent_op_arg(parent
, arg
, arg
->op
.left
,
897 case FILTER_VAL_FALSE
:
898 if (arg
->op
.type
== FILTER_OP_AND
)
899 return FILTER_VAL_FALSE
;
900 if (arg
->op
.type
== FILTER_OP_NOT
)
901 return FILTER_VAL_TRUE
;
903 return reparent_op_arg(parent
, arg
, arg
->op
.left
,
909 show_error(error_str
, "bad arg in filter tree");
910 return PEVENT_ERRNO__BAD_FILTER_ARG
;
912 return FILTER_VAL_NORM
;
915 /* Remove any unknown event fields */
916 static int collapse_tree(struct filter_arg
*arg
,
917 struct filter_arg
**arg_collapsed
, char *error_str
)
921 ret
= test_arg(arg
, arg
, error_str
);
923 case FILTER_VAL_NORM
:
926 case FILTER_VAL_TRUE
:
927 case FILTER_VAL_FALSE
:
929 arg
= allocate_arg();
931 arg
->type
= FILTER_ARG_BOOLEAN
;
932 arg
->boolean
.value
= ret
== FILTER_VAL_TRUE
;
934 show_error(error_str
, "Failed to allocate filter arg");
935 ret
= PEVENT_ERRNO__MEM_ALLOC_FAILED
;
940 /* test_arg() already set the error_str */
946 *arg_collapsed
= arg
;
950 static enum pevent_errno
951 process_filter(struct event_format
*event
, struct filter_arg
**parg
,
952 char *error_str
, int not)
954 enum event_type type
;
956 struct filter_arg
*current_op
= NULL
;
957 struct filter_arg
*current_exp
= NULL
;
958 struct filter_arg
*left_item
= NULL
;
959 struct filter_arg
*arg
= NULL
;
960 enum op_type op_type
;
961 enum filter_op_type btype
;
962 enum filter_exp_type etype
;
963 enum filter_cmp_type ctype
;
964 enum pevent_errno ret
;
970 type
= read_token(&token
);
975 ret
= create_arg_item(event
, token
, type
, &arg
, error_str
);
980 else if (current_exp
) {
981 ret
= add_right(current_exp
, arg
, error_str
);
985 /* Not's only one one expression */
1000 if (*token
== ',') {
1001 show_error(error_str
, "Illegal token ','");
1002 ret
= PEVENT_ERRNO__ILLEGAL_TOKEN
;
1006 if (*token
== '(') {
1008 show_error(error_str
,
1009 "Open paren can not come after item");
1010 ret
= PEVENT_ERRNO__INVALID_PAREN
;
1014 show_error(error_str
,
1015 "Open paren can not come after expression");
1016 ret
= PEVENT_ERRNO__INVALID_PAREN
;
1020 ret
= process_filter(event
, &arg
, error_str
, 0);
1021 if (ret
!= PEVENT_ERRNO__UNBALANCED_PAREN
) {
1023 show_error(error_str
,
1024 "Unbalanced number of '('");
1025 ret
= PEVENT_ERRNO__UNBALANCED_PAREN
;
1031 /* A not wants just one expression */
1040 ret
= add_right(current_op
, arg
, error_str
);
1048 if (!current_op
&& !current_exp
)
1051 /* Make sure everything is finished at this level */
1052 if (current_exp
&& !check_op_done(current_exp
))
1054 if (current_op
&& !check_op_done(current_op
))
1060 *parg
= current_exp
;
1061 return PEVENT_ERRNO__UNBALANCED_PAREN
;
1066 op_type
= process_op(token
, &btype
, &ctype
, &etype
);
1068 /* All expect a left arg except for NOT */
1071 /* Logic ops need a left expression */
1072 if (!current_exp
&& !current_op
)
1076 /* logic only processes ops and exp */
1086 show_error(error_str
,
1087 "Unknown op token %s", token
);
1088 ret
= PEVENT_ERRNO__UNKNOWN_TOKEN
;
1095 arg
= create_arg_op(btype
);
1099 ret
= add_left(arg
, current_op
);
1101 ret
= add_left(arg
, current_exp
);
1107 arg
= create_arg_op(btype
);
1111 ret
= add_right(current_op
, arg
, error_str
);
1115 ret
= process_filter(event
, &arg
, error_str
, 1);
1118 ret
= add_right(current_exp
, arg
, error_str
);
1125 if (op_type
== OP_EXP
)
1126 arg
= create_arg_exp(etype
);
1128 arg
= create_arg_cmp(ctype
);
1133 ret
= add_right(current_op
, arg
, error_str
);
1136 ret
= add_left(arg
, left_item
);
1157 } while (type
!= EVENT_NONE
);
1159 if (!current_op
&& !current_exp
)
1163 current_op
= current_exp
;
1165 ret
= collapse_tree(current_op
, parg
, error_str
);
1174 show_error(error_str
, "failed to allocate filter arg");
1175 ret
= PEVENT_ERRNO__MEM_ALLOC_FAILED
;
1178 show_error(error_str
, "Syntax error");
1179 ret
= PEVENT_ERRNO__SYNTAX_ERROR
;
1181 free_arg(current_op
);
1182 free_arg(current_exp
);
1188 static enum pevent_errno
1189 process_event(struct event_format
*event
, const char *filter_str
,
1190 struct filter_arg
**parg
, char *error_str
)
1194 pevent_buffer_init(filter_str
, strlen(filter_str
));
1196 ret
= process_filter(event
, parg
, error_str
, 0);
1200 /* If parg is NULL, then make it into FALSE */
1202 *parg
= allocate_arg();
1204 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
1206 (*parg
)->type
= FILTER_ARG_BOOLEAN
;
1207 (*parg
)->boolean
.value
= FILTER_FALSE
;
1213 static enum pevent_errno
1214 filter_event(struct event_filter
*filter
, struct event_format
*event
,
1215 const char *filter_str
, char *error_str
)
1217 struct filter_type
*filter_type
;
1218 struct filter_arg
*arg
;
1219 enum pevent_errno ret
;
1222 ret
= process_event(event
, filter_str
, &arg
, error_str
);
1227 /* just add a TRUE arg */
1228 arg
= allocate_arg();
1230 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
1232 arg
->type
= FILTER_ARG_BOOLEAN
;
1233 arg
->boolean
.value
= FILTER_TRUE
;
1236 filter_type
= add_filter_type(filter
, event
->id
);
1237 if (filter_type
== NULL
)
1238 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
1240 if (filter_type
->filter
)
1241 free_arg(filter_type
->filter
);
1242 filter_type
->filter
= arg
;
1247 static void filter_init_error_buf(struct event_filter
*filter
)
1249 /* clear buffer to reset show error */
1250 pevent_buffer_init("", 0);
1251 filter
->error_buffer
[0] = '\0';
1255 * pevent_filter_add_filter_str - add a new filter
1256 * @filter: the event filter to add to
1257 * @filter_str: the filter string that contains the filter
1259 * Returns 0 if the filter was successfully added or a
1260 * negative error code. Use pevent_filter_strerror() to see
1261 * actual error message in case of error.
1263 enum pevent_errno
pevent_filter_add_filter_str(struct event_filter
*filter
,
1264 const char *filter_str
)
1266 struct pevent
*pevent
= filter
->pevent
;
1267 struct event_list
*event
;
1268 struct event_list
*events
= NULL
;
1269 const char *filter_start
;
1270 const char *next_event
;
1272 char *event_name
= NULL
;
1273 char *sys_name
= NULL
;
1275 enum pevent_errno rtn
= 0; /* PEVENT_ERRNO__SUCCESS */
1279 filter_init_error_buf(filter
);
1281 filter_start
= strchr(filter_str
, ':');
1283 len
= filter_start
- filter_str
;
1285 len
= strlen(filter_str
);
1288 next_event
= strchr(filter_str
, ',');
1290 (!filter_start
|| next_event
< filter_start
))
1291 len
= next_event
- filter_str
;
1292 else if (filter_start
)
1293 len
= filter_start
- filter_str
;
1295 len
= strlen(filter_str
);
1297 this_event
= malloc(len
+ 1);
1298 if (this_event
== NULL
) {
1299 /* This can only happen when events is NULL, but still */
1300 free_events(events
);
1301 return PEVENT_ERRNO__MEM_ALLOC_FAILED
;
1303 memcpy(this_event
, filter_str
, len
);
1304 this_event
[len
] = 0;
1309 filter_str
= next_event
;
1311 sys_name
= strtok_r(this_event
, "/", &sp
);
1312 event_name
= strtok_r(NULL
, "/", &sp
);
1315 /* This can only happen when events is NULL, but still */
1316 free_events(events
);
1318 return PEVENT_ERRNO__FILTER_NOT_FOUND
;
1321 /* Find this event */
1322 ret
= find_event(pevent
, &events
, strim(sys_name
), strim(event_name
));
1324 free_events(events
);
1329 } while (filter_str
);
1335 /* filter starts here */
1336 for (event
= events
; event
; event
= event
->next
) {
1337 ret
= filter_event(filter
, event
->event
, filter_start
,
1338 filter
->error_buffer
);
1339 /* Failures are returned if a parse error happened */
1343 if (ret
>= 0 && pevent
->test_filters
) {
1345 test
= pevent_filter_make_string(filter
, event
->event
->id
);
1347 printf(" '%s: %s'\n", event
->event
->name
, test
);
1353 free_events(events
);
1355 if (rtn
>= 0 && pevent
->test_filters
)
1361 static void free_filter_type(struct filter_type
*filter_type
)
1363 free_arg(filter_type
->filter
);
1367 * pevent_filter_strerror - fill error message in a buffer
1368 * @filter: the event filter contains error
1369 * @err: the error code
1370 * @buf: the buffer to be filled in
1371 * @buflen: the size of the buffer
1373 * Returns 0 if message was filled successfully, -1 if error
1375 int pevent_filter_strerror(struct event_filter
*filter
, enum pevent_errno err
,
1376 char *buf
, size_t buflen
)
1378 if (err
<= __PEVENT_ERRNO__START
|| err
>= __PEVENT_ERRNO__END
)
1381 if (strlen(filter
->error_buffer
) > 0) {
1382 size_t len
= snprintf(buf
, buflen
, "%s", filter
->error_buffer
);
1389 return pevent_strerror(filter
->pevent
, err
, buf
, buflen
);
1393 * pevent_filter_remove_event - remove a filter for an event
1394 * @filter: the event filter to remove from
1395 * @event_id: the event to remove a filter for
1397 * Removes the filter saved for an event defined by @event_id
1400 * Returns 1: if an event was removed
1401 * 0: if the event was not found
1403 int pevent_filter_remove_event(struct event_filter
*filter
,
1406 struct filter_type
*filter_type
;
1409 if (!filter
->filters
)
1412 filter_type
= find_filter_type(filter
, event_id
);
1417 free_filter_type(filter_type
);
1419 /* The filter_type points into the event_filters array */
1420 len
= (unsigned long)(filter
->event_filters
+ filter
->filters
) -
1421 (unsigned long)(filter_type
+ 1);
1423 memmove(filter_type
, filter_type
+ 1, len
);
1426 memset(&filter
->event_filters
[filter
->filters
], 0,
1427 sizeof(*filter_type
));
1433 * pevent_filter_reset - clear all filters in a filter
1434 * @filter: the event filter to reset
1436 * Removes all filters from a filter and resets it.
1438 void pevent_filter_reset(struct event_filter
*filter
)
1442 for (i
= 0; i
< filter
->filters
; i
++)
1443 free_filter_type(&filter
->event_filters
[i
]);
1445 free(filter
->event_filters
);
1446 filter
->filters
= 0;
1447 filter
->event_filters
= NULL
;
1450 void pevent_filter_free(struct event_filter
*filter
)
1452 pevent_unref(filter
->pevent
);
1454 pevent_filter_reset(filter
);
1459 static char *arg_to_str(struct event_filter
*filter
, struct filter_arg
*arg
);
1461 static int copy_filter_type(struct event_filter
*filter
,
1462 struct event_filter
*source
,
1463 struct filter_type
*filter_type
)
1465 struct filter_arg
*arg
;
1466 struct event_format
*event
;
1471 /* Can't assume that the pevent's are the same */
1472 sys
= filter_type
->event
->system
;
1473 name
= filter_type
->event
->name
;
1474 event
= pevent_find_event_by_name(filter
->pevent
, sys
, name
);
1478 str
= arg_to_str(source
, filter_type
->filter
);
1482 if (strcmp(str
, "TRUE") == 0 || strcmp(str
, "FALSE") == 0) {
1483 /* Add trivial event */
1484 arg
= allocate_arg();
1488 arg
->type
= FILTER_ARG_BOOLEAN
;
1489 if (strcmp(str
, "TRUE") == 0)
1490 arg
->boolean
.value
= 1;
1492 arg
->boolean
.value
= 0;
1494 filter_type
= add_filter_type(filter
, event
->id
);
1495 if (filter_type
== NULL
)
1498 filter_type
->filter
= arg
;
1504 filter_event(filter
, event
, str
, NULL
);
1511 * pevent_filter_copy - copy a filter using another filter
1512 * @dest - the filter to copy to
1513 * @source - the filter to copy from
1515 * Returns 0 on success and -1 if not all filters were copied
1517 int pevent_filter_copy(struct event_filter
*dest
, struct event_filter
*source
)
1522 pevent_filter_reset(dest
);
1524 for (i
= 0; i
< source
->filters
; i
++) {
1525 if (copy_filter_type(dest
, source
, &source
->event_filters
[i
]))
1533 * pevent_update_trivial - update the trivial filters with the given filter
1534 * @dest - the filter to update
1535 * @source - the filter as the source of the update
1536 * @type - the type of trivial filter to update.
1538 * Scan dest for trivial events matching @type to replace with the source.
1540 * Returns 0 on success and -1 if there was a problem updating, but
1541 * events may have still been updated on error.
1543 int pevent_update_trivial(struct event_filter
*dest
, struct event_filter
*source
,
1544 enum filter_trivial_type type
)
1546 struct pevent
*src_pevent
;
1547 struct pevent
*dest_pevent
;
1548 struct event_format
*event
;
1549 struct filter_type
*filter_type
;
1550 struct filter_arg
*arg
;
1554 src_pevent
= source
->pevent
;
1555 dest_pevent
= dest
->pevent
;
1557 /* Do nothing if either of the filters has nothing to filter */
1558 if (!dest
->filters
|| !source
->filters
)
1561 for (i
= 0; i
< dest
->filters
; i
++) {
1562 filter_type
= &dest
->event_filters
[i
];
1563 arg
= filter_type
->filter
;
1564 if (arg
->type
!= FILTER_ARG_BOOLEAN
)
1566 if ((arg
->boolean
.value
&& type
== FILTER_TRIVIAL_FALSE
) ||
1567 (!arg
->boolean
.value
&& type
== FILTER_TRIVIAL_TRUE
))
1570 event
= filter_type
->event
;
1572 if (src_pevent
!= dest_pevent
) {
1574 event
= pevent_find_event_by_name(src_pevent
,
1581 str
= pevent_filter_make_string(source
, event
->id
);
1585 /* Don't bother if the filter is trivial too */
1586 if (strcmp(str
, "TRUE") != 0 && strcmp(str
, "FALSE") != 0)
1587 filter_event(dest
, event
, str
, NULL
);
1594 * pevent_filter_clear_trivial - clear TRUE and FALSE filters
1595 * @filter: the filter to remove trivial filters from
1596 * @type: remove only true, false, or both
1598 * Removes filters that only contain a TRUE or FALES boolean arg.
1600 * Returns 0 on success and -1 if there was a problem.
1602 int pevent_filter_clear_trivial(struct event_filter
*filter
,
1603 enum filter_trivial_type type
)
1605 struct filter_type
*filter_type
;
1610 if (!filter
->filters
)
1614 * Two steps, first get all ids with trivial filters.
1615 * then remove those ids.
1617 for (i
= 0; i
< filter
->filters
; i
++) {
1620 filter_type
= &filter
->event_filters
[i
];
1621 if (filter_type
->filter
->type
!= FILTER_ARG_BOOLEAN
)
1624 case FILTER_TRIVIAL_FALSE
:
1625 if (filter_type
->filter
->boolean
.value
)
1627 case FILTER_TRIVIAL_TRUE
:
1628 if (!filter_type
->filter
->boolean
.value
)
1634 new_ids
= realloc(ids
, sizeof(*ids
) * (count
+ 1));
1641 ids
[count
++] = filter_type
->event_id
;
1647 for (i
= 0; i
< count
; i
++)
1648 pevent_filter_remove_event(filter
, ids
[i
]);
1655 * pevent_filter_event_has_trivial - return true event contains trivial filter
1656 * @filter: the filter with the information
1657 * @event_id: the id of the event to test
1658 * @type: trivial type to test for (TRUE, FALSE, EITHER)
1660 * Returns 1 if the event contains a matching trivial type
1663 int pevent_filter_event_has_trivial(struct event_filter
*filter
,
1665 enum filter_trivial_type type
)
1667 struct filter_type
*filter_type
;
1669 if (!filter
->filters
)
1672 filter_type
= find_filter_type(filter
, event_id
);
1677 if (filter_type
->filter
->type
!= FILTER_ARG_BOOLEAN
)
1681 case FILTER_TRIVIAL_FALSE
:
1682 return !filter_type
->filter
->boolean
.value
;
1684 case FILTER_TRIVIAL_TRUE
:
1685 return filter_type
->filter
->boolean
.value
;
1691 static int test_filter(struct event_format
*event
, struct filter_arg
*arg
,
1692 struct pevent_record
*record
, enum pevent_errno
*err
);
1695 get_comm(struct event_format
*event
, struct pevent_record
*record
)
1700 pid
= pevent_data_pid(event
->pevent
, record
);
1701 comm
= pevent_data_comm_from_pid(event
->pevent
, pid
);
1705 static unsigned long long
1706 get_value(struct event_format
*event
,
1707 struct format_field
*field
, struct pevent_record
*record
)
1709 unsigned long long val
;
1711 /* Handle our dummy "comm" field */
1712 if (field
== &comm
) {
1715 name
= get_comm(event
, record
);
1716 return (unsigned long)name
;
1719 pevent_read_number_field(field
, record
->data
, &val
);
1721 if (!(field
->flags
& FIELD_IS_SIGNED
))
1724 switch (field
->size
) {
1732 return (long long)val
;
1737 static unsigned long long
1738 get_arg_value(struct event_format
*event
, struct filter_arg
*arg
,
1739 struct pevent_record
*record
, enum pevent_errno
*err
);
1741 static unsigned long long
1742 get_exp_value(struct event_format
*event
, struct filter_arg
*arg
,
1743 struct pevent_record
*record
, enum pevent_errno
*err
)
1745 unsigned long long lval
, rval
;
1747 lval
= get_arg_value(event
, arg
->exp
.left
, record
, err
);
1748 rval
= get_arg_value(event
, arg
->exp
.right
, record
, err
);
1752 * There was an error, no need to process anymore.
1757 switch (arg
->exp
.type
) {
1758 case FILTER_EXP_ADD
:
1761 case FILTER_EXP_SUB
:
1764 case FILTER_EXP_MUL
:
1767 case FILTER_EXP_DIV
:
1770 case FILTER_EXP_MOD
:
1773 case FILTER_EXP_RSHIFT
:
1774 return lval
>> rval
;
1776 case FILTER_EXP_LSHIFT
:
1777 return lval
<< rval
;
1779 case FILTER_EXP_AND
:
1785 case FILTER_EXP_XOR
:
1788 case FILTER_EXP_NOT
:
1791 *err
= PEVENT_ERRNO__INVALID_EXP_TYPE
;
1796 static unsigned long long
1797 get_arg_value(struct event_format
*event
, struct filter_arg
*arg
,
1798 struct pevent_record
*record
, enum pevent_errno
*err
)
1800 switch (arg
->type
) {
1801 case FILTER_ARG_FIELD
:
1802 return get_value(event
, arg
->field
.field
, record
);
1804 case FILTER_ARG_VALUE
:
1805 if (arg
->value
.type
!= FILTER_NUMBER
) {
1807 *err
= PEVENT_ERRNO__NOT_A_NUMBER
;
1809 return arg
->value
.val
;
1811 case FILTER_ARG_EXP
:
1812 return get_exp_value(event
, arg
, record
, err
);
1816 *err
= PEVENT_ERRNO__INVALID_ARG_TYPE
;
1821 static int test_num(struct event_format
*event
, struct filter_arg
*arg
,
1822 struct pevent_record
*record
, enum pevent_errno
*err
)
1824 unsigned long long lval
, rval
;
1826 lval
= get_arg_value(event
, arg
->num
.left
, record
, err
);
1827 rval
= get_arg_value(event
, arg
->num
.right
, record
, err
);
1831 * There was an error, no need to process anymore.
1836 switch (arg
->num
.type
) {
1838 return lval
== rval
;
1841 return lval
!= rval
;
1850 return lval
>= rval
;
1853 return lval
<= rval
;
1857 *err
= PEVENT_ERRNO__ILLEGAL_INTEGER_CMP
;
1862 static const char *get_field_str(struct filter_arg
*arg
, struct pevent_record
*record
)
1864 struct event_format
*event
;
1865 struct pevent
*pevent
;
1866 unsigned long long addr
;
1867 const char *val
= NULL
;
1870 /* If the field is not a string convert it */
1871 if (arg
->str
.field
->flags
& FIELD_IS_STRING
) {
1872 val
= record
->data
+ arg
->str
.field
->offset
;
1875 * We need to copy the data since we can't be sure the field
1876 * is null terminated.
1878 if (*(val
+ arg
->str
.field
->size
- 1)) {
1880 memcpy(arg
->str
.buffer
, val
, arg
->str
.field
->size
);
1881 /* the buffer is already NULL terminated */
1882 val
= arg
->str
.buffer
;
1886 event
= arg
->str
.field
->event
;
1887 pevent
= event
->pevent
;
1888 addr
= get_value(event
, arg
->str
.field
, record
);
1890 if (arg
->str
.field
->flags
& (FIELD_IS_POINTER
| FIELD_IS_LONG
))
1891 /* convert to a kernel symbol */
1892 val
= pevent_find_function(pevent
, addr
);
1895 /* just use the hex of the string name */
1896 snprintf(hex
, 64, "0x%llx", addr
);
1904 static int test_str(struct event_format
*event
, struct filter_arg
*arg
,
1905 struct pevent_record
*record
, enum pevent_errno
*err
)
1909 if (arg
->str
.field
== &comm
)
1910 val
= get_comm(event
, record
);
1912 val
= get_field_str(arg
, record
);
1914 switch (arg
->str
.type
) {
1915 case FILTER_CMP_MATCH
:
1916 return strcmp(val
, arg
->str
.val
) == 0;
1918 case FILTER_CMP_NOT_MATCH
:
1919 return strcmp(val
, arg
->str
.val
) != 0;
1921 case FILTER_CMP_REGEX
:
1922 /* Returns zero on match */
1923 return !regexec(&arg
->str
.reg
, val
, 0, NULL
, 0);
1925 case FILTER_CMP_NOT_REGEX
:
1926 return regexec(&arg
->str
.reg
, val
, 0, NULL
, 0);
1930 *err
= PEVENT_ERRNO__ILLEGAL_STRING_CMP
;
1935 static int test_op(struct event_format
*event
, struct filter_arg
*arg
,
1936 struct pevent_record
*record
, enum pevent_errno
*err
)
1938 switch (arg
->op
.type
) {
1940 return test_filter(event
, arg
->op
.left
, record
, err
) &&
1941 test_filter(event
, arg
->op
.right
, record
, err
);
1944 return test_filter(event
, arg
->op
.left
, record
, err
) ||
1945 test_filter(event
, arg
->op
.right
, record
, err
);
1948 return !test_filter(event
, arg
->op
.right
, record
, err
);
1952 *err
= PEVENT_ERRNO__INVALID_OP_TYPE
;
1957 static int test_filter(struct event_format
*event
, struct filter_arg
*arg
,
1958 struct pevent_record
*record
, enum pevent_errno
*err
)
1962 * There was an error, no need to process anymore.
1967 switch (arg
->type
) {
1968 case FILTER_ARG_BOOLEAN
:
1970 return arg
->boolean
.value
;
1973 return test_op(event
, arg
, record
, err
);
1975 case FILTER_ARG_NUM
:
1976 return test_num(event
, arg
, record
, err
);
1978 case FILTER_ARG_STR
:
1979 return test_str(event
, arg
, record
, err
);
1981 case FILTER_ARG_EXP
:
1982 case FILTER_ARG_VALUE
:
1983 case FILTER_ARG_FIELD
:
1985 * Expressions, fields and values evaluate
1986 * to true if they return non zero
1988 return !!get_arg_value(event
, arg
, record
, err
);
1992 *err
= PEVENT_ERRNO__INVALID_ARG_TYPE
;
1998 * pevent_event_filtered - return true if event has filter
1999 * @filter: filter struct with filter information
2000 * @event_id: event id to test if filter exists
2002 * Returns 1 if filter found for @event_id
2005 int pevent_event_filtered(struct event_filter
*filter
, int event_id
)
2007 struct filter_type
*filter_type
;
2009 if (!filter
->filters
)
2012 filter_type
= find_filter_type(filter
, event_id
);
2014 return filter_type
? 1 : 0;
2018 * pevent_filter_match - test if a record matches a filter
2019 * @filter: filter struct with filter information
2020 * @record: the record to test against the filter
2022 * Returns: match result or error code (prefixed with PEVENT_ERRNO__)
2023 * FILTER_MATCH - filter found for event and @record matches
2024 * FILTER_MISS - filter found for event and @record does not match
2025 * FILTER_NOT_FOUND - no filter found for @record's event
2026 * NO_FILTER - if no filters exist
2027 * otherwise - error occurred during test
2029 enum pevent_errno
pevent_filter_match(struct event_filter
*filter
,
2030 struct pevent_record
*record
)
2032 struct pevent
*pevent
= filter
->pevent
;
2033 struct filter_type
*filter_type
;
2036 enum pevent_errno err
= 0;
2038 filter_init_error_buf(filter
);
2040 if (!filter
->filters
)
2041 return PEVENT_ERRNO__NO_FILTER
;
2043 event_id
= pevent_data_type(pevent
, record
);
2045 filter_type
= find_filter_type(filter
, event_id
);
2047 return PEVENT_ERRNO__FILTER_NOT_FOUND
;
2049 ret
= test_filter(filter_type
->event
, filter_type
->filter
, record
, &err
);
2053 return ret
? PEVENT_ERRNO__FILTER_MATCH
: PEVENT_ERRNO__FILTER_MISS
;
2056 static char *op_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2066 switch (arg
->op
.type
) {
2074 left
= arg_to_str(filter
, arg
->op
.left
);
2075 right
= arg_to_str(filter
, arg
->op
.right
);
2076 if (!left
|| !right
)
2079 /* Try to consolidate boolean values */
2080 if (strcmp(left
, "TRUE") == 0)
2082 else if (strcmp(left
, "FALSE") == 0)
2085 if (strcmp(right
, "TRUE") == 0)
2087 else if (strcmp(right
, "FALSE") == 0)
2090 if (left_val
>= 0) {
2091 if ((arg
->op
.type
== FILTER_OP_AND
&& !left_val
) ||
2092 (arg
->op
.type
== FILTER_OP_OR
&& left_val
)) {
2093 /* Just return left value */
2098 if (right_val
>= 0) {
2099 /* just evaluate this. */
2101 switch (arg
->op
.type
) {
2103 val
= left_val
&& right_val
;
2106 val
= left_val
|| right_val
;
2111 asprintf(&str
, val
? "TRUE" : "FALSE");
2115 if (right_val
>= 0) {
2116 if ((arg
->op
.type
== FILTER_OP_AND
&& !right_val
) ||
2117 (arg
->op
.type
== FILTER_OP_OR
&& right_val
)) {
2118 /* Just return right value */
2123 /* The right value is meaningless */
2129 asprintf(&str
, "(%s) %s (%s)", left
, op
, right
);
2134 right
= arg_to_str(filter
, arg
->op
.right
);
2138 /* See if we can consolidate */
2139 if (strcmp(right
, "TRUE") == 0)
2141 else if (strcmp(right
, "FALSE") == 0)
2143 if (right_val
>= 0) {
2144 /* just return the opposite */
2145 asprintf(&str
, right_val
? "FALSE" : "TRUE");
2148 asprintf(&str
, "%s(%s)", op
, right
);
2160 static char *val_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2164 asprintf(&str
, "%lld", arg
->value
.val
);
2169 static char *field_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2171 return strdup(arg
->field
.field
->name
);
2174 static char *exp_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2181 lstr
= arg_to_str(filter
, arg
->exp
.left
);
2182 rstr
= arg_to_str(filter
, arg
->exp
.right
);
2186 switch (arg
->exp
.type
) {
2187 case FILTER_EXP_ADD
:
2190 case FILTER_EXP_SUB
:
2193 case FILTER_EXP_MUL
:
2196 case FILTER_EXP_DIV
:
2199 case FILTER_EXP_MOD
:
2202 case FILTER_EXP_RSHIFT
:
2205 case FILTER_EXP_LSHIFT
:
2208 case FILTER_EXP_AND
:
2214 case FILTER_EXP_XOR
:
2218 op
= "[ERROR IN EXPRESSION TYPE]";
2222 asprintf(&str
, "%s %s %s", lstr
, op
, rstr
);
2230 static char *num_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2237 lstr
= arg_to_str(filter
, arg
->num
.left
);
2238 rstr
= arg_to_str(filter
, arg
->num
.right
);
2242 switch (arg
->num
.type
) {
2266 asprintf(&str
, "%s %s %s", lstr
, op
, rstr
);
2280 static char *str_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2285 switch (arg
->str
.type
) {
2286 case FILTER_CMP_MATCH
:
2289 case FILTER_CMP_NOT_MATCH
:
2293 case FILTER_CMP_REGEX
:
2297 case FILTER_CMP_NOT_REGEX
:
2301 asprintf(&str
, "%s %s \"%s\"",
2302 arg
->str
.field
->name
, op
, arg
->str
.val
);
2312 static char *arg_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2316 switch (arg
->type
) {
2317 case FILTER_ARG_BOOLEAN
:
2318 asprintf(&str
, arg
->boolean
.value
? "TRUE" : "FALSE");
2322 return op_to_str(filter
, arg
);
2324 case FILTER_ARG_NUM
:
2325 return num_to_str(filter
, arg
);
2327 case FILTER_ARG_STR
:
2328 return str_to_str(filter
, arg
);
2330 case FILTER_ARG_VALUE
:
2331 return val_to_str(filter
, arg
);
2333 case FILTER_ARG_FIELD
:
2334 return field_to_str(filter
, arg
);
2336 case FILTER_ARG_EXP
:
2337 return exp_to_str(filter
, arg
);
2347 * pevent_filter_make_string - return a string showing the filter
2348 * @filter: filter struct with filter information
2349 * @event_id: the event id to return the filter string with
2351 * Returns a string that displays the filter contents.
2352 * This string must be freed with free(str).
2353 * NULL is returned if no filter is found or allocation failed.
2356 pevent_filter_make_string(struct event_filter
*filter
, int event_id
)
2358 struct filter_type
*filter_type
;
2360 if (!filter
->filters
)
2363 filter_type
= find_filter_type(filter
, event_id
);
2368 return arg_to_str(filter
, filter_type
->filter
);
2372 * pevent_filter_compare - compare two filters and return if they are the same
2373 * @filter1: Filter to compare with @filter2
2374 * @filter2: Filter to compare with @filter1
2377 * 1 if the two filters hold the same content.
2380 int pevent_filter_compare(struct event_filter
*filter1
, struct event_filter
*filter2
)
2382 struct filter_type
*filter_type1
;
2383 struct filter_type
*filter_type2
;
2388 /* Do the easy checks first */
2389 if (filter1
->filters
!= filter2
->filters
)
2391 if (!filter1
->filters
&& !filter2
->filters
)
2395 * Now take a look at each of the events to see if they have the same
2398 for (i
= 0; i
< filter1
->filters
; i
++) {
2399 filter_type1
= &filter1
->event_filters
[i
];
2400 filter_type2
= find_filter_type(filter2
, filter_type1
->event_id
);
2403 if (filter_type1
->filter
->type
!= filter_type2
->filter
->type
)
2405 switch (filter_type1
->filter
->type
) {
2406 case FILTER_TRIVIAL_FALSE
:
2407 case FILTER_TRIVIAL_TRUE
:
2408 /* trivial types just need the type compared */
2413 /* The best way to compare complex filters is with strings */
2414 str1
= arg_to_str(filter1
, filter_type1
->filter
);
2415 str2
= arg_to_str(filter2
, filter_type2
->filter
);
2417 result
= strcmp(str1
, str2
) != 0;
2419 /* bail out if allocation fails */
2428 if (i
< filter1
->filters
)