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, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 #include <sys/types.h>
28 #include "event-parse.h"
29 #include "event-utils.h"
33 static struct format_field comm
= {
38 struct event_list
*next
;
39 struct event_format
*event
;
42 #define MAX_ERR_STR_SIZE 256
44 static void show_error(char **error_str
, const char *fmt
, ...)
46 unsigned long long index
;
56 input
= pevent_get_input_buf();
57 index
= pevent_get_input_buf_ptr();
58 len
= input
? strlen(input
) : 0;
60 error
= malloc_or_die(MAX_ERR_STR_SIZE
+ (len
*2) + 3);
65 for (i
= 1; i
< len
&& i
< index
; i
++)
68 error
[len
+ i
+ 1] = '\n';
73 vsnprintf(error
+ len
, MAX_ERR_STR_SIZE
, fmt
, ap
);
79 static void free_token(char *token
)
81 pevent_free_token(token
);
84 static enum event_type
read_token(char **tok
)
91 type
= pevent_read_token(&token
);
92 } while (type
== EVENT_NEWLINE
|| type
== EVENT_SPACE
);
94 /* If token is = or ! check to see if the next char is ~ */
96 (strcmp(token
, "=") == 0 || strcmp(token
, "!") == 0) &&
97 pevent_peek_char() == '~') {
100 sprintf(*tok
, "%c%c", *token
, '~');
102 /* Now remove the '~' from the buffer */
103 pevent_read_token(&token
);
111 static int filter_cmp(const void *a
, const void *b
)
113 const struct filter_type
*ea
= a
;
114 const struct filter_type
*eb
= b
;
116 if (ea
->event_id
< eb
->event_id
)
119 if (ea
->event_id
> eb
->event_id
)
125 static struct filter_type
*
126 find_filter_type(struct event_filter
*filter
, int id
)
128 struct filter_type
*filter_type
;
129 struct filter_type key
;
133 filter_type
= bsearch(&key
, filter
->event_filters
,
135 sizeof(*filter
->event_filters
),
141 static struct filter_type
*
142 add_filter_type(struct event_filter
*filter
, int id
)
144 struct filter_type
*filter_type
;
147 filter_type
= find_filter_type(filter
, id
);
151 if (!filter
->filters
)
152 filter
->event_filters
=
153 malloc_or_die(sizeof(*filter
->event_filters
));
155 filter
->event_filters
=
156 realloc(filter
->event_filters
,
157 sizeof(*filter
->event_filters
) *
158 (filter
->filters
+ 1));
159 if (!filter
->event_filters
)
160 die("Could not allocate filter");
163 for (i
= 0; i
< filter
->filters
; i
++) {
164 if (filter
->event_filters
[i
].event_id
> id
)
168 if (i
< filter
->filters
)
169 memmove(&filter
->event_filters
[i
+1],
170 &filter
->event_filters
[i
],
171 sizeof(*filter
->event_filters
) *
172 (filter
->filters
- i
));
174 filter_type
= &filter
->event_filters
[i
];
175 filter_type
->event_id
= id
;
176 filter_type
->event
= pevent_find_event(filter
->pevent
, id
);
177 filter_type
->filter
= NULL
;
185 * pevent_filter_alloc - create a new event filter
186 * @pevent: The pevent that this filter is associated with
188 struct event_filter
*pevent_filter_alloc(struct pevent
*pevent
)
190 struct event_filter
*filter
;
192 filter
= malloc_or_die(sizeof(*filter
));
193 memset(filter
, 0, sizeof(*filter
));
194 filter
->pevent
= pevent
;
200 static struct filter_arg
*allocate_arg(void)
202 struct filter_arg
*arg
;
204 arg
= malloc_or_die(sizeof(*arg
));
205 memset(arg
, 0, sizeof(*arg
));
210 static void free_arg(struct filter_arg
*arg
)
216 case FILTER_ARG_NONE
:
217 case FILTER_ARG_BOOLEAN
:
223 regfree(&arg
->str
.reg
);
224 free(arg
->str
.buffer
);
228 free_arg(arg
->op
.left
);
229 free_arg(arg
->op
.right
);
237 static void add_event(struct event_list
**events
,
238 struct event_format
*event
)
240 struct event_list
*list
;
242 list
= malloc_or_die(sizeof(*list
));
243 list
->next
= *events
;
248 static int event_match(struct event_format
*event
,
249 regex_t
*sreg
, regex_t
*ereg
)
252 return !regexec(sreg
, event
->system
, 0, NULL
, 0) &&
253 !regexec(ereg
, event
->name
, 0, NULL
, 0);
256 return !regexec(ereg
, event
->system
, 0, NULL
, 0) ||
257 !regexec(ereg
, event
->name
, 0, NULL
, 0);
261 find_event(struct pevent
*pevent
, struct event_list
**events
,
262 char *sys_name
, char *event_name
)
264 struct event_format
*event
;
273 /* if no name is given, then swap sys and name */
274 event_name
= sys_name
;
278 reg
= malloc_or_die(strlen(event_name
) + 3);
279 sprintf(reg
, "^%s$", event_name
);
281 ret
= regcomp(&ereg
, reg
, REG_ICASE
|REG_NOSUB
);
288 reg
= malloc_or_die(strlen(sys_name
) + 3);
289 sprintf(reg
, "^%s$", sys_name
);
290 ret
= regcomp(&sreg
, reg
, REG_ICASE
|REG_NOSUB
);
298 for (i
= 0; i
< pevent
->nr_events
; i
++) {
299 event
= pevent
->events
[i
];
300 if (event_match(event
, sys_name
? &sreg
: NULL
, &ereg
)) {
302 add_event(events
, event
);
316 static void free_events(struct event_list
*events
)
318 struct event_list
*event
;
322 events
= events
->next
;
327 static struct filter_arg
*
328 create_arg_item(struct event_format
*event
, const char *token
,
329 enum event_type type
, char **error_str
)
331 struct format_field
*field
;
332 struct filter_arg
*arg
;
334 arg
= allocate_arg();
340 arg
->type
= FILTER_ARG_VALUE
;
342 type
== EVENT_DQUOTE
? FILTER_STRING
: FILTER_CHAR
;
343 arg
->value
.str
= strdup(token
);
345 die("malloc string");
348 /* if it is a number, then convert it */
349 if (isdigit(token
[0])) {
350 arg
->type
= FILTER_ARG_VALUE
;
351 arg
->value
.type
= FILTER_NUMBER
;
352 arg
->value
.val
= strtoull(token
, NULL
, 0);
355 /* Consider this a field */
356 field
= pevent_find_any_field(event
, token
);
358 if (strcmp(token
, COMM
) != 0) {
359 /* not a field, Make it false */
360 arg
->type
= FILTER_ARG_BOOLEAN
;
361 arg
->boolean
.value
= FILTER_FALSE
;
364 /* If token is 'COMM' then it is special */
367 arg
->type
= FILTER_ARG_FIELD
;
368 arg
->field
.field
= field
;
372 show_error(error_str
, "expected a value but found %s",
379 static struct filter_arg
*
380 create_arg_op(enum filter_op_type btype
)
382 struct filter_arg
*arg
;
384 arg
= allocate_arg();
385 arg
->type
= FILTER_ARG_OP
;
386 arg
->op
.type
= btype
;
391 static struct filter_arg
*
392 create_arg_exp(enum filter_exp_type etype
)
394 struct filter_arg
*arg
;
396 arg
= allocate_arg();
397 arg
->type
= FILTER_ARG_EXP
;
398 arg
->op
.type
= etype
;
403 static struct filter_arg
*
404 create_arg_cmp(enum filter_exp_type etype
)
406 struct filter_arg
*arg
;
408 arg
= allocate_arg();
409 /* Use NUM and change if necessary */
410 arg
->type
= FILTER_ARG_NUM
;
411 arg
->op
.type
= etype
;
416 static int add_right(struct filter_arg
*op
, struct filter_arg
*arg
,
419 struct filter_arg
*left
;
441 * The arg must be num, str, or field
444 case FILTER_ARG_VALUE
:
445 case FILTER_ARG_FIELD
:
448 show_error(error_str
,
454 * Depending on the type, we may need to
455 * convert this to a string or regex.
457 switch (arg
->value
.type
) {
460 * A char should be converted to number if
461 * the string is 1 byte, and the compare
464 if (strlen(arg
->value
.str
) == 1 &&
465 op
->num
.type
!= FILTER_CMP_REGEX
&&
466 op
->num
.type
!= FILTER_CMP_NOT_REGEX
) {
467 arg
->value
.type
= FILTER_NUMBER
;
473 /* convert op to a string arg */
474 op_type
= op
->num
.type
;
476 str
= arg
->value
.str
;
478 /* reset the op for the new field */
479 memset(op
, 0, sizeof(*op
));
482 * If left arg was a field not found then
483 * NULL the entire op.
485 if (left
->type
== FILTER_ARG_BOOLEAN
) {
488 op
->type
= FILTER_ARG_BOOLEAN
;
489 op
->boolean
.value
= FILTER_FALSE
;
493 /* Left arg must be a field */
494 if (left
->type
!= FILTER_ARG_FIELD
) {
495 show_error(error_str
,
496 "Illegal lvalue for string comparison");
500 /* Make sure this is a valid string compare */
503 op_type
= FILTER_CMP_MATCH
;
506 op_type
= FILTER_CMP_NOT_MATCH
;
509 case FILTER_CMP_REGEX
:
510 case FILTER_CMP_NOT_REGEX
:
511 ret
= regcomp(&op
->str
.reg
, str
, REG_ICASE
|REG_NOSUB
);
513 show_error(error_str
,
514 "RegEx '%s' did not compute",
520 show_error(error_str
,
521 "Illegal comparison for string");
525 op
->type
= FILTER_ARG_STR
;
526 op
->str
.type
= op_type
;
527 op
->str
.field
= left
->field
.field
;
528 op
->str
.val
= strdup(str
);
530 die("malloc string");
532 * Need a buffer to copy data for tests
534 op
->str
.buffer
= malloc_or_die(op
->str
.field
->size
+ 1);
535 /* Null terminate this buffer */
536 op
->str
.buffer
[op
->str
.field
->size
] = 0;
538 /* We no longer have left or right args */
547 switch (op
->num
.type
) {
548 case FILTER_CMP_REGEX
:
549 case FILTER_CMP_NOT_REGEX
:
550 show_error(error_str
,
551 "Op not allowed with integers");
558 /* numeric compare */
572 show_error(error_str
,
577 static struct filter_arg
*
578 rotate_op_right(struct filter_arg
*a
, struct filter_arg
*b
)
580 struct filter_arg
*arg
;
587 static int add_left(struct filter_arg
*op
, struct filter_arg
*arg
)
591 if (arg
->type
== FILTER_ARG_OP
)
592 arg
= rotate_op_right(arg
, op
);
600 if (arg
->type
== FILTER_ARG_OP
)
601 arg
= rotate_op_right(arg
, op
);
603 /* left arg of compares must be a field */
604 if (arg
->type
!= FILTER_ARG_FIELD
&&
605 arg
->type
!= FILTER_ARG_BOOLEAN
)
623 static enum op_type
process_op(const char *token
,
624 enum filter_op_type
*btype
,
625 enum filter_cmp_type
*ctype
,
626 enum filter_exp_type
*etype
)
628 *btype
= FILTER_OP_NOT
;
629 *etype
= FILTER_EXP_NONE
;
630 *ctype
= FILTER_CMP_NONE
;
632 if (strcmp(token
, "&&") == 0)
633 *btype
= FILTER_OP_AND
;
634 else if (strcmp(token
, "||") == 0)
635 *btype
= FILTER_OP_OR
;
636 else if (strcmp(token
, "!") == 0)
639 if (*btype
!= FILTER_OP_NOT
)
642 /* Check for value expressions */
643 if (strcmp(token
, "+") == 0) {
644 *etype
= FILTER_EXP_ADD
;
645 } else if (strcmp(token
, "-") == 0) {
646 *etype
= FILTER_EXP_SUB
;
647 } else if (strcmp(token
, "*") == 0) {
648 *etype
= FILTER_EXP_MUL
;
649 } else if (strcmp(token
, "/") == 0) {
650 *etype
= FILTER_EXP_DIV
;
651 } else if (strcmp(token
, "%") == 0) {
652 *etype
= FILTER_EXP_MOD
;
653 } else if (strcmp(token
, ">>") == 0) {
654 *etype
= FILTER_EXP_RSHIFT
;
655 } else if (strcmp(token
, "<<") == 0) {
656 *etype
= FILTER_EXP_LSHIFT
;
657 } else if (strcmp(token
, "&") == 0) {
658 *etype
= FILTER_EXP_AND
;
659 } else if (strcmp(token
, "|") == 0) {
660 *etype
= FILTER_EXP_OR
;
661 } else if (strcmp(token
, "^") == 0) {
662 *etype
= FILTER_EXP_XOR
;
663 } else if (strcmp(token
, "~") == 0)
664 *etype
= FILTER_EXP_NOT
;
666 if (*etype
!= FILTER_EXP_NONE
)
669 /* Check for compares */
670 if (strcmp(token
, "==") == 0)
671 *ctype
= FILTER_CMP_EQ
;
672 else if (strcmp(token
, "!=") == 0)
673 *ctype
= FILTER_CMP_NE
;
674 else if (strcmp(token
, "<") == 0)
675 *ctype
= FILTER_CMP_LT
;
676 else if (strcmp(token
, ">") == 0)
677 *ctype
= FILTER_CMP_GT
;
678 else if (strcmp(token
, "<=") == 0)
679 *ctype
= FILTER_CMP_LE
;
680 else if (strcmp(token
, ">=") == 0)
681 *ctype
= FILTER_CMP_GE
;
682 else if (strcmp(token
, "=~") == 0)
683 *ctype
= FILTER_CMP_REGEX
;
684 else if (strcmp(token
, "!~") == 0)
685 *ctype
= FILTER_CMP_NOT_REGEX
;
692 static int check_op_done(struct filter_arg
*arg
)
696 return arg
->exp
.right
!= NULL
;
699 return arg
->op
.right
!= NULL
;
702 return arg
->num
.right
!= NULL
;
705 /* A string conversion is always done */
708 case FILTER_ARG_BOOLEAN
:
709 /* field not found, is ok */
723 void reparent_op_arg(struct filter_arg
*parent
, struct filter_arg
*old_child
,
724 struct filter_arg
*arg
)
726 struct filter_arg
*other_child
;
727 struct filter_arg
**ptr
;
729 if (parent
->type
!= FILTER_ARG_OP
&&
730 arg
->type
!= FILTER_ARG_OP
)
731 die("can not reparent other than OP");
733 /* Get the sibling */
734 if (old_child
->op
.right
== arg
) {
735 ptr
= &old_child
->op
.right
;
736 other_child
= old_child
->op
.left
;
737 } else if (old_child
->op
.left
== arg
) {
738 ptr
= &old_child
->op
.left
;
739 other_child
= old_child
->op
.right
;
741 die("Error in reparent op, find other child");
743 /* Detach arg from old_child */
747 if (parent
== old_child
) {
748 free_arg(other_child
);
750 /* Free arg without recussion */
755 if (parent
->op
.right
== old_child
)
756 ptr
= &parent
->op
.right
;
757 else if (parent
->op
.left
== old_child
)
758 ptr
= &parent
->op
.left
;
760 die("Error in reparent op");
766 enum filter_vals
test_arg(struct filter_arg
*parent
, struct filter_arg
*arg
)
768 enum filter_vals lval
, rval
;
773 case FILTER_ARG_BOOLEAN
:
774 return FILTER_VAL_FALSE
+ arg
->boolean
.value
;
778 case FILTER_ARG_VALUE
:
779 case FILTER_ARG_FIELD
:
780 return FILTER_VAL_NORM
;
783 lval
= test_arg(arg
, arg
->exp
.left
);
784 if (lval
!= FILTER_VAL_NORM
)
786 rval
= test_arg(arg
, arg
->exp
.right
);
787 if (rval
!= FILTER_VAL_NORM
)
789 return FILTER_VAL_NORM
;
792 lval
= test_arg(arg
, arg
->num
.left
);
793 if (lval
!= FILTER_VAL_NORM
)
795 rval
= test_arg(arg
, arg
->num
.right
);
796 if (rval
!= FILTER_VAL_NORM
)
798 return FILTER_VAL_NORM
;
801 if (arg
->op
.type
!= FILTER_OP_NOT
) {
802 lval
= test_arg(arg
, arg
->op
.left
);
804 case FILTER_VAL_NORM
:
806 case FILTER_VAL_TRUE
:
807 if (arg
->op
.type
== FILTER_OP_OR
)
808 return FILTER_VAL_TRUE
;
809 rval
= test_arg(arg
, arg
->op
.right
);
810 if (rval
!= FILTER_VAL_NORM
)
813 reparent_op_arg(parent
, arg
, arg
->op
.right
);
814 return FILTER_VAL_NORM
;
816 case FILTER_VAL_FALSE
:
817 if (arg
->op
.type
== FILTER_OP_AND
)
818 return FILTER_VAL_FALSE
;
819 rval
= test_arg(arg
, arg
->op
.right
);
820 if (rval
!= FILTER_VAL_NORM
)
823 reparent_op_arg(parent
, arg
, arg
->op
.right
);
824 return FILTER_VAL_NORM
;
828 rval
= test_arg(arg
, arg
->op
.right
);
830 case FILTER_VAL_NORM
:
832 case FILTER_VAL_TRUE
:
833 if (arg
->op
.type
== FILTER_OP_OR
)
834 return FILTER_VAL_TRUE
;
835 if (arg
->op
.type
== FILTER_OP_NOT
)
836 return FILTER_VAL_FALSE
;
838 reparent_op_arg(parent
, arg
, arg
->op
.left
);
839 return FILTER_VAL_NORM
;
841 case FILTER_VAL_FALSE
:
842 if (arg
->op
.type
== FILTER_OP_AND
)
843 return FILTER_VAL_FALSE
;
844 if (arg
->op
.type
== FILTER_OP_NOT
)
845 return FILTER_VAL_TRUE
;
847 reparent_op_arg(parent
, arg
, arg
->op
.left
);
848 return FILTER_VAL_NORM
;
851 return FILTER_VAL_NORM
;
853 die("bad arg in filter tree");
855 return FILTER_VAL_NORM
;
858 /* Remove any unknown event fields */
859 static struct filter_arg
*collapse_tree(struct filter_arg
*arg
)
861 enum filter_vals ret
;
863 ret
= test_arg(arg
, arg
);
865 case FILTER_VAL_NORM
:
868 case FILTER_VAL_TRUE
:
869 case FILTER_VAL_FALSE
:
871 arg
= allocate_arg();
872 arg
->type
= FILTER_ARG_BOOLEAN
;
873 arg
->boolean
.value
= ret
== FILTER_VAL_TRUE
;
880 process_filter(struct event_format
*event
, struct filter_arg
**parg
,
881 char **error_str
, int not)
883 enum event_type type
;
885 struct filter_arg
*current_op
= NULL
;
886 struct filter_arg
*current_exp
= NULL
;
887 struct filter_arg
*left_item
= NULL
;
888 struct filter_arg
*arg
= NULL
;
889 enum op_type op_type
;
890 enum filter_op_type btype
;
891 enum filter_exp_type etype
;
892 enum filter_cmp_type ctype
;
899 type
= read_token(&token
);
904 arg
= create_arg_item(event
, token
, type
, error_str
);
909 else if (current_exp
) {
910 ret
= add_right(current_exp
, arg
, error_str
);
914 /* Not's only one one expression */
930 show_error(error_str
,
931 "Illegal token ','");
937 show_error(error_str
,
938 "Open paren can not come after item");
942 show_error(error_str
,
943 "Open paren can not come after expression");
947 ret
= process_filter(event
, &arg
, error_str
, 0);
950 show_error(error_str
,
951 "Unbalanced number of '('");
956 /* A not wants just one expression */
965 ret
= add_right(current_op
, arg
, error_str
);
973 if (!current_op
&& !current_exp
)
976 /* Make sure everything is finished at this level */
977 if (current_exp
&& !check_op_done(current_exp
))
979 if (current_op
&& !check_op_done(current_op
))
991 op_type
= process_op(token
, &btype
, &ctype
, &etype
);
993 /* All expect a left arg except for NOT */
996 /* Logic ops need a left expression */
997 if (!current_exp
&& !current_op
)
1001 /* logic only processes ops and exp */
1011 show_error(error_str
,
1012 "Unknown op token %s", token
);
1019 arg
= create_arg_op(btype
);
1021 ret
= add_left(arg
, current_op
);
1023 ret
= add_left(arg
, current_exp
);
1029 arg
= create_arg_op(btype
);
1031 ret
= add_right(current_op
, arg
, error_str
);
1035 ret
= process_filter(event
, &arg
, error_str
, 1);
1038 ret
= add_right(current_exp
, arg
, error_str
);
1045 if (op_type
== OP_EXP
)
1046 arg
= create_arg_exp(etype
);
1048 arg
= create_arg_cmp(ctype
);
1051 ret
= add_right(current_op
, arg
, error_str
);
1054 ret
= add_left(arg
, left_item
);
1073 } while (type
!= EVENT_NONE
);
1075 if (!current_op
&& !current_exp
)
1079 current_op
= current_exp
;
1081 current_op
= collapse_tree(current_op
);
1088 show_error(error_str
, "Syntax error");
1090 free_arg(current_op
);
1091 free_arg(current_exp
);
1098 process_event(struct event_format
*event
, const char *filter_str
,
1099 struct filter_arg
**parg
, char **error_str
)
1103 pevent_buffer_init(filter_str
, strlen(filter_str
));
1105 ret
= process_filter(event
, parg
, error_str
, 0);
1107 show_error(error_str
,
1108 "Unbalanced number of ')'");
1114 /* If parg is NULL, then make it into FALSE */
1116 *parg
= allocate_arg();
1117 (*parg
)->type
= FILTER_ARG_BOOLEAN
;
1118 (*parg
)->boolean
.value
= FILTER_FALSE
;
1124 static int filter_event(struct event_filter
*filter
,
1125 struct event_format
*event
,
1126 const char *filter_str
, char **error_str
)
1128 struct filter_type
*filter_type
;
1129 struct filter_arg
*arg
;
1133 ret
= process_event(event
, filter_str
, &arg
, error_str
);
1138 /* just add a TRUE arg */
1139 arg
= allocate_arg();
1140 arg
->type
= FILTER_ARG_BOOLEAN
;
1141 arg
->boolean
.value
= FILTER_TRUE
;
1144 filter_type
= add_filter_type(filter
, event
->id
);
1145 if (filter_type
->filter
)
1146 free_arg(filter_type
->filter
);
1147 filter_type
->filter
= arg
;
1153 * pevent_filter_add_filter_str - add a new filter
1154 * @filter: the event filter to add to
1155 * @filter_str: the filter string that contains the filter
1156 * @error_str: string containing reason for failed filter
1158 * Returns 0 if the filter was successfully added
1159 * -1 if there was an error.
1161 * On error, if @error_str points to a string pointer,
1162 * it is set to the reason that the filter failed.
1163 * This string must be freed with "free".
1165 int pevent_filter_add_filter_str(struct event_filter
*filter
,
1166 const char *filter_str
,
1169 struct pevent
*pevent
= filter
->pevent
;
1170 struct event_list
*event
;
1171 struct event_list
*events
= NULL
;
1172 const char *filter_start
;
1173 const char *next_event
;
1175 char *event_name
= NULL
;
1176 char *sys_name
= NULL
;
1182 /* clear buffer to reset show error */
1183 pevent_buffer_init("", 0);
1188 filter_start
= strchr(filter_str
, ':');
1190 len
= filter_start
- filter_str
;
1192 len
= strlen(filter_str
);
1196 next_event
= strchr(filter_str
, ',');
1198 (!filter_start
|| next_event
< filter_start
))
1199 len
= next_event
- filter_str
;
1200 else if (filter_start
)
1201 len
= filter_start
- filter_str
;
1203 len
= strlen(filter_str
);
1205 this_event
= malloc_or_die(len
+ 1);
1206 memcpy(this_event
, filter_str
, len
);
1207 this_event
[len
] = 0;
1212 filter_str
= next_event
;
1214 sys_name
= strtok_r(this_event
, "/", &sp
);
1215 event_name
= strtok_r(NULL
, "/", &sp
);
1218 show_error(error_str
, "No filter found");
1219 /* This can only happen when events is NULL, but still */
1220 free_events(events
);
1225 /* Find this event */
1226 ret
= find_event(pevent
, &events
, strim(sys_name
), strim(event_name
));
1229 show_error(error_str
,
1230 "No event found under '%s.%s'",
1231 sys_name
, event_name
);
1233 show_error(error_str
,
1234 "No event found under '%s'",
1236 free_events(events
);
1241 } while (filter_str
);
1247 /* filter starts here */
1248 for (event
= events
; event
; event
= event
->next
) {
1249 ret
= filter_event(filter
, event
->event
, filter_start
,
1251 /* Failures are returned if a parse error happened */
1255 if (ret
>= 0 && pevent
->test_filters
) {
1257 test
= pevent_filter_make_string(filter
, event
->event
->id
);
1258 printf(" '%s: %s'\n", event
->event
->name
, test
);
1263 free_events(events
);
1265 if (rtn
>= 0 && pevent
->test_filters
)
1271 static void free_filter_type(struct filter_type
*filter_type
)
1273 free_arg(filter_type
->filter
);
1277 * pevent_filter_remove_event - remove a filter for an event
1278 * @filter: the event filter to remove from
1279 * @event_id: the event to remove a filter for
1281 * Removes the filter saved for an event defined by @event_id
1284 * Returns 1: if an event was removed
1285 * 0: if the event was not found
1287 int pevent_filter_remove_event(struct event_filter
*filter
,
1290 struct filter_type
*filter_type
;
1293 if (!filter
->filters
)
1296 filter_type
= find_filter_type(filter
, event_id
);
1301 free_filter_type(filter_type
);
1303 /* The filter_type points into the event_filters array */
1304 len
= (unsigned long)(filter
->event_filters
+ filter
->filters
) -
1305 (unsigned long)(filter_type
+ 1);
1307 memmove(filter_type
, filter_type
+ 1, len
);
1310 memset(&filter
->event_filters
[filter
->filters
], 0,
1311 sizeof(*filter_type
));
1317 * pevent_filter_reset - clear all filters in a filter
1318 * @filter: the event filter to reset
1320 * Removes all filters from a filter and resets it.
1322 void pevent_filter_reset(struct event_filter
*filter
)
1326 for (i
= 0; i
< filter
->filters
; i
++)
1327 free_filter_type(&filter
->event_filters
[i
]);
1329 free(filter
->event_filters
);
1330 filter
->filters
= 0;
1331 filter
->event_filters
= NULL
;
1334 void pevent_filter_free(struct event_filter
*filter
)
1336 pevent_unref(filter
->pevent
);
1338 pevent_filter_reset(filter
);
1343 static char *arg_to_str(struct event_filter
*filter
, struct filter_arg
*arg
);
1345 static int copy_filter_type(struct event_filter
*filter
,
1346 struct event_filter
*source
,
1347 struct filter_type
*filter_type
)
1349 struct filter_arg
*arg
;
1350 struct event_format
*event
;
1355 /* Can't assume that the pevent's are the same */
1356 sys
= filter_type
->event
->system
;
1357 name
= filter_type
->event
->name
;
1358 event
= pevent_find_event_by_name(filter
->pevent
, sys
, name
);
1362 str
= arg_to_str(source
, filter_type
->filter
);
1366 if (strcmp(str
, "TRUE") == 0 || strcmp(str
, "FALSE") == 0) {
1367 /* Add trivial event */
1368 arg
= allocate_arg();
1369 arg
->type
= FILTER_ARG_BOOLEAN
;
1370 if (strcmp(str
, "TRUE") == 0)
1371 arg
->boolean
.value
= 1;
1373 arg
->boolean
.value
= 0;
1375 filter_type
= add_filter_type(filter
, event
->id
);
1376 filter_type
->filter
= arg
;
1382 filter_event(filter
, event
, str
, NULL
);
1389 * pevent_filter_copy - copy a filter using another filter
1390 * @dest - the filter to copy to
1391 * @source - the filter to copy from
1393 * Returns 0 on success and -1 if not all filters were copied
1395 int pevent_filter_copy(struct event_filter
*dest
, struct event_filter
*source
)
1400 pevent_filter_reset(dest
);
1402 for (i
= 0; i
< source
->filters
; i
++) {
1403 if (copy_filter_type(dest
, source
, &source
->event_filters
[i
]))
1411 * pevent_update_trivial - update the trivial filters with the given filter
1412 * @dest - the filter to update
1413 * @source - the filter as the source of the update
1414 * @type - the type of trivial filter to update.
1416 * Scan dest for trivial events matching @type to replace with the source.
1418 * Returns 0 on success and -1 if there was a problem updating, but
1419 * events may have still been updated on error.
1421 int pevent_update_trivial(struct event_filter
*dest
, struct event_filter
*source
,
1422 enum filter_trivial_type type
)
1424 struct pevent
*src_pevent
;
1425 struct pevent
*dest_pevent
;
1426 struct event_format
*event
;
1427 struct filter_type
*filter_type
;
1428 struct filter_arg
*arg
;
1432 src_pevent
= source
->pevent
;
1433 dest_pevent
= dest
->pevent
;
1435 /* Do nothing if either of the filters has nothing to filter */
1436 if (!dest
->filters
|| !source
->filters
)
1439 for (i
= 0; i
< dest
->filters
; i
++) {
1440 filter_type
= &dest
->event_filters
[i
];
1441 arg
= filter_type
->filter
;
1442 if (arg
->type
!= FILTER_ARG_BOOLEAN
)
1444 if ((arg
->boolean
.value
&& type
== FILTER_TRIVIAL_FALSE
) ||
1445 (!arg
->boolean
.value
&& type
== FILTER_TRIVIAL_TRUE
))
1448 event
= filter_type
->event
;
1450 if (src_pevent
!= dest_pevent
) {
1452 event
= pevent_find_event_by_name(src_pevent
,
1459 str
= pevent_filter_make_string(source
, event
->id
);
1463 /* Don't bother if the filter is trivial too */
1464 if (strcmp(str
, "TRUE") != 0 && strcmp(str
, "FALSE") != 0)
1465 filter_event(dest
, event
, str
, NULL
);
1472 * pevent_filter_clear_trivial - clear TRUE and FALSE filters
1473 * @filter: the filter to remove trivial filters from
1474 * @type: remove only true, false, or both
1476 * Removes filters that only contain a TRUE or FALES boolean arg.
1478 void pevent_filter_clear_trivial(struct event_filter
*filter
,
1479 enum filter_trivial_type type
)
1481 struct filter_type
*filter_type
;
1486 if (!filter
->filters
)
1490 * Two steps, first get all ids with trivial filters.
1491 * then remove those ids.
1493 for (i
= 0; i
< filter
->filters
; i
++) {
1494 filter_type
= &filter
->event_filters
[i
];
1495 if (filter_type
->filter
->type
!= FILTER_ARG_BOOLEAN
)
1498 case FILTER_TRIVIAL_FALSE
:
1499 if (filter_type
->filter
->boolean
.value
)
1501 case FILTER_TRIVIAL_TRUE
:
1502 if (!filter_type
->filter
->boolean
.value
)
1508 ids
= realloc(ids
, sizeof(*ids
) * (count
+ 1));
1510 ids
= malloc(sizeof(*ids
));
1512 die("Can't allocate ids");
1513 ids
[count
++] = filter_type
->event_id
;
1519 for (i
= 0; i
< count
; i
++)
1520 pevent_filter_remove_event(filter
, ids
[i
]);
1526 * pevent_filter_event_has_trivial - return true event contains trivial filter
1527 * @filter: the filter with the information
1528 * @event_id: the id of the event to test
1529 * @type: trivial type to test for (TRUE, FALSE, EITHER)
1531 * Returns 1 if the event contains a matching trivial type
1534 int pevent_filter_event_has_trivial(struct event_filter
*filter
,
1536 enum filter_trivial_type type
)
1538 struct filter_type
*filter_type
;
1540 if (!filter
->filters
)
1543 filter_type
= find_filter_type(filter
, event_id
);
1548 if (filter_type
->filter
->type
!= FILTER_ARG_BOOLEAN
)
1552 case FILTER_TRIVIAL_FALSE
:
1553 return !filter_type
->filter
->boolean
.value
;
1555 case FILTER_TRIVIAL_TRUE
:
1556 return filter_type
->filter
->boolean
.value
;
1562 static int test_filter(struct event_format
*event
,
1563 struct filter_arg
*arg
, struct pevent_record
*record
);
1566 get_comm(struct event_format
*event
, struct pevent_record
*record
)
1571 pid
= pevent_data_pid(event
->pevent
, record
);
1572 comm
= pevent_data_comm_from_pid(event
->pevent
, pid
);
1576 static unsigned long long
1577 get_value(struct event_format
*event
,
1578 struct format_field
*field
, struct pevent_record
*record
)
1580 unsigned long long val
;
1582 /* Handle our dummy "comm" field */
1583 if (field
== &comm
) {
1586 name
= get_comm(event
, record
);
1587 return (unsigned long)name
;
1590 pevent_read_number_field(field
, record
->data
, &val
);
1592 if (!(field
->flags
& FIELD_IS_SIGNED
))
1595 switch (field
->size
) {
1603 return (long long)val
;
1608 static unsigned long long
1609 get_arg_value(struct event_format
*event
, struct filter_arg
*arg
, struct pevent_record
*record
);
1611 static unsigned long long
1612 get_exp_value(struct event_format
*event
, struct filter_arg
*arg
, struct pevent_record
*record
)
1614 unsigned long long lval
, rval
;
1616 lval
= get_arg_value(event
, arg
->exp
.left
, record
);
1617 rval
= get_arg_value(event
, arg
->exp
.right
, record
);
1619 switch (arg
->exp
.type
) {
1620 case FILTER_EXP_ADD
:
1623 case FILTER_EXP_SUB
:
1626 case FILTER_EXP_MUL
:
1629 case FILTER_EXP_DIV
:
1632 case FILTER_EXP_MOD
:
1635 case FILTER_EXP_RSHIFT
:
1636 return lval
>> rval
;
1638 case FILTER_EXP_LSHIFT
:
1639 return lval
<< rval
;
1641 case FILTER_EXP_AND
:
1647 case FILTER_EXP_XOR
:
1650 case FILTER_EXP_NOT
:
1652 die("error in exp");
1657 static unsigned long long
1658 get_arg_value(struct event_format
*event
, struct filter_arg
*arg
, struct pevent_record
*record
)
1660 switch (arg
->type
) {
1661 case FILTER_ARG_FIELD
:
1662 return get_value(event
, arg
->field
.field
, record
);
1664 case FILTER_ARG_VALUE
:
1665 if (arg
->value
.type
!= FILTER_NUMBER
)
1666 die("must have number field!");
1667 return arg
->value
.val
;
1669 case FILTER_ARG_EXP
:
1670 return get_exp_value(event
, arg
, record
);
1673 die("oops in filter");
1678 static int test_num(struct event_format
*event
,
1679 struct filter_arg
*arg
, struct pevent_record
*record
)
1681 unsigned long long lval
, rval
;
1683 lval
= get_arg_value(event
, arg
->num
.left
, record
);
1684 rval
= get_arg_value(event
, arg
->num
.right
, record
);
1686 switch (arg
->num
.type
) {
1688 return lval
== rval
;
1691 return lval
!= rval
;
1700 return lval
>= rval
;
1703 return lval
<= rval
;
1711 static const char *get_field_str(struct filter_arg
*arg
, struct pevent_record
*record
)
1713 const char *val
= record
->data
+ arg
->str
.field
->offset
;
1716 * We need to copy the data since we can't be sure the field
1717 * is null terminated.
1719 if (*(val
+ arg
->str
.field
->size
- 1)) {
1721 memcpy(arg
->str
.buffer
, val
, arg
->str
.field
->size
);
1722 /* the buffer is already NULL terminated */
1723 val
= arg
->str
.buffer
;
1728 static int test_str(struct event_format
*event
,
1729 struct filter_arg
*arg
, struct pevent_record
*record
)
1733 if (arg
->str
.field
== &comm
)
1734 val
= get_comm(event
, record
);
1736 val
= get_field_str(arg
, record
);
1738 switch (arg
->str
.type
) {
1739 case FILTER_CMP_MATCH
:
1740 return strcmp(val
, arg
->str
.val
) == 0;
1742 case FILTER_CMP_NOT_MATCH
:
1743 return strcmp(val
, arg
->str
.val
) != 0;
1745 case FILTER_CMP_REGEX
:
1746 /* Returns zero on match */
1747 return !regexec(&arg
->str
.reg
, val
, 0, NULL
, 0);
1749 case FILTER_CMP_NOT_REGEX
:
1750 return regexec(&arg
->str
.reg
, val
, 0, NULL
, 0);
1758 static int test_op(struct event_format
*event
,
1759 struct filter_arg
*arg
, struct pevent_record
*record
)
1761 switch (arg
->op
.type
) {
1763 return test_filter(event
, arg
->op
.left
, record
) &&
1764 test_filter(event
, arg
->op
.right
, record
);
1767 return test_filter(event
, arg
->op
.left
, record
) ||
1768 test_filter(event
, arg
->op
.right
, record
);
1771 return !test_filter(event
, arg
->op
.right
, record
);
1779 static int test_filter(struct event_format
*event
,
1780 struct filter_arg
*arg
, struct pevent_record
*record
)
1782 switch (arg
->type
) {
1783 case FILTER_ARG_BOOLEAN
:
1785 return arg
->boolean
.value
;
1788 return test_op(event
, arg
, record
);
1790 case FILTER_ARG_NUM
:
1791 return test_num(event
, arg
, record
);
1793 case FILTER_ARG_STR
:
1794 return test_str(event
, arg
, record
);
1796 case FILTER_ARG_EXP
:
1797 case FILTER_ARG_VALUE
:
1798 case FILTER_ARG_FIELD
:
1800 * Expressions, fields and values evaluate
1801 * to true if they return non zero
1803 return !!get_arg_value(event
, arg
, record
);
1813 * pevent_event_filtered - return true if event has filter
1814 * @filter: filter struct with filter information
1815 * @event_id: event id to test if filter exists
1817 * Returns 1 if filter found for @event_id
1820 int pevent_event_filtered(struct event_filter
*filter
,
1823 struct filter_type
*filter_type
;
1825 if (!filter
->filters
)
1828 filter_type
= find_filter_type(filter
, event_id
);
1830 return filter_type
? 1 : 0;
1834 * pevent_filter_match - test if a record matches a filter
1835 * @filter: filter struct with filter information
1836 * @record: the record to test against the filter
1839 * 1 - filter found for event and @record matches
1840 * 0 - filter found for event and @record does not match
1841 * -1 - no filter found for @record's event
1842 * -2 - if no filters exist
1844 int pevent_filter_match(struct event_filter
*filter
,
1845 struct pevent_record
*record
)
1847 struct pevent
*pevent
= filter
->pevent
;
1848 struct filter_type
*filter_type
;
1851 if (!filter
->filters
)
1854 event_id
= pevent_data_type(pevent
, record
);
1856 filter_type
= find_filter_type(filter
, event_id
);
1859 return FILTER_NOEXIST
;
1861 return test_filter(filter_type
->event
, filter_type
->filter
, record
) ?
1862 FILTER_MATCH
: FILTER_MISS
;
1865 static char *op_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
1876 switch (arg
->op
.type
) {
1884 left
= arg_to_str(filter
, arg
->op
.left
);
1885 right
= arg_to_str(filter
, arg
->op
.right
);
1886 if (!left
|| !right
)
1889 /* Try to consolidate boolean values */
1890 if (strcmp(left
, "TRUE") == 0)
1892 else if (strcmp(left
, "FALSE") == 0)
1895 if (strcmp(right
, "TRUE") == 0)
1897 else if (strcmp(right
, "FALSE") == 0)
1900 if (left_val
>= 0) {
1901 if ((arg
->op
.type
== FILTER_OP_AND
&& !left_val
) ||
1902 (arg
->op
.type
== FILTER_OP_OR
&& left_val
)) {
1903 /* Just return left value */
1908 if (right_val
>= 0) {
1909 /* just evaluate this. */
1911 switch (arg
->op
.type
) {
1913 val
= left_val
&& right_val
;
1916 val
= left_val
|| right_val
;
1921 str
= malloc_or_die(6);
1923 strcpy(str
, "TRUE");
1925 strcpy(str
, "FALSE");
1929 if (right_val
>= 0) {
1930 if ((arg
->op
.type
== FILTER_OP_AND
&& !right_val
) ||
1931 (arg
->op
.type
== FILTER_OP_OR
&& right_val
)) {
1932 /* Just return right value */
1937 /* The right value is meaningless */
1943 len
= strlen(left
) + strlen(right
) + strlen(op
) + 10;
1944 str
= malloc_or_die(len
);
1945 snprintf(str
, len
, "(%s) %s (%s)",
1951 right
= arg_to_str(filter
, arg
->op
.right
);
1955 /* See if we can consolidate */
1956 if (strcmp(right
, "TRUE") == 0)
1958 else if (strcmp(right
, "FALSE") == 0)
1960 if (right_val
>= 0) {
1961 /* just return the opposite */
1962 str
= malloc_or_die(6);
1964 strcpy(str
, "FALSE");
1966 strcpy(str
, "TRUE");
1969 len
= strlen(right
) + strlen(op
) + 3;
1970 str
= malloc_or_die(len
);
1971 snprintf(str
, len
, "%s(%s)", op
, right
);
1983 static char *val_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
1987 str
= malloc_or_die(30);
1989 snprintf(str
, 30, "%lld", arg
->value
.val
);
1994 static char *field_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
1996 return strdup(arg
->field
.field
->name
);
1999 static char *exp_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2007 lstr
= arg_to_str(filter
, arg
->exp
.left
);
2008 rstr
= arg_to_str(filter
, arg
->exp
.right
);
2010 switch (arg
->exp
.type
) {
2011 case FILTER_EXP_ADD
:
2014 case FILTER_EXP_SUB
:
2017 case FILTER_EXP_MUL
:
2020 case FILTER_EXP_DIV
:
2023 case FILTER_EXP_MOD
:
2026 case FILTER_EXP_RSHIFT
:
2029 case FILTER_EXP_LSHIFT
:
2032 case FILTER_EXP_AND
:
2038 case FILTER_EXP_XOR
:
2045 len
= strlen(op
) + strlen(lstr
) + strlen(rstr
) + 4;
2046 str
= malloc_or_die(len
);
2047 snprintf(str
, len
, "%s %s %s", lstr
, op
, rstr
);
2054 static char *num_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2062 lstr
= arg_to_str(filter
, arg
->num
.left
);
2063 rstr
= arg_to_str(filter
, arg
->num
.right
);
2065 switch (arg
->num
.type
) {
2089 len
= strlen(lstr
) + strlen(op
) + strlen(rstr
) + 4;
2090 str
= malloc_or_die(len
);
2091 sprintf(str
, "%s %s %s", lstr
, op
, rstr
);
2105 static char *str_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2111 switch (arg
->str
.type
) {
2112 case FILTER_CMP_MATCH
:
2115 case FILTER_CMP_NOT_MATCH
:
2119 case FILTER_CMP_REGEX
:
2123 case FILTER_CMP_NOT_REGEX
:
2127 len
= strlen(arg
->str
.field
->name
) + strlen(op
) +
2128 strlen(arg
->str
.val
) + 6;
2129 str
= malloc_or_die(len
);
2130 snprintf(str
, len
, "%s %s \"%s\"",
2131 arg
->str
.field
->name
,
2142 static char *arg_to_str(struct event_filter
*filter
, struct filter_arg
*arg
)
2146 switch (arg
->type
) {
2147 case FILTER_ARG_BOOLEAN
:
2148 str
= malloc_or_die(6);
2149 if (arg
->boolean
.value
)
2150 strcpy(str
, "TRUE");
2152 strcpy(str
, "FALSE");
2156 return op_to_str(filter
, arg
);
2158 case FILTER_ARG_NUM
:
2159 return num_to_str(filter
, arg
);
2161 case FILTER_ARG_STR
:
2162 return str_to_str(filter
, arg
);
2164 case FILTER_ARG_VALUE
:
2165 return val_to_str(filter
, arg
);
2167 case FILTER_ARG_FIELD
:
2168 return field_to_str(filter
, arg
);
2170 case FILTER_ARG_EXP
:
2171 return exp_to_str(filter
, arg
);
2181 * pevent_filter_make_string - return a string showing the filter
2182 * @filter: filter struct with filter information
2183 * @event_id: the event id to return the filter string with
2185 * Returns a string that displays the filter contents.
2186 * This string must be freed with free(str).
2187 * NULL is returned if no filter is found.
2190 pevent_filter_make_string(struct event_filter
*filter
, int event_id
)
2192 struct filter_type
*filter_type
;
2194 if (!filter
->filters
)
2197 filter_type
= find_filter_type(filter
, event_id
);
2202 return arg_to_str(filter
, filter_type
->filter
);
2206 * pevent_filter_compare - compare two filters and return if they are the same
2207 * @filter1: Filter to compare with @filter2
2208 * @filter2: Filter to compare with @filter1
2211 * 1 if the two filters hold the same content.
2214 int pevent_filter_compare(struct event_filter
*filter1
, struct event_filter
*filter2
)
2216 struct filter_type
*filter_type1
;
2217 struct filter_type
*filter_type2
;
2222 /* Do the easy checks first */
2223 if (filter1
->filters
!= filter2
->filters
)
2225 if (!filter1
->filters
&& !filter2
->filters
)
2229 * Now take a look at each of the events to see if they have the same
2232 for (i
= 0; i
< filter1
->filters
; i
++) {
2233 filter_type1
= &filter1
->event_filters
[i
];
2234 filter_type2
= find_filter_type(filter2
, filter_type1
->event_id
);
2237 if (filter_type1
->filter
->type
!= filter_type2
->filter
->type
)
2239 switch (filter_type1
->filter
->type
) {
2240 case FILTER_TRIVIAL_FALSE
:
2241 case FILTER_TRIVIAL_TRUE
:
2242 /* trivial types just need the type compared */
2247 /* The best way to compare complex filters is with strings */
2248 str1
= arg_to_str(filter1
, filter_type1
->filter
);
2249 str2
= arg_to_str(filter2
, filter_type2
->filter
);
2250 result
= strcmp(str1
, str2
) != 0;
2257 if (i
< filter1
->filters
)
This page took 0.078786 seconds and 5 git commands to generate.