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