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