tools lib traceevent: Get rid of die() in reparent_op_arg()
[linux-2.6-block.git] / tools / lib / traceevent / parse-filter.c
CommitLineData
f7d82350
SR
1/*
2 * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
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!)
9 *
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.
14 *
15 * You should have received a copy of the GNU Lesser General Public
7b9f6b40 16 * License along with this program; if not, see <http://www.gnu.org/licenses>
f7d82350
SR
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <stdarg.h>
24#include <errno.h>
25#include <sys/types.h>
26
27#include "event-parse.h"
28#include "event-utils.h"
29
30#define COMM "COMM"
31
32static struct format_field comm = {
33 .name = "COMM",
34};
35
36struct event_list {
37 struct event_list *next;
38 struct event_format *event;
39};
40
41#define MAX_ERR_STR_SIZE 256
42
43static void show_error(char **error_str, const char *fmt, ...)
44{
45 unsigned long long index;
46 const char *input;
47 char *error;
48 va_list ap;
49 int len;
50 int i;
51
52 if (!error_str)
53 return;
54
55 input = pevent_get_input_buf();
56 index = pevent_get_input_buf_ptr();
57 len = input ? strlen(input) : 0;
58
9451a2fd
NK
59 error = malloc(MAX_ERR_STR_SIZE + (len*2) + 3);
60 if (error == NULL) {
61 /*
62 * Maybe it's due to len is too long.
63 * Retry without the input buffer part.
64 */
65 len = 0;
66
67 error = malloc(MAX_ERR_STR_SIZE);
68 if (error == NULL) {
69 /* no memory */
70 *error_str = NULL;
71 return;
72 }
73 }
f7d82350
SR
74
75 if (len) {
76 strcpy(error, input);
77 error[len] = '\n';
78 for (i = 1; i < len && i < index; i++)
79 error[len+i] = ' ';
80 error[len + i] = '^';
81 error[len + i + 1] = '\n';
82 len += i+2;
83 }
84
85 va_start(ap, fmt);
86 vsnprintf(error + len, MAX_ERR_STR_SIZE, fmt, ap);
87 va_end(ap);
88
89 *error_str = error;
90}
91
92static void free_token(char *token)
93{
94 pevent_free_token(token);
95}
96
97static enum event_type read_token(char **tok)
98{
99 enum event_type type;
100 char *token = NULL;
101
102 do {
103 free_token(token);
104 type = pevent_read_token(&token);
105 } while (type == EVENT_NEWLINE || type == EVENT_SPACE);
106
107 /* If token is = or ! check to see if the next char is ~ */
108 if (token &&
109 (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
110 pevent_peek_char() == '~') {
111 /* append it */
91dfa49b
NK
112 *tok = malloc(3);
113 if (*tok == NULL) {
114 free_token(token);
115 return EVENT_ERROR;
116 }
f7d82350
SR
117 sprintf(*tok, "%c%c", *token, '~');
118 free_token(token);
119 /* Now remove the '~' from the buffer */
120 pevent_read_token(&token);
121 free_token(token);
122 } else
123 *tok = token;
124
125 return type;
126}
127
128static int filter_cmp(const void *a, const void *b)
129{
130 const struct filter_type *ea = a;
131 const struct filter_type *eb = b;
132
133 if (ea->event_id < eb->event_id)
134 return -1;
135
136 if (ea->event_id > eb->event_id)
137 return 1;
138
139 return 0;
140}
141
142static struct filter_type *
143find_filter_type(struct event_filter *filter, int id)
144{
145 struct filter_type *filter_type;
146 struct filter_type key;
147
148 key.event_id = id;
149
150 filter_type = bsearch(&key, filter->event_filters,
151 filter->filters,
152 sizeof(*filter->event_filters),
153 filter_cmp);
154
155 return filter_type;
156}
157
158static struct filter_type *
159add_filter_type(struct event_filter *filter, int id)
160{
161 struct filter_type *filter_type;
162 int i;
163
164 filter_type = find_filter_type(filter, id);
165 if (filter_type)
166 return filter_type;
167
ef3072cd
NK
168 filter_type = realloc(filter->event_filters,
169 sizeof(*filter->event_filters) *
170 (filter->filters + 1));
171 if (!filter_type)
172 return NULL;
173
174 filter->event_filters = filter_type;
f7d82350
SR
175
176 for (i = 0; i < filter->filters; i++) {
177 if (filter->event_filters[i].event_id > id)
178 break;
179 }
180
181 if (i < filter->filters)
182 memmove(&filter->event_filters[i+1],
183 &filter->event_filters[i],
184 sizeof(*filter->event_filters) *
185 (filter->filters - i));
186
187 filter_type = &filter->event_filters[i];
188 filter_type->event_id = id;
189 filter_type->event = pevent_find_event(filter->pevent, id);
190 filter_type->filter = NULL;
191
192 filter->filters++;
193
194 return filter_type;
195}
196
197/**
198 * pevent_filter_alloc - create a new event filter
199 * @pevent: The pevent that this filter is associated with
200 */
201struct event_filter *pevent_filter_alloc(struct pevent *pevent)
202{
203 struct event_filter *filter;
204
4f244163
NK
205 filter = malloc(sizeof(*filter));
206 if (filter == NULL)
207 return NULL;
208
f7d82350
SR
209 memset(filter, 0, sizeof(*filter));
210 filter->pevent = pevent;
211 pevent_ref(pevent);
212
213 return filter;
214}
215
216static struct filter_arg *allocate_arg(void)
217{
2e4eb10d 218 return calloc(1, sizeof(struct filter_arg));
f7d82350
SR
219}
220
221static void free_arg(struct filter_arg *arg)
222{
223 if (!arg)
224 return;
225
226 switch (arg->type) {
227 case FILTER_ARG_NONE:
228 case FILTER_ARG_BOOLEAN:
743df75f
SR
229 break;
230
f7d82350 231 case FILTER_ARG_NUM:
743df75f
SR
232 free_arg(arg->num.left);
233 free_arg(arg->num.right);
234 break;
235
236 case FILTER_ARG_EXP:
237 free_arg(arg->exp.left);
238 free_arg(arg->exp.right);
f7d82350
SR
239 break;
240
241 case FILTER_ARG_STR:
242 free(arg->str.val);
243 regfree(&arg->str.reg);
244 free(arg->str.buffer);
245 break;
246
743df75f
SR
247 case FILTER_ARG_VALUE:
248 if (arg->value.type == FILTER_STRING ||
249 arg->value.type == FILTER_CHAR)
250 free(arg->value.str);
251 break;
252
f7d82350
SR
253 case FILTER_ARG_OP:
254 free_arg(arg->op.left);
255 free_arg(arg->op.right);
256 default:
257 break;
258 }
259
260 free(arg);
261}
262
234520d3 263static int add_event(struct event_list **events,
f7d82350
SR
264 struct event_format *event)
265{
266 struct event_list *list;
267
234520d3
NK
268 list = malloc(sizeof(*list));
269 if (list == NULL)
270 return -1;
271
f7d82350
SR
272 list->next = *events;
273 *events = list;
274 list->event = event;
234520d3 275 return 0;
f7d82350
SR
276}
277
278static int event_match(struct event_format *event,
279 regex_t *sreg, regex_t *ereg)
280{
281 if (sreg) {
282 return !regexec(sreg, event->system, 0, NULL, 0) &&
283 !regexec(ereg, event->name, 0, NULL, 0);
284 }
285
286 return !regexec(ereg, event->system, 0, NULL, 0) ||
287 !regexec(ereg, event->name, 0, NULL, 0);
288}
289
605b8fda 290static enum pevent_errno
f7d82350
SR
291find_event(struct pevent *pevent, struct event_list **events,
292 char *sys_name, char *event_name)
293{
294 struct event_format *event;
295 regex_t ereg;
296 regex_t sreg;
297 int match = 0;
234520d3 298 int fail = 0;
f7d82350
SR
299 char *reg;
300 int ret;
301 int i;
302
303 if (!event_name) {
304 /* if no name is given, then swap sys and name */
305 event_name = sys_name;
306 sys_name = NULL;
307 }
308
605b8fda
NK
309 reg = malloc(strlen(event_name) + 3);
310 if (reg == NULL)
311 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
312
f7d82350
SR
313 sprintf(reg, "^%s$", event_name);
314
315 ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
316 free(reg);
317
318 if (ret)
605b8fda 319 return PEVENT_ERRNO__INVALID_EVENT_NAME;
f7d82350
SR
320
321 if (sys_name) {
605b8fda
NK
322 reg = malloc(strlen(sys_name) + 3);
323 if (reg == NULL) {
324 regfree(&ereg);
325 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
326 }
327
f7d82350
SR
328 sprintf(reg, "^%s$", sys_name);
329 ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
330 free(reg);
331 if (ret) {
332 regfree(&ereg);
605b8fda 333 return PEVENT_ERRNO__INVALID_EVENT_NAME;
f7d82350
SR
334 }
335 }
336
337 for (i = 0; i < pevent->nr_events; i++) {
338 event = pevent->events[i];
339 if (event_match(event, sys_name ? &sreg : NULL, &ereg)) {
340 match = 1;
234520d3
NK
341 if (add_event(events, event) < 0) {
342 fail = 1;
343 break;
344 }
f7d82350
SR
345 }
346 }
347
348 regfree(&ereg);
349 if (sys_name)
350 regfree(&sreg);
351
352 if (!match)
605b8fda 353 return PEVENT_ERRNO__EVENT_NOT_FOUND;
234520d3 354 if (fail)
605b8fda 355 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
f7d82350
SR
356
357 return 0;
358}
359
360static void free_events(struct event_list *events)
361{
362 struct event_list *event;
363
364 while (events) {
365 event = events;
366 events = events->next;
367 free(event);
368 }
369}
370
371static struct filter_arg *
eaec12d7
NK
372create_arg_item(struct event_format *event, const char *token,
373 enum event_type type, char **error_str)
f7d82350
SR
374{
375 struct format_field *field;
376 struct filter_arg *arg;
377
378 arg = allocate_arg();
2e4eb10d
NK
379 if (arg == NULL) {
380 show_error(error_str, "failed to allocate filter arg");
381 return NULL;
382 }
f7d82350
SR
383
384 switch (type) {
385
386 case EVENT_SQUOTE:
387 case EVENT_DQUOTE:
388 arg->type = FILTER_ARG_VALUE;
389 arg->value.type =
390 type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR;
391 arg->value.str = strdup(token);
2036fcd1
NK
392 if (!arg->value.str) {
393 free_arg(arg);
394 show_error(error_str, "failed to allocate string filter arg");
395 return NULL;
396 }
f7d82350
SR
397 break;
398 case EVENT_ITEM:
399 /* if it is a number, then convert it */
400 if (isdigit(token[0])) {
401 arg->type = FILTER_ARG_VALUE;
402 arg->value.type = FILTER_NUMBER;
403 arg->value.val = strtoull(token, NULL, 0);
404 break;
405 }
406 /* Consider this a field */
407 field = pevent_find_any_field(event, token);
408 if (!field) {
409 if (strcmp(token, COMM) != 0) {
410 /* not a field, Make it false */
411 arg->type = FILTER_ARG_BOOLEAN;
668fe01f 412 arg->boolean.value = FILTER_FALSE;
f7d82350
SR
413 break;
414 }
415 /* If token is 'COMM' then it is special */
416 field = &comm;
417 }
418 arg->type = FILTER_ARG_FIELD;
419 arg->field.field = field;
420 break;
421 default:
422 free_arg(arg);
423 show_error(error_str, "expected a value but found %s",
424 token);
425 return NULL;
426 }
427 return arg;
428}
429
430static struct filter_arg *
431create_arg_op(enum filter_op_type btype)
432{
433 struct filter_arg *arg;
434
435 arg = allocate_arg();
2e4eb10d
NK
436 if (!arg)
437 return NULL;
438
f7d82350
SR
439 arg->type = FILTER_ARG_OP;
440 arg->op.type = btype;
441
442 return arg;
443}
444
445static struct filter_arg *
446create_arg_exp(enum filter_exp_type etype)
447{
448 struct filter_arg *arg;
449
450 arg = allocate_arg();
2e4eb10d
NK
451 if (!arg)
452 return NULL;
453
f7d82350
SR
454 arg->type = FILTER_ARG_EXP;
455 arg->op.type = etype;
456
457 return arg;
458}
459
460static struct filter_arg *
461create_arg_cmp(enum filter_exp_type etype)
462{
463 struct filter_arg *arg;
464
465 arg = allocate_arg();
2e4eb10d
NK
466 if (!arg)
467 return NULL;
468
f7d82350
SR
469 /* Use NUM and change if necessary */
470 arg->type = FILTER_ARG_NUM;
471 arg->op.type = etype;
472
473 return arg;
474}
475
02d62d6d
NK
476static enum pevent_errno
477add_right(struct filter_arg *op, struct filter_arg *arg, char **error_str)
f7d82350
SR
478{
479 struct filter_arg *left;
480 char *str;
481 int op_type;
482 int ret;
483
484 switch (op->type) {
485 case FILTER_ARG_EXP:
486 if (op->exp.right)
487 goto out_fail;
488 op->exp.right = arg;
489 break;
490
491 case FILTER_ARG_OP:
492 if (op->op.right)
493 goto out_fail;
494 op->op.right = arg;
495 break;
496
497 case FILTER_ARG_NUM:
498 if (op->op.right)
499 goto out_fail;
500 /*
501 * The arg must be num, str, or field
502 */
503 switch (arg->type) {
504 case FILTER_ARG_VALUE:
505 case FILTER_ARG_FIELD:
506 break;
507 default:
02d62d6d
NK
508 show_error(error_str, "Illegal rvalue");
509 return PEVENT_ERRNO__ILLEGAL_RVALUE;
f7d82350
SR
510 }
511
512 /*
513 * Depending on the type, we may need to
514 * convert this to a string or regex.
515 */
516 switch (arg->value.type) {
517 case FILTER_CHAR:
518 /*
519 * A char should be converted to number if
520 * the string is 1 byte, and the compare
521 * is not a REGEX.
522 */
523 if (strlen(arg->value.str) == 1 &&
524 op->num.type != FILTER_CMP_REGEX &&
525 op->num.type != FILTER_CMP_NOT_REGEX) {
526 arg->value.type = FILTER_NUMBER;
527 goto do_int;
528 }
529 /* fall through */
530 case FILTER_STRING:
531
532 /* convert op to a string arg */
533 op_type = op->num.type;
534 left = op->num.left;
535 str = arg->value.str;
536
537 /* reset the op for the new field */
538 memset(op, 0, sizeof(*op));
539
540 /*
541 * If left arg was a field not found then
542 * NULL the entire op.
543 */
544 if (left->type == FILTER_ARG_BOOLEAN) {
545 free_arg(left);
546 free_arg(arg);
547 op->type = FILTER_ARG_BOOLEAN;
668fe01f 548 op->boolean.value = FILTER_FALSE;
f7d82350
SR
549 break;
550 }
551
552 /* Left arg must be a field */
553 if (left->type != FILTER_ARG_FIELD) {
554 show_error(error_str,
555 "Illegal lvalue for string comparison");
02d62d6d 556 return PEVENT_ERRNO__ILLEGAL_LVALUE;
f7d82350
SR
557 }
558
559 /* Make sure this is a valid string compare */
560 switch (op_type) {
561 case FILTER_CMP_EQ:
562 op_type = FILTER_CMP_MATCH;
563 break;
564 case FILTER_CMP_NE:
565 op_type = FILTER_CMP_NOT_MATCH;
566 break;
567
568 case FILTER_CMP_REGEX:
569 case FILTER_CMP_NOT_REGEX:
570 ret = regcomp(&op->str.reg, str, REG_ICASE|REG_NOSUB);
571 if (ret) {
572 show_error(error_str,
573 "RegEx '%s' did not compute",
574 str);
02d62d6d 575 return PEVENT_ERRNO__INVALID_REGEX;
f7d82350
SR
576 }
577 break;
578 default:
579 show_error(error_str,
580 "Illegal comparison for string");
02d62d6d 581 return PEVENT_ERRNO__ILLEGAL_STRING_CMP;
f7d82350
SR
582 }
583
584 op->type = FILTER_ARG_STR;
585 op->str.type = op_type;
586 op->str.field = left->field.field;
587 op->str.val = strdup(str);
02d62d6d
NK
588 if (!op->str.val) {
589 show_error(error_str, "Failed to allocate string filter");
590 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
591 }
f7d82350
SR
592 /*
593 * Need a buffer to copy data for tests
594 */
02d62d6d
NK
595 op->str.buffer = malloc(op->str.field->size + 1);
596 if (!op->str.buffer) {
597 show_error(error_str, "Failed to allocate string filter");
598 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
599 }
f7d82350
SR
600 /* Null terminate this buffer */
601 op->str.buffer[op->str.field->size] = 0;
602
603 /* We no longer have left or right args */
604 free_arg(arg);
605 free_arg(left);
606
607 break;
608
609 case FILTER_NUMBER:
610
611 do_int:
612 switch (op->num.type) {
613 case FILTER_CMP_REGEX:
614 case FILTER_CMP_NOT_REGEX:
615 show_error(error_str,
616 "Op not allowed with integers");
02d62d6d 617 return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
f7d82350
SR
618
619 default:
620 break;
621 }
622
623 /* numeric compare */
624 op->num.right = arg;
625 break;
626 default:
627 goto out_fail;
628 }
629 break;
630 default:
631 goto out_fail;
632 }
633
634 return 0;
635
636 out_fail:
02d62d6d
NK
637 show_error(error_str, "Syntax error");
638 return PEVENT_ERRNO__SYNTAX_ERROR;
f7d82350
SR
639}
640
641static struct filter_arg *
642rotate_op_right(struct filter_arg *a, struct filter_arg *b)
643{
644 struct filter_arg *arg;
645
646 arg = a->op.right;
647 a->op.right = b;
648 return arg;
649}
650
ff533fc0 651static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg)
f7d82350
SR
652{
653 switch (op->type) {
654 case FILTER_ARG_EXP:
655 if (arg->type == FILTER_ARG_OP)
656 arg = rotate_op_right(arg, op);
657 op->exp.left = arg;
658 break;
659
660 case FILTER_ARG_OP:
661 op->op.left = arg;
662 break;
663 case FILTER_ARG_NUM:
664 if (arg->type == FILTER_ARG_OP)
665 arg = rotate_op_right(arg, op);
666
667 /* left arg of compares must be a field */
668 if (arg->type != FILTER_ARG_FIELD &&
669 arg->type != FILTER_ARG_BOOLEAN)
ff533fc0 670 return PEVENT_ERRNO__INVALID_ARG_TYPE;
f7d82350
SR
671 op->num.left = arg;
672 break;
673 default:
ff533fc0 674 return PEVENT_ERRNO__INVALID_ARG_TYPE;
f7d82350
SR
675 }
676 return 0;
677}
678
679enum op_type {
680 OP_NONE,
681 OP_BOOL,
682 OP_NOT,
683 OP_EXP,
684 OP_CMP,
685};
686
687static enum op_type process_op(const char *token,
688 enum filter_op_type *btype,
689 enum filter_cmp_type *ctype,
690 enum filter_exp_type *etype)
691{
692 *btype = FILTER_OP_NOT;
693 *etype = FILTER_EXP_NONE;
694 *ctype = FILTER_CMP_NONE;
695
696 if (strcmp(token, "&&") == 0)
697 *btype = FILTER_OP_AND;
698 else if (strcmp(token, "||") == 0)
699 *btype = FILTER_OP_OR;
700 else if (strcmp(token, "!") == 0)
701 return OP_NOT;
702
703 if (*btype != FILTER_OP_NOT)
704 return OP_BOOL;
705
706 /* Check for value expressions */
707 if (strcmp(token, "+") == 0) {
708 *etype = FILTER_EXP_ADD;
709 } else if (strcmp(token, "-") == 0) {
710 *etype = FILTER_EXP_SUB;
711 } else if (strcmp(token, "*") == 0) {
712 *etype = FILTER_EXP_MUL;
713 } else if (strcmp(token, "/") == 0) {
714 *etype = FILTER_EXP_DIV;
715 } else if (strcmp(token, "%") == 0) {
716 *etype = FILTER_EXP_MOD;
717 } else if (strcmp(token, ">>") == 0) {
718 *etype = FILTER_EXP_RSHIFT;
719 } else if (strcmp(token, "<<") == 0) {
720 *etype = FILTER_EXP_LSHIFT;
721 } else if (strcmp(token, "&") == 0) {
722 *etype = FILTER_EXP_AND;
723 } else if (strcmp(token, "|") == 0) {
724 *etype = FILTER_EXP_OR;
725 } else if (strcmp(token, "^") == 0) {
726 *etype = FILTER_EXP_XOR;
727 } else if (strcmp(token, "~") == 0)
728 *etype = FILTER_EXP_NOT;
729
730 if (*etype != FILTER_EXP_NONE)
731 return OP_EXP;
732
733 /* Check for compares */
734 if (strcmp(token, "==") == 0)
735 *ctype = FILTER_CMP_EQ;
736 else if (strcmp(token, "!=") == 0)
737 *ctype = FILTER_CMP_NE;
738 else if (strcmp(token, "<") == 0)
739 *ctype = FILTER_CMP_LT;
740 else if (strcmp(token, ">") == 0)
741 *ctype = FILTER_CMP_GT;
742 else if (strcmp(token, "<=") == 0)
743 *ctype = FILTER_CMP_LE;
744 else if (strcmp(token, ">=") == 0)
745 *ctype = FILTER_CMP_GE;
746 else if (strcmp(token, "=~") == 0)
747 *ctype = FILTER_CMP_REGEX;
748 else if (strcmp(token, "!~") == 0)
749 *ctype = FILTER_CMP_NOT_REGEX;
750 else
751 return OP_NONE;
752
753 return OP_CMP;
754}
755
756static int check_op_done(struct filter_arg *arg)
757{
758 switch (arg->type) {
759 case FILTER_ARG_EXP:
760 return arg->exp.right != NULL;
761
762 case FILTER_ARG_OP:
763 return arg->op.right != NULL;
764
765 case FILTER_ARG_NUM:
766 return arg->num.right != NULL;
767
768 case FILTER_ARG_STR:
769 /* A string conversion is always done */
770 return 1;
771
772 case FILTER_ARG_BOOLEAN:
773 /* field not found, is ok */
774 return 1;
775
776 default:
777 return 0;
778 }
779}
780
781enum filter_vals {
782 FILTER_VAL_NORM,
783 FILTER_VAL_FALSE,
784 FILTER_VAL_TRUE,
785};
786
7bb73553
NK
787static enum pevent_errno
788reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
789 struct filter_arg *arg, char **error_str)
f7d82350
SR
790{
791 struct filter_arg *other_child;
792 struct filter_arg **ptr;
793
794 if (parent->type != FILTER_ARG_OP &&
7bb73553
NK
795 arg->type != FILTER_ARG_OP) {
796 show_error(error_str, "can not reparent other than OP");
797 return PEVENT_ERRNO__REPARENT_NOT_OP;
798 }
f7d82350
SR
799
800 /* Get the sibling */
801 if (old_child->op.right == arg) {
802 ptr = &old_child->op.right;
803 other_child = old_child->op.left;
804 } else if (old_child->op.left == arg) {
805 ptr = &old_child->op.left;
806 other_child = old_child->op.right;
7bb73553
NK
807 } else {
808 show_error(error_str, "Error in reparent op, find other child");
809 return PEVENT_ERRNO__REPARENT_FAILED;
810 }
f7d82350
SR
811
812 /* Detach arg from old_child */
813 *ptr = NULL;
814
815 /* Check for root */
816 if (parent == old_child) {
817 free_arg(other_child);
818 *parent = *arg;
819 /* Free arg without recussion */
820 free(arg);
7bb73553 821 return 0;
f7d82350
SR
822 }
823
824 if (parent->op.right == old_child)
825 ptr = &parent->op.right;
826 else if (parent->op.left == old_child)
827 ptr = &parent->op.left;
7bb73553
NK
828 else {
829 show_error(error_str, "Error in reparent op");
830 return PEVENT_ERRNO__REPARENT_FAILED;
831 }
832
f7d82350
SR
833 *ptr = arg;
834
835 free_arg(old_child);
7bb73553 836 return 0;
f7d82350
SR
837}
838
7bb73553
NK
839/* Returns either filter_vals (success) or pevent_errno (failfure) */
840static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
841 char **error_str)
f7d82350 842{
7bb73553 843 int lval, rval;
f7d82350
SR
844
845 switch (arg->type) {
846
847 /* bad case */
848 case FILTER_ARG_BOOLEAN:
668fe01f 849 return FILTER_VAL_FALSE + arg->boolean.value;
f7d82350
SR
850
851 /* good cases: */
852 case FILTER_ARG_STR:
853 case FILTER_ARG_VALUE:
854 case FILTER_ARG_FIELD:
855 return FILTER_VAL_NORM;
856
857 case FILTER_ARG_EXP:
7bb73553 858 lval = test_arg(arg, arg->exp.left, error_str);
f7d82350
SR
859 if (lval != FILTER_VAL_NORM)
860 return lval;
7bb73553 861 rval = test_arg(arg, arg->exp.right, error_str);
f7d82350
SR
862 if (rval != FILTER_VAL_NORM)
863 return rval;
864 return FILTER_VAL_NORM;
865
866 case FILTER_ARG_NUM:
7bb73553 867 lval = test_arg(arg, arg->num.left, error_str);
f7d82350
SR
868 if (lval != FILTER_VAL_NORM)
869 return lval;
7bb73553 870 rval = test_arg(arg, arg->num.right, error_str);
f7d82350
SR
871 if (rval != FILTER_VAL_NORM)
872 return rval;
873 return FILTER_VAL_NORM;
874
875 case FILTER_ARG_OP:
876 if (arg->op.type != FILTER_OP_NOT) {
7bb73553 877 lval = test_arg(arg, arg->op.left, error_str);
f7d82350
SR
878 switch (lval) {
879 case FILTER_VAL_NORM:
880 break;
881 case FILTER_VAL_TRUE:
882 if (arg->op.type == FILTER_OP_OR)
883 return FILTER_VAL_TRUE;
7bb73553 884 rval = test_arg(arg, arg->op.right, error_str);
f7d82350
SR
885 if (rval != FILTER_VAL_NORM)
886 return rval;
887
7bb73553
NK
888 return reparent_op_arg(parent, arg, arg->op.right,
889 error_str);
f7d82350
SR
890
891 case FILTER_VAL_FALSE:
892 if (arg->op.type == FILTER_OP_AND)
893 return FILTER_VAL_FALSE;
7bb73553 894 rval = test_arg(arg, arg->op.right, error_str);
f7d82350
SR
895 if (rval != FILTER_VAL_NORM)
896 return rval;
897
7bb73553
NK
898 return reparent_op_arg(parent, arg, arg->op.right,
899 error_str);
900
901 default:
902 return lval;
f7d82350
SR
903 }
904 }
905
7bb73553 906 rval = test_arg(arg, arg->op.right, error_str);
f7d82350
SR
907 switch (rval) {
908 case FILTER_VAL_NORM:
7bb73553 909 default:
f7d82350 910 break;
7bb73553 911
f7d82350
SR
912 case FILTER_VAL_TRUE:
913 if (arg->op.type == FILTER_OP_OR)
914 return FILTER_VAL_TRUE;
915 if (arg->op.type == FILTER_OP_NOT)
916 return FILTER_VAL_FALSE;
917
7bb73553
NK
918 return reparent_op_arg(parent, arg, arg->op.left,
919 error_str);
f7d82350
SR
920
921 case FILTER_VAL_FALSE:
922 if (arg->op.type == FILTER_OP_AND)
923 return FILTER_VAL_FALSE;
924 if (arg->op.type == FILTER_OP_NOT)
925 return FILTER_VAL_TRUE;
926
7bb73553
NK
927 return reparent_op_arg(parent, arg, arg->op.left,
928 error_str);
f7d82350
SR
929 }
930
7bb73553 931 return rval;
f7d82350 932 default:
7bb73553
NK
933 show_error(error_str, "bad arg in filter tree");
934 return PEVENT_ERRNO__BAD_FILTER_ARG;
f7d82350
SR
935 }
936 return FILTER_VAL_NORM;
937}
938
939/* Remove any unknown event fields */
7bb73553 940static struct filter_arg *collapse_tree(struct filter_arg *arg, char **error_str)
f7d82350
SR
941{
942 enum filter_vals ret;
943
7bb73553 944 ret = test_arg(arg, arg, error_str);
f7d82350
SR
945 switch (ret) {
946 case FILTER_VAL_NORM:
7bb73553 947 break;
f7d82350
SR
948
949 case FILTER_VAL_TRUE:
950 case FILTER_VAL_FALSE:
951 free_arg(arg);
952 arg = allocate_arg();
2e4eb10d
NK
953 if (arg) {
954 arg->type = FILTER_ARG_BOOLEAN;
955 arg->boolean.value = ret == FILTER_VAL_TRUE;
7bb73553
NK
956 } else {
957 show_error(error_str, "Failed to allocate filter arg");
2e4eb10d 958 }
7bb73553
NK
959 break;
960
961 default:
962 /* test_arg() already set the error_str */
963 free_arg(arg);
964 arg = NULL;
965 break;
f7d82350
SR
966 }
967
968 return arg;
969}
970
971static int
972process_filter(struct event_format *event, struct filter_arg **parg,
973 char **error_str, int not)
974{
975 enum event_type type;
976 char *token = NULL;
977 struct filter_arg *current_op = NULL;
978 struct filter_arg *current_exp = NULL;
979 struct filter_arg *left_item = NULL;
980 struct filter_arg *arg = NULL;
981 enum op_type op_type;
982 enum filter_op_type btype;
983 enum filter_exp_type etype;
984 enum filter_cmp_type ctype;
985 int ret;
986
987 *parg = NULL;
988
989 do {
990 free(token);
991 type = read_token(&token);
992 switch (type) {
993 case EVENT_SQUOTE:
994 case EVENT_DQUOTE:
995 case EVENT_ITEM:
996 arg = create_arg_item(event, token, type, error_str);
997 if (!arg)
998 goto fail;
999 if (!left_item)
1000 left_item = arg;
1001 else if (current_exp) {
1002 ret = add_right(current_exp, arg, error_str);
1003 if (ret < 0)
1004 goto fail;
1005 left_item = NULL;
1006 /* Not's only one one expression */
1007 if (not) {
1008 arg = NULL;
1009 if (current_op)
1010 goto fail_print;
1011 free(token);
1012 *parg = current_exp;
1013 return 0;
1014 }
1015 } else
1016 goto fail_print;
1017 arg = NULL;
1018 break;
1019
1020 case EVENT_DELIM:
1021 if (*token == ',') {
1022 show_error(error_str,
1023 "Illegal token ','");
1024 goto fail;
1025 }
1026
1027 if (*token == '(') {
1028 if (left_item) {
1029 show_error(error_str,
1030 "Open paren can not come after item");
1031 goto fail;
1032 }
1033 if (current_exp) {
1034 show_error(error_str,
1035 "Open paren can not come after expression");
1036 goto fail;
1037 }
1038
1039 ret = process_filter(event, &arg, error_str, 0);
1040 if (ret != 1) {
1041 if (ret == 0)
1042 show_error(error_str,
1043 "Unbalanced number of '('");
1044 goto fail;
1045 }
1046 ret = 0;
1047
1048 /* A not wants just one expression */
1049 if (not) {
1050 if (current_op)
1051 goto fail_print;
1052 *parg = arg;
1053 return 0;
1054 }
1055
1056 if (current_op)
1057 ret = add_right(current_op, arg, error_str);
1058 else
1059 current_exp = arg;
1060
1061 if (ret < 0)
1062 goto fail;
1063
1064 } else { /* ')' */
1065 if (!current_op && !current_exp)
1066 goto fail_print;
1067
1068 /* Make sure everything is finished at this level */
1069 if (current_exp && !check_op_done(current_exp))
1070 goto fail_print;
1071 if (current_op && !check_op_done(current_op))
1072 goto fail_print;
1073
1074 if (current_op)
1075 *parg = current_op;
1076 else
1077 *parg = current_exp;
1078 return 1;
1079 }
1080 break;
1081
1082 case EVENT_OP:
1083 op_type = process_op(token, &btype, &ctype, &etype);
1084
1085 /* All expect a left arg except for NOT */
1086 switch (op_type) {
1087 case OP_BOOL:
1088 /* Logic ops need a left expression */
1089 if (!current_exp && !current_op)
1090 goto fail_print;
1091 /* fall through */
1092 case OP_NOT:
1093 /* logic only processes ops and exp */
1094 if (left_item)
1095 goto fail_print;
1096 break;
1097 case OP_EXP:
1098 case OP_CMP:
1099 if (!left_item)
1100 goto fail_print;
1101 break;
1102 case OP_NONE:
1103 show_error(error_str,
1104 "Unknown op token %s", token);
1105 goto fail;
1106 }
1107
1108 ret = 0;
1109 switch (op_type) {
1110 case OP_BOOL:
1111 arg = create_arg_op(btype);
2e4eb10d
NK
1112 if (arg == NULL)
1113 goto fail_alloc;
f7d82350
SR
1114 if (current_op)
1115 ret = add_left(arg, current_op);
1116 else
1117 ret = add_left(arg, current_exp);
1118 current_op = arg;
1119 current_exp = NULL;
1120 break;
1121
1122 case OP_NOT:
1123 arg = create_arg_op(btype);
2e4eb10d
NK
1124 if (arg == NULL)
1125 goto fail_alloc;
f7d82350
SR
1126 if (current_op)
1127 ret = add_right(current_op, arg, error_str);
1128 if (ret < 0)
1129 goto fail;
1130 current_exp = arg;
1131 ret = process_filter(event, &arg, error_str, 1);
1132 if (ret < 0)
1133 goto fail;
1134 ret = add_right(current_exp, arg, error_str);
1135 if (ret < 0)
1136 goto fail;
1137 break;
1138
1139 case OP_EXP:
1140 case OP_CMP:
1141 if (op_type == OP_EXP)
1142 arg = create_arg_exp(etype);
1143 else
1144 arg = create_arg_cmp(ctype);
2e4eb10d
NK
1145 if (arg == NULL)
1146 goto fail_alloc;
f7d82350
SR
1147
1148 if (current_op)
1149 ret = add_right(current_op, arg, error_str);
1150 if (ret < 0)
1151 goto fail;
1152 ret = add_left(arg, left_item);
1153 if (ret < 0) {
1154 arg = NULL;
1155 goto fail_print;
1156 }
1157 current_exp = arg;
1158 break;
1159 default:
1160 break;
1161 }
1162 arg = NULL;
1163 if (ret < 0)
1164 goto fail_print;
1165 break;
1166 case EVENT_NONE:
1167 break;
91dfa49b
NK
1168 case EVENT_ERROR:
1169 goto fail_alloc;
f7d82350
SR
1170 default:
1171 goto fail_print;
1172 }
1173 } while (type != EVENT_NONE);
1174
1175 if (!current_op && !current_exp)
1176 goto fail_print;
1177
1178 if (!current_op)
1179 current_op = current_exp;
1180
7bb73553 1181 current_op = collapse_tree(current_op, error_str);
2e4eb10d 1182 if (current_op == NULL)
7bb73553 1183 goto fail;
f7d82350
SR
1184
1185 *parg = current_op;
1186
1187 return 0;
1188
2e4eb10d
NK
1189 fail_alloc:
1190 show_error(error_str, "failed to allocate filter arg");
1191 goto fail;
f7d82350
SR
1192 fail_print:
1193 show_error(error_str, "Syntax error");
1194 fail:
1195 free_arg(current_op);
1196 free_arg(current_exp);
1197 free_arg(arg);
1198 free(token);
1199 return -1;
1200}
1201
1202static int
1203process_event(struct event_format *event, const char *filter_str,
1204 struct filter_arg **parg, char **error_str)
1205{
1206 int ret;
1207
1208 pevent_buffer_init(filter_str, strlen(filter_str));
1209
1210 ret = process_filter(event, parg, error_str, 0);
1211 if (ret == 1) {
1212 show_error(error_str,
1213 "Unbalanced number of ')'");
1214 return -1;
1215 }
1216 if (ret < 0)
1217 return ret;
1218
1219 /* If parg is NULL, then make it into FALSE */
1220 if (!*parg) {
1221 *parg = allocate_arg();
2e4eb10d
NK
1222 if (*parg == NULL) {
1223 show_error(error_str, "failed to allocate filter arg");
1224 return -1;
1225 }
f7d82350 1226 (*parg)->type = FILTER_ARG_BOOLEAN;
668fe01f 1227 (*parg)->boolean.value = FILTER_FALSE;
f7d82350
SR
1228 }
1229
1230 return 0;
1231}
1232
1233static int filter_event(struct event_filter *filter,
1234 struct event_format *event,
1235 const char *filter_str, char **error_str)
1236{
1237 struct filter_type *filter_type;
1238 struct filter_arg *arg;
1239 int ret;
1240
1241 if (filter_str) {
1242 ret = process_event(event, filter_str, &arg, error_str);
1243 if (ret < 0)
1244 return ret;
1245
1246 } else {
1247 /* just add a TRUE arg */
1248 arg = allocate_arg();
2e4eb10d
NK
1249 if (arg == NULL) {
1250 show_error(error_str, "failed to allocate filter arg");
1251 return -1;
1252 }
f7d82350 1253 arg->type = FILTER_ARG_BOOLEAN;
668fe01f 1254 arg->boolean.value = FILTER_TRUE;
f7d82350
SR
1255 }
1256
1257 filter_type = add_filter_type(filter, event->id);
ef3072cd
NK
1258 if (filter_type == NULL) {
1259 show_error(error_str, "failed to add a new filter: %s",
1260 filter_str ? filter_str : "true");
1261 return -1;
1262 }
1263
f7d82350
SR
1264 if (filter_type->filter)
1265 free_arg(filter_type->filter);
1266 filter_type->filter = arg;
1267
1268 return 0;
1269}
1270
1271/**
1272 * pevent_filter_add_filter_str - add a new filter
1273 * @filter: the event filter to add to
1274 * @filter_str: the filter string that contains the filter
1275 * @error_str: string containing reason for failed filter
1276 *
1277 * Returns 0 if the filter was successfully added
1278 * -1 if there was an error.
1279 *
1280 * On error, if @error_str points to a string pointer,
1281 * it is set to the reason that the filter failed.
1282 * This string must be freed with "free".
1283 */
1284int pevent_filter_add_filter_str(struct event_filter *filter,
1285 const char *filter_str,
1286 char **error_str)
1287{
1288 struct pevent *pevent = filter->pevent;
1289 struct event_list *event;
1290 struct event_list *events = NULL;
1291 const char *filter_start;
1292 const char *next_event;
1293 char *this_event;
1294 char *event_name = NULL;
1295 char *sys_name = NULL;
1296 char *sp;
1297 int rtn = 0;
1298 int len;
1299 int ret;
1300
1301 /* clear buffer to reset show error */
1302 pevent_buffer_init("", 0);
1303
1304 if (error_str)
1305 *error_str = NULL;
1306
1307 filter_start = strchr(filter_str, ':');
1308 if (filter_start)
1309 len = filter_start - filter_str;
1310 else
1311 len = strlen(filter_str);
1312
1313
1314 do {
1315 next_event = strchr(filter_str, ',');
1316 if (next_event &&
1317 (!filter_start || next_event < filter_start))
1318 len = next_event - filter_str;
1319 else if (filter_start)
1320 len = filter_start - filter_str;
1321 else
1322 len = strlen(filter_str);
1323
28942c87
NK
1324 this_event = malloc(len + 1);
1325 if (this_event == NULL) {
1326 show_error(error_str, "Memory allocation failure");
1327 /* This can only happen when events is NULL, but still */
1328 free_events(events);
1329 return -1;
1330 }
f7d82350
SR
1331 memcpy(this_event, filter_str, len);
1332 this_event[len] = 0;
1333
1334 if (next_event)
1335 next_event++;
1336
1337 filter_str = next_event;
1338
1339 sys_name = strtok_r(this_event, "/", &sp);
1340 event_name = strtok_r(NULL, "/", &sp);
1341
1342 if (!sys_name) {
1343 show_error(error_str, "No filter found");
1344 /* This can only happen when events is NULL, but still */
1345 free_events(events);
1346 free(this_event);
1347 return -1;
1348 }
1349
1350 /* Find this event */
1351 ret = find_event(pevent, &events, strim(sys_name), strim(event_name));
1352 if (ret < 0) {
605b8fda
NK
1353 if (ret == PEVENT_ERRNO__MEM_ALLOC_FAILED)
1354 show_error(error_str,
1355 "Memory allocation failure");
1356 else if (event_name)
f7d82350
SR
1357 show_error(error_str,
1358 "No event found under '%s.%s'",
1359 sys_name, event_name);
1360 else
1361 show_error(error_str,
1362 "No event found under '%s'",
1363 sys_name);
1364 free_events(events);
1365 free(this_event);
1366 return -1;
1367 }
1368 free(this_event);
1369 } while (filter_str);
1370
1371 /* Skip the ':' */
1372 if (filter_start)
1373 filter_start++;
1374
1375 /* filter starts here */
1376 for (event = events; event; event = event->next) {
1377 ret = filter_event(filter, event->event, filter_start,
1378 error_str);
1379 /* Failures are returned if a parse error happened */
1380 if (ret < 0)
1381 rtn = ret;
1382
1383 if (ret >= 0 && pevent->test_filters) {
1384 char *test;
1385 test = pevent_filter_make_string(filter, event->event->id);
1386 printf(" '%s: %s'\n", event->event->name, test);
1387 free(test);
1388 }
1389 }
1390
1391 free_events(events);
1392
1393 if (rtn >= 0 && pevent->test_filters)
1394 exit(0);
1395
1396 return rtn;
1397}
1398
1399static void free_filter_type(struct filter_type *filter_type)
1400{
1401 free_arg(filter_type->filter);
1402}
1403
1404/**
1405 * pevent_filter_remove_event - remove a filter for an event
1406 * @filter: the event filter to remove from
1407 * @event_id: the event to remove a filter for
1408 *
1409 * Removes the filter saved for an event defined by @event_id
1410 * from the @filter.
1411 *
1412 * Returns 1: if an event was removed
1413 * 0: if the event was not found
1414 */
1415int pevent_filter_remove_event(struct event_filter *filter,
1416 int event_id)
1417{
1418 struct filter_type *filter_type;
1419 unsigned long len;
1420
1421 if (!filter->filters)
1422 return 0;
1423
1424 filter_type = find_filter_type(filter, event_id);
1425
1426 if (!filter_type)
1427 return 0;
1428
1429 free_filter_type(filter_type);
1430
1431 /* The filter_type points into the event_filters array */
1432 len = (unsigned long)(filter->event_filters + filter->filters) -
1433 (unsigned long)(filter_type + 1);
1434
1435 memmove(filter_type, filter_type + 1, len);
1436 filter->filters--;
1437
1438 memset(&filter->event_filters[filter->filters], 0,
1439 sizeof(*filter_type));
1440
1441 return 1;
1442}
1443
1444/**
1445 * pevent_filter_reset - clear all filters in a filter
1446 * @filter: the event filter to reset
1447 *
1448 * Removes all filters from a filter and resets it.
1449 */
1450void pevent_filter_reset(struct event_filter *filter)
1451{
1452 int i;
1453
1454 for (i = 0; i < filter->filters; i++)
1455 free_filter_type(&filter->event_filters[i]);
1456
1457 free(filter->event_filters);
1458 filter->filters = 0;
1459 filter->event_filters = NULL;
1460}
1461
1462void pevent_filter_free(struct event_filter *filter)
1463{
1464 pevent_unref(filter->pevent);
1465
1466 pevent_filter_reset(filter);
1467
1468 free(filter);
1469}
1470
1471static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg);
1472
1473static int copy_filter_type(struct event_filter *filter,
1474 struct event_filter *source,
1475 struct filter_type *filter_type)
1476{
1477 struct filter_arg *arg;
1478 struct event_format *event;
1479 const char *sys;
1480 const char *name;
1481 char *str;
1482
1483 /* Can't assume that the pevent's are the same */
1484 sys = filter_type->event->system;
1485 name = filter_type->event->name;
1486 event = pevent_find_event_by_name(filter->pevent, sys, name);
1487 if (!event)
1488 return -1;
1489
1490 str = arg_to_str(source, filter_type->filter);
1491 if (!str)
1492 return -1;
1493
1494 if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
1495 /* Add trivial event */
1496 arg = allocate_arg();
2e4eb10d
NK
1497 if (arg == NULL)
1498 return -1;
1499
f7d82350
SR
1500 arg->type = FILTER_ARG_BOOLEAN;
1501 if (strcmp(str, "TRUE") == 0)
668fe01f 1502 arg->boolean.value = 1;
f7d82350 1503 else
668fe01f 1504 arg->boolean.value = 0;
f7d82350
SR
1505
1506 filter_type = add_filter_type(filter, event->id);
ef3072cd
NK
1507 if (filter_type == NULL)
1508 return -1;
1509
f7d82350
SR
1510 filter_type->filter = arg;
1511
1512 free(str);
1513 return 0;
1514 }
1515
1516 filter_event(filter, event, str, NULL);
1517 free(str);
1518
1519 return 0;
1520}
1521
1522/**
1523 * pevent_filter_copy - copy a filter using another filter
1524 * @dest - the filter to copy to
1525 * @source - the filter to copy from
1526 *
1527 * Returns 0 on success and -1 if not all filters were copied
1528 */
1529int pevent_filter_copy(struct event_filter *dest, struct event_filter *source)
1530{
1531 int ret = 0;
1532 int i;
1533
1534 pevent_filter_reset(dest);
1535
1536 for (i = 0; i < source->filters; i++) {
1537 if (copy_filter_type(dest, source, &source->event_filters[i]))
1538 ret = -1;
1539 }
1540 return ret;
1541}
1542
1543
1544/**
1545 * pevent_update_trivial - update the trivial filters with the given filter
1546 * @dest - the filter to update
1547 * @source - the filter as the source of the update
1548 * @type - the type of trivial filter to update.
1549 *
1550 * Scan dest for trivial events matching @type to replace with the source.
1551 *
1552 * Returns 0 on success and -1 if there was a problem updating, but
1553 * events may have still been updated on error.
1554 */
1555int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
1556 enum filter_trivial_type type)
1557{
1558 struct pevent *src_pevent;
1559 struct pevent *dest_pevent;
1560 struct event_format *event;
1561 struct filter_type *filter_type;
1562 struct filter_arg *arg;
1563 char *str;
1564 int i;
1565
1566 src_pevent = source->pevent;
1567 dest_pevent = dest->pevent;
1568
1569 /* Do nothing if either of the filters has nothing to filter */
1570 if (!dest->filters || !source->filters)
1571 return 0;
1572
1573 for (i = 0; i < dest->filters; i++) {
1574 filter_type = &dest->event_filters[i];
1575 arg = filter_type->filter;
1576 if (arg->type != FILTER_ARG_BOOLEAN)
1577 continue;
668fe01f
SR
1578 if ((arg->boolean.value && type == FILTER_TRIVIAL_FALSE) ||
1579 (!arg->boolean.value && type == FILTER_TRIVIAL_TRUE))
f7d82350
SR
1580 continue;
1581
1582 event = filter_type->event;
1583
1584 if (src_pevent != dest_pevent) {
1585 /* do a look up */
1586 event = pevent_find_event_by_name(src_pevent,
1587 event->system,
1588 event->name);
1589 if (!event)
1590 return -1;
1591 }
1592
1593 str = pevent_filter_make_string(source, event->id);
1594 if (!str)
1595 continue;
1596
1597 /* Don't bother if the filter is trivial too */
1598 if (strcmp(str, "TRUE") != 0 && strcmp(str, "FALSE") != 0)
1599 filter_event(dest, event, str, NULL);
1600 free(str);
1601 }
1602 return 0;
1603}
1604
1605/**
1606 * pevent_filter_clear_trivial - clear TRUE and FALSE filters
1607 * @filter: the filter to remove trivial filters from
1608 * @type: remove only true, false, or both
1609 *
1610 * Removes filters that only contain a TRUE or FALES boolean arg.
7ef2e813
NK
1611 *
1612 * Returns 0 on success and -1 if there was a problem.
f7d82350 1613 */
7ef2e813 1614int pevent_filter_clear_trivial(struct event_filter *filter,
f7d82350
SR
1615 enum filter_trivial_type type)
1616{
1617 struct filter_type *filter_type;
1618 int count = 0;
f6ced60f 1619 int *ids = NULL;
f7d82350
SR
1620 int i;
1621
1622 if (!filter->filters)
7ef2e813 1623 return 0;
f7d82350
SR
1624
1625 /*
1626 * Two steps, first get all ids with trivial filters.
1627 * then remove those ids.
1628 */
1629 for (i = 0; i < filter->filters; i++) {
7ef2e813
NK
1630 int *new_ids;
1631
f7d82350
SR
1632 filter_type = &filter->event_filters[i];
1633 if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1634 continue;
1635 switch (type) {
1636 case FILTER_TRIVIAL_FALSE:
668fe01f 1637 if (filter_type->filter->boolean.value)
f7d82350
SR
1638 continue;
1639 case FILTER_TRIVIAL_TRUE:
668fe01f 1640 if (!filter_type->filter->boolean.value)
f7d82350
SR
1641 continue;
1642 default:
1643 break;
1644 }
f6ced60f 1645
7ef2e813
NK
1646 new_ids = realloc(ids, sizeof(*ids) * (count + 1));
1647 if (!new_ids) {
1648 free(ids);
1649 return -1;
1650 }
1651
1652 ids = new_ids;
f7d82350
SR
1653 ids[count++] = filter_type->event_id;
1654 }
1655
1656 if (!count)
7ef2e813 1657 return 0;
f7d82350
SR
1658
1659 for (i = 0; i < count; i++)
1660 pevent_filter_remove_event(filter, ids[i]);
1661
1662 free(ids);
7ef2e813 1663 return 0;
f7d82350
SR
1664}
1665
1666/**
1667 * pevent_filter_event_has_trivial - return true event contains trivial filter
1668 * @filter: the filter with the information
1669 * @event_id: the id of the event to test
1670 * @type: trivial type to test for (TRUE, FALSE, EITHER)
1671 *
1672 * Returns 1 if the event contains a matching trivial type
1673 * otherwise 0.
1674 */
1675int pevent_filter_event_has_trivial(struct event_filter *filter,
1676 int event_id,
1677 enum filter_trivial_type type)
1678{
1679 struct filter_type *filter_type;
1680
1681 if (!filter->filters)
1682 return 0;
1683
1684 filter_type = find_filter_type(filter, event_id);
1685
1686 if (!filter_type)
1687 return 0;
1688
1689 if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1690 return 0;
1691
1692 switch (type) {
1693 case FILTER_TRIVIAL_FALSE:
668fe01f 1694 return !filter_type->filter->boolean.value;
f7d82350
SR
1695
1696 case FILTER_TRIVIAL_TRUE:
668fe01f 1697 return filter_type->filter->boolean.value;
f7d82350
SR
1698 default:
1699 return 1;
1700 }
1701}
1702
1703static int test_filter(struct event_format *event,
1c698186 1704 struct filter_arg *arg, struct pevent_record *record);
f7d82350
SR
1705
1706static const char *
1c698186 1707get_comm(struct event_format *event, struct pevent_record *record)
f7d82350
SR
1708{
1709 const char *comm;
1710 int pid;
1711
1712 pid = pevent_data_pid(event->pevent, record);
1713 comm = pevent_data_comm_from_pid(event->pevent, pid);
1714 return comm;
1715}
1716
1717static unsigned long long
1718get_value(struct event_format *event,
1c698186 1719 struct format_field *field, struct pevent_record *record)
f7d82350
SR
1720{
1721 unsigned long long val;
1722
1723 /* Handle our dummy "comm" field */
1724 if (field == &comm) {
1725 const char *name;
1726
1727 name = get_comm(event, record);
42c59cda 1728 return (unsigned long)name;
f7d82350
SR
1729 }
1730
1731 pevent_read_number_field(field, record->data, &val);
1732
1733 if (!(field->flags & FIELD_IS_SIGNED))
1734 return val;
1735
1736 switch (field->size) {
1737 case 1:
1738 return (char)val;
1739 case 2:
1740 return (short)val;
1741 case 4:
1742 return (int)val;
1743 case 8:
1744 return (long long)val;
1745 }
1746 return val;
1747}
1748
1749static unsigned long long
1c698186 1750get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record);
f7d82350
SR
1751
1752static unsigned long long
1c698186 1753get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record)
f7d82350
SR
1754{
1755 unsigned long long lval, rval;
1756
1757 lval = get_arg_value(event, arg->exp.left, record);
1758 rval = get_arg_value(event, arg->exp.right, record);
1759
1760 switch (arg->exp.type) {
1761 case FILTER_EXP_ADD:
1762 return lval + rval;
1763
1764 case FILTER_EXP_SUB:
1765 return lval - rval;
1766
1767 case FILTER_EXP_MUL:
1768 return lval * rval;
1769
1770 case FILTER_EXP_DIV:
1771 return lval / rval;
1772
1773 case FILTER_EXP_MOD:
1774 return lval % rval;
1775
1776 case FILTER_EXP_RSHIFT:
1777 return lval >> rval;
1778
1779 case FILTER_EXP_LSHIFT:
1780 return lval << rval;
1781
1782 case FILTER_EXP_AND:
1783 return lval & rval;
1784
1785 case FILTER_EXP_OR:
1786 return lval | rval;
1787
1788 case FILTER_EXP_XOR:
1789 return lval ^ rval;
1790
1791 case FILTER_EXP_NOT:
1792 default:
1793 die("error in exp");
1794 }
1795 return 0;
1796}
1797
1798static unsigned long long
1c698186 1799get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record)
f7d82350
SR
1800{
1801 switch (arg->type) {
1802 case FILTER_ARG_FIELD:
1803 return get_value(event, arg->field.field, record);
1804
1805 case FILTER_ARG_VALUE:
1806 if (arg->value.type != FILTER_NUMBER)
1807 die("must have number field!");
1808 return arg->value.val;
1809
1810 case FILTER_ARG_EXP:
1811 return get_exp_value(event, arg, record);
1812
1813 default:
1814 die("oops in filter");
1815 }
1816 return 0;
1817}
1818
1819static int test_num(struct event_format *event,
1c698186 1820 struct filter_arg *arg, struct pevent_record *record)
f7d82350
SR
1821{
1822 unsigned long long lval, rval;
1823
1824 lval = get_arg_value(event, arg->num.left, record);
1825 rval = get_arg_value(event, arg->num.right, record);
1826
1827 switch (arg->num.type) {
1828 case FILTER_CMP_EQ:
1829 return lval == rval;
1830
1831 case FILTER_CMP_NE:
1832 return lval != rval;
1833
1834 case FILTER_CMP_GT:
1835 return lval > rval;
1836
1837 case FILTER_CMP_LT:
1838 return lval < rval;
1839
1840 case FILTER_CMP_GE:
1841 return lval >= rval;
1842
1843 case FILTER_CMP_LE:
1844 return lval <= rval;
1845
1846 default:
1847 /* ?? */
1848 return 0;
1849 }
1850}
1851
1c698186 1852static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
f7d82350 1853{
e84c282b
SR
1854 struct event_format *event;
1855 struct pevent *pevent;
1856 unsigned long long addr;
1857 const char *val = NULL;
1858 char hex[64];
f7d82350 1859
e84c282b
SR
1860 /* If the field is not a string convert it */
1861 if (arg->str.field->flags & FIELD_IS_STRING) {
1862 val = record->data + arg->str.field->offset;
1863
1864 /*
1865 * We need to copy the data since we can't be sure the field
1866 * is null terminated.
1867 */
1868 if (*(val + arg->str.field->size - 1)) {
1869 /* copy it */
1870 memcpy(arg->str.buffer, val, arg->str.field->size);
1871 /* the buffer is already NULL terminated */
1872 val = arg->str.buffer;
1873 }
1874
1875 } else {
1876 event = arg->str.field->event;
1877 pevent = event->pevent;
1878 addr = get_value(event, arg->str.field, record);
1879
1880 if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
1881 /* convert to a kernel symbol */
1882 val = pevent_find_function(pevent, addr);
1883
1884 if (val == NULL) {
1885 /* just use the hex of the string name */
1886 snprintf(hex, 64, "0x%llx", addr);
1887 val = hex;
1888 }
f7d82350 1889 }
e84c282b 1890
f7d82350
SR
1891 return val;
1892}
1893
1894static int test_str(struct event_format *event,
1c698186 1895 struct filter_arg *arg, struct pevent_record *record)
f7d82350
SR
1896{
1897 const char *val;
1898
1899 if (arg->str.field == &comm)
1900 val = get_comm(event, record);
1901 else
1902 val = get_field_str(arg, record);
1903
1904 switch (arg->str.type) {
1905 case FILTER_CMP_MATCH:
1906 return strcmp(val, arg->str.val) == 0;
1907
1908 case FILTER_CMP_NOT_MATCH:
1909 return strcmp(val, arg->str.val) != 0;
1910
1911 case FILTER_CMP_REGEX:
1912 /* Returns zero on match */
1913 return !regexec(&arg->str.reg, val, 0, NULL, 0);
1914
1915 case FILTER_CMP_NOT_REGEX:
1916 return regexec(&arg->str.reg, val, 0, NULL, 0);
1917
1918 default:
1919 /* ?? */
1920 return 0;
1921 }
1922}
1923
1924static int test_op(struct event_format *event,
1c698186 1925 struct filter_arg *arg, struct pevent_record *record)
f7d82350
SR
1926{
1927 switch (arg->op.type) {
1928 case FILTER_OP_AND:
1929 return test_filter(event, arg->op.left, record) &&
1930 test_filter(event, arg->op.right, record);
1931
1932 case FILTER_OP_OR:
1933 return test_filter(event, arg->op.left, record) ||
1934 test_filter(event, arg->op.right, record);
1935
1936 case FILTER_OP_NOT:
1937 return !test_filter(event, arg->op.right, record);
1938
1939 default:
1940 /* ?? */
1941 return 0;
1942 }
1943}
1944
1945static int test_filter(struct event_format *event,
1c698186 1946 struct filter_arg *arg, struct pevent_record *record)
f7d82350
SR
1947{
1948 switch (arg->type) {
1949 case FILTER_ARG_BOOLEAN:
1950 /* easy case */
668fe01f 1951 return arg->boolean.value;
f7d82350
SR
1952
1953 case FILTER_ARG_OP:
1954 return test_op(event, arg, record);
1955
1956 case FILTER_ARG_NUM:
1957 return test_num(event, arg, record);
1958
1959 case FILTER_ARG_STR:
1960 return test_str(event, arg, record);
1961
1962 case FILTER_ARG_EXP:
1963 case FILTER_ARG_VALUE:
1964 case FILTER_ARG_FIELD:
1965 /*
1966 * Expressions, fields and values evaluate
1967 * to true if they return non zero
1968 */
1969 return !!get_arg_value(event, arg, record);
1970
1971 default:
1972 die("oops!");
1973 /* ?? */
1974 return 0;
1975 }
1976}
1977
1978/**
1979 * pevent_event_filtered - return true if event has filter
1980 * @filter: filter struct with filter information
1981 * @event_id: event id to test if filter exists
1982 *
1983 * Returns 1 if filter found for @event_id
1984 * otherwise 0;
1985 */
1986int pevent_event_filtered(struct event_filter *filter,
1987 int event_id)
1988{
1989 struct filter_type *filter_type;
1990
1991 if (!filter->filters)
1992 return 0;
1993
1994 filter_type = find_filter_type(filter, event_id);
1995
1996 return filter_type ? 1 : 0;
1997}
1998
1999/**
2000 * pevent_filter_match - test if a record matches a filter
2001 * @filter: filter struct with filter information
2002 * @record: the record to test against the filter
2003 *
2004 * Returns:
2005 * 1 - filter found for event and @record matches
2006 * 0 - filter found for event and @record does not match
2007 * -1 - no filter found for @record's event
2008 * -2 - if no filters exist
2009 */
2010int pevent_filter_match(struct event_filter *filter,
1c698186 2011 struct pevent_record *record)
f7d82350
SR
2012{
2013 struct pevent *pevent = filter->pevent;
2014 struct filter_type *filter_type;
2015 int event_id;
2016
2017 if (!filter->filters)
2018 return FILTER_NONE;
2019
2020 event_id = pevent_data_type(pevent, record);
2021
2022 filter_type = find_filter_type(filter, event_id);
2023
2024 if (!filter_type)
2025 return FILTER_NOEXIST;
2026
2027 return test_filter(filter_type->event, filter_type->filter, record) ?
2028 FILTER_MATCH : FILTER_MISS;
2029}
2030
2031static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
2032{
2033 char *str = NULL;
2034 char *left = NULL;
2035 char *right = NULL;
2036 char *op = NULL;
2037 int left_val = -1;
2038 int right_val = -1;
2039 int val;
2040 int len;
2041
2042 switch (arg->op.type) {
2043 case FILTER_OP_AND:
2044 op = "&&";
2045 /* fall through */
2046 case FILTER_OP_OR:
2047 if (!op)
2048 op = "||";
2049
2050 left = arg_to_str(filter, arg->op.left);
2051 right = arg_to_str(filter, arg->op.right);
2052 if (!left || !right)
2053 break;
2054
2055 /* Try to consolidate boolean values */
2056 if (strcmp(left, "TRUE") == 0)
2057 left_val = 1;
2058 else if (strcmp(left, "FALSE") == 0)
2059 left_val = 0;
2060
2061 if (strcmp(right, "TRUE") == 0)
2062 right_val = 1;
2063 else if (strcmp(right, "FALSE") == 0)
2064 right_val = 0;
2065
2066 if (left_val >= 0) {
2067 if ((arg->op.type == FILTER_OP_AND && !left_val) ||
2068 (arg->op.type == FILTER_OP_OR && left_val)) {
2069 /* Just return left value */
2070 str = left;
2071 left = NULL;
2072 break;
2073 }
2074 if (right_val >= 0) {
2075 /* just evaluate this. */
2076 val = 0;
2077 switch (arg->op.type) {
2078 case FILTER_OP_AND:
2079 val = left_val && right_val;
2080 break;
2081 case FILTER_OP_OR:
2082 val = left_val || right_val;
2083 break;
2084 default:
2085 break;
2086 }
2087 str = malloc_or_die(6);
2088 if (val)
2089 strcpy(str, "TRUE");
2090 else
2091 strcpy(str, "FALSE");
2092 break;
2093 }
2094 }
2095 if (right_val >= 0) {
2096 if ((arg->op.type == FILTER_OP_AND && !right_val) ||
2097 (arg->op.type == FILTER_OP_OR && right_val)) {
2098 /* Just return right value */
2099 str = right;
2100 right = NULL;
2101 break;
2102 }
2103 /* The right value is meaningless */
2104 str = left;
2105 left = NULL;
2106 break;
2107 }
2108
2109 len = strlen(left) + strlen(right) + strlen(op) + 10;
2110 str = malloc_or_die(len);
2111 snprintf(str, len, "(%s) %s (%s)",
2112 left, op, right);
2113 break;
2114
2115 case FILTER_OP_NOT:
2116 op = "!";
2117 right = arg_to_str(filter, arg->op.right);
2118 if (!right)
2119 break;
2120
2121 /* See if we can consolidate */
2122 if (strcmp(right, "TRUE") == 0)
2123 right_val = 1;
2124 else if (strcmp(right, "FALSE") == 0)
2125 right_val = 0;
2126 if (right_val >= 0) {
2127 /* just return the opposite */
2128 str = malloc_or_die(6);
2129 if (right_val)
2130 strcpy(str, "FALSE");
2131 else
2132 strcpy(str, "TRUE");
2133 break;
2134 }
2135 len = strlen(right) + strlen(op) + 3;
2136 str = malloc_or_die(len);
2137 snprintf(str, len, "%s(%s)", op, right);
2138 break;
2139
2140 default:
2141 /* ?? */
2142 break;
2143 }
2144 free(left);
2145 free(right);
2146 return str;
2147}
2148
2149static char *val_to_str(struct event_filter *filter, struct filter_arg *arg)
2150{
2151 char *str;
2152
2153 str = malloc_or_die(30);
2154
2155 snprintf(str, 30, "%lld", arg->value.val);
2156
2157 return str;
2158}
2159
2160static char *field_to_str(struct event_filter *filter, struct filter_arg *arg)
2161{
2162 return strdup(arg->field.field->name);
2163}
2164
2165static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
2166{
2167 char *lstr;
2168 char *rstr;
2169 char *op;
0fed4834 2170 char *str = NULL;
f7d82350
SR
2171 int len;
2172
2173 lstr = arg_to_str(filter, arg->exp.left);
2174 rstr = arg_to_str(filter, arg->exp.right);
0fed4834
NK
2175 if (!lstr || !rstr)
2176 goto out;
f7d82350
SR
2177
2178 switch (arg->exp.type) {
2179 case FILTER_EXP_ADD:
2180 op = "+";
2181 break;
2182 case FILTER_EXP_SUB:
2183 op = "-";
2184 break;
2185 case FILTER_EXP_MUL:
2186 op = "*";
2187 break;
2188 case FILTER_EXP_DIV:
2189 op = "/";
2190 break;
2191 case FILTER_EXP_MOD:
2192 op = "%";
2193 break;
2194 case FILTER_EXP_RSHIFT:
2195 op = ">>";
2196 break;
2197 case FILTER_EXP_LSHIFT:
2198 op = "<<";
2199 break;
2200 case FILTER_EXP_AND:
2201 op = "&";
2202 break;
2203 case FILTER_EXP_OR:
2204 op = "|";
2205 break;
2206 case FILTER_EXP_XOR:
2207 op = "^";
2208 break;
2209 default:
2210 die("oops in exp");
2211 }
2212
2213 len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
2214 str = malloc_or_die(len);
2215 snprintf(str, len, "%s %s %s", lstr, op, rstr);
0fed4834 2216out:
f7d82350
SR
2217 free(lstr);
2218 free(rstr);
2219
2220 return str;
2221}
2222
2223static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
2224{
2225 char *lstr;
2226 char *rstr;
2227 char *str = NULL;
2228 char *op = NULL;
2229 int len;
2230
2231 lstr = arg_to_str(filter, arg->num.left);
2232 rstr = arg_to_str(filter, arg->num.right);
0fed4834
NK
2233 if (!lstr || !rstr)
2234 goto out;
f7d82350
SR
2235
2236 switch (arg->num.type) {
2237 case FILTER_CMP_EQ:
2238 op = "==";
2239 /* fall through */
2240 case FILTER_CMP_NE:
2241 if (!op)
2242 op = "!=";
2243 /* fall through */
2244 case FILTER_CMP_GT:
2245 if (!op)
2246 op = ">";
2247 /* fall through */
2248 case FILTER_CMP_LT:
2249 if (!op)
2250 op = "<";
2251 /* fall through */
2252 case FILTER_CMP_GE:
2253 if (!op)
2254 op = ">=";
2255 /* fall through */
2256 case FILTER_CMP_LE:
2257 if (!op)
2258 op = "<=";
2259
2260 len = strlen(lstr) + strlen(op) + strlen(rstr) + 4;
2261 str = malloc_or_die(len);
2262 sprintf(str, "%s %s %s", lstr, op, rstr);
2263
2264 break;
2265
2266 default:
2267 /* ?? */
2268 break;
2269 }
2270
0fed4834 2271out:
f7d82350
SR
2272 free(lstr);
2273 free(rstr);
2274 return str;
2275}
2276
2277static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
2278{
2279 char *str = NULL;
2280 char *op = NULL;
2281 int len;
2282
2283 switch (arg->str.type) {
2284 case FILTER_CMP_MATCH:
2285 op = "==";
2286 /* fall through */
2287 case FILTER_CMP_NOT_MATCH:
2288 if (!op)
2289 op = "!=";
2290 /* fall through */
2291 case FILTER_CMP_REGEX:
2292 if (!op)
2293 op = "=~";
2294 /* fall through */
2295 case FILTER_CMP_NOT_REGEX:
2296 if (!op)
2297 op = "!~";
2298
2299 len = strlen(arg->str.field->name) + strlen(op) +
2300 strlen(arg->str.val) + 6;
2301 str = malloc_or_die(len);
2302 snprintf(str, len, "%s %s \"%s\"",
2303 arg->str.field->name,
2304 op, arg->str.val);
2305 break;
2306
2307 default:
2308 /* ?? */
2309 break;
2310 }
2311 return str;
2312}
2313
2314static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
2315{
2316 char *str;
2317
2318 switch (arg->type) {
2319 case FILTER_ARG_BOOLEAN:
2320 str = malloc_or_die(6);
668fe01f 2321 if (arg->boolean.value)
f7d82350
SR
2322 strcpy(str, "TRUE");
2323 else
2324 strcpy(str, "FALSE");
2325 return str;
2326
2327 case FILTER_ARG_OP:
2328 return op_to_str(filter, arg);
2329
2330 case FILTER_ARG_NUM:
2331 return num_to_str(filter, arg);
2332
2333 case FILTER_ARG_STR:
2334 return str_to_str(filter, arg);
2335
2336 case FILTER_ARG_VALUE:
2337 return val_to_str(filter, arg);
2338
2339 case FILTER_ARG_FIELD:
2340 return field_to_str(filter, arg);
2341
2342 case FILTER_ARG_EXP:
2343 return exp_to_str(filter, arg);
2344
2345 default:
2346 /* ?? */
2347 return NULL;
2348 }
2349
2350}
2351
2352/**
2353 * pevent_filter_make_string - return a string showing the filter
2354 * @filter: filter struct with filter information
2355 * @event_id: the event id to return the filter string with
2356 *
2357 * Returns a string that displays the filter contents.
2358 * This string must be freed with free(str).
2359 * NULL is returned if no filter is found.
2360 */
2361char *
2362pevent_filter_make_string(struct event_filter *filter, int event_id)
2363{
2364 struct filter_type *filter_type;
2365
2366 if (!filter->filters)
2367 return NULL;
2368
2369 filter_type = find_filter_type(filter, event_id);
2370
2371 if (!filter_type)
2372 return NULL;
2373
2374 return arg_to_str(filter, filter_type->filter);
2375}
2376
2377/**
2378 * pevent_filter_compare - compare two filters and return if they are the same
2379 * @filter1: Filter to compare with @filter2
2380 * @filter2: Filter to compare with @filter1
2381 *
2382 * Returns:
2383 * 1 if the two filters hold the same content.
2384 * 0 if they do not.
2385 */
2386int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2)
2387{
2388 struct filter_type *filter_type1;
2389 struct filter_type *filter_type2;
2390 char *str1, *str2;
2391 int result;
2392 int i;
2393
2394 /* Do the easy checks first */
2395 if (filter1->filters != filter2->filters)
2396 return 0;
2397 if (!filter1->filters && !filter2->filters)
2398 return 1;
2399
2400 /*
2401 * Now take a look at each of the events to see if they have the same
2402 * filters to them.
2403 */
2404 for (i = 0; i < filter1->filters; i++) {
2405 filter_type1 = &filter1->event_filters[i];
2406 filter_type2 = find_filter_type(filter2, filter_type1->event_id);
2407 if (!filter_type2)
2408 break;
2409 if (filter_type1->filter->type != filter_type2->filter->type)
2410 break;
2411 switch (filter_type1->filter->type) {
2412 case FILTER_TRIVIAL_FALSE:
2413 case FILTER_TRIVIAL_TRUE:
2414 /* trivial types just need the type compared */
2415 continue;
2416 default:
2417 break;
2418 }
2419 /* The best way to compare complex filters is with strings */
2420 str1 = arg_to_str(filter1, filter_type1->filter);
2421 str2 = arg_to_str(filter2, filter_type2->filter);
0fed4834
NK
2422 if (str1 && str2)
2423 result = strcmp(str1, str2) != 0;
2424 else
2425 /* bail out if allocation fails */
2426 result = 1;
2427
f7d82350
SR
2428 free(str1);
2429 free(str2);
2430 if (result)
2431 break;
2432 }
2433
2434 if (i < filter1->filters)
2435 return 0;
2436 return 1;
2437}
2438