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 reg = malloc(strlen(event_name) + 3);
292 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
294 sprintf(reg, "^%s$", event_name);
296 ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
300 return PEVENT_ERRNO__INVALID_EVENT_NAME;
303 reg = malloc(strlen(sys_name) + 3);
306 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
309 sprintf(reg, "^%s$", sys_name);
310 ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
314 return PEVENT_ERRNO__INVALID_EVENT_NAME;
318 for (i = 0; i < pevent->nr_events; i++) {
319 event = pevent->events[i];
320 if (event_match(event, sys_name ? &sreg : NULL, &ereg)) {
322 if (add_event(events, event) < 0) {
334 return PEVENT_ERRNO__EVENT_NOT_FOUND;
336 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
341 static void free_events(struct event_list *events)
343 struct event_list *event;
347 events = events->next;
352 static enum pevent_errno
353 create_arg_item(struct event_format *event, const char *token,
354 enum event_type type, struct filter_arg **parg, char *error_str)
356 struct format_field *field;
357 struct filter_arg *arg;
359 arg = allocate_arg();
361 show_error(error_str, "failed to allocate filter arg");
362 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
369 arg->type = FILTER_ARG_VALUE;
371 type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR;
372 arg->value.str = strdup(token);
373 if (!arg->value.str) {
375 show_error(error_str, "failed to allocate string filter arg");
376 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
380 /* if it is a number, then convert it */
381 if (isdigit(token[0])) {
382 arg->type = FILTER_ARG_VALUE;
383 arg->value.type = FILTER_NUMBER;
384 arg->value.val = strtoull(token, NULL, 0);
387 /* Consider this a field */
388 field = pevent_find_any_field(event, token);
390 /* If token is 'COMM' or 'CPU' then it is special */
391 if (strcmp(token, COMM) == 0) {
393 } else if (strcmp(token, CPU) == 0) {
396 /* not a field, Make it false */
397 arg->type = FILTER_ARG_BOOLEAN;
398 arg->boolean.value = FILTER_FALSE;
402 arg->type = FILTER_ARG_FIELD;
403 arg->field.field = field;
407 show_error(error_str, "expected a value but found %s", token);
408 return PEVENT_ERRNO__UNEXPECTED_TYPE;
414 static struct filter_arg *
415 create_arg_op(enum filter_op_type btype)
417 struct filter_arg *arg;
419 arg = allocate_arg();
423 arg->type = FILTER_ARG_OP;
424 arg->op.type = btype;
429 static struct filter_arg *
430 create_arg_exp(enum filter_exp_type etype)
432 struct filter_arg *arg;
434 arg = allocate_arg();
438 arg->type = FILTER_ARG_EXP;
439 arg->op.type = etype;
444 static struct filter_arg *
445 create_arg_cmp(enum filter_exp_type etype)
447 struct filter_arg *arg;
449 arg = allocate_arg();
453 /* Use NUM and change if necessary */
454 arg->type = FILTER_ARG_NUM;
455 arg->op.type = etype;
460 static enum pevent_errno
461 add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
463 struct filter_arg *left;
485 * The arg must be num, str, or field
488 case FILTER_ARG_VALUE:
489 case FILTER_ARG_FIELD:
492 show_error(error_str, "Illegal rvalue");
493 return PEVENT_ERRNO__ILLEGAL_RVALUE;
497 * Depending on the type, we may need to
498 * convert this to a string or regex.
500 switch (arg->value.type) {
503 * A char should be converted to number if
504 * the string is 1 byte, and the compare
507 if (strlen(arg->value.str) == 1 &&
508 op->num.type != FILTER_CMP_REGEX &&
509 op->num.type != FILTER_CMP_NOT_REGEX) {
510 arg->value.type = FILTER_NUMBER;
516 /* convert op to a string arg */
517 op_type = op->num.type;
519 str = arg->value.str;
521 /* reset the op for the new field */
522 memset(op, 0, sizeof(*op));
525 * If left arg was a field not found then
526 * NULL the entire op.
528 if (left->type == FILTER_ARG_BOOLEAN) {
531 op->type = FILTER_ARG_BOOLEAN;
532 op->boolean.value = FILTER_FALSE;
536 /* Left arg must be a field */
537 if (left->type != FILTER_ARG_FIELD) {
538 show_error(error_str,
539 "Illegal lvalue for string comparison");
540 return PEVENT_ERRNO__ILLEGAL_LVALUE;
543 /* Make sure this is a valid string compare */
546 op_type = FILTER_CMP_MATCH;
549 op_type = FILTER_CMP_NOT_MATCH;
552 case FILTER_CMP_REGEX:
553 case FILTER_CMP_NOT_REGEX:
554 ret = regcomp(&op->str.reg, str, REG_ICASE|REG_NOSUB);
556 show_error(error_str,
557 "RegEx '%s' did not compute",
559 return PEVENT_ERRNO__INVALID_REGEX;
563 show_error(error_str,
564 "Illegal comparison for string");
565 return PEVENT_ERRNO__ILLEGAL_STRING_CMP;
568 op->type = FILTER_ARG_STR;
569 op->str.type = op_type;
570 op->str.field = left->field.field;
571 op->str.val = strdup(str);
573 show_error(error_str, "Failed to allocate string filter");
574 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
577 * Need a buffer to copy data for tests
579 op->str.buffer = malloc(op->str.field->size + 1);
580 if (!op->str.buffer) {
581 show_error(error_str, "Failed to allocate string filter");
582 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
584 /* Null terminate this buffer */
585 op->str.buffer[op->str.field->size] = 0;
587 /* We no longer have left or right args */
596 switch (op->num.type) {
597 case FILTER_CMP_REGEX:
598 case FILTER_CMP_NOT_REGEX:
599 show_error(error_str,
600 "Op not allowed with integers");
601 return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
607 /* numeric compare */
621 show_error(error_str, "Syntax error");
622 return PEVENT_ERRNO__SYNTAX_ERROR;
625 static struct filter_arg *
626 rotate_op_right(struct filter_arg *a, struct filter_arg *b)
628 struct filter_arg *arg;
635 static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg)
639 if (arg->type == FILTER_ARG_OP)
640 arg = rotate_op_right(arg, op);
648 if (arg->type == FILTER_ARG_OP)
649 arg = rotate_op_right(arg, op);
651 /* left arg of compares must be a field */
652 if (arg->type != FILTER_ARG_FIELD &&
653 arg->type != FILTER_ARG_BOOLEAN)
654 return PEVENT_ERRNO__INVALID_ARG_TYPE;
658 return PEVENT_ERRNO__INVALID_ARG_TYPE;
671 static enum op_type process_op(const char *token,
672 enum filter_op_type *btype,
673 enum filter_cmp_type *ctype,
674 enum filter_exp_type *etype)
676 *btype = FILTER_OP_NOT;
677 *etype = FILTER_EXP_NONE;
678 *ctype = FILTER_CMP_NONE;
680 if (strcmp(token, "&&") == 0)
681 *btype = FILTER_OP_AND;
682 else if (strcmp(token, "||") == 0)
683 *btype = FILTER_OP_OR;
684 else if (strcmp(token, "!") == 0)
687 if (*btype != FILTER_OP_NOT)
690 /* Check for value expressions */
691 if (strcmp(token, "+") == 0) {
692 *etype = FILTER_EXP_ADD;
693 } else if (strcmp(token, "-") == 0) {
694 *etype = FILTER_EXP_SUB;
695 } else if (strcmp(token, "*") == 0) {
696 *etype = FILTER_EXP_MUL;
697 } else if (strcmp(token, "/") == 0) {
698 *etype = FILTER_EXP_DIV;
699 } else if (strcmp(token, "%") == 0) {
700 *etype = FILTER_EXP_MOD;
701 } else if (strcmp(token, ">>") == 0) {
702 *etype = FILTER_EXP_RSHIFT;
703 } else if (strcmp(token, "<<") == 0) {
704 *etype = FILTER_EXP_LSHIFT;
705 } else if (strcmp(token, "&") == 0) {
706 *etype = FILTER_EXP_AND;
707 } else if (strcmp(token, "|") == 0) {
708 *etype = FILTER_EXP_OR;
709 } else if (strcmp(token, "^") == 0) {
710 *etype = FILTER_EXP_XOR;
711 } else if (strcmp(token, "~") == 0)
712 *etype = FILTER_EXP_NOT;
714 if (*etype != FILTER_EXP_NONE)
717 /* Check for compares */
718 if (strcmp(token, "==") == 0)
719 *ctype = FILTER_CMP_EQ;
720 else if (strcmp(token, "!=") == 0)
721 *ctype = FILTER_CMP_NE;
722 else if (strcmp(token, "<") == 0)
723 *ctype = FILTER_CMP_LT;
724 else if (strcmp(token, ">") == 0)
725 *ctype = FILTER_CMP_GT;
726 else if (strcmp(token, "<=") == 0)
727 *ctype = FILTER_CMP_LE;
728 else if (strcmp(token, ">=") == 0)
729 *ctype = FILTER_CMP_GE;
730 else if (strcmp(token, "=~") == 0)
731 *ctype = FILTER_CMP_REGEX;
732 else if (strcmp(token, "!~") == 0)
733 *ctype = FILTER_CMP_NOT_REGEX;
740 static int check_op_done(struct filter_arg *arg)
744 return arg->exp.right != NULL;
747 return arg->op.right != NULL;
750 return arg->num.right != NULL;
753 /* A string conversion is always done */
756 case FILTER_ARG_BOOLEAN:
757 /* field not found, is ok */
771 static enum pevent_errno
772 reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
773 struct filter_arg *arg, char *error_str)
775 struct filter_arg *other_child;
776 struct filter_arg **ptr;
778 if (parent->type != FILTER_ARG_OP &&
779 arg->type != FILTER_ARG_OP) {
780 show_error(error_str, "can not reparent other than OP");
781 return PEVENT_ERRNO__REPARENT_NOT_OP;
784 /* Get the sibling */
785 if (old_child->op.right == arg) {
786 ptr = &old_child->op.right;
787 other_child = old_child->op.left;
788 } else if (old_child->op.left == arg) {
789 ptr = &old_child->op.left;
790 other_child = old_child->op.right;
792 show_error(error_str, "Error in reparent op, find other child");
793 return PEVENT_ERRNO__REPARENT_FAILED;
796 /* Detach arg from old_child */
800 if (parent == old_child) {
801 free_arg(other_child);
803 /* Free arg without recussion */
808 if (parent->op.right == old_child)
809 ptr = &parent->op.right;
810 else if (parent->op.left == old_child)
811 ptr = &parent->op.left;
813 show_error(error_str, "Error in reparent op");
814 return PEVENT_ERRNO__REPARENT_FAILED;
823 /* Returns either filter_vals (success) or pevent_errno (failfure) */
824 static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
832 case FILTER_ARG_BOOLEAN:
833 return FILTER_VAL_FALSE + arg->boolean.value;
837 case FILTER_ARG_VALUE:
838 case FILTER_ARG_FIELD:
839 return FILTER_VAL_NORM;
842 lval = test_arg(arg, arg->exp.left, error_str);
843 if (lval != FILTER_VAL_NORM)
845 rval = test_arg(arg, arg->exp.right, error_str);
846 if (rval != FILTER_VAL_NORM)
848 return FILTER_VAL_NORM;
851 lval = test_arg(arg, arg->num.left, error_str);
852 if (lval != FILTER_VAL_NORM)
854 rval = test_arg(arg, arg->num.right, error_str);
855 if (rval != FILTER_VAL_NORM)
857 return FILTER_VAL_NORM;
860 if (arg->op.type != FILTER_OP_NOT) {
861 lval = test_arg(arg, arg->op.left, error_str);
863 case FILTER_VAL_NORM:
865 case FILTER_VAL_TRUE:
866 if (arg->op.type == FILTER_OP_OR)
867 return FILTER_VAL_TRUE;
868 rval = test_arg(arg, arg->op.right, error_str);
869 if (rval != FILTER_VAL_NORM)
872 return reparent_op_arg(parent, arg, arg->op.right,
875 case FILTER_VAL_FALSE:
876 if (arg->op.type == FILTER_OP_AND)
877 return FILTER_VAL_FALSE;
878 rval = test_arg(arg, arg->op.right, error_str);
879 if (rval != FILTER_VAL_NORM)
882 return reparent_op_arg(parent, arg, arg->op.right,
890 rval = test_arg(arg, arg->op.right, error_str);
892 case FILTER_VAL_NORM:
896 case FILTER_VAL_TRUE:
897 if (arg->op.type == FILTER_OP_OR)
898 return FILTER_VAL_TRUE;
899 if (arg->op.type == FILTER_OP_NOT)
900 return FILTER_VAL_FALSE;
902 return reparent_op_arg(parent, arg, arg->op.left,
905 case FILTER_VAL_FALSE:
906 if (arg->op.type == FILTER_OP_AND)
907 return FILTER_VAL_FALSE;
908 if (arg->op.type == FILTER_OP_NOT)
909 return FILTER_VAL_TRUE;
911 return reparent_op_arg(parent, arg, arg->op.left,
917 show_error(error_str, "bad arg in filter tree");
918 return PEVENT_ERRNO__BAD_FILTER_ARG;
920 return FILTER_VAL_NORM;
923 /* Remove any unknown event fields */
924 static int collapse_tree(struct filter_arg *arg,
925 struct filter_arg **arg_collapsed, char *error_str)
929 ret = test_arg(arg, arg, error_str);
931 case FILTER_VAL_NORM:
934 case FILTER_VAL_TRUE:
935 case FILTER_VAL_FALSE:
937 arg = allocate_arg();
939 arg->type = FILTER_ARG_BOOLEAN;
940 arg->boolean.value = ret == FILTER_VAL_TRUE;
942 show_error(error_str, "Failed to allocate filter arg");
943 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
948 /* test_arg() already set the error_str */
954 *arg_collapsed = arg;
958 static enum pevent_errno
959 process_filter(struct event_format *event, struct filter_arg **parg,
960 char *error_str, int not)
962 enum event_type type;
964 struct filter_arg *current_op = NULL;
965 struct filter_arg *current_exp = NULL;
966 struct filter_arg *left_item = NULL;
967 struct filter_arg *arg = NULL;
968 enum op_type op_type;
969 enum filter_op_type btype;
970 enum filter_exp_type etype;
971 enum filter_cmp_type ctype;
972 enum pevent_errno ret;
978 type = read_token(&token);
983 ret = create_arg_item(event, token, type, &arg, error_str);
988 else if (current_exp) {
989 ret = add_right(current_exp, arg, error_str);
993 /* Not's only one one expression */
1008 if (*token == ',') {
1009 show_error(error_str, "Illegal token ','");
1010 ret = PEVENT_ERRNO__ILLEGAL_TOKEN;
1014 if (*token == '(') {
1016 show_error(error_str,
1017 "Open paren can not come after item");
1018 ret = PEVENT_ERRNO__INVALID_PAREN;
1022 show_error(error_str,
1023 "Open paren can not come after expression");
1024 ret = PEVENT_ERRNO__INVALID_PAREN;
1028 ret = process_filter(event, &arg, error_str, 0);
1029 if (ret != PEVENT_ERRNO__UNBALANCED_PAREN) {
1031 show_error(error_str,
1032 "Unbalanced number of '('");
1033 ret = PEVENT_ERRNO__UNBALANCED_PAREN;
1039 /* A not wants just one expression */
1048 ret = add_right(current_op, arg, error_str);
1056 if (!current_op && !current_exp)
1059 /* Make sure everything is finished at this level */
1060 if (current_exp && !check_op_done(current_exp))
1062 if (current_op && !check_op_done(current_op))
1068 *parg = current_exp;
1070 return PEVENT_ERRNO__UNBALANCED_PAREN;
1075 op_type = process_op(token, &btype, &ctype, &etype);
1077 /* All expect a left arg except for NOT */
1080 /* Logic ops need a left expression */
1081 if (!current_exp && !current_op)
1085 /* logic only processes ops and exp */
1095 show_error(error_str,
1096 "Unknown op token %s", token);
1097 ret = PEVENT_ERRNO__UNKNOWN_TOKEN;
1104 arg = create_arg_op(btype);
1108 ret = add_left(arg, current_op);
1110 ret = add_left(arg, current_exp);
1116 arg = create_arg_op(btype);
1120 ret = add_right(current_op, arg, error_str);
1124 ret = process_filter(event, &arg, error_str, 1);
1127 ret = add_right(current_exp, arg, error_str);
1134 if (op_type == OP_EXP)
1135 arg = create_arg_exp(etype);
1137 arg = create_arg_cmp(ctype);
1142 ret = add_right(current_op, arg, error_str);
1145 ret = add_left(arg, left_item);
1166 } while (type != EVENT_NONE);
1168 if (!current_op && !current_exp)
1172 current_op = current_exp;
1174 ret = collapse_tree(current_op, parg, error_str);
1175 /* collapse_tree() may free current_op, and updates parg accordingly */
1184 show_error(error_str, "failed to allocate filter arg");
1185 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
1188 show_error(error_str, "Syntax error");
1189 ret = PEVENT_ERRNO__SYNTAX_ERROR;
1191 free_arg(current_op);
1192 free_arg(current_exp);
1198 static enum pevent_errno
1199 process_event(struct event_format *event, const char *filter_str,
1200 struct filter_arg **parg, char *error_str)
1204 pevent_buffer_init(filter_str, strlen(filter_str));
1206 ret = process_filter(event, parg, error_str, 0);
1210 /* If parg is NULL, then make it into FALSE */
1212 *parg = allocate_arg();
1214 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1216 (*parg)->type = FILTER_ARG_BOOLEAN;
1217 (*parg)->boolean.value = FILTER_FALSE;
1223 static enum pevent_errno
1224 filter_event(struct event_filter *filter, struct event_format *event,
1225 const char *filter_str, char *error_str)
1227 struct filter_type *filter_type;
1228 struct filter_arg *arg;
1229 enum pevent_errno ret;
1232 ret = process_event(event, filter_str, &arg, error_str);
1237 /* just add a TRUE arg */
1238 arg = allocate_arg();
1240 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1242 arg->type = FILTER_ARG_BOOLEAN;
1243 arg->boolean.value = FILTER_TRUE;
1246 filter_type = add_filter_type(filter, event->id);
1247 if (filter_type == NULL)
1248 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1250 if (filter_type->filter)
1251 free_arg(filter_type->filter);
1252 filter_type->filter = arg;
1257 static void filter_init_error_buf(struct event_filter *filter)
1259 /* clear buffer to reset show error */
1260 pevent_buffer_init("", 0);
1261 filter->error_buffer[0] = '\0';
1265 * pevent_filter_add_filter_str - add a new filter
1266 * @filter: the event filter to add to
1267 * @filter_str: the filter string that contains the filter
1269 * Returns 0 if the filter was successfully added or a
1270 * negative error code. Use pevent_filter_strerror() to see
1271 * actual error message in case of error.
1273 enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
1274 const char *filter_str)
1276 struct pevent *pevent = filter->pevent;
1277 struct event_list *event;
1278 struct event_list *events = NULL;
1279 const char *filter_start;
1280 const char *next_event;
1282 char *event_name = NULL;
1283 char *sys_name = NULL;
1285 enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */
1289 filter_init_error_buf(filter);
1291 filter_start = strchr(filter_str, ':');
1293 len = filter_start - filter_str;
1295 len = strlen(filter_str);
1298 next_event = strchr(filter_str, ',');
1300 (!filter_start || next_event < filter_start))
1301 len = next_event - filter_str;
1302 else if (filter_start)
1303 len = filter_start - filter_str;
1305 len = strlen(filter_str);
1307 this_event = malloc(len + 1);
1308 if (this_event == NULL) {
1309 /* This can only happen when events is NULL, but still */
1310 free_events(events);
1311 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1313 memcpy(this_event, filter_str, len);
1314 this_event[len] = 0;
1319 filter_str = next_event;
1321 sys_name = strtok_r(this_event, "/", &sp);
1322 event_name = strtok_r(NULL, "/", &sp);
1325 /* This can only happen when events is NULL, but still */
1326 free_events(events);
1328 return PEVENT_ERRNO__FILTER_NOT_FOUND;
1331 /* Find this event */
1332 ret = find_event(pevent, &events, strim(sys_name), strim(event_name));
1334 free_events(events);
1339 } while (filter_str);
1345 /* filter starts here */
1346 for (event = events; event; event = event->next) {
1347 ret = filter_event(filter, event->event, filter_start,
1348 filter->error_buffer);
1349 /* Failures are returned if a parse error happened */
1353 if (ret >= 0 && pevent->test_filters) {
1355 test = pevent_filter_make_string(filter, event->event->id);
1357 printf(" '%s: %s'\n", event->event->name, test);
1363 free_events(events);
1365 if (rtn >= 0 && pevent->test_filters)
1371 static void free_filter_type(struct filter_type *filter_type)
1373 free_arg(filter_type->filter);
1377 * pevent_filter_strerror - fill error message in a buffer
1378 * @filter: the event filter contains error
1379 * @err: the error code
1380 * @buf: the buffer to be filled in
1381 * @buflen: the size of the buffer
1383 * Returns 0 if message was filled successfully, -1 if error
1385 int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err,
1386 char *buf, size_t buflen)
1388 if (err <= __PEVENT_ERRNO__START || err >= __PEVENT_ERRNO__END)
1391 if (strlen(filter->error_buffer) > 0) {
1392 size_t len = snprintf(buf, buflen, "%s", filter->error_buffer);
1399 return pevent_strerror(filter->pevent, err, buf, buflen);
1403 * pevent_filter_remove_event - remove a filter for an event
1404 * @filter: the event filter to remove from
1405 * @event_id: the event to remove a filter for
1407 * Removes the filter saved for an event defined by @event_id
1410 * Returns 1: if an event was removed
1411 * 0: if the event was not found
1413 int pevent_filter_remove_event(struct event_filter *filter,
1416 struct filter_type *filter_type;
1419 if (!filter->filters)
1422 filter_type = find_filter_type(filter, event_id);
1427 free_filter_type(filter_type);
1429 /* The filter_type points into the event_filters array */
1430 len = (unsigned long)(filter->event_filters + filter->filters) -
1431 (unsigned long)(filter_type + 1);
1433 memmove(filter_type, filter_type + 1, len);
1436 memset(&filter->event_filters[filter->filters], 0,
1437 sizeof(*filter_type));
1443 * pevent_filter_reset - clear all filters in a filter
1444 * @filter: the event filter to reset
1446 * Removes all filters from a filter and resets it.
1448 void pevent_filter_reset(struct event_filter *filter)
1452 for (i = 0; i < filter->filters; i++)
1453 free_filter_type(&filter->event_filters[i]);
1455 free(filter->event_filters);
1456 filter->filters = 0;
1457 filter->event_filters = NULL;
1460 void pevent_filter_free(struct event_filter *filter)
1462 pevent_unref(filter->pevent);
1464 pevent_filter_reset(filter);
1469 static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg);
1471 static int copy_filter_type(struct event_filter *filter,
1472 struct event_filter *source,
1473 struct filter_type *filter_type)
1475 struct filter_arg *arg;
1476 struct event_format *event;
1481 /* Can't assume that the pevent's are the same */
1482 sys = filter_type->event->system;
1483 name = filter_type->event->name;
1484 event = pevent_find_event_by_name(filter->pevent, sys, name);
1488 str = arg_to_str(source, filter_type->filter);
1492 if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
1493 /* Add trivial event */
1494 arg = allocate_arg();
1500 arg->type = FILTER_ARG_BOOLEAN;
1501 if (strcmp(str, "TRUE") == 0)
1502 arg->boolean.value = 1;
1504 arg->boolean.value = 0;
1506 filter_type = add_filter_type(filter, event->id);
1507 if (filter_type == NULL) {
1513 filter_type->filter = arg;
1519 filter_event(filter, event, str, NULL);
1526 * pevent_filter_copy - copy a filter using another filter
1527 * @dest - the filter to copy to
1528 * @source - the filter to copy from
1530 * Returns 0 on success and -1 if not all filters were copied
1532 int pevent_filter_copy(struct event_filter *dest, struct event_filter *source)
1537 pevent_filter_reset(dest);
1539 for (i = 0; i < source->filters; i++) {
1540 if (copy_filter_type(dest, source, &source->event_filters[i]))
1548 * pevent_update_trivial - update the trivial filters with the given filter
1549 * @dest - the filter to update
1550 * @source - the filter as the source of the update
1551 * @type - the type of trivial filter to update.
1553 * Scan dest for trivial events matching @type to replace with the source.
1555 * Returns 0 on success and -1 if there was a problem updating, but
1556 * events may have still been updated on error.
1558 int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
1559 enum filter_trivial_type type)
1561 struct pevent *src_pevent;
1562 struct pevent *dest_pevent;
1563 struct event_format *event;
1564 struct filter_type *filter_type;
1565 struct filter_arg *arg;
1569 src_pevent = source->pevent;
1570 dest_pevent = dest->pevent;
1572 /* Do nothing if either of the filters has nothing to filter */
1573 if (!dest->filters || !source->filters)
1576 for (i = 0; i < dest->filters; i++) {
1577 filter_type = &dest->event_filters[i];
1578 arg = filter_type->filter;
1579 if (arg->type != FILTER_ARG_BOOLEAN)
1581 if ((arg->boolean.value && type == FILTER_TRIVIAL_FALSE) ||
1582 (!arg->boolean.value && type == FILTER_TRIVIAL_TRUE))
1585 event = filter_type->event;
1587 if (src_pevent != dest_pevent) {
1589 event = pevent_find_event_by_name(src_pevent,
1596 str = pevent_filter_make_string(source, event->id);
1600 /* Don't bother if the filter is trivial too */
1601 if (strcmp(str, "TRUE") != 0 && strcmp(str, "FALSE") != 0)
1602 filter_event(dest, event, str, NULL);
1609 * pevent_filter_clear_trivial - clear TRUE and FALSE filters
1610 * @filter: the filter to remove trivial filters from
1611 * @type: remove only true, false, or both
1613 * Removes filters that only contain a TRUE or FALES boolean arg.
1615 * Returns 0 on success and -1 if there was a problem.
1617 int pevent_filter_clear_trivial(struct event_filter *filter,
1618 enum filter_trivial_type type)
1620 struct filter_type *filter_type;
1625 if (!filter->filters)
1629 * Two steps, first get all ids with trivial filters.
1630 * then remove those ids.
1632 for (i = 0; i < filter->filters; i++) {
1635 filter_type = &filter->event_filters[i];
1636 if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1639 case FILTER_TRIVIAL_FALSE:
1640 if (filter_type->filter->boolean.value)
1642 case FILTER_TRIVIAL_TRUE:
1643 if (!filter_type->filter->boolean.value)
1649 new_ids = realloc(ids, sizeof(*ids) * (count + 1));
1656 ids[count++] = filter_type->event_id;
1662 for (i = 0; i < count; i++)
1663 pevent_filter_remove_event(filter, ids[i]);
1670 * pevent_filter_event_has_trivial - return true event contains trivial filter
1671 * @filter: the filter with the information
1672 * @event_id: the id of the event to test
1673 * @type: trivial type to test for (TRUE, FALSE, EITHER)
1675 * Returns 1 if the event contains a matching trivial type
1678 int pevent_filter_event_has_trivial(struct event_filter *filter,
1680 enum filter_trivial_type type)
1682 struct filter_type *filter_type;
1684 if (!filter->filters)
1687 filter_type = find_filter_type(filter, event_id);
1692 if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1696 case FILTER_TRIVIAL_FALSE:
1697 return !filter_type->filter->boolean.value;
1699 case FILTER_TRIVIAL_TRUE:
1700 return filter_type->filter->boolean.value;
1706 static int test_filter(struct event_format *event, struct filter_arg *arg,
1707 struct pevent_record *record, enum pevent_errno *err);
1710 get_comm(struct event_format *event, struct pevent_record *record)
1715 pid = pevent_data_pid(event->pevent, record);
1716 comm = pevent_data_comm_from_pid(event->pevent, pid);
1720 static unsigned long long
1721 get_value(struct event_format *event,
1722 struct format_field *field, struct pevent_record *record)
1724 unsigned long long val;
1726 /* Handle our dummy "comm" field */
1727 if (field == &comm) {
1730 name = get_comm(event, record);
1731 return (unsigned long)name;
1734 /* Handle our dummy "cpu" field */
1738 pevent_read_number_field(field, record->data, &val);
1740 if (!(field->flags & FIELD_IS_SIGNED))
1743 switch (field->size) {
1751 return (long long)val;
1756 static unsigned long long
1757 get_arg_value(struct event_format *event, struct filter_arg *arg,
1758 struct pevent_record *record, enum pevent_errno *err);
1760 static unsigned long long
1761 get_exp_value(struct event_format *event, struct filter_arg *arg,
1762 struct pevent_record *record, enum pevent_errno *err)
1764 unsigned long long lval, rval;
1766 lval = get_arg_value(event, arg->exp.left, record, err);
1767 rval = get_arg_value(event, arg->exp.right, record, err);
1771 * There was an error, no need to process anymore.
1776 switch (arg->exp.type) {
1777 case FILTER_EXP_ADD:
1780 case FILTER_EXP_SUB:
1783 case FILTER_EXP_MUL:
1786 case FILTER_EXP_DIV:
1789 case FILTER_EXP_MOD:
1792 case FILTER_EXP_RSHIFT:
1793 return lval >> rval;
1795 case FILTER_EXP_LSHIFT:
1796 return lval << rval;
1798 case FILTER_EXP_AND:
1804 case FILTER_EXP_XOR:
1807 case FILTER_EXP_NOT:
1810 *err = PEVENT_ERRNO__INVALID_EXP_TYPE;
1815 static unsigned long long
1816 get_arg_value(struct event_format *event, struct filter_arg *arg,
1817 struct pevent_record *record, enum pevent_errno *err)
1819 switch (arg->type) {
1820 case FILTER_ARG_FIELD:
1821 return get_value(event, arg->field.field, record);
1823 case FILTER_ARG_VALUE:
1824 if (arg->value.type != FILTER_NUMBER) {
1826 *err = PEVENT_ERRNO__NOT_A_NUMBER;
1828 return arg->value.val;
1830 case FILTER_ARG_EXP:
1831 return get_exp_value(event, arg, record, err);
1835 *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
1840 static int test_num(struct event_format *event, struct filter_arg *arg,
1841 struct pevent_record *record, enum pevent_errno *err)
1843 unsigned long long lval, rval;
1845 lval = get_arg_value(event, arg->num.left, record, err);
1846 rval = get_arg_value(event, arg->num.right, record, err);
1850 * There was an error, no need to process anymore.
1855 switch (arg->num.type) {
1857 return lval == rval;
1860 return lval != rval;
1869 return lval >= rval;
1872 return lval <= rval;
1876 *err = PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
1881 static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
1883 struct event_format *event;
1884 struct pevent *pevent;
1885 unsigned long long addr;
1886 const char *val = NULL;
1890 /* If the field is not a string convert it */
1891 if (arg->str.field->flags & FIELD_IS_STRING) {
1892 val = record->data + arg->str.field->offset;
1893 size = arg->str.field->size;
1895 if (arg->str.field->flags & FIELD_IS_DYNAMIC) {
1896 addr = *(unsigned int *)val;
1897 val = record->data + (addr & 0xffff);
1902 * We need to copy the data since we can't be sure the field
1903 * is null terminated.
1905 if (*(val + size - 1)) {
1907 memcpy(arg->str.buffer, val, arg->str.field->size);
1908 /* the buffer is already NULL terminated */
1909 val = arg->str.buffer;
1913 event = arg->str.field->event;
1914 pevent = event->pevent;
1915 addr = get_value(event, arg->str.field, record);
1917 if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
1918 /* convert to a kernel symbol */
1919 val = pevent_find_function(pevent, addr);
1922 /* just use the hex of the string name */
1923 snprintf(hex, 64, "0x%llx", addr);
1931 static int test_str(struct event_format *event, struct filter_arg *arg,
1932 struct pevent_record *record, enum pevent_errno *err)
1936 if (arg->str.field == &comm)
1937 val = get_comm(event, record);
1939 val = get_field_str(arg, record);
1941 switch (arg->str.type) {
1942 case FILTER_CMP_MATCH:
1943 return strcmp(val, arg->str.val) == 0;
1945 case FILTER_CMP_NOT_MATCH:
1946 return strcmp(val, arg->str.val) != 0;
1948 case FILTER_CMP_REGEX:
1949 /* Returns zero on match */
1950 return !regexec(&arg->str.reg, val, 0, NULL, 0);
1952 case FILTER_CMP_NOT_REGEX:
1953 return regexec(&arg->str.reg, val, 0, NULL, 0);
1957 *err = PEVENT_ERRNO__ILLEGAL_STRING_CMP;
1962 static int test_op(struct event_format *event, struct filter_arg *arg,
1963 struct pevent_record *record, enum pevent_errno *err)
1965 switch (arg->op.type) {
1967 return test_filter(event, arg->op.left, record, err) &&
1968 test_filter(event, arg->op.right, record, err);
1971 return test_filter(event, arg->op.left, record, err) ||
1972 test_filter(event, arg->op.right, record, err);
1975 return !test_filter(event, arg->op.right, record, err);
1979 *err = PEVENT_ERRNO__INVALID_OP_TYPE;
1984 static int test_filter(struct event_format *event, struct filter_arg *arg,
1985 struct pevent_record *record, enum pevent_errno *err)
1989 * There was an error, no need to process anymore.
1994 switch (arg->type) {
1995 case FILTER_ARG_BOOLEAN:
1997 return arg->boolean.value;
2000 return test_op(event, arg, record, err);
2002 case FILTER_ARG_NUM:
2003 return test_num(event, arg, record, err);
2005 case FILTER_ARG_STR:
2006 return test_str(event, arg, record, err);
2008 case FILTER_ARG_EXP:
2009 case FILTER_ARG_VALUE:
2010 case FILTER_ARG_FIELD:
2012 * Expressions, fields and values evaluate
2013 * to true if they return non zero
2015 return !!get_arg_value(event, arg, record, err);
2019 *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
2025 * pevent_event_filtered - return true if event has filter
2026 * @filter: filter struct with filter information
2027 * @event_id: event id to test if filter exists
2029 * Returns 1 if filter found for @event_id
2032 int pevent_event_filtered(struct event_filter *filter, int event_id)
2034 struct filter_type *filter_type;
2036 if (!filter->filters)
2039 filter_type = find_filter_type(filter, event_id);
2041 return filter_type ? 1 : 0;
2045 * pevent_filter_match - test if a record matches a filter
2046 * @filter: filter struct with filter information
2047 * @record: the record to test against the filter
2049 * Returns: match result or error code (prefixed with PEVENT_ERRNO__)
2050 * FILTER_MATCH - filter found for event and @record matches
2051 * FILTER_MISS - filter found for event and @record does not match
2052 * FILTER_NOT_FOUND - no filter found for @record's event
2053 * NO_FILTER - if no filters exist
2054 * otherwise - error occurred during test
2056 enum pevent_errno pevent_filter_match(struct event_filter *filter,
2057 struct pevent_record *record)
2059 struct pevent *pevent = filter->pevent;
2060 struct filter_type *filter_type;
2063 enum pevent_errno err = 0;
2065 filter_init_error_buf(filter);
2067 if (!filter->filters)
2068 return PEVENT_ERRNO__NO_FILTER;
2070 event_id = pevent_data_type(pevent, record);
2072 filter_type = find_filter_type(filter, event_id);
2074 return PEVENT_ERRNO__FILTER_NOT_FOUND;
2076 ret = test_filter(filter_type->event, filter_type->filter, record, &err);
2080 return ret ? PEVENT_ERRNO__FILTER_MATCH : PEVENT_ERRNO__FILTER_MISS;
2083 static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
2093 switch (arg->op.type) {
2101 left = arg_to_str(filter, arg->op.left);
2102 right = arg_to_str(filter, arg->op.right);
2103 if (!left || !right)
2106 /* Try to consolidate boolean values */
2107 if (strcmp(left, "TRUE") == 0)
2109 else if (strcmp(left, "FALSE") == 0)
2112 if (strcmp(right, "TRUE") == 0)
2114 else if (strcmp(right, "FALSE") == 0)
2117 if (left_val >= 0) {
2118 if ((arg->op.type == FILTER_OP_AND && !left_val) ||
2119 (arg->op.type == FILTER_OP_OR && left_val)) {
2120 /* Just return left value */
2125 if (right_val >= 0) {
2126 /* just evaluate this. */
2128 switch (arg->op.type) {
2130 val = left_val && right_val;
2133 val = left_val || right_val;
2138 asprintf(&str, val ? "TRUE" : "FALSE");
2142 if (right_val >= 0) {
2143 if ((arg->op.type == FILTER_OP_AND && !right_val) ||
2144 (arg->op.type == FILTER_OP_OR && right_val)) {
2145 /* Just return right value */
2150 /* The right value is meaningless */
2156 asprintf(&str, "(%s) %s (%s)", left, op, right);
2161 right = arg_to_str(filter, arg->op.right);
2165 /* See if we can consolidate */
2166 if (strcmp(right, "TRUE") == 0)
2168 else if (strcmp(right, "FALSE") == 0)
2170 if (right_val >= 0) {
2171 /* just return the opposite */
2172 asprintf(&str, right_val ? "FALSE" : "TRUE");
2175 asprintf(&str, "%s(%s)", op, right);
2187 static char *val_to_str(struct event_filter *filter, struct filter_arg *arg)
2191 asprintf(&str, "%lld", arg->value.val);
2196 static char *field_to_str(struct event_filter *filter, struct filter_arg *arg)
2198 return strdup(arg->field.field->name);
2201 static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
2208 lstr = arg_to_str(filter, arg->exp.left);
2209 rstr = arg_to_str(filter, arg->exp.right);
2213 switch (arg->exp.type) {
2214 case FILTER_EXP_ADD:
2217 case FILTER_EXP_SUB:
2220 case FILTER_EXP_MUL:
2223 case FILTER_EXP_DIV:
2226 case FILTER_EXP_MOD:
2229 case FILTER_EXP_RSHIFT:
2232 case FILTER_EXP_LSHIFT:
2235 case FILTER_EXP_AND:
2241 case FILTER_EXP_XOR:
2245 op = "[ERROR IN EXPRESSION TYPE]";
2249 asprintf(&str, "%s %s %s", lstr, op, rstr);
2257 static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
2264 lstr = arg_to_str(filter, arg->num.left);
2265 rstr = arg_to_str(filter, arg->num.right);
2269 switch (arg->num.type) {
2293 asprintf(&str, "%s %s %s", lstr, op, rstr);
2307 static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
2312 switch (arg->str.type) {
2313 case FILTER_CMP_MATCH:
2316 case FILTER_CMP_NOT_MATCH:
2320 case FILTER_CMP_REGEX:
2324 case FILTER_CMP_NOT_REGEX:
2328 asprintf(&str, "%s %s \"%s\"",
2329 arg->str.field->name, op, arg->str.val);
2339 static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
2343 switch (arg->type) {
2344 case FILTER_ARG_BOOLEAN:
2345 asprintf(&str, arg->boolean.value ? "TRUE" : "FALSE");
2349 return op_to_str(filter, arg);
2351 case FILTER_ARG_NUM:
2352 return num_to_str(filter, arg);
2354 case FILTER_ARG_STR:
2355 return str_to_str(filter, arg);
2357 case FILTER_ARG_VALUE:
2358 return val_to_str(filter, arg);
2360 case FILTER_ARG_FIELD:
2361 return field_to_str(filter, arg);
2363 case FILTER_ARG_EXP:
2364 return exp_to_str(filter, arg);
2374 * pevent_filter_make_string - return a string showing the filter
2375 * @filter: filter struct with filter information
2376 * @event_id: the event id to return the filter string with
2378 * Returns a string that displays the filter contents.
2379 * This string must be freed with free(str).
2380 * NULL is returned if no filter is found or allocation failed.
2383 pevent_filter_make_string(struct event_filter *filter, int event_id)
2385 struct filter_type *filter_type;
2387 if (!filter->filters)
2390 filter_type = find_filter_type(filter, event_id);
2395 return arg_to_str(filter, filter_type->filter);
2399 * pevent_filter_compare - compare two filters and return if they are the same
2400 * @filter1: Filter to compare with @filter2
2401 * @filter2: Filter to compare with @filter1
2404 * 1 if the two filters hold the same content.
2407 int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2)
2409 struct filter_type *filter_type1;
2410 struct filter_type *filter_type2;
2415 /* Do the easy checks first */
2416 if (filter1->filters != filter2->filters)
2418 if (!filter1->filters && !filter2->filters)
2422 * Now take a look at each of the events to see if they have the same
2425 for (i = 0; i < filter1->filters; i++) {
2426 filter_type1 = &filter1->event_filters[i];
2427 filter_type2 = find_filter_type(filter2, filter_type1->event_id);
2430 if (filter_type1->filter->type != filter_type2->filter->type)
2432 switch (filter_type1->filter->type) {
2433 case FILTER_TRIVIAL_FALSE:
2434 case FILTER_TRIVIAL_TRUE:
2435 /* trivial types just need the type compared */
2440 /* The best way to compare complex filters is with strings */
2441 str1 = arg_to_str(filter1, filter_type1->filter);
2442 str2 = arg_to_str(filter2, filter_type2->filter);
2444 result = strcmp(str1, str2) != 0;
2446 /* bail out if allocation fails */
2455 if (i < filter1->filters)