xref: /aosp_15_r20/external/libtracefs/src/tracefs-sqlhist.c (revision 287e80b3a36113050663245e7f2c00d274188f18)
1*287e80b3SSadaf Ebrahimi // SPDX-License-Identifier: LGPL-2.1
2*287e80b3SSadaf Ebrahimi /*
3*287e80b3SSadaf Ebrahimi  * Copyright (C) 2021 VMware Inc, Steven Rostedt <[email protected]>
4*287e80b3SSadaf Ebrahimi  *
5*287e80b3SSadaf Ebrahimi  * Updates:
6*287e80b3SSadaf Ebrahimi  * Copyright (C) 2021, VMware, Tzvetomir Stoyanov <[email protected]>
7*287e80b3SSadaf Ebrahimi  *
8*287e80b3SSadaf Ebrahimi  */
9*287e80b3SSadaf Ebrahimi #include <trace-seq.h>
10*287e80b3SSadaf Ebrahimi #include <stdlib.h>
11*287e80b3SSadaf Ebrahimi #include <stdarg.h>
12*287e80b3SSadaf Ebrahimi #include <ctype.h>
13*287e80b3SSadaf Ebrahimi #include <errno.h>
14*287e80b3SSadaf Ebrahimi 
15*287e80b3SSadaf Ebrahimi #include "tracefs.h"
16*287e80b3SSadaf Ebrahimi #include "tracefs-local.h"
17*287e80b3SSadaf Ebrahimi #include "sqlhist-parse.h"
18*287e80b3SSadaf Ebrahimi 
19*287e80b3SSadaf Ebrahimi extern int yylex_init(void* ptr_yy_globals);
20*287e80b3SSadaf Ebrahimi extern int yylex_init_extra(struct sqlhist_bison *sb, void* ptr_yy_globals);
21*287e80b3SSadaf Ebrahimi extern int yylex_destroy (void * yyscanner );
22*287e80b3SSadaf Ebrahimi 
23*287e80b3SSadaf Ebrahimi struct str_hash {
24*287e80b3SSadaf Ebrahimi 	struct str_hash		*next;
25*287e80b3SSadaf Ebrahimi 	char			*str;
26*287e80b3SSadaf Ebrahimi };
27*287e80b3SSadaf Ebrahimi 
28*287e80b3SSadaf Ebrahimi enum alias_type {
29*287e80b3SSadaf Ebrahimi 	ALIAS_EVENT,
30*287e80b3SSadaf Ebrahimi 	ALIAS_FIELD,
31*287e80b3SSadaf Ebrahimi };
32*287e80b3SSadaf Ebrahimi 
33*287e80b3SSadaf Ebrahimi enum field_type {
34*287e80b3SSadaf Ebrahimi 	FIELD_NONE,
35*287e80b3SSadaf Ebrahimi 	FIELD_FROM,
36*287e80b3SSadaf Ebrahimi 	FIELD_TO,
37*287e80b3SSadaf Ebrahimi };
38*287e80b3SSadaf Ebrahimi 
39*287e80b3SSadaf Ebrahimi #define for_each_field(expr, field, table) \
40*287e80b3SSadaf Ebrahimi 	for (expr = (table)->fields; expr; expr = (field)->next)
41*287e80b3SSadaf Ebrahimi 
42*287e80b3SSadaf Ebrahimi struct field {
43*287e80b3SSadaf Ebrahimi 	struct expr		*next;	/* private link list */
44*287e80b3SSadaf Ebrahimi 	const char		*system;
45*287e80b3SSadaf Ebrahimi 	const char		*event_name;
46*287e80b3SSadaf Ebrahimi 	struct tep_event	*event;
47*287e80b3SSadaf Ebrahimi 	const char		*raw;
48*287e80b3SSadaf Ebrahimi 	const char		*label;
49*287e80b3SSadaf Ebrahimi 	const char		*field;
50*287e80b3SSadaf Ebrahimi 	const char		*type;
51*287e80b3SSadaf Ebrahimi 	enum field_type		ftype;
52*287e80b3SSadaf Ebrahimi };
53*287e80b3SSadaf Ebrahimi 
54*287e80b3SSadaf Ebrahimi struct filter {
55*287e80b3SSadaf Ebrahimi 	enum filter_type	type;
56*287e80b3SSadaf Ebrahimi 	struct expr		*lval;
57*287e80b3SSadaf Ebrahimi 	struct expr		*rval;
58*287e80b3SSadaf Ebrahimi };
59*287e80b3SSadaf Ebrahimi 
60*287e80b3SSadaf Ebrahimi struct match {
61*287e80b3SSadaf Ebrahimi 	struct match		*next;
62*287e80b3SSadaf Ebrahimi 	struct expr		*lval;
63*287e80b3SSadaf Ebrahimi 	struct expr		*rval;
64*287e80b3SSadaf Ebrahimi };
65*287e80b3SSadaf Ebrahimi 
66*287e80b3SSadaf Ebrahimi struct compare {
67*287e80b3SSadaf Ebrahimi 	enum compare_type	type;
68*287e80b3SSadaf Ebrahimi 	struct expr		*lval;
69*287e80b3SSadaf Ebrahimi 	struct expr		*rval;
70*287e80b3SSadaf Ebrahimi 	const char		*name;
71*287e80b3SSadaf Ebrahimi };
72*287e80b3SSadaf Ebrahimi 
73*287e80b3SSadaf Ebrahimi enum expr_type
74*287e80b3SSadaf Ebrahimi {
75*287e80b3SSadaf Ebrahimi 	EXPR_NUMBER,
76*287e80b3SSadaf Ebrahimi 	EXPR_STRING,
77*287e80b3SSadaf Ebrahimi 	EXPR_FIELD,
78*287e80b3SSadaf Ebrahimi 	EXPR_FILTER,
79*287e80b3SSadaf Ebrahimi 	EXPR_COMPARE,
80*287e80b3SSadaf Ebrahimi };
81*287e80b3SSadaf Ebrahimi 
82*287e80b3SSadaf Ebrahimi struct expr {
83*287e80b3SSadaf Ebrahimi 	struct expr		*free_list;
84*287e80b3SSadaf Ebrahimi 	struct expr		*next;
85*287e80b3SSadaf Ebrahimi 	enum expr_type		type;
86*287e80b3SSadaf Ebrahimi 	int			line;
87*287e80b3SSadaf Ebrahimi 	int			idx;
88*287e80b3SSadaf Ebrahimi 	union {
89*287e80b3SSadaf Ebrahimi 		struct field	field;
90*287e80b3SSadaf Ebrahimi 		struct filter	filter;
91*287e80b3SSadaf Ebrahimi 		struct compare	compare;
92*287e80b3SSadaf Ebrahimi 		const char	*string;
93*287e80b3SSadaf Ebrahimi 		long		number;
94*287e80b3SSadaf Ebrahimi 	};
95*287e80b3SSadaf Ebrahimi };
96*287e80b3SSadaf Ebrahimi 
97*287e80b3SSadaf Ebrahimi struct sql_table {
98*287e80b3SSadaf Ebrahimi 	struct sqlhist_bison	*sb;
99*287e80b3SSadaf Ebrahimi 	const char		*name;
100*287e80b3SSadaf Ebrahimi 	struct expr		*exprs;
101*287e80b3SSadaf Ebrahimi 	struct expr		*fields;
102*287e80b3SSadaf Ebrahimi 	struct expr		*from;
103*287e80b3SSadaf Ebrahimi 	struct expr		*to;
104*287e80b3SSadaf Ebrahimi 	struct expr		*where;
105*287e80b3SSadaf Ebrahimi 	struct expr		**next_where;
106*287e80b3SSadaf Ebrahimi 	struct match		*matches;
107*287e80b3SSadaf Ebrahimi 	struct match		**next_match;
108*287e80b3SSadaf Ebrahimi 	struct expr		*selections;
109*287e80b3SSadaf Ebrahimi 	struct expr		**next_selection;
110*287e80b3SSadaf Ebrahimi };
111*287e80b3SSadaf Ebrahimi 
my_yyinput(void * extra,char * buf,int max)112*287e80b3SSadaf Ebrahimi __hidden int my_yyinput(void *extra, char *buf, int max)
113*287e80b3SSadaf Ebrahimi {
114*287e80b3SSadaf Ebrahimi 	struct sqlhist_bison *sb = extra;
115*287e80b3SSadaf Ebrahimi 
116*287e80b3SSadaf Ebrahimi 	if (!sb || !sb->buffer)
117*287e80b3SSadaf Ebrahimi 		return -1;
118*287e80b3SSadaf Ebrahimi 
119*287e80b3SSadaf Ebrahimi 	if (sb->buffer_idx + max > sb->buffer_size)
120*287e80b3SSadaf Ebrahimi 		max = sb->buffer_size - sb->buffer_idx;
121*287e80b3SSadaf Ebrahimi 
122*287e80b3SSadaf Ebrahimi 	if (max)
123*287e80b3SSadaf Ebrahimi 		memcpy(buf, sb->buffer + sb->buffer_idx, max);
124*287e80b3SSadaf Ebrahimi 
125*287e80b3SSadaf Ebrahimi 	sb->buffer_idx += max;
126*287e80b3SSadaf Ebrahimi 
127*287e80b3SSadaf Ebrahimi 	return max;
128*287e80b3SSadaf Ebrahimi }
129*287e80b3SSadaf Ebrahimi 
sql_parse_error(struct sqlhist_bison * sb,const char * text,const char * fmt,va_list ap)130*287e80b3SSadaf Ebrahimi __hidden void sql_parse_error(struct sqlhist_bison *sb, const char *text,
131*287e80b3SSadaf Ebrahimi 			      const char *fmt, va_list ap)
132*287e80b3SSadaf Ebrahimi {
133*287e80b3SSadaf Ebrahimi 	const char *buffer = sb->buffer;
134*287e80b3SSadaf Ebrahimi 	struct trace_seq s;
135*287e80b3SSadaf Ebrahimi 	int line = sb->line_no;
136*287e80b3SSadaf Ebrahimi 	int idx = sb->line_idx - strlen(text);
137*287e80b3SSadaf Ebrahimi 	int i;
138*287e80b3SSadaf Ebrahimi 
139*287e80b3SSadaf Ebrahimi 	if (!buffer)
140*287e80b3SSadaf Ebrahimi 		return;
141*287e80b3SSadaf Ebrahimi 
142*287e80b3SSadaf Ebrahimi 	trace_seq_init(&s);
143*287e80b3SSadaf Ebrahimi 	if (!s.buffer) {
144*287e80b3SSadaf Ebrahimi 		tracefs_warning("Error allocating internal buffer\n");
145*287e80b3SSadaf Ebrahimi 		return;
146*287e80b3SSadaf Ebrahimi 	}
147*287e80b3SSadaf Ebrahimi 
148*287e80b3SSadaf Ebrahimi 	for (i = 0; line && buffer[i]; i++) {
149*287e80b3SSadaf Ebrahimi 		if (buffer[i] == '\n')
150*287e80b3SSadaf Ebrahimi 			line--;
151*287e80b3SSadaf Ebrahimi 	}
152*287e80b3SSadaf Ebrahimi 	for (; buffer[i] && buffer[i] != '\n'; i++)
153*287e80b3SSadaf Ebrahimi 		trace_seq_putc(&s, buffer[i]);
154*287e80b3SSadaf Ebrahimi 	trace_seq_putc(&s, '\n');
155*287e80b3SSadaf Ebrahimi 	for (i = idx; i > 0; i--)
156*287e80b3SSadaf Ebrahimi 		trace_seq_putc(&s, ' ');
157*287e80b3SSadaf Ebrahimi 	trace_seq_puts(&s, "^\n");
158*287e80b3SSadaf Ebrahimi 	trace_seq_printf(&s, "ERROR: '%s'\n", text);
159*287e80b3SSadaf Ebrahimi 	trace_seq_vprintf(&s, fmt, ap);
160*287e80b3SSadaf Ebrahimi 
161*287e80b3SSadaf Ebrahimi 	trace_seq_terminate(&s);
162*287e80b3SSadaf Ebrahimi 
163*287e80b3SSadaf Ebrahimi 	sb->parse_error_str = strdup(s.buffer);
164*287e80b3SSadaf Ebrahimi 	trace_seq_destroy(&s);
165*287e80b3SSadaf Ebrahimi }
166*287e80b3SSadaf Ebrahimi 
parse_error(struct sqlhist_bison * sb,const char * text,const char * fmt,...)167*287e80b3SSadaf Ebrahimi static void parse_error(struct sqlhist_bison *sb, const char *text,
168*287e80b3SSadaf Ebrahimi 			const char *fmt, ...)
169*287e80b3SSadaf Ebrahimi {
170*287e80b3SSadaf Ebrahimi 	va_list ap;
171*287e80b3SSadaf Ebrahimi 
172*287e80b3SSadaf Ebrahimi 	va_start(ap, fmt);
173*287e80b3SSadaf Ebrahimi 	sql_parse_error(sb, text, fmt, ap);
174*287e80b3SSadaf Ebrahimi 	va_end(ap);
175*287e80b3SSadaf Ebrahimi }
176*287e80b3SSadaf Ebrahimi 
quick_hash(const char * str)177*287e80b3SSadaf Ebrahimi __hidden unsigned int quick_hash(const char *str)
178*287e80b3SSadaf Ebrahimi {
179*287e80b3SSadaf Ebrahimi 	unsigned int val = 0;
180*287e80b3SSadaf Ebrahimi 	int len = strlen(str);
181*287e80b3SSadaf Ebrahimi 
182*287e80b3SSadaf Ebrahimi 	for (; len >= 4; str += 4, len -= 4) {
183*287e80b3SSadaf Ebrahimi 		val += str[0];
184*287e80b3SSadaf Ebrahimi 		val += str[1] << 8;
185*287e80b3SSadaf Ebrahimi 		val += str[2] << 16;
186*287e80b3SSadaf Ebrahimi 		val += str[3] << 24;
187*287e80b3SSadaf Ebrahimi 	}
188*287e80b3SSadaf Ebrahimi 	for (; len > 0; str++, len--)
189*287e80b3SSadaf Ebrahimi 		val += str[0] << (len * 8);
190*287e80b3SSadaf Ebrahimi 
191*287e80b3SSadaf Ebrahimi         val *= 2654435761;
192*287e80b3SSadaf Ebrahimi 
193*287e80b3SSadaf Ebrahimi         return val & ((1 << HASH_BITS) - 1);
194*287e80b3SSadaf Ebrahimi }
195*287e80b3SSadaf Ebrahimi 
196*287e80b3SSadaf Ebrahimi 
find_string(struct sqlhist_bison * sb,const char * str)197*287e80b3SSadaf Ebrahimi static struct str_hash *find_string(struct sqlhist_bison *sb, const char *str)
198*287e80b3SSadaf Ebrahimi {
199*287e80b3SSadaf Ebrahimi 	unsigned int key = quick_hash(str);
200*287e80b3SSadaf Ebrahimi 	struct str_hash *hash = sb->str_hash[key];
201*287e80b3SSadaf Ebrahimi 
202*287e80b3SSadaf Ebrahimi 	for (; hash; hash = hash->next) {
203*287e80b3SSadaf Ebrahimi 		if (!strcmp(hash->str, str))
204*287e80b3SSadaf Ebrahimi 			return hash;
205*287e80b3SSadaf Ebrahimi 	}
206*287e80b3SSadaf Ebrahimi 	return NULL;
207*287e80b3SSadaf Ebrahimi }
208*287e80b3SSadaf Ebrahimi 
209*287e80b3SSadaf Ebrahimi /*
210*287e80b3SSadaf Ebrahimi  * If @str is found, then return the hash string.
211*287e80b3SSadaf Ebrahimi  * This lets store_str() know to free str.
212*287e80b3SSadaf Ebrahimi  */
add_hash(struct sqlhist_bison * sb,const char * str)213*287e80b3SSadaf Ebrahimi static char **add_hash(struct sqlhist_bison *sb, const char *str)
214*287e80b3SSadaf Ebrahimi {
215*287e80b3SSadaf Ebrahimi 	struct str_hash *hash;
216*287e80b3SSadaf Ebrahimi 	unsigned int key;
217*287e80b3SSadaf Ebrahimi 
218*287e80b3SSadaf Ebrahimi 	if ((hash = find_string(sb, str))) {
219*287e80b3SSadaf Ebrahimi 		return &hash->str;
220*287e80b3SSadaf Ebrahimi 	}
221*287e80b3SSadaf Ebrahimi 
222*287e80b3SSadaf Ebrahimi 	hash = malloc(sizeof(*hash));
223*287e80b3SSadaf Ebrahimi 	if (!hash)
224*287e80b3SSadaf Ebrahimi 		return NULL;
225*287e80b3SSadaf Ebrahimi 	key = quick_hash(str);
226*287e80b3SSadaf Ebrahimi 	hash->next = sb->str_hash[key];
227*287e80b3SSadaf Ebrahimi 	sb->str_hash[key] = hash;
228*287e80b3SSadaf Ebrahimi 	hash->str = NULL;
229*287e80b3SSadaf Ebrahimi 	return &hash->str;
230*287e80b3SSadaf Ebrahimi }
231*287e80b3SSadaf Ebrahimi 
store_str(struct sqlhist_bison * sb,const char * str)232*287e80b3SSadaf Ebrahimi __hidden char *store_str(struct sqlhist_bison *sb, const char *str)
233*287e80b3SSadaf Ebrahimi {
234*287e80b3SSadaf Ebrahimi 	char **pstr = add_hash(sb, str);
235*287e80b3SSadaf Ebrahimi 
236*287e80b3SSadaf Ebrahimi 	if (!pstr)
237*287e80b3SSadaf Ebrahimi 		return NULL;
238*287e80b3SSadaf Ebrahimi 
239*287e80b3SSadaf Ebrahimi 	if (!(*pstr))
240*287e80b3SSadaf Ebrahimi 		*pstr = strdup(str);
241*287e80b3SSadaf Ebrahimi 
242*287e80b3SSadaf Ebrahimi 	return *pstr;
243*287e80b3SSadaf Ebrahimi }
244*287e80b3SSadaf Ebrahimi 
add_cast(struct sqlhist_bison * sb,void * data,const char * type)245*287e80b3SSadaf Ebrahimi __hidden void *add_cast(struct sqlhist_bison *sb,
246*287e80b3SSadaf Ebrahimi 			void *data, const char *type)
247*287e80b3SSadaf Ebrahimi {
248*287e80b3SSadaf Ebrahimi 	struct expr *expr = data;
249*287e80b3SSadaf Ebrahimi 	struct field *field = &expr->field;
250*287e80b3SSadaf Ebrahimi 
251*287e80b3SSadaf Ebrahimi 	field->type = type;
252*287e80b3SSadaf Ebrahimi 	return expr;
253*287e80b3SSadaf Ebrahimi }
254*287e80b3SSadaf Ebrahimi 
add_selection(struct sqlhist_bison * sb,void * select,const char * name)255*287e80b3SSadaf Ebrahimi __hidden int add_selection(struct sqlhist_bison *sb, void *select,
256*287e80b3SSadaf Ebrahimi 			   const char *name)
257*287e80b3SSadaf Ebrahimi {
258*287e80b3SSadaf Ebrahimi 	struct sql_table *table = sb->table;
259*287e80b3SSadaf Ebrahimi 	struct expr *expr = select;
260*287e80b3SSadaf Ebrahimi 
261*287e80b3SSadaf Ebrahimi 	switch (expr->type) {
262*287e80b3SSadaf Ebrahimi 	case EXPR_FIELD:
263*287e80b3SSadaf Ebrahimi 		expr->field.label = name;
264*287e80b3SSadaf Ebrahimi 		break;
265*287e80b3SSadaf Ebrahimi 	case EXPR_COMPARE:
266*287e80b3SSadaf Ebrahimi 		expr->compare.name = name;
267*287e80b3SSadaf Ebrahimi 		break;
268*287e80b3SSadaf Ebrahimi 	case EXPR_NUMBER:
269*287e80b3SSadaf Ebrahimi 	case EXPR_STRING:
270*287e80b3SSadaf Ebrahimi 	case EXPR_FILTER:
271*287e80b3SSadaf Ebrahimi 	default:
272*287e80b3SSadaf Ebrahimi 		return -1;
273*287e80b3SSadaf Ebrahimi 	}
274*287e80b3SSadaf Ebrahimi 
275*287e80b3SSadaf Ebrahimi 	if (expr->next)
276*287e80b3SSadaf Ebrahimi 		return -1;
277*287e80b3SSadaf Ebrahimi 
278*287e80b3SSadaf Ebrahimi 	*table->next_selection = expr;
279*287e80b3SSadaf Ebrahimi 	table->next_selection = &expr->next;
280*287e80b3SSadaf Ebrahimi 
281*287e80b3SSadaf Ebrahimi 	return 0;
282*287e80b3SSadaf Ebrahimi }
283*287e80b3SSadaf Ebrahimi 
find_field(struct sqlhist_bison * sb,const char * raw,const char * label)284*287e80b3SSadaf Ebrahimi static struct expr *find_field(struct sqlhist_bison *sb,
285*287e80b3SSadaf Ebrahimi 				const char *raw, const char *label)
286*287e80b3SSadaf Ebrahimi {
287*287e80b3SSadaf Ebrahimi 	struct field *field;
288*287e80b3SSadaf Ebrahimi 	struct expr *expr;
289*287e80b3SSadaf Ebrahimi 
290*287e80b3SSadaf Ebrahimi 	for_each_field(expr, field, sb->table) {
291*287e80b3SSadaf Ebrahimi 		field = &expr->field;
292*287e80b3SSadaf Ebrahimi 
293*287e80b3SSadaf Ebrahimi 		if (!strcmp(field->raw, raw)) {
294*287e80b3SSadaf Ebrahimi 			if (label && !field->label)
295*287e80b3SSadaf Ebrahimi 				field->label = label;
296*287e80b3SSadaf Ebrahimi 			if (label && strcmp(label, field->label) != 0)
297*287e80b3SSadaf Ebrahimi 				continue;
298*287e80b3SSadaf Ebrahimi 			return expr;
299*287e80b3SSadaf Ebrahimi 		}
300*287e80b3SSadaf Ebrahimi 
301*287e80b3SSadaf Ebrahimi 		if (label && !strcmp(field->raw, label)) {
302*287e80b3SSadaf Ebrahimi 			if (!field->label) {
303*287e80b3SSadaf Ebrahimi 				field->label = label;
304*287e80b3SSadaf Ebrahimi 				field->raw = raw;
305*287e80b3SSadaf Ebrahimi 			}
306*287e80b3SSadaf Ebrahimi 			return expr;
307*287e80b3SSadaf Ebrahimi 		}
308*287e80b3SSadaf Ebrahimi 
309*287e80b3SSadaf Ebrahimi 		if (!field->label)
310*287e80b3SSadaf Ebrahimi 			continue;
311*287e80b3SSadaf Ebrahimi 
312*287e80b3SSadaf Ebrahimi 		if (!strcmp(field->label, raw))
313*287e80b3SSadaf Ebrahimi 			return expr;
314*287e80b3SSadaf Ebrahimi 
315*287e80b3SSadaf Ebrahimi 		if (label && !strcmp(field->label, label))
316*287e80b3SSadaf Ebrahimi 			return expr;
317*287e80b3SSadaf Ebrahimi 	}
318*287e80b3SSadaf Ebrahimi 	return NULL;
319*287e80b3SSadaf Ebrahimi }
320*287e80b3SSadaf Ebrahimi 
create_expr(struct sqlhist_bison * sb,enum expr_type type,struct expr ** expr_p)321*287e80b3SSadaf Ebrahimi static void *create_expr(struct sqlhist_bison *sb,
322*287e80b3SSadaf Ebrahimi 			 enum expr_type type, struct expr **expr_p)
323*287e80b3SSadaf Ebrahimi {
324*287e80b3SSadaf Ebrahimi 	struct expr *expr;
325*287e80b3SSadaf Ebrahimi 
326*287e80b3SSadaf Ebrahimi 	expr = calloc(1, sizeof(*expr));
327*287e80b3SSadaf Ebrahimi 	if (!expr)
328*287e80b3SSadaf Ebrahimi 		return NULL;
329*287e80b3SSadaf Ebrahimi 
330*287e80b3SSadaf Ebrahimi 	if (expr_p)
331*287e80b3SSadaf Ebrahimi 		*expr_p = expr;
332*287e80b3SSadaf Ebrahimi 
333*287e80b3SSadaf Ebrahimi 	expr->free_list = sb->table->exprs;
334*287e80b3SSadaf Ebrahimi 	sb->table->exprs = expr;
335*287e80b3SSadaf Ebrahimi 
336*287e80b3SSadaf Ebrahimi 	expr->type = type;
337*287e80b3SSadaf Ebrahimi 	expr->line = sb->line_no;
338*287e80b3SSadaf Ebrahimi 	expr->idx = sb->line_idx;
339*287e80b3SSadaf Ebrahimi 
340*287e80b3SSadaf Ebrahimi 	switch (type) {
341*287e80b3SSadaf Ebrahimi 	case EXPR_FIELD:	return &expr->field;
342*287e80b3SSadaf Ebrahimi 	case EXPR_COMPARE:	return &expr->compare;
343*287e80b3SSadaf Ebrahimi 	case EXPR_NUMBER:	return &expr->number;
344*287e80b3SSadaf Ebrahimi 	case EXPR_STRING:	return &expr->string;
345*287e80b3SSadaf Ebrahimi 	case EXPR_FILTER:	return &expr->filter;
346*287e80b3SSadaf Ebrahimi 	}
347*287e80b3SSadaf Ebrahimi 
348*287e80b3SSadaf Ebrahimi 	return NULL;
349*287e80b3SSadaf Ebrahimi }
350*287e80b3SSadaf Ebrahimi 
351*287e80b3SSadaf Ebrahimi #define __create_expr(var, type, ENUM, expr)			\
352*287e80b3SSadaf Ebrahimi 	do {							\
353*287e80b3SSadaf Ebrahimi 		var = (type *)create_expr(sb, EXPR_##ENUM, expr);	\
354*287e80b3SSadaf Ebrahimi 	} while(0)
355*287e80b3SSadaf Ebrahimi 
356*287e80b3SSadaf Ebrahimi #define create_field(var, expr)				\
357*287e80b3SSadaf Ebrahimi 	__create_expr(var, struct field, FIELD, expr)
358*287e80b3SSadaf Ebrahimi 
359*287e80b3SSadaf Ebrahimi #define create_filter(var, expr)			\
360*287e80b3SSadaf Ebrahimi 	__create_expr(var, struct filter, FILTER, expr)
361*287e80b3SSadaf Ebrahimi 
362*287e80b3SSadaf Ebrahimi #define create_compare(var, expr)				\
363*287e80b3SSadaf Ebrahimi 	__create_expr(var, struct compare, COMPARE, expr)
364*287e80b3SSadaf Ebrahimi 
365*287e80b3SSadaf Ebrahimi #define create_string(var, expr)			\
366*287e80b3SSadaf Ebrahimi 	__create_expr(var, const char *, STRING, expr)
367*287e80b3SSadaf Ebrahimi 
368*287e80b3SSadaf Ebrahimi #define create_number(var, expr)			\
369*287e80b3SSadaf Ebrahimi 	__create_expr(var, long, NUMBER, expr)
370*287e80b3SSadaf Ebrahimi 
add_field(struct sqlhist_bison * sb,const char * field_name,const char * label)371*287e80b3SSadaf Ebrahimi __hidden void *add_field(struct sqlhist_bison *sb,
372*287e80b3SSadaf Ebrahimi 			 const char *field_name, const char *label)
373*287e80b3SSadaf Ebrahimi {
374*287e80b3SSadaf Ebrahimi 	struct sql_table *table = sb->table;
375*287e80b3SSadaf Ebrahimi 	struct expr *expr;
376*287e80b3SSadaf Ebrahimi 	struct field *field;
377*287e80b3SSadaf Ebrahimi 
378*287e80b3SSadaf Ebrahimi 	expr = find_field(sb, field_name, label);
379*287e80b3SSadaf Ebrahimi 	if (expr)
380*287e80b3SSadaf Ebrahimi 		return expr;
381*287e80b3SSadaf Ebrahimi 
382*287e80b3SSadaf Ebrahimi 	create_field(field, &expr);
383*287e80b3SSadaf Ebrahimi 
384*287e80b3SSadaf Ebrahimi 	field->next = table->fields;
385*287e80b3SSadaf Ebrahimi 	table->fields = expr;
386*287e80b3SSadaf Ebrahimi 
387*287e80b3SSadaf Ebrahimi 	field->raw = field_name;
388*287e80b3SSadaf Ebrahimi 	field->label = label;
389*287e80b3SSadaf Ebrahimi 
390*287e80b3SSadaf Ebrahimi 	return expr;
391*287e80b3SSadaf Ebrahimi }
392*287e80b3SSadaf Ebrahimi 
add_filter(struct sqlhist_bison * sb,void * A,void * B,enum filter_type op)393*287e80b3SSadaf Ebrahimi __hidden void *add_filter(struct sqlhist_bison *sb,
394*287e80b3SSadaf Ebrahimi 			  void *A, void *B, enum filter_type op)
395*287e80b3SSadaf Ebrahimi {
396*287e80b3SSadaf Ebrahimi 	struct filter *filter;
397*287e80b3SSadaf Ebrahimi 	struct expr *expr;
398*287e80b3SSadaf Ebrahimi 
399*287e80b3SSadaf Ebrahimi 	create_filter(filter, &expr);
400*287e80b3SSadaf Ebrahimi 
401*287e80b3SSadaf Ebrahimi 	filter->lval = A;
402*287e80b3SSadaf Ebrahimi 	filter->rval = B;
403*287e80b3SSadaf Ebrahimi 
404*287e80b3SSadaf Ebrahimi 	filter->type = op;
405*287e80b3SSadaf Ebrahimi 
406*287e80b3SSadaf Ebrahimi 	return expr;
407*287e80b3SSadaf Ebrahimi }
408*287e80b3SSadaf Ebrahimi 
add_match(struct sqlhist_bison * sb,void * A,void * B)409*287e80b3SSadaf Ebrahimi __hidden int add_match(struct sqlhist_bison *sb, void *A, void *B)
410*287e80b3SSadaf Ebrahimi {
411*287e80b3SSadaf Ebrahimi 	struct sql_table *table = sb->table;
412*287e80b3SSadaf Ebrahimi 	struct match *match;
413*287e80b3SSadaf Ebrahimi 
414*287e80b3SSadaf Ebrahimi 	match = calloc(1, sizeof(*match));
415*287e80b3SSadaf Ebrahimi 	if (!match)
416*287e80b3SSadaf Ebrahimi 		return -1;
417*287e80b3SSadaf Ebrahimi 
418*287e80b3SSadaf Ebrahimi 	match->lval = A;
419*287e80b3SSadaf Ebrahimi 	match->rval = B;
420*287e80b3SSadaf Ebrahimi 
421*287e80b3SSadaf Ebrahimi 	*table->next_match = match;
422*287e80b3SSadaf Ebrahimi 	table->next_match = &match->next;
423*287e80b3SSadaf Ebrahimi 
424*287e80b3SSadaf Ebrahimi 	return 0;
425*287e80b3SSadaf Ebrahimi }
add_compare(struct sqlhist_bison * sb,void * A,void * B,enum compare_type type)426*287e80b3SSadaf Ebrahimi __hidden void *add_compare(struct sqlhist_bison *sb,
427*287e80b3SSadaf Ebrahimi 			   void *A, void *B, enum compare_type type)
428*287e80b3SSadaf Ebrahimi {
429*287e80b3SSadaf Ebrahimi 	struct compare *compare;
430*287e80b3SSadaf Ebrahimi 	struct expr *expr;
431*287e80b3SSadaf Ebrahimi 
432*287e80b3SSadaf Ebrahimi 	create_compare(compare, &expr);
433*287e80b3SSadaf Ebrahimi 
434*287e80b3SSadaf Ebrahimi 	compare = &expr->compare;
435*287e80b3SSadaf Ebrahimi 	compare->lval = A;
436*287e80b3SSadaf Ebrahimi 	compare->rval = B;
437*287e80b3SSadaf Ebrahimi 	compare->type = type;
438*287e80b3SSadaf Ebrahimi 
439*287e80b3SSadaf Ebrahimi 	return expr;
440*287e80b3SSadaf Ebrahimi }
441*287e80b3SSadaf Ebrahimi 
add_where(struct sqlhist_bison * sb,void * item)442*287e80b3SSadaf Ebrahimi __hidden int add_where(struct sqlhist_bison *sb, void *item)
443*287e80b3SSadaf Ebrahimi {
444*287e80b3SSadaf Ebrahimi 	struct expr *expr = item;
445*287e80b3SSadaf Ebrahimi 	struct sql_table *table = sb->table;
446*287e80b3SSadaf Ebrahimi 
447*287e80b3SSadaf Ebrahimi 	if (expr->type != EXPR_FILTER)
448*287e80b3SSadaf Ebrahimi 		return -1;
449*287e80b3SSadaf Ebrahimi 
450*287e80b3SSadaf Ebrahimi 	*table->next_where = expr;
451*287e80b3SSadaf Ebrahimi 	table->next_where = &expr->next;
452*287e80b3SSadaf Ebrahimi 
453*287e80b3SSadaf Ebrahimi 	if (expr->next)
454*287e80b3SSadaf Ebrahimi 		return -1;
455*287e80b3SSadaf Ebrahimi 
456*287e80b3SSadaf Ebrahimi 	return 0;
457*287e80b3SSadaf Ebrahimi }
458*287e80b3SSadaf Ebrahimi 
add_from(struct sqlhist_bison * sb,void * item)459*287e80b3SSadaf Ebrahimi __hidden int add_from(struct sqlhist_bison *sb, void *item)
460*287e80b3SSadaf Ebrahimi {
461*287e80b3SSadaf Ebrahimi 	struct expr *expr = item;
462*287e80b3SSadaf Ebrahimi 
463*287e80b3SSadaf Ebrahimi 	if (expr->type != EXPR_FIELD)
464*287e80b3SSadaf Ebrahimi 		return -1;
465*287e80b3SSadaf Ebrahimi 
466*287e80b3SSadaf Ebrahimi 	sb->table->from = expr;
467*287e80b3SSadaf Ebrahimi 
468*287e80b3SSadaf Ebrahimi 	return 0;
469*287e80b3SSadaf Ebrahimi }
470*287e80b3SSadaf Ebrahimi 
add_to(struct sqlhist_bison * sb,void * item)471*287e80b3SSadaf Ebrahimi __hidden int add_to(struct sqlhist_bison *sb, void *item)
472*287e80b3SSadaf Ebrahimi {
473*287e80b3SSadaf Ebrahimi 	struct expr *expr = item;
474*287e80b3SSadaf Ebrahimi 
475*287e80b3SSadaf Ebrahimi 	if (expr->type != EXPR_FIELD)
476*287e80b3SSadaf Ebrahimi 		return -1;
477*287e80b3SSadaf Ebrahimi 
478*287e80b3SSadaf Ebrahimi 	sb->table->to = expr;
479*287e80b3SSadaf Ebrahimi 
480*287e80b3SSadaf Ebrahimi 	return 0;
481*287e80b3SSadaf Ebrahimi }
482*287e80b3SSadaf Ebrahimi 
add_string(struct sqlhist_bison * sb,const char * str)483*287e80b3SSadaf Ebrahimi __hidden void *add_string(struct sqlhist_bison *sb, const char *str)
484*287e80b3SSadaf Ebrahimi {
485*287e80b3SSadaf Ebrahimi 	struct expr *expr;
486*287e80b3SSadaf Ebrahimi 	const char **str_p;
487*287e80b3SSadaf Ebrahimi 
488*287e80b3SSadaf Ebrahimi 	create_string(str_p, &expr);
489*287e80b3SSadaf Ebrahimi 	*str_p = str;
490*287e80b3SSadaf Ebrahimi 	return expr;
491*287e80b3SSadaf Ebrahimi }
492*287e80b3SSadaf Ebrahimi 
add_number(struct sqlhist_bison * sb,long val)493*287e80b3SSadaf Ebrahimi __hidden void *add_number(struct sqlhist_bison *sb, long val)
494*287e80b3SSadaf Ebrahimi {
495*287e80b3SSadaf Ebrahimi 	struct expr *expr;
496*287e80b3SSadaf Ebrahimi 	long *num;
497*287e80b3SSadaf Ebrahimi 
498*287e80b3SSadaf Ebrahimi 	create_number(num, &expr);
499*287e80b3SSadaf Ebrahimi 	*num = val;
500*287e80b3SSadaf Ebrahimi 	return expr;
501*287e80b3SSadaf Ebrahimi }
502*287e80b3SSadaf Ebrahimi 
table_start(struct sqlhist_bison * sb)503*287e80b3SSadaf Ebrahimi __hidden int table_start(struct sqlhist_bison *sb)
504*287e80b3SSadaf Ebrahimi {
505*287e80b3SSadaf Ebrahimi 	struct sql_table *table;
506*287e80b3SSadaf Ebrahimi 
507*287e80b3SSadaf Ebrahimi 	table = calloc(1, sizeof(*table));
508*287e80b3SSadaf Ebrahimi 	if (!table)
509*287e80b3SSadaf Ebrahimi 		return -ENOMEM;
510*287e80b3SSadaf Ebrahimi 
511*287e80b3SSadaf Ebrahimi 	table->sb = sb;
512*287e80b3SSadaf Ebrahimi 	sb->table = table;
513*287e80b3SSadaf Ebrahimi 
514*287e80b3SSadaf Ebrahimi 	table->next_where = &table->where;
515*287e80b3SSadaf Ebrahimi 	table->next_match = &table->matches;
516*287e80b3SSadaf Ebrahimi 	table->next_selection = &table->selections;
517*287e80b3SSadaf Ebrahimi 
518*287e80b3SSadaf Ebrahimi 	return 0;
519*287e80b3SSadaf Ebrahimi }
520*287e80b3SSadaf Ebrahimi 
test_event_exists(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr,struct tep_event ** pevent)521*287e80b3SSadaf Ebrahimi static int test_event_exists(struct tep_handle *tep,
522*287e80b3SSadaf Ebrahimi 			     struct sqlhist_bison *sb,
523*287e80b3SSadaf Ebrahimi 			     struct expr *expr, struct tep_event **pevent)
524*287e80b3SSadaf Ebrahimi {
525*287e80b3SSadaf Ebrahimi 	struct field *field = &expr->field;
526*287e80b3SSadaf Ebrahimi 	const char *system = field->system;
527*287e80b3SSadaf Ebrahimi 	const char *event = field->event_name;
528*287e80b3SSadaf Ebrahimi 
529*287e80b3SSadaf Ebrahimi 	if (!field->event)
530*287e80b3SSadaf Ebrahimi 		field->event = tep_find_event_by_name(tep, system, event);
531*287e80b3SSadaf Ebrahimi 	if (pevent)
532*287e80b3SSadaf Ebrahimi 		*pevent = field->event;
533*287e80b3SSadaf Ebrahimi 
534*287e80b3SSadaf Ebrahimi 	if (field->event)
535*287e80b3SSadaf Ebrahimi 		return 0;
536*287e80b3SSadaf Ebrahimi 
537*287e80b3SSadaf Ebrahimi 	sb->line_no = expr->line;
538*287e80b3SSadaf Ebrahimi 	sb->line_idx = expr->idx;
539*287e80b3SSadaf Ebrahimi 
540*287e80b3SSadaf Ebrahimi 	parse_error(sb, field->raw, "event not found\n");
541*287e80b3SSadaf Ebrahimi 	return -1;
542*287e80b3SSadaf Ebrahimi }
543*287e80b3SSadaf Ebrahimi 
test_field_exists(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr)544*287e80b3SSadaf Ebrahimi static int test_field_exists(struct tep_handle *tep,
545*287e80b3SSadaf Ebrahimi 			     struct sqlhist_bison *sb,
546*287e80b3SSadaf Ebrahimi 			     struct expr *expr)
547*287e80b3SSadaf Ebrahimi {
548*287e80b3SSadaf Ebrahimi 	struct field *field = &expr->field;
549*287e80b3SSadaf Ebrahimi 	struct tep_format_field *tfield;
550*287e80b3SSadaf Ebrahimi 	char *field_name;
551*287e80b3SSadaf Ebrahimi 	const char *p;
552*287e80b3SSadaf Ebrahimi 
553*287e80b3SSadaf Ebrahimi 	if (!field->event) {
554*287e80b3SSadaf Ebrahimi 		if (test_event_exists(tep, sb, expr, NULL))
555*287e80b3SSadaf Ebrahimi 			return -1;
556*287e80b3SSadaf Ebrahimi 	}
557*287e80b3SSadaf Ebrahimi 
558*287e80b3SSadaf Ebrahimi 	/* The field could have a conversion */
559*287e80b3SSadaf Ebrahimi 	p = strchr(field->field, '.');
560*287e80b3SSadaf Ebrahimi 	if (p)
561*287e80b3SSadaf Ebrahimi 		field_name = strndup(field->field, p - field->field);
562*287e80b3SSadaf Ebrahimi 	else
563*287e80b3SSadaf Ebrahimi 		field_name = strdup(field->field);
564*287e80b3SSadaf Ebrahimi 
565*287e80b3SSadaf Ebrahimi 	if (!field_name)
566*287e80b3SSadaf Ebrahimi 		return -1;
567*287e80b3SSadaf Ebrahimi 
568*287e80b3SSadaf Ebrahimi 	if (!strcmp(field_name, TRACEFS_TIMESTAMP) ||
569*287e80b3SSadaf Ebrahimi 	    !strcmp(field->field, TRACEFS_TIMESTAMP_USECS))
570*287e80b3SSadaf Ebrahimi 		tfield = (void *)1L;
571*287e80b3SSadaf Ebrahimi 	else
572*287e80b3SSadaf Ebrahimi 		tfield = tep_find_any_field(field->event, field_name);
573*287e80b3SSadaf Ebrahimi 	free(field_name);
574*287e80b3SSadaf Ebrahimi 
575*287e80b3SSadaf Ebrahimi 	if (!tfield && (!strcmp(field->field, "COMM") || !strcmp(field->field, "comm")))
576*287e80b3SSadaf Ebrahimi 		tfield = (void *)1L;
577*287e80b3SSadaf Ebrahimi 
578*287e80b3SSadaf Ebrahimi 	if (tfield)
579*287e80b3SSadaf Ebrahimi 		return 0;
580*287e80b3SSadaf Ebrahimi 
581*287e80b3SSadaf Ebrahimi 	sb->line_no = expr->line;
582*287e80b3SSadaf Ebrahimi 	sb->line_idx = expr->idx;
583*287e80b3SSadaf Ebrahimi 
584*287e80b3SSadaf Ebrahimi 	parse_error(sb, field->raw,
585*287e80b3SSadaf Ebrahimi 		    "Field '%s' not part of event %s\n",
586*287e80b3SSadaf Ebrahimi 		    field->field, field->event_name);
587*287e80b3SSadaf Ebrahimi 	return -1;
588*287e80b3SSadaf Ebrahimi }
589*287e80b3SSadaf Ebrahimi 
update_vars(struct tep_handle * tep,struct sql_table * table,struct expr * expr)590*287e80b3SSadaf Ebrahimi static int update_vars(struct tep_handle *tep,
591*287e80b3SSadaf Ebrahimi 		       struct sql_table *table,
592*287e80b3SSadaf Ebrahimi 		       struct expr *expr)
593*287e80b3SSadaf Ebrahimi {
594*287e80b3SSadaf Ebrahimi 	struct sqlhist_bison *sb = table->sb;
595*287e80b3SSadaf Ebrahimi 	struct field *event_field = &expr->field;
596*287e80b3SSadaf Ebrahimi 	enum field_type ftype = FIELD_NONE;
597*287e80b3SSadaf Ebrahimi 	struct tep_event *event;
598*287e80b3SSadaf Ebrahimi 	struct field *field;
599*287e80b3SSadaf Ebrahimi 	const char *label;
600*287e80b3SSadaf Ebrahimi 	const char *raw = event_field->raw;
601*287e80b3SSadaf Ebrahimi 	const char *event_name;
602*287e80b3SSadaf Ebrahimi 	const char *system;
603*287e80b3SSadaf Ebrahimi 	const char *p;
604*287e80b3SSadaf Ebrahimi 	int label_len = 0, event_len, system_len;
605*287e80b3SSadaf Ebrahimi 
606*287e80b3SSadaf Ebrahimi 	if (expr == table->to)
607*287e80b3SSadaf Ebrahimi 		ftype = FIELD_TO;
608*287e80b3SSadaf Ebrahimi 	else if (expr == table->from)
609*287e80b3SSadaf Ebrahimi 		ftype = FIELD_FROM;
610*287e80b3SSadaf Ebrahimi 
611*287e80b3SSadaf Ebrahimi 	p = strchr(raw, '.');
612*287e80b3SSadaf Ebrahimi 	if (p) {
613*287e80b3SSadaf Ebrahimi 		char *str;
614*287e80b3SSadaf Ebrahimi 
615*287e80b3SSadaf Ebrahimi 		str = strndup(raw, p - raw);
616*287e80b3SSadaf Ebrahimi 		if (!str)
617*287e80b3SSadaf Ebrahimi 			return -1;
618*287e80b3SSadaf Ebrahimi 		event_field->system = store_str(sb, str);
619*287e80b3SSadaf Ebrahimi 		free(str);
620*287e80b3SSadaf Ebrahimi 		if (!event_field->system)
621*287e80b3SSadaf Ebrahimi 			return -1;
622*287e80b3SSadaf Ebrahimi 		p++;
623*287e80b3SSadaf Ebrahimi 	} else {
624*287e80b3SSadaf Ebrahimi 		p = raw;
625*287e80b3SSadaf Ebrahimi 	}
626*287e80b3SSadaf Ebrahimi 
627*287e80b3SSadaf Ebrahimi 	event_field->event_name = store_str(sb, p);
628*287e80b3SSadaf Ebrahimi 	if (!event_field->event_name)
629*287e80b3SSadaf Ebrahimi 		return -1;
630*287e80b3SSadaf Ebrahimi 
631*287e80b3SSadaf Ebrahimi 	if (test_event_exists(tep, sb, expr, &event))
632*287e80b3SSadaf Ebrahimi 		return -1;
633*287e80b3SSadaf Ebrahimi 
634*287e80b3SSadaf Ebrahimi 	if (!event_field->system)
635*287e80b3SSadaf Ebrahimi 		event_field->system = store_str(sb, event->system);
636*287e80b3SSadaf Ebrahimi 
637*287e80b3SSadaf Ebrahimi 	if (!event_field->system)
638*287e80b3SSadaf Ebrahimi 		return -1;
639*287e80b3SSadaf Ebrahimi 
640*287e80b3SSadaf Ebrahimi 	label = event_field->label;
641*287e80b3SSadaf Ebrahimi 	if (label)
642*287e80b3SSadaf Ebrahimi 		label_len = strlen(label);
643*287e80b3SSadaf Ebrahimi 
644*287e80b3SSadaf Ebrahimi 	system = event_field->system;
645*287e80b3SSadaf Ebrahimi 	system_len = strlen(system);
646*287e80b3SSadaf Ebrahimi 
647*287e80b3SSadaf Ebrahimi 	event_name = event_field->event_name;
648*287e80b3SSadaf Ebrahimi 	event_len = strlen(event_name);
649*287e80b3SSadaf Ebrahimi 
650*287e80b3SSadaf Ebrahimi 	for_each_field(expr, field, table) {
651*287e80b3SSadaf Ebrahimi 		int len;
652*287e80b3SSadaf Ebrahimi 
653*287e80b3SSadaf Ebrahimi 		field = &expr->field;
654*287e80b3SSadaf Ebrahimi 
655*287e80b3SSadaf Ebrahimi 		if (field->event)
656*287e80b3SSadaf Ebrahimi 			continue;
657*287e80b3SSadaf Ebrahimi 
658*287e80b3SSadaf Ebrahimi 		raw = field->raw;
659*287e80b3SSadaf Ebrahimi 
660*287e80b3SSadaf Ebrahimi 		/*
661*287e80b3SSadaf Ebrahimi 		 * The field could be:
662*287e80b3SSadaf Ebrahimi 		 *     system.event.field...
663*287e80b3SSadaf Ebrahimi 		 *     event.field...
664*287e80b3SSadaf Ebrahimi 		 *     label.field...
665*287e80b3SSadaf Ebrahimi 		 * We check label first.
666*287e80b3SSadaf Ebrahimi 		 */
667*287e80b3SSadaf Ebrahimi 
668*287e80b3SSadaf Ebrahimi 		len = label_len;
669*287e80b3SSadaf Ebrahimi 		if (label && !strncmp(raw, label, len) &&
670*287e80b3SSadaf Ebrahimi 		    raw[len] == '.') {
671*287e80b3SSadaf Ebrahimi 			/* Label matches and takes precedence */
672*287e80b3SSadaf Ebrahimi 			goto found;
673*287e80b3SSadaf Ebrahimi 		}
674*287e80b3SSadaf Ebrahimi 
675*287e80b3SSadaf Ebrahimi 		if (!strncmp(raw, system, system_len) &&
676*287e80b3SSadaf Ebrahimi 		    raw[system_len] == '.') {
677*287e80b3SSadaf Ebrahimi 			raw += system_len + 1;
678*287e80b3SSadaf Ebrahimi 			/* Check the event portion next */
679*287e80b3SSadaf Ebrahimi 		}
680*287e80b3SSadaf Ebrahimi 
681*287e80b3SSadaf Ebrahimi 		len = event_len;
682*287e80b3SSadaf Ebrahimi 		if (strncmp(raw, event_name, len) ||
683*287e80b3SSadaf Ebrahimi 		    raw[len] != '.') {
684*287e80b3SSadaf Ebrahimi 			/* Does not match */
685*287e80b3SSadaf Ebrahimi 			continue;
686*287e80b3SSadaf Ebrahimi 		}
687*287e80b3SSadaf Ebrahimi  found:
688*287e80b3SSadaf Ebrahimi 		field->system = system;
689*287e80b3SSadaf Ebrahimi 		field->event_name = event_name;
690*287e80b3SSadaf Ebrahimi 		field->event = event;
691*287e80b3SSadaf Ebrahimi 		field->field = raw + len + 1;
692*287e80b3SSadaf Ebrahimi 		field->ftype = ftype;
693*287e80b3SSadaf Ebrahimi 
694*287e80b3SSadaf Ebrahimi 		if (!strcmp(field->field, "TIMESTAMP"))
695*287e80b3SSadaf Ebrahimi 			field->field = store_str(sb, TRACEFS_TIMESTAMP);
696*287e80b3SSadaf Ebrahimi 		if (!strcmp(field->field, "TIMESTAMP_USECS"))
697*287e80b3SSadaf Ebrahimi 			field->field = store_str(sb, TRACEFS_TIMESTAMP_USECS);
698*287e80b3SSadaf Ebrahimi 		if (test_field_exists(tep, sb, expr))
699*287e80b3SSadaf Ebrahimi 			return -1;
700*287e80b3SSadaf Ebrahimi 	}
701*287e80b3SSadaf Ebrahimi 
702*287e80b3SSadaf Ebrahimi 	return 0;
703*287e80b3SSadaf Ebrahimi }
704*287e80b3SSadaf Ebrahimi 
705*287e80b3SSadaf Ebrahimi /*
706*287e80b3SSadaf Ebrahimi  * Called when there's a FROM but no JOIN(to), which means that the
707*287e80b3SSadaf Ebrahimi  * selections can be fields and not mention the event itself.
708*287e80b3SSadaf Ebrahimi  */
update_fields(struct tep_handle * tep,struct sql_table * table,struct expr * expr)709*287e80b3SSadaf Ebrahimi static int update_fields(struct tep_handle *tep,
710*287e80b3SSadaf Ebrahimi 			 struct sql_table *table,
711*287e80b3SSadaf Ebrahimi 			 struct expr *expr)
712*287e80b3SSadaf Ebrahimi {
713*287e80b3SSadaf Ebrahimi 	struct field *event_field = &expr->field;
714*287e80b3SSadaf Ebrahimi 	struct sqlhist_bison *sb = table->sb;
715*287e80b3SSadaf Ebrahimi 	struct tep_format_field *tfield;
716*287e80b3SSadaf Ebrahimi 	struct tep_event *event;
717*287e80b3SSadaf Ebrahimi 	struct field *field;
718*287e80b3SSadaf Ebrahimi 	const char *p;
719*287e80b3SSadaf Ebrahimi 	int len;
720*287e80b3SSadaf Ebrahimi 
721*287e80b3SSadaf Ebrahimi 	/* First update fields with aliases an such and add event */
722*287e80b3SSadaf Ebrahimi 	update_vars(tep, table, expr);
723*287e80b3SSadaf Ebrahimi 
724*287e80b3SSadaf Ebrahimi 	/*
725*287e80b3SSadaf Ebrahimi 	 * If event is not found, the creation of the synth will
726*287e80b3SSadaf Ebrahimi 	 * add a proper error, so return "success".
727*287e80b3SSadaf Ebrahimi 	*/
728*287e80b3SSadaf Ebrahimi 	if (!event_field->event)
729*287e80b3SSadaf Ebrahimi 		return 0;
730*287e80b3SSadaf Ebrahimi 
731*287e80b3SSadaf Ebrahimi 	event = event_field->event;
732*287e80b3SSadaf Ebrahimi 
733*287e80b3SSadaf Ebrahimi 	for_each_field(expr, field, table) {
734*287e80b3SSadaf Ebrahimi 		const char *field_name;
735*287e80b3SSadaf Ebrahimi 
736*287e80b3SSadaf Ebrahimi 		field = &expr->field;
737*287e80b3SSadaf Ebrahimi 
738*287e80b3SSadaf Ebrahimi 		if (field->event)
739*287e80b3SSadaf Ebrahimi 			continue;
740*287e80b3SSadaf Ebrahimi 
741*287e80b3SSadaf Ebrahimi 		field_name = field->raw;
742*287e80b3SSadaf Ebrahimi 
743*287e80b3SSadaf Ebrahimi 		p = strchr(field_name, '.');
744*287e80b3SSadaf Ebrahimi 		if (p) {
745*287e80b3SSadaf Ebrahimi 			len = p - field_name;
746*287e80b3SSadaf Ebrahimi 			p = strndup(field_name, len);
747*287e80b3SSadaf Ebrahimi 			if (!p)
748*287e80b3SSadaf Ebrahimi 				return -1;
749*287e80b3SSadaf Ebrahimi 			field_name = store_str(sb, p);
750*287e80b3SSadaf Ebrahimi 			if (!field_name)
751*287e80b3SSadaf Ebrahimi 				return -1;
752*287e80b3SSadaf Ebrahimi 			free((char *)p);
753*287e80b3SSadaf Ebrahimi 		}
754*287e80b3SSadaf Ebrahimi 
755*287e80b3SSadaf Ebrahimi 		tfield = tep_find_any_field(event, field_name);
756*287e80b3SSadaf Ebrahimi 		/* Let it error properly later */
757*287e80b3SSadaf Ebrahimi 		if (!tfield)
758*287e80b3SSadaf Ebrahimi 			continue;
759*287e80b3SSadaf Ebrahimi 
760*287e80b3SSadaf Ebrahimi 		field->system = event_field->system;
761*287e80b3SSadaf Ebrahimi 		field->event_name = event_field->event_name;
762*287e80b3SSadaf Ebrahimi 		field->event = event;
763*287e80b3SSadaf Ebrahimi 		field->field = field_name;
764*287e80b3SSadaf Ebrahimi 	}
765*287e80b3SSadaf Ebrahimi 
766*287e80b3SSadaf Ebrahimi 	return 0;
767*287e80b3SSadaf Ebrahimi }
768*287e80b3SSadaf Ebrahimi 
match_error(struct sqlhist_bison * sb,struct match * match,struct field * lmatch,struct field * rmatch)769*287e80b3SSadaf Ebrahimi static int match_error(struct sqlhist_bison *sb, struct match *match,
770*287e80b3SSadaf Ebrahimi 		       struct field *lmatch, struct field *rmatch)
771*287e80b3SSadaf Ebrahimi {
772*287e80b3SSadaf Ebrahimi 	struct field *lval = &match->lval->field;
773*287e80b3SSadaf Ebrahimi 	struct field *rval = &match->rval->field;
774*287e80b3SSadaf Ebrahimi 	struct field *field;
775*287e80b3SSadaf Ebrahimi 	struct expr *expr;
776*287e80b3SSadaf Ebrahimi 
777*287e80b3SSadaf Ebrahimi 	if (lval->system != lmatch->system ||
778*287e80b3SSadaf Ebrahimi 	    lval->event != lmatch->event) {
779*287e80b3SSadaf Ebrahimi 		expr = match->lval;
780*287e80b3SSadaf Ebrahimi 		field = lval;
781*287e80b3SSadaf Ebrahimi 	} else {
782*287e80b3SSadaf Ebrahimi 		expr = match->rval;
783*287e80b3SSadaf Ebrahimi 		field = rval;
784*287e80b3SSadaf Ebrahimi 	}
785*287e80b3SSadaf Ebrahimi 
786*287e80b3SSadaf Ebrahimi 	sb->line_no = expr->line;
787*287e80b3SSadaf Ebrahimi 	sb->line_idx = expr->idx;
788*287e80b3SSadaf Ebrahimi 
789*287e80b3SSadaf Ebrahimi 	parse_error(sb, field->raw,
790*287e80b3SSadaf Ebrahimi 		    "'%s' and '%s' must be a field for each event: '%s' and '%s'\n",
791*287e80b3SSadaf Ebrahimi 		    lval->raw, rval->raw, sb->table->to->field.raw,
792*287e80b3SSadaf Ebrahimi 		    sb->table->from->field.raw);
793*287e80b3SSadaf Ebrahimi 
794*287e80b3SSadaf Ebrahimi 	return -1;
795*287e80b3SSadaf Ebrahimi }
796*287e80b3SSadaf Ebrahimi 
test_match(struct sql_table * table,struct match * match)797*287e80b3SSadaf Ebrahimi static int test_match(struct sql_table *table, struct match *match)
798*287e80b3SSadaf Ebrahimi {
799*287e80b3SSadaf Ebrahimi 	struct field *lval, *rval;
800*287e80b3SSadaf Ebrahimi 	struct field *to, *from;
801*287e80b3SSadaf Ebrahimi 
802*287e80b3SSadaf Ebrahimi 	if (!match->lval || !match->rval)
803*287e80b3SSadaf Ebrahimi 		return -1;
804*287e80b3SSadaf Ebrahimi 
805*287e80b3SSadaf Ebrahimi 	if (match->lval->type != EXPR_FIELD || match->rval->type != EXPR_FIELD)
806*287e80b3SSadaf Ebrahimi 		return -1;
807*287e80b3SSadaf Ebrahimi 
808*287e80b3SSadaf Ebrahimi 	to = &table->to->field;
809*287e80b3SSadaf Ebrahimi 	from = &table->from->field;
810*287e80b3SSadaf Ebrahimi 
811*287e80b3SSadaf Ebrahimi 	lval = &match->lval->field;
812*287e80b3SSadaf Ebrahimi 	rval = &match->rval->field;
813*287e80b3SSadaf Ebrahimi 
814*287e80b3SSadaf Ebrahimi 	/*
815*287e80b3SSadaf Ebrahimi 	 * Note, strings are stored in the string store, so all
816*287e80b3SSadaf Ebrahimi 	 * duplicate strings are the same value, and we can use
817*287e80b3SSadaf Ebrahimi 	 * normal "==" and "!=" instead of strcmp().
818*287e80b3SSadaf Ebrahimi 	 *
819*287e80b3SSadaf Ebrahimi 	 * Either lval == to and rval == from
820*287e80b3SSadaf Ebrahimi 	 * or lval == from and rval == to.
821*287e80b3SSadaf Ebrahimi 	 */
822*287e80b3SSadaf Ebrahimi 	if ((lval->system != to->system) ||
823*287e80b3SSadaf Ebrahimi 	    (lval->event != to->event)) {
824*287e80b3SSadaf Ebrahimi 		if ((rval->system != to->system) ||
825*287e80b3SSadaf Ebrahimi 		    (rval->event != to->event) ||
826*287e80b3SSadaf Ebrahimi 		    (lval->system != from->system) ||
827*287e80b3SSadaf Ebrahimi 		    (lval->event != from->event))
828*287e80b3SSadaf Ebrahimi 			return match_error(table->sb, match, from, to);
829*287e80b3SSadaf Ebrahimi 	} else {
830*287e80b3SSadaf Ebrahimi 		if ((rval->system != from->system) ||
831*287e80b3SSadaf Ebrahimi 		    (rval->event != from->event) ||
832*287e80b3SSadaf Ebrahimi 		    (lval->system != to->system) ||
833*287e80b3SSadaf Ebrahimi 		    (lval->event != to->event))
834*287e80b3SSadaf Ebrahimi 			return match_error(table->sb, match, to, from);
835*287e80b3SSadaf Ebrahimi 	}
836*287e80b3SSadaf Ebrahimi 	return 0;
837*287e80b3SSadaf Ebrahimi }
838*287e80b3SSadaf Ebrahimi 
assign_match(const char * system,const char * event,struct match * match,const char ** start_match,const char ** end_match)839*287e80b3SSadaf Ebrahimi static void assign_match(const char *system, const char *event,
840*287e80b3SSadaf Ebrahimi 			 struct match *match,
841*287e80b3SSadaf Ebrahimi 			 const char **start_match, const char **end_match)
842*287e80b3SSadaf Ebrahimi {
843*287e80b3SSadaf Ebrahimi 	struct field *lval, *rval;
844*287e80b3SSadaf Ebrahimi 
845*287e80b3SSadaf Ebrahimi 	lval = &match->lval->field;
846*287e80b3SSadaf Ebrahimi 	rval = &match->rval->field;
847*287e80b3SSadaf Ebrahimi 
848*287e80b3SSadaf Ebrahimi 	if (lval->system == system &&
849*287e80b3SSadaf Ebrahimi 	    lval->event_name == event) {
850*287e80b3SSadaf Ebrahimi 		*start_match = lval->field;
851*287e80b3SSadaf Ebrahimi 		*end_match = rval->field;
852*287e80b3SSadaf Ebrahimi 	} else {
853*287e80b3SSadaf Ebrahimi 		*start_match = rval->field;
854*287e80b3SSadaf Ebrahimi 		*end_match = lval->field;
855*287e80b3SSadaf Ebrahimi 	}
856*287e80b3SSadaf Ebrahimi }
857*287e80b3SSadaf Ebrahimi 
build_compare(struct tracefs_synth * synth,const char * system,const char * event,struct compare * compare)858*287e80b3SSadaf Ebrahimi static int build_compare(struct tracefs_synth *synth,
859*287e80b3SSadaf Ebrahimi 			 const char *system, const char *event,
860*287e80b3SSadaf Ebrahimi 			 struct compare *compare)
861*287e80b3SSadaf Ebrahimi {
862*287e80b3SSadaf Ebrahimi 	const char *start_field;
863*287e80b3SSadaf Ebrahimi 	const char *end_field;
864*287e80b3SSadaf Ebrahimi 	struct field *lval, *rval;
865*287e80b3SSadaf Ebrahimi 	enum tracefs_synth_calc calc;
866*287e80b3SSadaf Ebrahimi 	int ret;
867*287e80b3SSadaf Ebrahimi 
868*287e80b3SSadaf Ebrahimi 	if (!compare->name)
869*287e80b3SSadaf Ebrahimi 		return -1;
870*287e80b3SSadaf Ebrahimi 
871*287e80b3SSadaf Ebrahimi 	lval = &compare->lval->field;
872*287e80b3SSadaf Ebrahimi 	rval = &compare->rval->field;
873*287e80b3SSadaf Ebrahimi 
874*287e80b3SSadaf Ebrahimi 	if (lval->system == system &&
875*287e80b3SSadaf Ebrahimi 	    lval->event_name == event) {
876*287e80b3SSadaf Ebrahimi 		start_field = lval->field;
877*287e80b3SSadaf Ebrahimi 		end_field = rval->field;
878*287e80b3SSadaf Ebrahimi 		calc = TRACEFS_SYNTH_DELTA_START;
879*287e80b3SSadaf Ebrahimi 	} else {
880*287e80b3SSadaf Ebrahimi 		start_field = rval->field;
881*287e80b3SSadaf Ebrahimi 		end_field = lval->field;
882*287e80b3SSadaf Ebrahimi 		calc = TRACEFS_SYNTH_DELTA_END;
883*287e80b3SSadaf Ebrahimi 	}
884*287e80b3SSadaf Ebrahimi 
885*287e80b3SSadaf Ebrahimi 	if (compare->type == COMPARE_ADD)
886*287e80b3SSadaf Ebrahimi 		calc = TRACEFS_SYNTH_ADD;
887*287e80b3SSadaf Ebrahimi 
888*287e80b3SSadaf Ebrahimi 	ret = tracefs_synth_add_compare_field(synth, start_field,
889*287e80b3SSadaf Ebrahimi 					      end_field, calc,
890*287e80b3SSadaf Ebrahimi 					      compare->name);
891*287e80b3SSadaf Ebrahimi 	return ret;
892*287e80b3SSadaf Ebrahimi }
893*287e80b3SSadaf Ebrahimi 
verify_filter_error(struct sqlhist_bison * sb,struct expr * expr,const char * event)894*287e80b3SSadaf Ebrahimi static int verify_filter_error(struct sqlhist_bison *sb, struct expr *expr,
895*287e80b3SSadaf Ebrahimi 			       const char *event)
896*287e80b3SSadaf Ebrahimi {
897*287e80b3SSadaf Ebrahimi 	struct field *field = &expr->field;
898*287e80b3SSadaf Ebrahimi 
899*287e80b3SSadaf Ebrahimi 	sb->line_no = expr->line;
900*287e80b3SSadaf Ebrahimi 	sb->line_idx = expr->idx;
901*287e80b3SSadaf Ebrahimi 
902*287e80b3SSadaf Ebrahimi 	parse_error(sb, field->raw,
903*287e80b3SSadaf Ebrahimi 		    "event '%s' can not be grouped or '||' together with '%s'\n"
904*287e80b3SSadaf Ebrahimi 		    "All filters between '&&' must be for the same event\n",
905*287e80b3SSadaf Ebrahimi 		    field->event, event);
906*287e80b3SSadaf Ebrahimi 	return -1;
907*287e80b3SSadaf Ebrahimi }
908*287e80b3SSadaf Ebrahimi 
do_verify_filter(struct sqlhist_bison * sb,struct filter * filter,const char ** system,const char ** event,enum field_type * ftype)909*287e80b3SSadaf Ebrahimi static int do_verify_filter(struct sqlhist_bison *sb, struct filter *filter,
910*287e80b3SSadaf Ebrahimi 			    const char **system, const char **event,
911*287e80b3SSadaf Ebrahimi 			    enum field_type *ftype)
912*287e80b3SSadaf Ebrahimi {
913*287e80b3SSadaf Ebrahimi 	int ret;
914*287e80b3SSadaf Ebrahimi 
915*287e80b3SSadaf Ebrahimi 	if (filter->type == FILTER_OR ||
916*287e80b3SSadaf Ebrahimi 	    filter->type == FILTER_AND) {
917*287e80b3SSadaf Ebrahimi 		ret = do_verify_filter(sb, &filter->lval->filter, system, event, ftype);
918*287e80b3SSadaf Ebrahimi 		if (ret)
919*287e80b3SSadaf Ebrahimi 			return ret;
920*287e80b3SSadaf Ebrahimi 		return do_verify_filter(sb, &filter->rval->filter, system, event, ftype);
921*287e80b3SSadaf Ebrahimi 	}
922*287e80b3SSadaf Ebrahimi 	if (filter->type == FILTER_GROUP ||
923*287e80b3SSadaf Ebrahimi 	    filter->type == FILTER_NOT_GROUP) {
924*287e80b3SSadaf Ebrahimi 		return do_verify_filter(sb, &filter->lval->filter, system, event, ftype);
925*287e80b3SSadaf Ebrahimi 	}
926*287e80b3SSadaf Ebrahimi 
927*287e80b3SSadaf Ebrahimi 	/*
928*287e80b3SSadaf Ebrahimi 	 * system and event will be NULL until we find the left most
929*287e80b3SSadaf Ebrahimi 	 * node. Then assign it, and compare on the way back up.
930*287e80b3SSadaf Ebrahimi 	 */
931*287e80b3SSadaf Ebrahimi 	if (!*system && !*event) {
932*287e80b3SSadaf Ebrahimi 		*system = filter->lval->field.system;
933*287e80b3SSadaf Ebrahimi 		*event = filter->lval->field.event_name;
934*287e80b3SSadaf Ebrahimi 		*ftype = filter->lval->field.ftype;
935*287e80b3SSadaf Ebrahimi 		return 0;
936*287e80b3SSadaf Ebrahimi 	}
937*287e80b3SSadaf Ebrahimi 
938*287e80b3SSadaf Ebrahimi 	if (filter->lval->field.system != *system ||
939*287e80b3SSadaf Ebrahimi 	    filter->lval->field.event_name != *event)
940*287e80b3SSadaf Ebrahimi 		return verify_filter_error(sb, filter->lval, *event);
941*287e80b3SSadaf Ebrahimi 
942*287e80b3SSadaf Ebrahimi 	return 0;
943*287e80b3SSadaf Ebrahimi }
944*287e80b3SSadaf Ebrahimi 
verify_filter(struct sqlhist_bison * sb,struct filter * filter,const char ** system,const char ** event,enum field_type * ftype)945*287e80b3SSadaf Ebrahimi static int verify_filter(struct sqlhist_bison *sb, struct filter *filter,
946*287e80b3SSadaf Ebrahimi 			 const char **system, const char **event,
947*287e80b3SSadaf Ebrahimi 			 enum field_type *ftype)
948*287e80b3SSadaf Ebrahimi {
949*287e80b3SSadaf Ebrahimi 	int ret;
950*287e80b3SSadaf Ebrahimi 
951*287e80b3SSadaf Ebrahimi 	switch (filter->type) {
952*287e80b3SSadaf Ebrahimi 	case FILTER_OR:
953*287e80b3SSadaf Ebrahimi 	case FILTER_AND:
954*287e80b3SSadaf Ebrahimi 	case FILTER_GROUP:
955*287e80b3SSadaf Ebrahimi 	case FILTER_NOT_GROUP:
956*287e80b3SSadaf Ebrahimi 		break;
957*287e80b3SSadaf Ebrahimi 	default:
958*287e80b3SSadaf Ebrahimi 		return do_verify_filter(sb, filter, system, event, ftype);
959*287e80b3SSadaf Ebrahimi 	}
960*287e80b3SSadaf Ebrahimi 
961*287e80b3SSadaf Ebrahimi 	ret = do_verify_filter(sb, &filter->lval->filter, system, event, ftype);
962*287e80b3SSadaf Ebrahimi 	if (ret)
963*287e80b3SSadaf Ebrahimi 		return ret;
964*287e80b3SSadaf Ebrahimi 
965*287e80b3SSadaf Ebrahimi 	switch (filter->type) {
966*287e80b3SSadaf Ebrahimi 	case FILTER_OR:
967*287e80b3SSadaf Ebrahimi 	case FILTER_AND:
968*287e80b3SSadaf Ebrahimi 		return do_verify_filter(sb, &filter->rval->filter, system, event, ftype);
969*287e80b3SSadaf Ebrahimi 	default:
970*287e80b3SSadaf Ebrahimi 		return 0;
971*287e80b3SSadaf Ebrahimi 	}
972*287e80b3SSadaf Ebrahimi }
973*287e80b3SSadaf Ebrahimi 
974*287e80b3SSadaf Ebrahimi static int test_field_exists(struct tep_handle *tep, struct sqlhist_bison *sb,
975*287e80b3SSadaf Ebrahimi 			     struct expr *expr);
976*287e80b3SSadaf Ebrahimi 
filter_compare_error(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr)977*287e80b3SSadaf Ebrahimi static void filter_compare_error(struct tep_handle *tep,
978*287e80b3SSadaf Ebrahimi 				 struct sqlhist_bison *sb,
979*287e80b3SSadaf Ebrahimi 				 struct expr *expr)
980*287e80b3SSadaf Ebrahimi {
981*287e80b3SSadaf Ebrahimi 	struct field *field = &expr->field;
982*287e80b3SSadaf Ebrahimi 
983*287e80b3SSadaf Ebrahimi 	switch (errno) {
984*287e80b3SSadaf Ebrahimi 	case ENODEV:
985*287e80b3SSadaf Ebrahimi 	case EBADE:
986*287e80b3SSadaf Ebrahimi 		break;
987*287e80b3SSadaf Ebrahimi 	case EINVAL:
988*287e80b3SSadaf Ebrahimi 		parse_error(sb, field->raw, "Invalid compare\n");
989*287e80b3SSadaf Ebrahimi 		break;
990*287e80b3SSadaf Ebrahimi 	default:
991*287e80b3SSadaf Ebrahimi 		parse_error(sb, field->raw, "System error?\n");
992*287e80b3SSadaf Ebrahimi 		return;
993*287e80b3SSadaf Ebrahimi 	}
994*287e80b3SSadaf Ebrahimi 
995*287e80b3SSadaf Ebrahimi 	/* ENODEV means that an event or field does not exist */
996*287e80b3SSadaf Ebrahimi 	if (errno == ENODEV) {
997*287e80b3SSadaf Ebrahimi 		if (test_field_exists(tep, sb, expr))
998*287e80b3SSadaf Ebrahimi 			return;
999*287e80b3SSadaf Ebrahimi 		if (test_field_exists(tep, sb, expr))
1000*287e80b3SSadaf Ebrahimi 			return;
1001*287e80b3SSadaf Ebrahimi 		return;
1002*287e80b3SSadaf Ebrahimi 	}
1003*287e80b3SSadaf Ebrahimi 
1004*287e80b3SSadaf Ebrahimi 	/* fields exist, but values are not compatible */
1005*287e80b3SSadaf Ebrahimi 	sb->line_no = expr->line;
1006*287e80b3SSadaf Ebrahimi 	sb->line_idx = expr->idx;
1007*287e80b3SSadaf Ebrahimi 
1008*287e80b3SSadaf Ebrahimi 	parse_error(sb, field->raw,
1009*287e80b3SSadaf Ebrahimi 		    "Field '%s' is not compatible to be compared with the given value\n",
1010*287e80b3SSadaf Ebrahimi 		    field->field);
1011*287e80b3SSadaf Ebrahimi }
1012*287e80b3SSadaf Ebrahimi 
filter_error(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr)1013*287e80b3SSadaf Ebrahimi static void filter_error(struct tep_handle *tep,
1014*287e80b3SSadaf Ebrahimi 			 struct sqlhist_bison *sb, struct expr *expr)
1015*287e80b3SSadaf Ebrahimi {
1016*287e80b3SSadaf Ebrahimi 	struct filter *filter = &expr->filter;
1017*287e80b3SSadaf Ebrahimi 
1018*287e80b3SSadaf Ebrahimi 	sb->line_no = expr->line;
1019*287e80b3SSadaf Ebrahimi 	sb->line_idx = expr->idx;
1020*287e80b3SSadaf Ebrahimi 
1021*287e80b3SSadaf Ebrahimi 	switch (filter->type) {
1022*287e80b3SSadaf Ebrahimi 	case FILTER_NOT_GROUP:
1023*287e80b3SSadaf Ebrahimi 	case FILTER_GROUP:
1024*287e80b3SSadaf Ebrahimi 	case FILTER_OR:
1025*287e80b3SSadaf Ebrahimi 	case FILTER_AND:
1026*287e80b3SSadaf Ebrahimi 		break;
1027*287e80b3SSadaf Ebrahimi 	default:
1028*287e80b3SSadaf Ebrahimi 		filter_compare_error(tep, sb, filter->lval);
1029*287e80b3SSadaf Ebrahimi 		return;
1030*287e80b3SSadaf Ebrahimi 	}
1031*287e80b3SSadaf Ebrahimi 
1032*287e80b3SSadaf Ebrahimi 	sb->line_no = expr->line;
1033*287e80b3SSadaf Ebrahimi 	sb->line_idx = expr->idx;
1034*287e80b3SSadaf Ebrahimi 
1035*287e80b3SSadaf Ebrahimi 	parse_error(sb, "", "Problem with filter entry?\n");
1036*287e80b3SSadaf Ebrahimi }
1037*287e80b3SSadaf Ebrahimi 
build_filter(struct tep_handle * tep,struct sqlhist_bison * sb,struct tracefs_synth * synth,bool start,struct expr * expr,bool * started)1038*287e80b3SSadaf Ebrahimi static int build_filter(struct tep_handle *tep, struct sqlhist_bison *sb,
1039*287e80b3SSadaf Ebrahimi 			struct tracefs_synth *synth,
1040*287e80b3SSadaf Ebrahimi 			bool start, struct expr *expr, bool *started)
1041*287e80b3SSadaf Ebrahimi {
1042*287e80b3SSadaf Ebrahimi 	int (*append_filter)(struct tracefs_synth *synth,
1043*287e80b3SSadaf Ebrahimi 			     enum tracefs_filter type,
1044*287e80b3SSadaf Ebrahimi 			     const char *field,
1045*287e80b3SSadaf Ebrahimi 			     enum tracefs_compare compare,
1046*287e80b3SSadaf Ebrahimi 			     const char *val);
1047*287e80b3SSadaf Ebrahimi 	struct filter *filter = &expr->filter;
1048*287e80b3SSadaf Ebrahimi 	enum tracefs_compare cmp;
1049*287e80b3SSadaf Ebrahimi 	const char *val;
1050*287e80b3SSadaf Ebrahimi 	int and_or = TRACEFS_FILTER_AND;
1051*287e80b3SSadaf Ebrahimi 	char num[64];
1052*287e80b3SSadaf Ebrahimi 	int ret;
1053*287e80b3SSadaf Ebrahimi 
1054*287e80b3SSadaf Ebrahimi 	if (start)
1055*287e80b3SSadaf Ebrahimi 		append_filter = tracefs_synth_append_start_filter;
1056*287e80b3SSadaf Ebrahimi 	else
1057*287e80b3SSadaf Ebrahimi 		append_filter = tracefs_synth_append_end_filter;
1058*287e80b3SSadaf Ebrahimi 
1059*287e80b3SSadaf Ebrahimi 	if (started && *started) {
1060*287e80b3SSadaf Ebrahimi 		ret = append_filter(synth, and_or, NULL, 0, NULL);
1061*287e80b3SSadaf Ebrahimi 		ret = append_filter(synth, TRACEFS_FILTER_OPEN_PAREN,
1062*287e80b3SSadaf Ebrahimi 				    NULL, 0, NULL);
1063*287e80b3SSadaf Ebrahimi 	}
1064*287e80b3SSadaf Ebrahimi 
1065*287e80b3SSadaf Ebrahimi 	switch (filter->type) {
1066*287e80b3SSadaf Ebrahimi 	case FILTER_NOT_GROUP:
1067*287e80b3SSadaf Ebrahimi 		ret = append_filter(synth, TRACEFS_FILTER_NOT,
1068*287e80b3SSadaf Ebrahimi 				    NULL, 0, NULL);
1069*287e80b3SSadaf Ebrahimi 		if (ret < 0)
1070*287e80b3SSadaf Ebrahimi 			goto out;
1071*287e80b3SSadaf Ebrahimi 		/* Fall through */
1072*287e80b3SSadaf Ebrahimi 	case FILTER_GROUP:
1073*287e80b3SSadaf Ebrahimi 		ret = append_filter(synth, TRACEFS_FILTER_OPEN_PAREN,
1074*287e80b3SSadaf Ebrahimi 				    NULL, 0, NULL);
1075*287e80b3SSadaf Ebrahimi 		if (ret < 0)
1076*287e80b3SSadaf Ebrahimi 			goto out;
1077*287e80b3SSadaf Ebrahimi 		ret = build_filter(tep, sb, synth, start, filter->lval, NULL);
1078*287e80b3SSadaf Ebrahimi 		if (ret < 0)
1079*287e80b3SSadaf Ebrahimi 			goto out;
1080*287e80b3SSadaf Ebrahimi 		ret = append_filter(synth, TRACEFS_FILTER_CLOSE_PAREN,
1081*287e80b3SSadaf Ebrahimi 				    NULL, 0, NULL);
1082*287e80b3SSadaf Ebrahimi 		goto out;
1083*287e80b3SSadaf Ebrahimi 
1084*287e80b3SSadaf Ebrahimi 	case FILTER_OR:
1085*287e80b3SSadaf Ebrahimi 		and_or = TRACEFS_FILTER_OR;
1086*287e80b3SSadaf Ebrahimi 		/* Fall through */
1087*287e80b3SSadaf Ebrahimi 	case FILTER_AND:
1088*287e80b3SSadaf Ebrahimi 		ret = build_filter(tep, sb, synth, start, filter->lval, NULL);
1089*287e80b3SSadaf Ebrahimi 		if (ret < 0)
1090*287e80b3SSadaf Ebrahimi 			goto out;
1091*287e80b3SSadaf Ebrahimi 		ret = append_filter(synth, and_or, NULL, 0, NULL);
1092*287e80b3SSadaf Ebrahimi 
1093*287e80b3SSadaf Ebrahimi 		if (ret)
1094*287e80b3SSadaf Ebrahimi 			goto out;
1095*287e80b3SSadaf Ebrahimi 		ret = build_filter(tep, sb, synth, start, filter->rval, NULL);
1096*287e80b3SSadaf Ebrahimi 		goto out;
1097*287e80b3SSadaf Ebrahimi 	default:
1098*287e80b3SSadaf Ebrahimi 		break;
1099*287e80b3SSadaf Ebrahimi 	}
1100*287e80b3SSadaf Ebrahimi 
1101*287e80b3SSadaf Ebrahimi 	switch (filter->rval->type) {
1102*287e80b3SSadaf Ebrahimi 	case EXPR_NUMBER:
1103*287e80b3SSadaf Ebrahimi 		sprintf(num, "%ld", filter->rval->number);
1104*287e80b3SSadaf Ebrahimi 		val = num;
1105*287e80b3SSadaf Ebrahimi 		break;
1106*287e80b3SSadaf Ebrahimi 	case EXPR_STRING:
1107*287e80b3SSadaf Ebrahimi 		val = filter->rval->string;
1108*287e80b3SSadaf Ebrahimi 		break;
1109*287e80b3SSadaf Ebrahimi 	default:
1110*287e80b3SSadaf Ebrahimi 		break;
1111*287e80b3SSadaf Ebrahimi 	}
1112*287e80b3SSadaf Ebrahimi 
1113*287e80b3SSadaf Ebrahimi 	switch (filter->type) {
1114*287e80b3SSadaf Ebrahimi 	case FILTER_EQ:		cmp = TRACEFS_COMPARE_EQ; break;
1115*287e80b3SSadaf Ebrahimi 	case FILTER_NE:		cmp = TRACEFS_COMPARE_NE; break;
1116*287e80b3SSadaf Ebrahimi 	case FILTER_LE:		cmp = TRACEFS_COMPARE_LE; break;
1117*287e80b3SSadaf Ebrahimi 	case FILTER_LT:		cmp = TRACEFS_COMPARE_LT; break;
1118*287e80b3SSadaf Ebrahimi 	case FILTER_GE:		cmp = TRACEFS_COMPARE_GE; break;
1119*287e80b3SSadaf Ebrahimi 	case FILTER_GT:		cmp = TRACEFS_COMPARE_GT; break;
1120*287e80b3SSadaf Ebrahimi 	case FILTER_BIN_AND:	cmp = TRACEFS_COMPARE_AND; break;
1121*287e80b3SSadaf Ebrahimi 	case FILTER_STR_CMP:	cmp = TRACEFS_COMPARE_RE; break;
1122*287e80b3SSadaf Ebrahimi 	default:
1123*287e80b3SSadaf Ebrahimi 		tracefs_warning("Error invalid filter type '%d'", filter->type);
1124*287e80b3SSadaf Ebrahimi 		return ERANGE;
1125*287e80b3SSadaf Ebrahimi 	}
1126*287e80b3SSadaf Ebrahimi 
1127*287e80b3SSadaf Ebrahimi 	ret = append_filter(synth, TRACEFS_FILTER_COMPARE,
1128*287e80b3SSadaf Ebrahimi 			    filter->lval->field.field, cmp, val);
1129*287e80b3SSadaf Ebrahimi 
1130*287e80b3SSadaf Ebrahimi 	if (ret)
1131*287e80b3SSadaf Ebrahimi 		filter_error(tep, sb, expr);
1132*287e80b3SSadaf Ebrahimi  out:
1133*287e80b3SSadaf Ebrahimi 	if (!ret && started) {
1134*287e80b3SSadaf Ebrahimi 		if (*started)
1135*287e80b3SSadaf Ebrahimi 			ret = append_filter(synth, TRACEFS_FILTER_CLOSE_PAREN,
1136*287e80b3SSadaf Ebrahimi 					    NULL, 0, NULL);
1137*287e80b3SSadaf Ebrahimi 		*started = true;
1138*287e80b3SSadaf Ebrahimi 	}
1139*287e80b3SSadaf Ebrahimi 	return ret;
1140*287e80b3SSadaf Ebrahimi }
1141*287e80b3SSadaf Ebrahimi 
field_match_error(struct tep_handle * tep,struct sqlhist_bison * sb,struct match * match)1142*287e80b3SSadaf Ebrahimi static void *field_match_error(struct tep_handle *tep, struct sqlhist_bison *sb,
1143*287e80b3SSadaf Ebrahimi 			       struct match *match)
1144*287e80b3SSadaf Ebrahimi {
1145*287e80b3SSadaf Ebrahimi 	switch (errno) {
1146*287e80b3SSadaf Ebrahimi 	case ENODEV:
1147*287e80b3SSadaf Ebrahimi 	case EBADE:
1148*287e80b3SSadaf Ebrahimi 		break;
1149*287e80b3SSadaf Ebrahimi 	default:
1150*287e80b3SSadaf Ebrahimi 		/* System error */
1151*287e80b3SSadaf Ebrahimi 		return NULL;
1152*287e80b3SSadaf Ebrahimi 	}
1153*287e80b3SSadaf Ebrahimi 
1154*287e80b3SSadaf Ebrahimi 	/* ENODEV means that an event or field does not exist */
1155*287e80b3SSadaf Ebrahimi 	if (errno == ENODEV) {
1156*287e80b3SSadaf Ebrahimi 		if (test_field_exists(tep, sb, match->lval))
1157*287e80b3SSadaf Ebrahimi 			return NULL;
1158*287e80b3SSadaf Ebrahimi 		if (test_field_exists(tep, sb, match->rval))
1159*287e80b3SSadaf Ebrahimi 			return NULL;
1160*287e80b3SSadaf Ebrahimi 		return NULL;
1161*287e80b3SSadaf Ebrahimi 	}
1162*287e80b3SSadaf Ebrahimi 
1163*287e80b3SSadaf Ebrahimi 	/* fields exist, but values are not compatible */
1164*287e80b3SSadaf Ebrahimi 	sb->line_no = match->lval->line;
1165*287e80b3SSadaf Ebrahimi 	sb->line_idx = match->lval->idx;
1166*287e80b3SSadaf Ebrahimi 
1167*287e80b3SSadaf Ebrahimi 	parse_error(sb, match->lval->field.raw,
1168*287e80b3SSadaf Ebrahimi 		    "Field '%s' is not compatible to match field '%s'\n",
1169*287e80b3SSadaf Ebrahimi 		    match->lval->field.raw, match->rval->field.raw);
1170*287e80b3SSadaf Ebrahimi 	return NULL;
1171*287e80b3SSadaf Ebrahimi }
1172*287e80b3SSadaf Ebrahimi 
synth_init_error(struct tep_handle * tep,struct sql_table * table)1173*287e80b3SSadaf Ebrahimi static void *synth_init_error(struct tep_handle *tep, struct sql_table *table)
1174*287e80b3SSadaf Ebrahimi {
1175*287e80b3SSadaf Ebrahimi 	struct sqlhist_bison *sb = table->sb;
1176*287e80b3SSadaf Ebrahimi 	struct match *match = table->matches;
1177*287e80b3SSadaf Ebrahimi 
1178*287e80b3SSadaf Ebrahimi 	switch (errno) {
1179*287e80b3SSadaf Ebrahimi 	case ENODEV:
1180*287e80b3SSadaf Ebrahimi 	case EBADE:
1181*287e80b3SSadaf Ebrahimi 		break;
1182*287e80b3SSadaf Ebrahimi 	default:
1183*287e80b3SSadaf Ebrahimi 		/* System error */
1184*287e80b3SSadaf Ebrahimi 		return NULL;
1185*287e80b3SSadaf Ebrahimi 	}
1186*287e80b3SSadaf Ebrahimi 
1187*287e80b3SSadaf Ebrahimi 	/* ENODEV could mean that start or end events do not exist */
1188*287e80b3SSadaf Ebrahimi 	if (errno == ENODEV) {
1189*287e80b3SSadaf Ebrahimi 		if (test_event_exists(tep, sb, table->from, NULL))
1190*287e80b3SSadaf Ebrahimi 			return NULL;
1191*287e80b3SSadaf Ebrahimi 		if (test_event_exists(tep, sb, table->to, NULL))
1192*287e80b3SSadaf Ebrahimi 			return NULL;
1193*287e80b3SSadaf Ebrahimi 	}
1194*287e80b3SSadaf Ebrahimi 
1195*287e80b3SSadaf Ebrahimi 	return field_match_error(tep, sb, match);
1196*287e80b3SSadaf Ebrahimi }
1197*287e80b3SSadaf Ebrahimi 
selection_error(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr)1198*287e80b3SSadaf Ebrahimi static void selection_error(struct tep_handle *tep,
1199*287e80b3SSadaf Ebrahimi 			    struct sqlhist_bison *sb, struct expr *expr)
1200*287e80b3SSadaf Ebrahimi {
1201*287e80b3SSadaf Ebrahimi 	/* We just care about event not existing */
1202*287e80b3SSadaf Ebrahimi 	if (errno != ENODEV)
1203*287e80b3SSadaf Ebrahimi 		return;
1204*287e80b3SSadaf Ebrahimi 
1205*287e80b3SSadaf Ebrahimi 	test_field_exists(tep, sb, expr);
1206*287e80b3SSadaf Ebrahimi }
1207*287e80b3SSadaf Ebrahimi 
compare_error(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr)1208*287e80b3SSadaf Ebrahimi static void compare_error(struct tep_handle *tep,
1209*287e80b3SSadaf Ebrahimi 			    struct sqlhist_bison *sb, struct expr *expr)
1210*287e80b3SSadaf Ebrahimi {
1211*287e80b3SSadaf Ebrahimi 	struct compare *compare = &expr->compare;
1212*287e80b3SSadaf Ebrahimi 
1213*287e80b3SSadaf Ebrahimi 	if (!compare->name) {
1214*287e80b3SSadaf Ebrahimi 		sb->line_no = expr->line;
1215*287e80b3SSadaf Ebrahimi 		sb->line_idx = expr->idx + strlen("no name");
1216*287e80b3SSadaf Ebrahimi 
1217*287e80b3SSadaf Ebrahimi 		parse_error(sb, "no name",
1218*287e80b3SSadaf Ebrahimi 		    "Field calculations must be labeled 'AS name'\n");
1219*287e80b3SSadaf Ebrahimi 	}
1220*287e80b3SSadaf Ebrahimi 
1221*287e80b3SSadaf Ebrahimi 	switch (errno) {
1222*287e80b3SSadaf Ebrahimi 	case ENODEV:
1223*287e80b3SSadaf Ebrahimi 	case EBADE:
1224*287e80b3SSadaf Ebrahimi 		break;
1225*287e80b3SSadaf Ebrahimi 	default:
1226*287e80b3SSadaf Ebrahimi 		/* System error */
1227*287e80b3SSadaf Ebrahimi 		return;
1228*287e80b3SSadaf Ebrahimi 	}
1229*287e80b3SSadaf Ebrahimi 
1230*287e80b3SSadaf Ebrahimi 	/* ENODEV means that an event or field does not exist */
1231*287e80b3SSadaf Ebrahimi 	if (errno == ENODEV) {
1232*287e80b3SSadaf Ebrahimi 		if (test_field_exists(tep, sb, compare->lval))
1233*287e80b3SSadaf Ebrahimi 			return;
1234*287e80b3SSadaf Ebrahimi 		if (test_field_exists(tep, sb, compare->rval))
1235*287e80b3SSadaf Ebrahimi 			return;
1236*287e80b3SSadaf Ebrahimi 		return;
1237*287e80b3SSadaf Ebrahimi 	}
1238*287e80b3SSadaf Ebrahimi 
1239*287e80b3SSadaf Ebrahimi 	/* fields exist, but values are not compatible */
1240*287e80b3SSadaf Ebrahimi 	sb->line_no = compare->lval->line;
1241*287e80b3SSadaf Ebrahimi 	sb->line_idx = compare->lval->idx;
1242*287e80b3SSadaf Ebrahimi 
1243*287e80b3SSadaf Ebrahimi 	parse_error(sb, compare->lval->field.raw,
1244*287e80b3SSadaf Ebrahimi 		    "'%s' is not compatible to compare with '%s'\n",
1245*287e80b3SSadaf Ebrahimi 		    compare->lval->field.raw, compare->rval->field.raw);
1246*287e80b3SSadaf Ebrahimi }
1247*287e80b3SSadaf Ebrahimi 
compare_no_to_error(struct sqlhist_bison * sb,struct expr * expr)1248*287e80b3SSadaf Ebrahimi static void compare_no_to_error(struct sqlhist_bison *sb, struct expr *expr)
1249*287e80b3SSadaf Ebrahimi {
1250*287e80b3SSadaf Ebrahimi 	struct compare *compare = &expr->compare;
1251*287e80b3SSadaf Ebrahimi 
1252*287e80b3SSadaf Ebrahimi 	sb->line_no = compare->lval->line;
1253*287e80b3SSadaf Ebrahimi 	sb->line_idx = compare->lval->idx;
1254*287e80b3SSadaf Ebrahimi 
1255*287e80b3SSadaf Ebrahimi 	parse_error(sb, compare->lval->field.raw,
1256*287e80b3SSadaf Ebrahimi 		    "Simple SQL (without JOIN/ON) do not allow comparisons\n",
1257*287e80b3SSadaf Ebrahimi 		    compare->lval->field.raw, compare->rval->field.raw);
1258*287e80b3SSadaf Ebrahimi }
1259*287e80b3SSadaf Ebrahimi 
where_no_to_error(struct sqlhist_bison * sb,struct expr * expr,const char * from_event,const char * event)1260*287e80b3SSadaf Ebrahimi static void where_no_to_error(struct sqlhist_bison *sb, struct expr *expr,
1261*287e80b3SSadaf Ebrahimi 			      const char *from_event, const char *event)
1262*287e80b3SSadaf Ebrahimi {
1263*287e80b3SSadaf Ebrahimi 	while (expr) {
1264*287e80b3SSadaf Ebrahimi 		switch (expr->filter.type) {
1265*287e80b3SSadaf Ebrahimi 		case FILTER_OR:
1266*287e80b3SSadaf Ebrahimi 		case FILTER_AND:
1267*287e80b3SSadaf Ebrahimi 		case FILTER_GROUP:
1268*287e80b3SSadaf Ebrahimi 		case FILTER_NOT_GROUP:
1269*287e80b3SSadaf Ebrahimi 			expr = expr->filter.lval;
1270*287e80b3SSadaf Ebrahimi 			continue;
1271*287e80b3SSadaf Ebrahimi 		default:
1272*287e80b3SSadaf Ebrahimi 			break;
1273*287e80b3SSadaf Ebrahimi 		}
1274*287e80b3SSadaf Ebrahimi 		break;
1275*287e80b3SSadaf Ebrahimi 	}
1276*287e80b3SSadaf Ebrahimi 	sb->line_no = expr->filter.lval->line;
1277*287e80b3SSadaf Ebrahimi 	sb->line_idx = expr->filter.lval->idx;
1278*287e80b3SSadaf Ebrahimi 
1279*287e80b3SSadaf Ebrahimi 	parse_error(sb, expr->filter.lval->field.raw,
1280*287e80b3SSadaf Ebrahimi 		    "Event '%s' does not match FROM event '%s'\n",
1281*287e80b3SSadaf Ebrahimi 		    event, from_event);
1282*287e80b3SSadaf Ebrahimi }
1283*287e80b3SSadaf Ebrahimi 
verify_field_type(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr,int * cnt)1284*287e80b3SSadaf Ebrahimi static int verify_field_type(struct tep_handle *tep,
1285*287e80b3SSadaf Ebrahimi 			     struct sqlhist_bison *sb,
1286*287e80b3SSadaf Ebrahimi 			     struct expr *expr, int *cnt)
1287*287e80b3SSadaf Ebrahimi {
1288*287e80b3SSadaf Ebrahimi 	struct field *field = &expr->field;
1289*287e80b3SSadaf Ebrahimi 	struct tep_event *event;
1290*287e80b3SSadaf Ebrahimi 	struct tep_format_field *tfield;
1291*287e80b3SSadaf Ebrahimi 	char *type;
1292*287e80b3SSadaf Ebrahimi 	int ret;
1293*287e80b3SSadaf Ebrahimi 	int i;
1294*287e80b3SSadaf Ebrahimi 
1295*287e80b3SSadaf Ebrahimi 	if (!field->type)
1296*287e80b3SSadaf Ebrahimi 		return 0;
1297*287e80b3SSadaf Ebrahimi 
1298*287e80b3SSadaf Ebrahimi 	sb->line_no = expr->line;
1299*287e80b3SSadaf Ebrahimi 	sb->line_idx = expr->idx;
1300*287e80b3SSadaf Ebrahimi 
1301*287e80b3SSadaf Ebrahimi 	event = tep_find_event_by_name(tep, field->system, field->event_name);
1302*287e80b3SSadaf Ebrahimi 	if (!event) {
1303*287e80b3SSadaf Ebrahimi 		parse_error(sb, field->raw,
1304*287e80b3SSadaf Ebrahimi 			    "Event '%s' not found\n",
1305*287e80b3SSadaf Ebrahimi 			    field->event_name ? : "(null)");
1306*287e80b3SSadaf Ebrahimi 		return -1;
1307*287e80b3SSadaf Ebrahimi 	}
1308*287e80b3SSadaf Ebrahimi 
1309*287e80b3SSadaf Ebrahimi 	tfield = tep_find_any_field(event, field->field);
1310*287e80b3SSadaf Ebrahimi 	if (!tfield) {
1311*287e80b3SSadaf Ebrahimi 		parse_error(sb, field->raw,
1312*287e80b3SSadaf Ebrahimi 			    "Field '%s' not part of event '%s'\n",
1313*287e80b3SSadaf Ebrahimi 			    field->field ? : "(null)", field->event);
1314*287e80b3SSadaf Ebrahimi 		return -1;
1315*287e80b3SSadaf Ebrahimi 	}
1316*287e80b3SSadaf Ebrahimi 
1317*287e80b3SSadaf Ebrahimi 	type = strdup(field->type);
1318*287e80b3SSadaf Ebrahimi 	if (!type)
1319*287e80b3SSadaf Ebrahimi 		return -1;
1320*287e80b3SSadaf Ebrahimi 
1321*287e80b3SSadaf Ebrahimi 	if (!strcmp(type, TRACEFS_HIST_COUNTER) ||
1322*287e80b3SSadaf Ebrahimi 	    !strcmp(type, "_COUNTER_")) {
1323*287e80b3SSadaf Ebrahimi 		ret = HIST_COUNTER_TYPE;
1324*287e80b3SSadaf Ebrahimi 		if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY)) {
1325*287e80b3SSadaf Ebrahimi 			parse_error(sb, field->raw,
1326*287e80b3SSadaf Ebrahimi 				    "'%s' is a string, and counters may only be used with numbers\n");
1327*287e80b3SSadaf Ebrahimi 			ret = -1;
1328*287e80b3SSadaf Ebrahimi 		}
1329*287e80b3SSadaf Ebrahimi 		goto out;
1330*287e80b3SSadaf Ebrahimi 	}
1331*287e80b3SSadaf Ebrahimi 
1332*287e80b3SSadaf Ebrahimi 	for (i = 0; type[i]; i++)
1333*287e80b3SSadaf Ebrahimi 		type[i] = tolower(type[i]);
1334*287e80b3SSadaf Ebrahimi 
1335*287e80b3SSadaf Ebrahimi 	if (!strcmp(type, "hex")) {
1336*287e80b3SSadaf Ebrahimi 		if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY))
1337*287e80b3SSadaf Ebrahimi 			goto fail_type;
1338*287e80b3SSadaf Ebrahimi 		ret = TRACEFS_HIST_KEY_HEX;
1339*287e80b3SSadaf Ebrahimi 	} else if (!strcmp(type, "sym")) {
1340*287e80b3SSadaf Ebrahimi 		if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY))
1341*287e80b3SSadaf Ebrahimi 			goto fail_type;
1342*287e80b3SSadaf Ebrahimi 		ret = TRACEFS_HIST_KEY_SYM;
1343*287e80b3SSadaf Ebrahimi 	} else if (!strcmp(type, "sym-offset")) {
1344*287e80b3SSadaf Ebrahimi 		if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY))
1345*287e80b3SSadaf Ebrahimi 			goto fail_type;
1346*287e80b3SSadaf Ebrahimi 		ret = TRACEFS_HIST_KEY_SYM_OFFSET;
1347*287e80b3SSadaf Ebrahimi 	} else if (!strcmp(type, "syscall")) {
1348*287e80b3SSadaf Ebrahimi 		if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY))
1349*287e80b3SSadaf Ebrahimi 			goto fail_type;
1350*287e80b3SSadaf Ebrahimi 		ret = TRACEFS_HIST_KEY_SYSCALL;
1351*287e80b3SSadaf Ebrahimi 	} else if (!strcmp(type, "execname") ||
1352*287e80b3SSadaf Ebrahimi 		   !strcmp(type, "comm")) {
1353*287e80b3SSadaf Ebrahimi 		ret = TRACEFS_HIST_KEY_EXECNAME;
1354*287e80b3SSadaf Ebrahimi 		if (strcmp(field->field, "common_pid")) {
1355*287e80b3SSadaf Ebrahimi 			parse_error(sb, field->raw,
1356*287e80b3SSadaf Ebrahimi 				    "'%s' is only allowed for common_pid\n",
1357*287e80b3SSadaf Ebrahimi 				    type);
1358*287e80b3SSadaf Ebrahimi 			ret = -1;
1359*287e80b3SSadaf Ebrahimi 		}
1360*287e80b3SSadaf Ebrahimi 	} else if (!strcmp(type, "log") ||
1361*287e80b3SSadaf Ebrahimi 		   !strcmp(type, "log2")) {
1362*287e80b3SSadaf Ebrahimi 		if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY))
1363*287e80b3SSadaf Ebrahimi 			goto fail_type;
1364*287e80b3SSadaf Ebrahimi 		ret = TRACEFS_HIST_KEY_LOG;
1365*287e80b3SSadaf Ebrahimi 	} else if (!strncmp(type, "buckets", 7)) {
1366*287e80b3SSadaf Ebrahimi 		if (type[7] != '=' || !isdigit(type[8])) {
1367*287e80b3SSadaf Ebrahimi 			parse_error(sb, field->raw,
1368*287e80b3SSadaf Ebrahimi 				    "buckets type must have '=[number]' after it\n");
1369*287e80b3SSadaf Ebrahimi 			ret = -1;
1370*287e80b3SSadaf Ebrahimi 			goto out;
1371*287e80b3SSadaf Ebrahimi 		}
1372*287e80b3SSadaf Ebrahimi 		*cnt = atoi(&type[8]);
1373*287e80b3SSadaf Ebrahimi 		if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY))
1374*287e80b3SSadaf Ebrahimi 			goto fail_type;
1375*287e80b3SSadaf Ebrahimi 		ret = TRACEFS_HIST_KEY_BUCKETS;
1376*287e80b3SSadaf Ebrahimi 	} else {
1377*287e80b3SSadaf Ebrahimi 		parse_error(sb, field->raw,
1378*287e80b3SSadaf Ebrahimi 			    "Cast of '%s' to unknown type '%s'\n",
1379*287e80b3SSadaf Ebrahimi 			    field->raw, type);
1380*287e80b3SSadaf Ebrahimi 		ret = -1;
1381*287e80b3SSadaf Ebrahimi 	}
1382*287e80b3SSadaf Ebrahimi  out:
1383*287e80b3SSadaf Ebrahimi 	free(type);
1384*287e80b3SSadaf Ebrahimi 	return ret;
1385*287e80b3SSadaf Ebrahimi  fail_type:
1386*287e80b3SSadaf Ebrahimi 	parse_error(sb, field->raw,
1387*287e80b3SSadaf Ebrahimi 		    "Field '%s' cast to '%s' but is of type %s\n",
1388*287e80b3SSadaf Ebrahimi 		    field->field, type, tfield->flags & TEP_FIELD_IS_STRING ?
1389*287e80b3SSadaf Ebrahimi 		    "string" : "array");
1390*287e80b3SSadaf Ebrahimi 	free(type);
1391*287e80b3SSadaf Ebrahimi 	return -1;
1392*287e80b3SSadaf Ebrahimi }
1393*287e80b3SSadaf Ebrahimi 
build_synth(struct tep_handle * tep,const char * name,struct sql_table * table)1394*287e80b3SSadaf Ebrahimi static struct tracefs_synth *build_synth(struct tep_handle *tep,
1395*287e80b3SSadaf Ebrahimi 					 const char *name,
1396*287e80b3SSadaf Ebrahimi 					 struct sql_table *table)
1397*287e80b3SSadaf Ebrahimi {
1398*287e80b3SSadaf Ebrahimi 	struct tracefs_synth *synth;
1399*287e80b3SSadaf Ebrahimi 	struct field *field;
1400*287e80b3SSadaf Ebrahimi 	struct match *match;
1401*287e80b3SSadaf Ebrahimi 	struct expr *expr;
1402*287e80b3SSadaf Ebrahimi 	const char *start_system;
1403*287e80b3SSadaf Ebrahimi 	const char *start_event;
1404*287e80b3SSadaf Ebrahimi 	const char *end_system;
1405*287e80b3SSadaf Ebrahimi 	const char *end_event;
1406*287e80b3SSadaf Ebrahimi 	const char *start_match;
1407*287e80b3SSadaf Ebrahimi 	const char *end_match;
1408*287e80b3SSadaf Ebrahimi 	bool started_start = false;
1409*287e80b3SSadaf Ebrahimi 	bool started_end = false;
1410*287e80b3SSadaf Ebrahimi 	bool non_val = false;
1411*287e80b3SSadaf Ebrahimi 	int ret;
1412*287e80b3SSadaf Ebrahimi 
1413*287e80b3SSadaf Ebrahimi 	if (!table->from)
1414*287e80b3SSadaf Ebrahimi 		return NULL;
1415*287e80b3SSadaf Ebrahimi 
1416*287e80b3SSadaf Ebrahimi 	/* This could be a simple SQL statement to only build a histogram */
1417*287e80b3SSadaf Ebrahimi 	if (!table->to) {
1418*287e80b3SSadaf Ebrahimi 		ret = update_fields(tep, table, table->from);
1419*287e80b3SSadaf Ebrahimi 		if (ret < 0)
1420*287e80b3SSadaf Ebrahimi 			return NULL;
1421*287e80b3SSadaf Ebrahimi 
1422*287e80b3SSadaf Ebrahimi 		start_system = table->from->field.system;
1423*287e80b3SSadaf Ebrahimi 		start_event = table->from->field.event_name;
1424*287e80b3SSadaf Ebrahimi 
1425*287e80b3SSadaf Ebrahimi 		synth = synth_init_from(tep, start_system, start_event);
1426*287e80b3SSadaf Ebrahimi 		if (!synth)
1427*287e80b3SSadaf Ebrahimi 			return synth_init_error(tep, table);
1428*287e80b3SSadaf Ebrahimi 		goto hist_only;
1429*287e80b3SSadaf Ebrahimi 	}
1430*287e80b3SSadaf Ebrahimi 
1431*287e80b3SSadaf Ebrahimi 	ret = update_vars(tep, table, table->from);
1432*287e80b3SSadaf Ebrahimi 	if (ret < 0)
1433*287e80b3SSadaf Ebrahimi 		return NULL;
1434*287e80b3SSadaf Ebrahimi 
1435*287e80b3SSadaf Ebrahimi 	ret = update_vars(tep, table, table->to);
1436*287e80b3SSadaf Ebrahimi 	if (ret < 0)
1437*287e80b3SSadaf Ebrahimi 		return NULL;
1438*287e80b3SSadaf Ebrahimi 
1439*287e80b3SSadaf Ebrahimi 	start_system = table->from->field.system;
1440*287e80b3SSadaf Ebrahimi 	start_event = table->from->field.event_name;
1441*287e80b3SSadaf Ebrahimi 
1442*287e80b3SSadaf Ebrahimi 	match = table->matches;
1443*287e80b3SSadaf Ebrahimi 	if (!match)
1444*287e80b3SSadaf Ebrahimi 		return NULL;
1445*287e80b3SSadaf Ebrahimi 
1446*287e80b3SSadaf Ebrahimi 	ret = test_match(table, match);
1447*287e80b3SSadaf Ebrahimi 	if (ret < 0)
1448*287e80b3SSadaf Ebrahimi 		return NULL;
1449*287e80b3SSadaf Ebrahimi 
1450*287e80b3SSadaf Ebrahimi 	end_system = table->to->field.system;
1451*287e80b3SSadaf Ebrahimi 	end_event = table->to->field.event_name;
1452*287e80b3SSadaf Ebrahimi 
1453*287e80b3SSadaf Ebrahimi 	assign_match(start_system, start_event, match,
1454*287e80b3SSadaf Ebrahimi 		     &start_match, &end_match);
1455*287e80b3SSadaf Ebrahimi 
1456*287e80b3SSadaf Ebrahimi 	synth = tracefs_synth_alloc(tep, name, start_system,
1457*287e80b3SSadaf Ebrahimi 				    start_event, end_system, end_event,
1458*287e80b3SSadaf Ebrahimi 				    start_match, end_match, NULL);
1459*287e80b3SSadaf Ebrahimi 	if (!synth)
1460*287e80b3SSadaf Ebrahimi 		return synth_init_error(tep, table);
1461*287e80b3SSadaf Ebrahimi 
1462*287e80b3SSadaf Ebrahimi 	for (match = match->next; match; match = match->next) {
1463*287e80b3SSadaf Ebrahimi 		ret = test_match(table, match);
1464*287e80b3SSadaf Ebrahimi 		if (ret < 0)
1465*287e80b3SSadaf Ebrahimi 			goto free;
1466*287e80b3SSadaf Ebrahimi 
1467*287e80b3SSadaf Ebrahimi 		assign_match(start_system, start_event, match,
1468*287e80b3SSadaf Ebrahimi 			     &start_match, &end_match);
1469*287e80b3SSadaf Ebrahimi 
1470*287e80b3SSadaf Ebrahimi 		ret = tracefs_synth_add_match_field(synth,
1471*287e80b3SSadaf Ebrahimi 						    start_match,
1472*287e80b3SSadaf Ebrahimi 						    end_match, NULL);
1473*287e80b3SSadaf Ebrahimi 		if (ret < 0) {
1474*287e80b3SSadaf Ebrahimi 			field_match_error(tep, table->sb, match);
1475*287e80b3SSadaf Ebrahimi 			goto free;
1476*287e80b3SSadaf Ebrahimi 		}
1477*287e80b3SSadaf Ebrahimi 	}
1478*287e80b3SSadaf Ebrahimi 
1479*287e80b3SSadaf Ebrahimi  hist_only:
1480*287e80b3SSadaf Ebrahimi 	/* table->to may be NULL here */
1481*287e80b3SSadaf Ebrahimi 
1482*287e80b3SSadaf Ebrahimi 	for (expr = table->selections; expr; expr = expr->next) {
1483*287e80b3SSadaf Ebrahimi 		if (expr->type == EXPR_FIELD) {
1484*287e80b3SSadaf Ebrahimi 			ret = -1;
1485*287e80b3SSadaf Ebrahimi 			field = &expr->field;
1486*287e80b3SSadaf Ebrahimi 			if (field->ftype != FIELD_TO &&
1487*287e80b3SSadaf Ebrahimi 			    field->system == start_system &&
1488*287e80b3SSadaf Ebrahimi 			    field->event_name == start_event) {
1489*287e80b3SSadaf Ebrahimi 				int type;
1490*287e80b3SSadaf Ebrahimi 				int cnt = 0;
1491*287e80b3SSadaf Ebrahimi 				type = verify_field_type(tep, table->sb, expr, &cnt);
1492*287e80b3SSadaf Ebrahimi 				if (type < 0)
1493*287e80b3SSadaf Ebrahimi 					goto free;
1494*287e80b3SSadaf Ebrahimi 				if (type != HIST_COUNTER_TYPE)
1495*287e80b3SSadaf Ebrahimi 					non_val = true;
1496*287e80b3SSadaf Ebrahimi 				ret = synth_add_start_field(synth,
1497*287e80b3SSadaf Ebrahimi 						field->field, field->label,
1498*287e80b3SSadaf Ebrahimi 						type, cnt);
1499*287e80b3SSadaf Ebrahimi 			} else if (table->to) {
1500*287e80b3SSadaf Ebrahimi 				ret = tracefs_synth_add_end_field(synth,
1501*287e80b3SSadaf Ebrahimi 						field->field, field->label);
1502*287e80b3SSadaf Ebrahimi 			}
1503*287e80b3SSadaf Ebrahimi 			if (ret < 0) {
1504*287e80b3SSadaf Ebrahimi 				selection_error(tep, table->sb, expr);
1505*287e80b3SSadaf Ebrahimi 				goto free;
1506*287e80b3SSadaf Ebrahimi 			}
1507*287e80b3SSadaf Ebrahimi 			continue;
1508*287e80b3SSadaf Ebrahimi 		}
1509*287e80b3SSadaf Ebrahimi 
1510*287e80b3SSadaf Ebrahimi 		if (!table->to) {
1511*287e80b3SSadaf Ebrahimi 			compare_no_to_error(table->sb, expr);
1512*287e80b3SSadaf Ebrahimi 			goto free;
1513*287e80b3SSadaf Ebrahimi 		}
1514*287e80b3SSadaf Ebrahimi 
1515*287e80b3SSadaf Ebrahimi 		if (expr->type != EXPR_COMPARE)
1516*287e80b3SSadaf Ebrahimi 			goto free;
1517*287e80b3SSadaf Ebrahimi 
1518*287e80b3SSadaf Ebrahimi 		ret = build_compare(synth, start_system, end_system,
1519*287e80b3SSadaf Ebrahimi 				    &expr->compare);
1520*287e80b3SSadaf Ebrahimi 		if (ret < 0) {
1521*287e80b3SSadaf Ebrahimi 			compare_error(tep, table->sb, expr);
1522*287e80b3SSadaf Ebrahimi 			goto free;
1523*287e80b3SSadaf Ebrahimi 		}
1524*287e80b3SSadaf Ebrahimi 	}
1525*287e80b3SSadaf Ebrahimi 
1526*287e80b3SSadaf Ebrahimi 	if (!non_val && !table->to) {
1527*287e80b3SSadaf Ebrahimi 		table->sb->line_no = 0;
1528*287e80b3SSadaf Ebrahimi 		table->sb->line_idx = 10;
1529*287e80b3SSadaf Ebrahimi 		parse_error(table->sb, "CAST",
1530*287e80b3SSadaf Ebrahimi 			    "Not all SELECT items can be of type _COUNTER_\n");
1531*287e80b3SSadaf Ebrahimi 		goto free;
1532*287e80b3SSadaf Ebrahimi 	}
1533*287e80b3SSadaf Ebrahimi 
1534*287e80b3SSadaf Ebrahimi 	for (expr = table->where; expr; expr = expr->next) {
1535*287e80b3SSadaf Ebrahimi 		const char *filter_system = NULL;
1536*287e80b3SSadaf Ebrahimi 		const char *filter_event = NULL;
1537*287e80b3SSadaf Ebrahimi 		enum field_type ftype = FIELD_NONE;
1538*287e80b3SSadaf Ebrahimi 		bool *started;
1539*287e80b3SSadaf Ebrahimi 		bool start;
1540*287e80b3SSadaf Ebrahimi 
1541*287e80b3SSadaf Ebrahimi 		ret = verify_filter(table->sb, &expr->filter, &filter_system,
1542*287e80b3SSadaf Ebrahimi 				    &filter_event, &ftype);
1543*287e80b3SSadaf Ebrahimi 		if (ret < 0)
1544*287e80b3SSadaf Ebrahimi 			goto free;
1545*287e80b3SSadaf Ebrahimi 
1546*287e80b3SSadaf Ebrahimi 		start = filter_system == start_system &&
1547*287e80b3SSadaf Ebrahimi 			filter_event == start_event &&
1548*287e80b3SSadaf Ebrahimi 			ftype != FIELD_TO;
1549*287e80b3SSadaf Ebrahimi 
1550*287e80b3SSadaf Ebrahimi 		if (start)
1551*287e80b3SSadaf Ebrahimi 			started = &started_start;
1552*287e80b3SSadaf Ebrahimi 		else if (!table->to) {
1553*287e80b3SSadaf Ebrahimi 			where_no_to_error(table->sb, expr, start_event,
1554*287e80b3SSadaf Ebrahimi 					  filter_event);
1555*287e80b3SSadaf Ebrahimi 			goto free;
1556*287e80b3SSadaf Ebrahimi 		} else
1557*287e80b3SSadaf Ebrahimi 			started = &started_end;
1558*287e80b3SSadaf Ebrahimi 
1559*287e80b3SSadaf Ebrahimi 		ret = build_filter(tep, table->sb, synth, start, expr, started);
1560*287e80b3SSadaf Ebrahimi 		if (ret < 0)
1561*287e80b3SSadaf Ebrahimi 			goto free;
1562*287e80b3SSadaf Ebrahimi 	}
1563*287e80b3SSadaf Ebrahimi 
1564*287e80b3SSadaf Ebrahimi 	return synth;
1565*287e80b3SSadaf Ebrahimi  free:
1566*287e80b3SSadaf Ebrahimi 	tracefs_synth_free(synth);
1567*287e80b3SSadaf Ebrahimi 	return NULL;
1568*287e80b3SSadaf Ebrahimi }
1569*287e80b3SSadaf Ebrahimi 
free_sql_table(struct sql_table * table)1570*287e80b3SSadaf Ebrahimi static void free_sql_table(struct sql_table *table)
1571*287e80b3SSadaf Ebrahimi {
1572*287e80b3SSadaf Ebrahimi 	struct match *match;
1573*287e80b3SSadaf Ebrahimi 	struct expr *expr;
1574*287e80b3SSadaf Ebrahimi 
1575*287e80b3SSadaf Ebrahimi 	if (!table)
1576*287e80b3SSadaf Ebrahimi 		return;
1577*287e80b3SSadaf Ebrahimi 
1578*287e80b3SSadaf Ebrahimi 	while ((expr = table->exprs)) {
1579*287e80b3SSadaf Ebrahimi 		table->exprs = expr->free_list;
1580*287e80b3SSadaf Ebrahimi 		free(expr);
1581*287e80b3SSadaf Ebrahimi 	}
1582*287e80b3SSadaf Ebrahimi 
1583*287e80b3SSadaf Ebrahimi 	while ((match = table->matches)) {
1584*287e80b3SSadaf Ebrahimi 		table->matches = match->next;
1585*287e80b3SSadaf Ebrahimi 		free(match);
1586*287e80b3SSadaf Ebrahimi 	}
1587*287e80b3SSadaf Ebrahimi 
1588*287e80b3SSadaf Ebrahimi 	free(table);
1589*287e80b3SSadaf Ebrahimi }
1590*287e80b3SSadaf Ebrahimi 
free_str_hash(struct str_hash ** hash)1591*287e80b3SSadaf Ebrahimi static void free_str_hash(struct str_hash **hash)
1592*287e80b3SSadaf Ebrahimi {
1593*287e80b3SSadaf Ebrahimi 	struct str_hash *item;
1594*287e80b3SSadaf Ebrahimi 	int i;
1595*287e80b3SSadaf Ebrahimi 
1596*287e80b3SSadaf Ebrahimi 	for (i = 0; i < 1 << HASH_BITS; i++) {
1597*287e80b3SSadaf Ebrahimi 		while ((item = hash[i])) {
1598*287e80b3SSadaf Ebrahimi 			hash[i] = item->next;
1599*287e80b3SSadaf Ebrahimi 			free(item->str);
1600*287e80b3SSadaf Ebrahimi 			free(item);
1601*287e80b3SSadaf Ebrahimi 		}
1602*287e80b3SSadaf Ebrahimi 	}
1603*287e80b3SSadaf Ebrahimi }
1604*287e80b3SSadaf Ebrahimi 
free_sb(struct sqlhist_bison * sb)1605*287e80b3SSadaf Ebrahimi static void free_sb(struct sqlhist_bison *sb)
1606*287e80b3SSadaf Ebrahimi {
1607*287e80b3SSadaf Ebrahimi 	free_sql_table(sb->table);
1608*287e80b3SSadaf Ebrahimi 	free_str_hash(sb->str_hash);
1609*287e80b3SSadaf Ebrahimi 	free(sb->parse_error_str);
1610*287e80b3SSadaf Ebrahimi }
1611*287e80b3SSadaf Ebrahimi 
tracefs_sql(struct tep_handle * tep,const char * name,const char * sql_buffer,char ** err)1612*287e80b3SSadaf Ebrahimi struct tracefs_synth *tracefs_sql(struct tep_handle *tep, const char *name,
1613*287e80b3SSadaf Ebrahimi 				  const char *sql_buffer, char **err)
1614*287e80b3SSadaf Ebrahimi {
1615*287e80b3SSadaf Ebrahimi 	struct tracefs_synth *synth = NULL;
1616*287e80b3SSadaf Ebrahimi 	struct sqlhist_bison sb;
1617*287e80b3SSadaf Ebrahimi 	int ret;
1618*287e80b3SSadaf Ebrahimi 
1619*287e80b3SSadaf Ebrahimi 	if (!tep || !sql_buffer) {
1620*287e80b3SSadaf Ebrahimi 		errno = EINVAL;
1621*287e80b3SSadaf Ebrahimi 		return NULL;
1622*287e80b3SSadaf Ebrahimi 	}
1623*287e80b3SSadaf Ebrahimi 
1624*287e80b3SSadaf Ebrahimi 	memset(&sb, 0, sizeof(sb));
1625*287e80b3SSadaf Ebrahimi 
1626*287e80b3SSadaf Ebrahimi 	sb.buffer = sql_buffer;
1627*287e80b3SSadaf Ebrahimi 	sb.buffer_size = strlen(sql_buffer);
1628*287e80b3SSadaf Ebrahimi 	sb.buffer_idx = 0;
1629*287e80b3SSadaf Ebrahimi 
1630*287e80b3SSadaf Ebrahimi 	ret = yylex_init_extra(&sb, &sb.scanner);
1631*287e80b3SSadaf Ebrahimi 	if (ret < 0) {
1632*287e80b3SSadaf Ebrahimi 		yylex_destroy(sb.scanner);
1633*287e80b3SSadaf Ebrahimi 		return NULL;
1634*287e80b3SSadaf Ebrahimi 	}
1635*287e80b3SSadaf Ebrahimi 
1636*287e80b3SSadaf Ebrahimi 	ret = tracefs_parse(&sb);
1637*287e80b3SSadaf Ebrahimi 	yylex_destroy(sb.scanner);
1638*287e80b3SSadaf Ebrahimi 
1639*287e80b3SSadaf Ebrahimi 	if (ret)
1640*287e80b3SSadaf Ebrahimi 		goto free;
1641*287e80b3SSadaf Ebrahimi 
1642*287e80b3SSadaf Ebrahimi 	synth = build_synth(tep, name, sb.table);
1643*287e80b3SSadaf Ebrahimi 
1644*287e80b3SSadaf Ebrahimi  free:
1645*287e80b3SSadaf Ebrahimi 	if (!synth) {
1646*287e80b3SSadaf Ebrahimi 		if (sb.parse_error_str && err) {
1647*287e80b3SSadaf Ebrahimi 			*err = sb.parse_error_str;
1648*287e80b3SSadaf Ebrahimi 			sb.parse_error_str = NULL;
1649*287e80b3SSadaf Ebrahimi 		}
1650*287e80b3SSadaf Ebrahimi 	}
1651*287e80b3SSadaf Ebrahimi 	free_sb(&sb);
1652*287e80b3SSadaf Ebrahimi 	return synth;
1653*287e80b3SSadaf Ebrahimi }
1654