]> git.karo-electronics.de Git - karo-tx-linux.git/blob - tools/lib/traceevent/parse-filter.c
tools lib traceevent: Refactor pevent_filter_match() to get rid of die()
[karo-tx-linux.git] / tools / lib / traceevent / parse-filter.c
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
16  * License along with this program; if not,  see <http://www.gnu.org/licenses>
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
32 static struct format_field comm = {
33         .name = "COMM",
34 };
35
36 struct event_list {
37         struct event_list       *next;
38         struct event_format     *event;
39 };
40
41 #define MAX_ERR_STR_SIZE 256
42
43 static 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
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         }
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
92 static void free_token(char *token)
93 {
94         pevent_free_token(token);
95 }
96
97 static 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 */
112                 *tok = malloc(3);
113                 if (*tok == NULL) {
114                         free_token(token);
115                         return EVENT_ERROR;
116                 }
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
128 static 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
142 static struct filter_type *
143 find_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
158 static struct filter_type *
159 add_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
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;
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  */
201 struct event_filter *pevent_filter_alloc(struct pevent *pevent)
202 {
203         struct event_filter *filter;
204
205         filter = malloc(sizeof(*filter));
206         if (filter == NULL)
207                 return NULL;
208
209         memset(filter, 0, sizeof(*filter));
210         filter->pevent = pevent;
211         pevent_ref(pevent);
212
213         return filter;
214 }
215
216 static struct filter_arg *allocate_arg(void)
217 {
218         return calloc(1, sizeof(struct filter_arg));
219 }
220
221 static 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:
229                 break;
230
231         case FILTER_ARG_NUM:
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);
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
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
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
263 static int add_event(struct event_list **events,
264                       struct event_format *event)
265 {
266         struct event_list *list;
267
268         list = malloc(sizeof(*list));
269         if (list == NULL)
270                 return -1;
271
272         list->next = *events;
273         *events = list;
274         list->event = event;
275         return 0;
276 }
277
278 static 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
290 static enum pevent_errno
291 find_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;
298         int fail = 0;
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
309         reg = malloc(strlen(event_name) + 3);
310         if (reg == NULL)
311                 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
312
313         sprintf(reg, "^%s$", event_name);
314
315         ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
316         free(reg);
317
318         if (ret)
319                 return PEVENT_ERRNO__INVALID_EVENT_NAME;
320
321         if (sys_name) {
322                 reg = malloc(strlen(sys_name) + 3);
323                 if (reg == NULL) {
324                         regfree(&ereg);
325                         return PEVENT_ERRNO__MEM_ALLOC_FAILED;
326                 }
327
328                 sprintf(reg, "^%s$", sys_name);
329                 ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
330                 free(reg);
331                 if (ret) {
332                         regfree(&ereg);
333                         return PEVENT_ERRNO__INVALID_EVENT_NAME;
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;
341                         if (add_event(events, event) < 0) {
342                                 fail = 1;
343                                 break;
344                         }
345                 }
346         }
347
348         regfree(&ereg);
349         if (sys_name)
350                 regfree(&sreg);
351
352         if (!match)
353                 return PEVENT_ERRNO__EVENT_NOT_FOUND;
354         if (fail)
355                 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
356
357         return 0;
358 }
359
360 static 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
371 static enum pevent_errno
372 create_arg_item(struct event_format *event, const char *token,
373                 enum event_type type, struct filter_arg **parg, char **error_str)
374 {
375         struct format_field *field;
376         struct filter_arg *arg;
377
378         arg = allocate_arg();
379         if (arg == NULL) {
380                 show_error(error_str, "failed to allocate filter arg");
381                 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
382         }
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);
392                 if (!arg->value.str) {
393                         free_arg(arg);
394                         show_error(error_str, "failed to allocate string filter arg");
395                         return PEVENT_ERRNO__MEM_ALLOC_FAILED;
396                 }
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;
412                                 arg->boolean.value = FILTER_FALSE;
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", token);
424                 return PEVENT_ERRNO__UNEXPECTED_TYPE;
425         }
426         *parg = arg;
427         return 0;
428 }
429
430 static struct filter_arg *
431 create_arg_op(enum filter_op_type btype)
432 {
433         struct filter_arg *arg;
434
435         arg = allocate_arg();
436         if (!arg)
437                 return NULL;
438
439         arg->type = FILTER_ARG_OP;
440         arg->op.type = btype;
441
442         return arg;
443 }
444
445 static struct filter_arg *
446 create_arg_exp(enum filter_exp_type etype)
447 {
448         struct filter_arg *arg;
449
450         arg = allocate_arg();
451         if (!arg)
452                 return NULL;
453
454         arg->type = FILTER_ARG_EXP;
455         arg->op.type = etype;
456
457         return arg;
458 }
459
460 static struct filter_arg *
461 create_arg_cmp(enum filter_exp_type etype)
462 {
463         struct filter_arg *arg;
464
465         arg = allocate_arg();
466         if (!arg)
467                 return NULL;
468
469         /* Use NUM and change if necessary */
470         arg->type = FILTER_ARG_NUM;
471         arg->op.type = etype;
472
473         return arg;
474 }
475
476 static enum pevent_errno
477 add_right(struct filter_arg *op, struct filter_arg *arg, char **error_str)
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:
508                         show_error(error_str, "Illegal rvalue");
509                         return PEVENT_ERRNO__ILLEGAL_RVALUE;
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;
548                                 op->boolean.value = FILTER_FALSE;
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");
556                                 return PEVENT_ERRNO__ILLEGAL_LVALUE;
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);
575                                         return PEVENT_ERRNO__INVALID_REGEX;
576                                 }
577                                 break;
578                         default:
579                                 show_error(error_str,
580                                            "Illegal comparison for string");
581                                 return PEVENT_ERRNO__ILLEGAL_STRING_CMP;
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);
588                         if (!op->str.val) {
589                                 show_error(error_str, "Failed to allocate string filter");
590                                 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
591                         }
592                         /*
593                          * Need a buffer to copy data for tests
594                          */
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                         }
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");
617                                 return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
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:
637         show_error(error_str, "Syntax error");
638         return PEVENT_ERRNO__SYNTAX_ERROR;
639 }
640
641 static struct filter_arg *
642 rotate_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
651 static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg)
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)
670                         return PEVENT_ERRNO__INVALID_ARG_TYPE;
671                 op->num.left = arg;
672                 break;
673         default:
674                 return PEVENT_ERRNO__INVALID_ARG_TYPE;
675         }
676         return 0;
677 }
678
679 enum op_type {
680         OP_NONE,
681         OP_BOOL,
682         OP_NOT,
683         OP_EXP,
684         OP_CMP,
685 };
686
687 static 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
756 static 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
781 enum filter_vals {
782         FILTER_VAL_NORM,
783         FILTER_VAL_FALSE,
784         FILTER_VAL_TRUE,
785 };
786
787 static enum pevent_errno
788 reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
789                 struct filter_arg *arg, char **error_str)
790 {
791         struct filter_arg *other_child;
792         struct filter_arg **ptr;
793
794         if (parent->type != FILTER_ARG_OP &&
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         }
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;
807         } else {
808                 show_error(error_str, "Error in reparent op, find other child");
809                 return PEVENT_ERRNO__REPARENT_FAILED;
810         }
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);
821                 return 0;
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;
828         else {
829                 show_error(error_str, "Error in reparent op");
830                 return PEVENT_ERRNO__REPARENT_FAILED;
831         }
832
833         *ptr = arg;
834
835         free_arg(old_child);
836         return 0;
837 }
838
839 /* Returns either filter_vals (success) or pevent_errno (failfure) */
840 static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
841                     char **error_str)
842 {
843         int lval, rval;
844
845         switch (arg->type) {
846
847                 /* bad case */
848         case FILTER_ARG_BOOLEAN:
849                 return FILTER_VAL_FALSE + arg->boolean.value;
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:
858                 lval = test_arg(arg, arg->exp.left, error_str);
859                 if (lval != FILTER_VAL_NORM)
860                         return lval;
861                 rval = test_arg(arg, arg->exp.right, error_str);
862                 if (rval != FILTER_VAL_NORM)
863                         return rval;
864                 return FILTER_VAL_NORM;
865
866         case FILTER_ARG_NUM:
867                 lval = test_arg(arg, arg->num.left, error_str);
868                 if (lval != FILTER_VAL_NORM)
869                         return lval;
870                 rval = test_arg(arg, arg->num.right, error_str);
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) {
877                         lval = test_arg(arg, arg->op.left, error_str);
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;
884                                 rval = test_arg(arg, arg->op.right, error_str);
885                                 if (rval != FILTER_VAL_NORM)
886                                         return rval;
887
888                                 return reparent_op_arg(parent, arg, arg->op.right,
889                                                        error_str);
890
891                         case FILTER_VAL_FALSE:
892                                 if (arg->op.type == FILTER_OP_AND)
893                                         return FILTER_VAL_FALSE;
894                                 rval = test_arg(arg, arg->op.right, error_str);
895                                 if (rval != FILTER_VAL_NORM)
896                                         return rval;
897
898                                 return reparent_op_arg(parent, arg, arg->op.right,
899                                                        error_str);
900
901                         default:
902                                 return lval;
903                         }
904                 }
905
906                 rval = test_arg(arg, arg->op.right, error_str);
907                 switch (rval) {
908                 case FILTER_VAL_NORM:
909                 default:
910                         break;
911
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
918                         return reparent_op_arg(parent, arg, arg->op.left,
919                                                error_str);
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
927                         return reparent_op_arg(parent, arg, arg->op.left,
928                                                error_str);
929                 }
930
931                 return rval;
932         default:
933                 show_error(error_str, "bad arg in filter tree");
934                 return PEVENT_ERRNO__BAD_FILTER_ARG;
935         }
936         return FILTER_VAL_NORM;
937 }
938
939 /* Remove any unknown event fields */
940 static int collapse_tree(struct filter_arg *arg,
941                          struct filter_arg **arg_collapsed, char **error_str)
942 {
943         int ret;
944
945         ret = test_arg(arg, arg, error_str);
946         switch (ret) {
947         case FILTER_VAL_NORM:
948                 break;
949
950         case FILTER_VAL_TRUE:
951         case FILTER_VAL_FALSE:
952                 free_arg(arg);
953                 arg = allocate_arg();
954                 if (arg) {
955                         arg->type = FILTER_ARG_BOOLEAN;
956                         arg->boolean.value = ret == FILTER_VAL_TRUE;
957                 } else {
958                         show_error(error_str, "Failed to allocate filter arg");
959                         ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
960                 }
961                 break;
962
963         default:
964                 /* test_arg() already set the error_str */
965                 free_arg(arg);
966                 arg = NULL;
967                 break;
968         }
969
970         *arg_collapsed = arg;
971         return ret;
972 }
973
974 static enum pevent_errno
975 process_filter(struct event_format *event, struct filter_arg **parg,
976                char **error_str, int not)
977 {
978         enum event_type type;
979         char *token = NULL;
980         struct filter_arg *current_op = NULL;
981         struct filter_arg *current_exp = NULL;
982         struct filter_arg *left_item = NULL;
983         struct filter_arg *arg = NULL;
984         enum op_type op_type;
985         enum filter_op_type btype;
986         enum filter_exp_type etype;
987         enum filter_cmp_type ctype;
988         enum pevent_errno ret;
989
990         *parg = NULL;
991
992         do {
993                 free(token);
994                 type = read_token(&token);
995                 switch (type) {
996                 case EVENT_SQUOTE:
997                 case EVENT_DQUOTE:
998                 case EVENT_ITEM:
999                         ret = create_arg_item(event, token, type, &arg, error_str);
1000                         if (ret < 0)
1001                                 goto fail;
1002                         if (!left_item)
1003                                 left_item = arg;
1004                         else if (current_exp) {
1005                                 ret = add_right(current_exp, arg, error_str);
1006                                 if (ret < 0)
1007                                         goto fail;
1008                                 left_item = NULL;
1009                                 /* Not's only one one expression */
1010                                 if (not) {
1011                                         arg = NULL;
1012                                         if (current_op)
1013                                                 goto fail_syntax;
1014                                         free(token);
1015                                         *parg = current_exp;
1016                                         return 0;
1017                                 }
1018                         } else
1019                                 goto fail_syntax;
1020                         arg = NULL;
1021                         break;
1022
1023                 case EVENT_DELIM:
1024                         if (*token == ',') {
1025                                 show_error(error_str, "Illegal token ','");
1026                                 ret = PEVENT_ERRNO__ILLEGAL_TOKEN;
1027                                 goto fail;
1028                         }
1029
1030                         if (*token == '(') {
1031                                 if (left_item) {
1032                                         show_error(error_str,
1033                                                    "Open paren can not come after item");
1034                                         ret = PEVENT_ERRNO__INVALID_PAREN;
1035                                         goto fail;
1036                                 }
1037                                 if (current_exp) {
1038                                         show_error(error_str,
1039                                                    "Open paren can not come after expression");
1040                                         ret = PEVENT_ERRNO__INVALID_PAREN;
1041                                         goto fail;
1042                                 }
1043
1044                                 ret = process_filter(event, &arg, error_str, 0);
1045                                 if (ret != PEVENT_ERRNO__UNBALANCED_PAREN) {
1046                                         if (ret == 0) {
1047                                                 show_error(error_str,
1048                                                            "Unbalanced number of '('");
1049                                                 ret = PEVENT_ERRNO__UNBALANCED_PAREN;
1050                                         }
1051                                         goto fail;
1052                                 }
1053                                 ret = 0;
1054
1055                                 /* A not wants just one expression */
1056                                 if (not) {
1057                                         if (current_op)
1058                                                 goto fail_syntax;
1059                                         *parg = arg;
1060                                         return 0;
1061                                 }
1062
1063                                 if (current_op)
1064                                         ret = add_right(current_op, arg, error_str);
1065                                 else
1066                                         current_exp = arg;
1067
1068                                 if (ret < 0)
1069                                         goto fail;
1070
1071                         } else { /* ')' */
1072                                 if (!current_op && !current_exp)
1073                                         goto fail_syntax;
1074
1075                                 /* Make sure everything is finished at this level */
1076                                 if (current_exp && !check_op_done(current_exp))
1077                                         goto fail_syntax;
1078                                 if (current_op && !check_op_done(current_op))
1079                                         goto fail_syntax;
1080
1081                                 if (current_op)
1082                                         *parg = current_op;
1083                                 else
1084                                         *parg = current_exp;
1085                                 return PEVENT_ERRNO__UNBALANCED_PAREN;
1086                         }
1087                         break;
1088
1089                 case EVENT_OP:
1090                         op_type = process_op(token, &btype, &ctype, &etype);
1091
1092                         /* All expect a left arg except for NOT */
1093                         switch (op_type) {
1094                         case OP_BOOL:
1095                                 /* Logic ops need a left expression */
1096                                 if (!current_exp && !current_op)
1097                                         goto fail_syntax;
1098                                 /* fall through */
1099                         case OP_NOT:
1100                                 /* logic only processes ops and exp */
1101                                 if (left_item)
1102                                         goto fail_syntax;
1103                                 break;
1104                         case OP_EXP:
1105                         case OP_CMP:
1106                                 if (!left_item)
1107                                         goto fail_syntax;
1108                                 break;
1109                         case OP_NONE:
1110                                 show_error(error_str,
1111                                            "Unknown op token %s", token);
1112                                 ret = PEVENT_ERRNO__UNKNOWN_TOKEN;
1113                                 goto fail;
1114                         }
1115
1116                         ret = 0;
1117                         switch (op_type) {
1118                         case OP_BOOL:
1119                                 arg = create_arg_op(btype);
1120                                 if (arg == NULL)
1121                                         goto fail_alloc;
1122                                 if (current_op)
1123                                         ret = add_left(arg, current_op);
1124                                 else
1125                                         ret = add_left(arg, current_exp);
1126                                 current_op = arg;
1127                                 current_exp = NULL;
1128                                 break;
1129
1130                         case OP_NOT:
1131                                 arg = create_arg_op(btype);
1132                                 if (arg == NULL)
1133                                         goto fail_alloc;
1134                                 if (current_op)
1135                                         ret = add_right(current_op, arg, error_str);
1136                                 if (ret < 0)
1137                                         goto fail;
1138                                 current_exp = arg;
1139                                 ret = process_filter(event, &arg, error_str, 1);
1140                                 if (ret < 0)
1141                                         goto fail;
1142                                 ret = add_right(current_exp, arg, error_str);
1143                                 if (ret < 0)
1144                                         goto fail;
1145                                 break;
1146
1147                         case OP_EXP:
1148                         case OP_CMP:
1149                                 if (op_type == OP_EXP)
1150                                         arg = create_arg_exp(etype);
1151                                 else
1152                                         arg = create_arg_cmp(ctype);
1153                                 if (arg == NULL)
1154                                         goto fail_alloc;
1155
1156                                 if (current_op)
1157                                         ret = add_right(current_op, arg, error_str);
1158                                 if (ret < 0)
1159                                         goto fail;
1160                                 ret = add_left(arg, left_item);
1161                                 if (ret < 0) {
1162                                         arg = NULL;
1163                                         goto fail_syntax;
1164                                 }
1165                                 current_exp = arg;
1166                                 break;
1167                         default:
1168                                 break;
1169                         }
1170                         arg = NULL;
1171                         if (ret < 0)
1172                                 goto fail_syntax;
1173                         break;
1174                 case EVENT_NONE:
1175                         break;
1176                 case EVENT_ERROR:
1177                         goto fail_alloc;
1178                 default:
1179                         goto fail_syntax;
1180                 }
1181         } while (type != EVENT_NONE);
1182
1183         if (!current_op && !current_exp)
1184                 goto fail_syntax;
1185
1186         if (!current_op)
1187                 current_op = current_exp;
1188
1189         ret = collapse_tree(current_op, parg, error_str);
1190         if (ret < 0)
1191                 goto fail;
1192
1193         *parg = current_op;
1194
1195         return 0;
1196
1197  fail_alloc:
1198         show_error(error_str, "failed to allocate filter arg");
1199         ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
1200         goto fail;
1201  fail_syntax:
1202         show_error(error_str, "Syntax error");
1203         ret = PEVENT_ERRNO__SYNTAX_ERROR;
1204  fail:
1205         free_arg(current_op);
1206         free_arg(current_exp);
1207         free_arg(arg);
1208         free(token);
1209         return ret;
1210 }
1211
1212 static enum pevent_errno
1213 process_event(struct event_format *event, const char *filter_str,
1214               struct filter_arg **parg, char **error_str)
1215 {
1216         int ret;
1217
1218         pevent_buffer_init(filter_str, strlen(filter_str));
1219
1220         ret = process_filter(event, parg, error_str, 0);
1221         if (ret < 0)
1222                 return ret;
1223
1224         /* If parg is NULL, then make it into FALSE */
1225         if (!*parg) {
1226                 *parg = allocate_arg();
1227                 if (*parg == NULL)
1228                         return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1229
1230                 (*parg)->type = FILTER_ARG_BOOLEAN;
1231                 (*parg)->boolean.value = FILTER_FALSE;
1232         }
1233
1234         return 0;
1235 }
1236
1237 static enum pevent_errno
1238 filter_event(struct event_filter *filter, struct event_format *event,
1239              const char *filter_str, char **error_str)
1240 {
1241         struct filter_type *filter_type;
1242         struct filter_arg *arg;
1243         enum pevent_errno ret;
1244
1245         if (filter_str) {
1246                 ret = process_event(event, filter_str, &arg, error_str);
1247                 if (ret < 0)
1248                         return ret;
1249
1250         } else {
1251                 /* just add a TRUE arg */
1252                 arg = allocate_arg();
1253                 if (arg == NULL)
1254                         return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1255
1256                 arg->type = FILTER_ARG_BOOLEAN;
1257                 arg->boolean.value = FILTER_TRUE;
1258         }
1259
1260         filter_type = add_filter_type(filter, event->id);
1261         if (filter_type == NULL)
1262                 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1263
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  *
1276  * Returns 0 if the filter was successfully added or a
1277  * negative error code.
1278  */
1279 enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
1280                                                const char *filter_str)
1281 {
1282         struct pevent *pevent = filter->pevent;
1283         struct event_list *event;
1284         struct event_list *events = NULL;
1285         const char *filter_start;
1286         const char *next_event;
1287         char *this_event;
1288         char *event_name = NULL;
1289         char *sys_name = NULL;
1290         char *sp;
1291         enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */
1292         int len;
1293         int ret;
1294         char *error_str = NULL;
1295
1296         /* clear buffer to reset show error */
1297         pevent_buffer_init("", 0);
1298
1299         filter_start = strchr(filter_str, ':');
1300         if (filter_start)
1301                 len = filter_start - filter_str;
1302         else
1303                 len = strlen(filter_str);
1304
1305         do {
1306                 next_event = strchr(filter_str, ',');
1307                 if (next_event &&
1308                     (!filter_start || next_event < filter_start))
1309                         len = next_event - filter_str;
1310                 else if (filter_start)
1311                         len = filter_start - filter_str;
1312                 else
1313                         len = strlen(filter_str);
1314
1315                 this_event = malloc(len + 1);
1316                 if (this_event == NULL) {
1317                         /* This can only happen when events is NULL, but still */
1318                         free_events(events);
1319                         return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1320                 }
1321                 memcpy(this_event, filter_str, len);
1322                 this_event[len] = 0;
1323
1324                 if (next_event)
1325                         next_event++;
1326
1327                 filter_str = next_event;
1328
1329                 sys_name = strtok_r(this_event, "/", &sp);
1330                 event_name = strtok_r(NULL, "/", &sp);
1331
1332                 if (!sys_name) {
1333                         /* This can only happen when events is NULL, but still */
1334                         free_events(events);
1335                         free(this_event);
1336                         return PEVENT_ERRNO__FILTER_NOT_FOUND;
1337                 }
1338
1339                 /* Find this event */
1340                 ret = find_event(pevent, &events, strim(sys_name), strim(event_name));
1341                 if (ret < 0) {
1342                         free_events(events);
1343                         free(this_event);
1344                         return ret;
1345                 }
1346                 free(this_event);
1347         } while (filter_str);
1348
1349         /* Skip the ':' */
1350         if (filter_start)
1351                 filter_start++;
1352
1353         /* filter starts here */
1354         for (event = events; event; event = event->next) {
1355                 ret = filter_event(filter, event->event, filter_start,
1356                                    &error_str);
1357                 /* Failures are returned if a parse error happened */
1358                 if (ret < 0)
1359                         rtn = ret;
1360
1361                 if (ret >= 0 && pevent->test_filters) {
1362                         char *test;
1363                         test = pevent_filter_make_string(filter, event->event->id);
1364                         printf(" '%s: %s'\n", event->event->name, test);
1365                         free(test);
1366                 }
1367         }
1368
1369         free_events(events);
1370
1371         if (rtn >= 0 && pevent->test_filters)
1372                 exit(0);
1373
1374         return rtn;
1375 }
1376
1377 static void free_filter_type(struct filter_type *filter_type)
1378 {
1379         free_arg(filter_type->filter);
1380 }
1381
1382 /**
1383  * pevent_filter_remove_event - remove a filter for an event
1384  * @filter: the event filter to remove from
1385  * @event_id: the event to remove a filter for
1386  *
1387  * Removes the filter saved for an event defined by @event_id
1388  * from the @filter.
1389  *
1390  * Returns 1: if an event was removed
1391  *   0: if the event was not found
1392  */
1393 int pevent_filter_remove_event(struct event_filter *filter,
1394                                int event_id)
1395 {
1396         struct filter_type *filter_type;
1397         unsigned long len;
1398
1399         if (!filter->filters)
1400                 return 0;
1401
1402         filter_type = find_filter_type(filter, event_id);
1403
1404         if (!filter_type)
1405                 return 0;
1406
1407         free_filter_type(filter_type);
1408
1409         /* The filter_type points into the event_filters array */
1410         len = (unsigned long)(filter->event_filters + filter->filters) -
1411                 (unsigned long)(filter_type + 1);
1412
1413         memmove(filter_type, filter_type + 1, len);
1414         filter->filters--;
1415
1416         memset(&filter->event_filters[filter->filters], 0,
1417                sizeof(*filter_type));
1418
1419         return 1;
1420 }
1421
1422 /**
1423  * pevent_filter_reset - clear all filters in a filter
1424  * @filter: the event filter to reset
1425  *
1426  * Removes all filters from a filter and resets it.
1427  */
1428 void pevent_filter_reset(struct event_filter *filter)
1429 {
1430         int i;
1431
1432         for (i = 0; i < filter->filters; i++)
1433                 free_filter_type(&filter->event_filters[i]);
1434
1435         free(filter->event_filters);
1436         filter->filters = 0;
1437         filter->event_filters = NULL;
1438 }
1439
1440 void pevent_filter_free(struct event_filter *filter)
1441 {
1442         pevent_unref(filter->pevent);
1443
1444         pevent_filter_reset(filter);
1445
1446         free(filter);
1447 }
1448
1449 static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg);
1450
1451 static int copy_filter_type(struct event_filter *filter,
1452                              struct event_filter *source,
1453                              struct filter_type *filter_type)
1454 {
1455         struct filter_arg *arg;
1456         struct event_format *event;
1457         const char *sys;
1458         const char *name;
1459         char *str;
1460
1461         /* Can't assume that the pevent's are the same */
1462         sys = filter_type->event->system;
1463         name = filter_type->event->name;
1464         event = pevent_find_event_by_name(filter->pevent, sys, name);
1465         if (!event)
1466                 return -1;
1467
1468         str = arg_to_str(source, filter_type->filter);
1469         if (!str)
1470                 return -1;
1471
1472         if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
1473                 /* Add trivial event */
1474                 arg = allocate_arg();
1475                 if (arg == NULL)
1476                         return -1;
1477
1478                 arg->type = FILTER_ARG_BOOLEAN;
1479                 if (strcmp(str, "TRUE") == 0)
1480                         arg->boolean.value = 1;
1481                 else
1482                         arg->boolean.value = 0;
1483
1484                 filter_type = add_filter_type(filter, event->id);
1485                 if (filter_type == NULL)
1486                         return -1;
1487
1488                 filter_type->filter = arg;
1489
1490                 free(str);
1491                 return 0;
1492         }
1493
1494         filter_event(filter, event, str, NULL);
1495         free(str);
1496
1497         return 0;
1498 }
1499
1500 /**
1501  * pevent_filter_copy - copy a filter using another filter
1502  * @dest - the filter to copy to
1503  * @source - the filter to copy from
1504  *
1505  * Returns 0 on success and -1 if not all filters were copied
1506  */
1507 int pevent_filter_copy(struct event_filter *dest, struct event_filter *source)
1508 {
1509         int ret = 0;
1510         int i;
1511
1512         pevent_filter_reset(dest);
1513
1514         for (i = 0; i < source->filters; i++) {
1515                 if (copy_filter_type(dest, source, &source->event_filters[i]))
1516                         ret = -1;
1517         }
1518         return ret;
1519 }
1520
1521
1522 /**
1523  * pevent_update_trivial - update the trivial filters with the given filter
1524  * @dest - the filter to update
1525  * @source - the filter as the source of the update
1526  * @type - the type of trivial filter to update.
1527  *
1528  * Scan dest for trivial events matching @type to replace with the source.
1529  *
1530  * Returns 0 on success and -1 if there was a problem updating, but
1531  *   events may have still been updated on error.
1532  */
1533 int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
1534                           enum filter_trivial_type type)
1535 {
1536         struct pevent *src_pevent;
1537         struct pevent *dest_pevent;
1538         struct event_format *event;
1539         struct filter_type *filter_type;
1540         struct filter_arg *arg;
1541         char *str;
1542         int i;
1543
1544         src_pevent = source->pevent;
1545         dest_pevent = dest->pevent;
1546
1547         /* Do nothing if either of the filters has nothing to filter */
1548         if (!dest->filters || !source->filters)
1549                 return 0;
1550
1551         for (i = 0; i < dest->filters; i++) {
1552                 filter_type = &dest->event_filters[i];
1553                 arg = filter_type->filter;
1554                 if (arg->type != FILTER_ARG_BOOLEAN)
1555                         continue;
1556                 if ((arg->boolean.value && type == FILTER_TRIVIAL_FALSE) ||
1557                     (!arg->boolean.value && type == FILTER_TRIVIAL_TRUE))
1558                         continue;
1559
1560                 event = filter_type->event;
1561
1562                 if (src_pevent != dest_pevent) {
1563                         /* do a look up */
1564                         event = pevent_find_event_by_name(src_pevent,
1565                                                           event->system,
1566                                                           event->name);
1567                         if (!event)
1568                                 return -1;
1569                 }
1570
1571                 str = pevent_filter_make_string(source, event->id);
1572                 if (!str)
1573                         continue;
1574
1575                 /* Don't bother if the filter is trivial too */
1576                 if (strcmp(str, "TRUE") != 0 && strcmp(str, "FALSE") != 0)
1577                         filter_event(dest, event, str, NULL);
1578                 free(str);
1579         }
1580         return 0;
1581 }
1582
1583 /**
1584  * pevent_filter_clear_trivial - clear TRUE and FALSE filters
1585  * @filter: the filter to remove trivial filters from
1586  * @type: remove only true, false, or both
1587  *
1588  * Removes filters that only contain a TRUE or FALES boolean arg.
1589  *
1590  * Returns 0 on success and -1 if there was a problem.
1591  */
1592 int pevent_filter_clear_trivial(struct event_filter *filter,
1593                                  enum filter_trivial_type type)
1594 {
1595         struct filter_type *filter_type;
1596         int count = 0;
1597         int *ids = NULL;
1598         int i;
1599
1600         if (!filter->filters)
1601                 return 0;
1602
1603         /*
1604          * Two steps, first get all ids with trivial filters.
1605          *  then remove those ids.
1606          */
1607         for (i = 0; i < filter->filters; i++) {
1608                 int *new_ids;
1609
1610                 filter_type = &filter->event_filters[i];
1611                 if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1612                         continue;
1613                 switch (type) {
1614                 case FILTER_TRIVIAL_FALSE:
1615                         if (filter_type->filter->boolean.value)
1616                                 continue;
1617                 case FILTER_TRIVIAL_TRUE:
1618                         if (!filter_type->filter->boolean.value)
1619                                 continue;
1620                 default:
1621                         break;
1622                 }
1623
1624                 new_ids = realloc(ids, sizeof(*ids) * (count + 1));
1625                 if (!new_ids) {
1626                         free(ids);
1627                         return -1;
1628                 }
1629
1630                 ids = new_ids;
1631                 ids[count++] = filter_type->event_id;
1632         }
1633
1634         if (!count)
1635                 return 0;
1636
1637         for (i = 0; i < count; i++)
1638                 pevent_filter_remove_event(filter, ids[i]);
1639
1640         free(ids);
1641         return 0;
1642 }
1643
1644 /**
1645  * pevent_filter_event_has_trivial - return true event contains trivial filter
1646  * @filter: the filter with the information
1647  * @event_id: the id of the event to test
1648  * @type: trivial type to test for (TRUE, FALSE, EITHER)
1649  *
1650  * Returns 1 if the event contains a matching trivial type
1651  *  otherwise 0.
1652  */
1653 int pevent_filter_event_has_trivial(struct event_filter *filter,
1654                                     int event_id,
1655                                     enum filter_trivial_type type)
1656 {
1657         struct filter_type *filter_type;
1658
1659         if (!filter->filters)
1660                 return 0;
1661
1662         filter_type = find_filter_type(filter, event_id);
1663
1664         if (!filter_type)
1665                 return 0;
1666
1667         if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1668                 return 0;
1669
1670         switch (type) {
1671         case FILTER_TRIVIAL_FALSE:
1672                 return !filter_type->filter->boolean.value;
1673
1674         case FILTER_TRIVIAL_TRUE:
1675                 return filter_type->filter->boolean.value;
1676         default:
1677                 return 1;
1678         }
1679 }
1680
1681 static int test_filter(struct event_format *event, struct filter_arg *arg,
1682                        struct pevent_record *record, enum pevent_errno *err);
1683
1684 static const char *
1685 get_comm(struct event_format *event, struct pevent_record *record)
1686 {
1687         const char *comm;
1688         int pid;
1689
1690         pid = pevent_data_pid(event->pevent, record);
1691         comm = pevent_data_comm_from_pid(event->pevent, pid);
1692         return comm;
1693 }
1694
1695 static unsigned long long
1696 get_value(struct event_format *event,
1697           struct format_field *field, struct pevent_record *record)
1698 {
1699         unsigned long long val;
1700
1701         /* Handle our dummy "comm" field */
1702         if (field == &comm) {
1703                 const char *name;
1704
1705                 name = get_comm(event, record);
1706                 return (unsigned long)name;
1707         }
1708
1709         pevent_read_number_field(field, record->data, &val);
1710
1711         if (!(field->flags & FIELD_IS_SIGNED))
1712                 return val;
1713
1714         switch (field->size) {
1715         case 1:
1716                 return (char)val;
1717         case 2:
1718                 return (short)val;
1719         case 4:
1720                 return (int)val;
1721         case 8:
1722                 return (long long)val;
1723         }
1724         return val;
1725 }
1726
1727 static unsigned long long
1728 get_arg_value(struct event_format *event, struct filter_arg *arg,
1729               struct pevent_record *record, enum pevent_errno *err);
1730
1731 static unsigned long long
1732 get_exp_value(struct event_format *event, struct filter_arg *arg,
1733               struct pevent_record *record, enum pevent_errno *err)
1734 {
1735         unsigned long long lval, rval;
1736
1737         lval = get_arg_value(event, arg->exp.left, record, err);
1738         rval = get_arg_value(event, arg->exp.right, record, err);
1739
1740         if (*err) {
1741                 /*
1742                  * There was an error, no need to process anymore.
1743                  */
1744                 return 0;
1745         }
1746
1747         switch (arg->exp.type) {
1748         case FILTER_EXP_ADD:
1749                 return lval + rval;
1750
1751         case FILTER_EXP_SUB:
1752                 return lval - rval;
1753
1754         case FILTER_EXP_MUL:
1755                 return lval * rval;
1756
1757         case FILTER_EXP_DIV:
1758                 return lval / rval;
1759
1760         case FILTER_EXP_MOD:
1761                 return lval % rval;
1762
1763         case FILTER_EXP_RSHIFT:
1764                 return lval >> rval;
1765
1766         case FILTER_EXP_LSHIFT:
1767                 return lval << rval;
1768
1769         case FILTER_EXP_AND:
1770                 return lval & rval;
1771
1772         case FILTER_EXP_OR:
1773                 return lval | rval;
1774
1775         case FILTER_EXP_XOR:
1776                 return lval ^ rval;
1777
1778         case FILTER_EXP_NOT:
1779         default:
1780                 if (!*err)
1781                         *err = PEVENT_ERRNO__INVALID_EXP_TYPE;
1782         }
1783         return 0;
1784 }
1785
1786 static unsigned long long
1787 get_arg_value(struct event_format *event, struct filter_arg *arg,
1788               struct pevent_record *record, enum pevent_errno *err)
1789 {
1790         switch (arg->type) {
1791         case FILTER_ARG_FIELD:
1792                 return get_value(event, arg->field.field, record);
1793
1794         case FILTER_ARG_VALUE:
1795                 if (arg->value.type != FILTER_NUMBER) {
1796                         if (!*err)
1797                                 *err = PEVENT_ERRNO__NOT_A_NUMBER;
1798                 }
1799                 return arg->value.val;
1800
1801         case FILTER_ARG_EXP:
1802                 return get_exp_value(event, arg, record, err);
1803
1804         default:
1805                 if (!*err)
1806                         *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
1807         }
1808         return 0;
1809 }
1810
1811 static int test_num(struct event_format *event, struct filter_arg *arg,
1812                     struct pevent_record *record, enum pevent_errno *err)
1813 {
1814         unsigned long long lval, rval;
1815
1816         lval = get_arg_value(event, arg->num.left, record, err);
1817         rval = get_arg_value(event, arg->num.right, record, err);
1818
1819         if (*err) {
1820                 /*
1821                  * There was an error, no need to process anymore.
1822                  */
1823                 return 0;
1824         }
1825
1826         switch (arg->num.type) {
1827         case FILTER_CMP_EQ:
1828                 return lval == rval;
1829
1830         case FILTER_CMP_NE:
1831                 return lval != rval;
1832
1833         case FILTER_CMP_GT:
1834                 return lval > rval;
1835
1836         case FILTER_CMP_LT:
1837                 return lval < rval;
1838
1839         case FILTER_CMP_GE:
1840                 return lval >= rval;
1841
1842         case FILTER_CMP_LE:
1843                 return lval <= rval;
1844
1845         default:
1846                 if (!*err)
1847                         *err = PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
1848                 return 0;
1849         }
1850 }
1851
1852 static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
1853 {
1854         struct event_format *event;
1855         struct pevent *pevent;
1856         unsigned long long addr;
1857         const char *val = NULL;
1858         char hex[64];
1859
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                 }
1889         }
1890
1891         return val;
1892 }
1893
1894 static int test_str(struct event_format *event, struct filter_arg *arg,
1895                     struct pevent_record *record, enum pevent_errno *err)
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                 if (!*err)
1920                         *err = PEVENT_ERRNO__ILLEGAL_STRING_CMP;
1921                 return 0;
1922         }
1923 }
1924
1925 static int test_op(struct event_format *event, struct filter_arg *arg,
1926                    struct pevent_record *record, enum pevent_errno *err)
1927 {
1928         switch (arg->op.type) {
1929         case FILTER_OP_AND:
1930                 return test_filter(event, arg->op.left, record, err) &&
1931                         test_filter(event, arg->op.right, record, err);
1932
1933         case FILTER_OP_OR:
1934                 return test_filter(event, arg->op.left, record, err) ||
1935                         test_filter(event, arg->op.right, record, err);
1936
1937         case FILTER_OP_NOT:
1938                 return !test_filter(event, arg->op.right, record, err);
1939
1940         default:
1941                 if (!*err)
1942                         *err = PEVENT_ERRNO__INVALID_OP_TYPE;
1943                 return 0;
1944         }
1945 }
1946
1947 static int test_filter(struct event_format *event, struct filter_arg *arg,
1948                        struct pevent_record *record, enum pevent_errno *err)
1949 {
1950         if (*err) {
1951                 /*
1952                  * There was an error, no need to process anymore.
1953                  */
1954                 return 0;
1955         }
1956
1957         switch (arg->type) {
1958         case FILTER_ARG_BOOLEAN:
1959                 /* easy case */
1960                 return arg->boolean.value;
1961
1962         case FILTER_ARG_OP:
1963                 return test_op(event, arg, record, err);
1964
1965         case FILTER_ARG_NUM:
1966                 return test_num(event, arg, record, err);
1967
1968         case FILTER_ARG_STR:
1969                 return test_str(event, arg, record, err);
1970
1971         case FILTER_ARG_EXP:
1972         case FILTER_ARG_VALUE:
1973         case FILTER_ARG_FIELD:
1974                 /*
1975                  * Expressions, fields and values evaluate
1976                  * to true if they return non zero
1977                  */
1978                 return !!get_arg_value(event, arg, record, err);
1979
1980         default:
1981                 if (!*err)
1982                         *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
1983                 return 0;
1984         }
1985 }
1986
1987 /**
1988  * pevent_event_filtered - return true if event has filter
1989  * @filter: filter struct with filter information
1990  * @event_id: event id to test if filter exists
1991  *
1992  * Returns 1 if filter found for @event_id
1993  *   otherwise 0;
1994  */
1995 int pevent_event_filtered(struct event_filter *filter, int event_id)
1996 {
1997         struct filter_type *filter_type;
1998
1999         if (!filter->filters)
2000                 return 0;
2001
2002         filter_type = find_filter_type(filter, event_id);
2003
2004         return filter_type ? 1 : 0;
2005 }
2006
2007 /**
2008  * pevent_filter_match - test if a record matches a filter
2009  * @filter: filter struct with filter information
2010  * @record: the record to test against the filter
2011  *
2012  * Returns: match result or error code (prefixed with PEVENT_ERRNO__)
2013  * FILTER_MATCH - filter found for event and @record matches
2014  * FILTER_MISS  - filter found for event and @record does not match
2015  * FILTER_NOT_FOUND - no filter found for @record's event
2016  * NO_FILTER - if no filters exist
2017  * otherwise - error occurred during test
2018  */
2019 enum pevent_errno pevent_filter_match(struct event_filter *filter,
2020                                       struct pevent_record *record)
2021 {
2022         struct pevent *pevent = filter->pevent;
2023         struct filter_type *filter_type;
2024         int event_id;
2025         int ret;
2026         enum pevent_errno err = 0;
2027
2028         if (!filter->filters)
2029                 return PEVENT_ERRNO__NO_FILTER;
2030
2031         event_id = pevent_data_type(pevent, record);
2032
2033         filter_type = find_filter_type(filter, event_id);
2034         if (!filter_type)
2035                 return PEVENT_ERRNO__FILTER_NOT_FOUND;
2036
2037         ret = test_filter(filter_type->event, filter_type->filter, record, &err);
2038         if (err)
2039                 return err;
2040
2041         return ret ? PEVENT_ERRNO__FILTER_MATCH : PEVENT_ERRNO__FILTER_MISS;
2042 }
2043
2044 static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
2045 {
2046         char *str = NULL;
2047         char *left = NULL;
2048         char *right = NULL;
2049         char *op = NULL;
2050         int left_val = -1;
2051         int right_val = -1;
2052         int val;
2053         int len;
2054
2055         switch (arg->op.type) {
2056         case FILTER_OP_AND:
2057                 op = "&&";
2058                 /* fall through */
2059         case FILTER_OP_OR:
2060                 if (!op)
2061                         op = "||";
2062
2063                 left = arg_to_str(filter, arg->op.left);
2064                 right = arg_to_str(filter, arg->op.right);
2065                 if (!left || !right)
2066                         break;
2067
2068                 /* Try to consolidate boolean values */
2069                 if (strcmp(left, "TRUE") == 0)
2070                         left_val = 1;
2071                 else if (strcmp(left, "FALSE") == 0)
2072                         left_val = 0;
2073
2074                 if (strcmp(right, "TRUE") == 0)
2075                         right_val = 1;
2076                 else if (strcmp(right, "FALSE") == 0)
2077                         right_val = 0;
2078
2079                 if (left_val >= 0) {
2080                         if ((arg->op.type == FILTER_OP_AND && !left_val) ||
2081                             (arg->op.type == FILTER_OP_OR && left_val)) {
2082                                 /* Just return left value */
2083                                 str = left;
2084                                 left = NULL;
2085                                 break;
2086                         }
2087                         if (right_val >= 0) {
2088                                 /* just evaluate this. */
2089                                 val = 0;
2090                                 switch (arg->op.type) {
2091                                 case FILTER_OP_AND:
2092                                         val = left_val && right_val;
2093                                         break;
2094                                 case FILTER_OP_OR:
2095                                         val = left_val || right_val;
2096                                         break;
2097                                 default:
2098                                         break;
2099                                 }
2100                                 str = malloc_or_die(6);
2101                                 if (val)
2102                                         strcpy(str, "TRUE");
2103                                 else
2104                                         strcpy(str, "FALSE");
2105                                 break;
2106                         }
2107                 }
2108                 if (right_val >= 0) {
2109                         if ((arg->op.type == FILTER_OP_AND && !right_val) ||
2110                             (arg->op.type == FILTER_OP_OR && right_val)) {
2111                                 /* Just return right value */
2112                                 str = right;
2113                                 right = NULL;
2114                                 break;
2115                         }
2116                         /* The right value is meaningless */
2117                         str = left;
2118                         left = NULL;
2119                         break;
2120                 }
2121
2122                 len = strlen(left) + strlen(right) + strlen(op) + 10;
2123                 str = malloc_or_die(len);
2124                 snprintf(str, len, "(%s) %s (%s)",
2125                          left, op, right);
2126                 break;
2127
2128         case FILTER_OP_NOT:
2129                 op = "!";
2130                 right = arg_to_str(filter, arg->op.right);
2131                 if (!right)
2132                         break;
2133
2134                 /* See if we can consolidate */
2135                 if (strcmp(right, "TRUE") == 0)
2136                         right_val = 1;
2137                 else if (strcmp(right, "FALSE") == 0)
2138                         right_val = 0;
2139                 if (right_val >= 0) {
2140                         /* just return the opposite */
2141                         str = malloc_or_die(6);
2142                         if (right_val)
2143                                 strcpy(str, "FALSE");
2144                         else
2145                                 strcpy(str, "TRUE");
2146                         break;
2147                 }
2148                 len = strlen(right) + strlen(op) + 3;
2149                 str = malloc_or_die(len);
2150                 snprintf(str, len, "%s(%s)", op, right);
2151                 break;
2152
2153         default:
2154                 /* ?? */
2155                 break;
2156         }
2157         free(left);
2158         free(right);
2159         return str;
2160 }
2161
2162 static char *val_to_str(struct event_filter *filter, struct filter_arg *arg)
2163 {
2164         char *str;
2165
2166         str = malloc_or_die(30);
2167
2168         snprintf(str, 30, "%lld", arg->value.val);
2169
2170         return str;
2171 }
2172
2173 static char *field_to_str(struct event_filter *filter, struct filter_arg *arg)
2174 {
2175         return strdup(arg->field.field->name);
2176 }
2177
2178 static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
2179 {
2180         char *lstr;
2181         char *rstr;
2182         char *op;
2183         char *str = NULL;
2184         int len;
2185
2186         lstr = arg_to_str(filter, arg->exp.left);
2187         rstr = arg_to_str(filter, arg->exp.right);
2188         if (!lstr || !rstr)
2189                 goto out;
2190
2191         switch (arg->exp.type) {
2192         case FILTER_EXP_ADD:
2193                 op = "+";
2194                 break;
2195         case FILTER_EXP_SUB:
2196                 op = "-";
2197                 break;
2198         case FILTER_EXP_MUL:
2199                 op = "*";
2200                 break;
2201         case FILTER_EXP_DIV:
2202                 op = "/";
2203                 break;
2204         case FILTER_EXP_MOD:
2205                 op = "%";
2206                 break;
2207         case FILTER_EXP_RSHIFT:
2208                 op = ">>";
2209                 break;
2210         case FILTER_EXP_LSHIFT:
2211                 op = "<<";
2212                 break;
2213         case FILTER_EXP_AND:
2214                 op = "&";
2215                 break;
2216         case FILTER_EXP_OR:
2217                 op = "|";
2218                 break;
2219         case FILTER_EXP_XOR:
2220                 op = "^";
2221                 break;
2222         default:
2223                 die("oops in exp");
2224         }
2225
2226         len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
2227         str = malloc_or_die(len);
2228         snprintf(str, len, "%s %s %s", lstr, op, rstr);
2229 out:
2230         free(lstr);
2231         free(rstr);
2232
2233         return str;
2234 }
2235
2236 static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
2237 {
2238         char *lstr;
2239         char *rstr;
2240         char *str = NULL;
2241         char *op = NULL;
2242         int len;
2243
2244         lstr = arg_to_str(filter, arg->num.left);
2245         rstr = arg_to_str(filter, arg->num.right);
2246         if (!lstr || !rstr)
2247                 goto out;
2248
2249         switch (arg->num.type) {
2250         case FILTER_CMP_EQ:
2251                 op = "==";
2252                 /* fall through */
2253         case FILTER_CMP_NE:
2254                 if (!op)
2255                         op = "!=";
2256                 /* fall through */
2257         case FILTER_CMP_GT:
2258                 if (!op)
2259                         op = ">";
2260                 /* fall through */
2261         case FILTER_CMP_LT:
2262                 if (!op)
2263                         op = "<";
2264                 /* fall through */
2265         case FILTER_CMP_GE:
2266                 if (!op)
2267                         op = ">=";
2268                 /* fall through */
2269         case FILTER_CMP_LE:
2270                 if (!op)
2271                         op = "<=";
2272
2273                 len = strlen(lstr) + strlen(op) + strlen(rstr) + 4;
2274                 str = malloc_or_die(len);
2275                 sprintf(str, "%s %s %s", lstr, op, rstr);
2276
2277                 break;
2278
2279         default:
2280                 /* ?? */
2281                 break;
2282         }
2283
2284 out:
2285         free(lstr);
2286         free(rstr);
2287         return str;
2288 }
2289
2290 static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
2291 {
2292         char *str = NULL;
2293         char *op = NULL;
2294         int len;
2295
2296         switch (arg->str.type) {
2297         case FILTER_CMP_MATCH:
2298                 op = "==";
2299                 /* fall through */
2300         case FILTER_CMP_NOT_MATCH:
2301                 if (!op)
2302                         op = "!=";
2303                 /* fall through */
2304         case FILTER_CMP_REGEX:
2305                 if (!op)
2306                         op = "=~";
2307                 /* fall through */
2308         case FILTER_CMP_NOT_REGEX:
2309                 if (!op)
2310                         op = "!~";
2311
2312                 len = strlen(arg->str.field->name) + strlen(op) +
2313                         strlen(arg->str.val) + 6;
2314                 str = malloc_or_die(len);
2315                 snprintf(str, len, "%s %s \"%s\"",
2316                          arg->str.field->name,
2317                          op, arg->str.val);
2318                 break;
2319
2320         default:
2321                 /* ?? */
2322                 break;
2323         }
2324         return str;
2325 }
2326
2327 static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
2328 {
2329         char *str;
2330
2331         switch (arg->type) {
2332         case FILTER_ARG_BOOLEAN:
2333                 str = malloc_or_die(6);
2334                 if (arg->boolean.value)
2335                         strcpy(str, "TRUE");
2336                 else
2337                         strcpy(str, "FALSE");
2338                 return str;
2339
2340         case FILTER_ARG_OP:
2341                 return op_to_str(filter, arg);
2342
2343         case FILTER_ARG_NUM:
2344                 return num_to_str(filter, arg);
2345
2346         case FILTER_ARG_STR:
2347                 return str_to_str(filter, arg);
2348
2349         case FILTER_ARG_VALUE:
2350                 return val_to_str(filter, arg);
2351
2352         case FILTER_ARG_FIELD:
2353                 return field_to_str(filter, arg);
2354
2355         case FILTER_ARG_EXP:
2356                 return exp_to_str(filter, arg);
2357
2358         default:
2359                 /* ?? */
2360                 return NULL;
2361         }
2362
2363 }
2364
2365 /**
2366  * pevent_filter_make_string - return a string showing the filter
2367  * @filter: filter struct with filter information
2368  * @event_id: the event id to return the filter string with
2369  *
2370  * Returns a string that displays the filter contents.
2371  *  This string must be freed with free(str).
2372  *  NULL is returned if no filter is found.
2373  */
2374 char *
2375 pevent_filter_make_string(struct event_filter *filter, int event_id)
2376 {
2377         struct filter_type *filter_type;
2378
2379         if (!filter->filters)
2380                 return NULL;
2381
2382         filter_type = find_filter_type(filter, event_id);
2383
2384         if (!filter_type)
2385                 return NULL;
2386
2387         return arg_to_str(filter, filter_type->filter);
2388 }
2389
2390 /**
2391  * pevent_filter_compare - compare two filters and return if they are the same
2392  * @filter1: Filter to compare with @filter2
2393  * @filter2: Filter to compare with @filter1
2394  *
2395  * Returns:
2396  *  1 if the two filters hold the same content.
2397  *  0 if they do not.
2398  */
2399 int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2)
2400 {
2401         struct filter_type *filter_type1;
2402         struct filter_type *filter_type2;
2403         char *str1, *str2;
2404         int result;
2405         int i;
2406
2407         /* Do the easy checks first */
2408         if (filter1->filters != filter2->filters)
2409                 return 0;
2410         if (!filter1->filters && !filter2->filters)
2411                 return 1;
2412
2413         /*
2414          * Now take a look at each of the events to see if they have the same
2415          * filters to them.
2416          */
2417         for (i = 0; i < filter1->filters; i++) {
2418                 filter_type1 = &filter1->event_filters[i];
2419                 filter_type2 = find_filter_type(filter2, filter_type1->event_id);
2420                 if (!filter_type2)
2421                         break;
2422                 if (filter_type1->filter->type != filter_type2->filter->type)
2423                         break;
2424                 switch (filter_type1->filter->type) {
2425                 case FILTER_TRIVIAL_FALSE:
2426                 case FILTER_TRIVIAL_TRUE:
2427                         /* trivial types just need the type compared */
2428                         continue;
2429                 default:
2430                         break;
2431                 }
2432                 /* The best way to compare complex filters is with strings */
2433                 str1 = arg_to_str(filter1, filter_type1->filter);
2434                 str2 = arg_to_str(filter2, filter_type2->filter);
2435                 if (str1 && str2)
2436                         result = strcmp(str1, str2) != 0;
2437                 else
2438                         /* bail out if allocation fails */
2439                         result = 1;
2440
2441                 free(str1);
2442                 free(str2);
2443                 if (result)
2444                         break;
2445         }
2446
2447         if (i < filter1->filters)
2448                 return 0;
2449         return 1;
2450 }
2451