Code

187f3599c08e2514596bd5046d653c8f03c26842
[sysdb.git] / src / frontend / grammar.y
1 /*
2  * SysDB - src/frontend/grammar.y
3  * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
28 %{
30 #include "frontend/connection-private.h"
31 #include "frontend/parser.h"
32 #include "frontend/grammar.h"
34 #include "core/store.h"
35 #include "core/store-private.h"
36 #include "core/time.h"
38 #include "utils/error.h"
39 #include "utils/llist.h"
41 #include <assert.h>
43 #include <stdio.h>
44 #include <string.h>
46 /*
47  * private helper functions
48  */
50 static sdb_store_matcher_t *
51 name_iter_matcher(int m_type, int type, const char *cmp,
52                 sdb_store_expr_t *expr);
54 /*
55  * public API
56  */
58 int
59 sdb_fe_yylex(YYSTYPE *yylval, YYLTYPE *yylloc, sdb_fe_yyscan_t yyscanner);
61 sdb_fe_yyextra_t *
62 sdb_fe_yyget_extra(sdb_fe_yyscan_t scanner);
64 void
65 sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg);
66 void
67 sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...);
69 /* quick access to the current parse tree */
70 #define pt sdb_fe_yyget_extra(scanner)->parsetree
72 /* quick access to the parser mode */
73 #define parser_mode sdb_fe_yyget_extra(scanner)->mode
75 /* quick access to the parser's error buffer */
76 #define errbuf sdb_fe_yyget_extra(scanner)->errbuf
78 #define MODE_TO_STRING(m) \
79         (((m) == SDB_PARSE_DEFAULT) ? "statement" \
80                 : ((m) == SDB_PARSE_COND) ? "condition" \
81                 : ((m) == SDB_PARSE_EXPR) ? "expression" \
82                 : "UNKNOWN")
84 %}
86 %pure-parser
87 %lex-param {sdb_fe_yyscan_t scanner}
88 %parse-param {sdb_fe_yyscan_t scanner}
89 %locations
90 %error-verbose
91 %expect 0
92 %name-prefix "sdb_fe_yy"
94 %union {
95         const char *sstr; /* static string */
96         char *str;
97         int integer;
99         sdb_data_t data;
100         sdb_time_t datetime;
102         sdb_llist_t     *list;
103         sdb_conn_node_t *node;
105         sdb_store_matcher_t *m;
106         sdb_store_expr_t *expr;
109 %start statements
111 %token SCANNER_ERROR
113 %token AND OR IS NOT MATCHING FILTER
114 %token CMP_EQUAL CMP_NEQUAL CMP_REGEX CMP_NREGEX
115 %token CMP_LT CMP_LE CMP_GE CMP_GT ALL ANY IN
116 %token CONCAT
118 %token HOST_T HOSTS_T SERVICE_T SERVICES_T METRIC_T METRICS_T
119 %token ATTRIBUTE_T ATTRIBUTES_T
120 %token NAME_T LAST_UPDATE_T AGE_T INTERVAL_T BACKEND_T
122 %token START END
124 /* NULL token */
125 %token NULL_T
127 %token FETCH LIST LOOKUP TIMESERIES
129 %token <str> IDENTIFIER STRING
131 %token <data> INTEGER FLOAT
133 %token <datetime> DATE TIME
135 /* Precedence (lowest first): */
136 %left OR
137 %left AND
138 %right NOT
139 %left CMP_EQUAL CMP_NEQUAL
140 %left CMP_LT CMP_LE CMP_GE CMP_GT
141 %nonassoc CMP_REGEX CMP_NREGEX
142 %nonassoc IN
143 %left CONCAT
144 %nonassoc IS
145 %left '+' '-'
146 %left '*' '/' '%'
147 %left '[' ']'
148 %left '(' ')'
149 %left '.'
151 %type <list> statements
152 %type <node> statement
153         fetch_statement
154         list_statement
155         lookup_statement
156         timeseries_statement
157         matching_clause
158         filter_clause
159         condition
161 %type <m> matcher
162         compare_matcher
164 %type <expr> expression object_expression
166 %type <integer> object_type object_type_plural
167 %type <integer> iterable
168 %type <integer> field
170 %type <sstr> cmp
172 %type <data> data
173         interval interval_elem
174         array array_elem_list
176 %type <datetime> datetime
177         start_clause end_clause
179 %destructor { free($$); } <str>
180 %destructor { sdb_object_deref(SDB_OBJ($$)); } <node> <m> <expr>
181 %destructor { sdb_data_free_datum(&$$); } <data>
183 %%
185 statements:
186         statements ';' statement
187                 {
188                         /* only accepted in default parse mode */
189                         if (parser_mode != SDB_PARSE_DEFAULT) {
190                                 sdb_fe_yyerrorf(&yylloc, scanner,
191                                                 YY_("syntax error, unexpected statement, "
192                                                         "expecting %s"), MODE_TO_STRING(parser_mode));
193                                 sdb_object_deref(SDB_OBJ($3));
194                                 YYABORT;
195                         }
197                         if ($3) {
198                                 sdb_llist_append(pt, SDB_OBJ($3));
199                                 sdb_object_deref(SDB_OBJ($3));
200                         }
201                 }
202         |
203         statement
204                 {
205                         /* only accepted in default parse mode */
206                         if (parser_mode != SDB_PARSE_DEFAULT) {
207                                 sdb_fe_yyerrorf(&yylloc, scanner,
208                                                 YY_("syntax error, unexpected statement, "
209                                                         "expecting %s"), MODE_TO_STRING(parser_mode));
210                                 sdb_object_deref(SDB_OBJ($1));
211                                 YYABORT;
212                         }
214                         if ($1) {
215                                 sdb_llist_append(pt, SDB_OBJ($1));
216                                 sdb_object_deref(SDB_OBJ($1));
217                         }
218                 }
219         |
220         condition
221                 {
222                         /* only accepted in condition parse mode */
223                         if (! (parser_mode & SDB_PARSE_COND)) {
224                                 sdb_fe_yyerrorf(&yylloc, scanner,
225                                                 YY_("syntax error, unexpected condition, "
226                                                         "expecting %s"), MODE_TO_STRING(parser_mode));
227                                 sdb_object_deref(SDB_OBJ($1));
228                                 YYABORT;
229                         }
231                         if ($1) {
232                                 sdb_llist_append(pt, SDB_OBJ($1));
233                                 sdb_object_deref(SDB_OBJ($1));
234                         }
235                 }
236         |
237         expression
238                 {
239                         /* only accepted in expression parse mode */
240                         if (! (parser_mode & SDB_PARSE_EXPR)) {
241                                 sdb_fe_yyerrorf(&yylloc, scanner,
242                                                 YY_("syntax error, unexpected expression, "
243                                                         "expecting %s"), MODE_TO_STRING(parser_mode));
244                                 sdb_object_deref(SDB_OBJ($1));
245                                 YYABORT;
246                         }
248                         if ($1) {
249                                 sdb_conn_node_t *n;
250                                 n = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL,
251                                                         conn_expr_t, conn_expr_destroy));
252                                 n->cmd = SDB_CONNECTION_EXPR;
253                                 CONN_EXPR(n)->expr = $1;
255                                 sdb_llist_append(pt, SDB_OBJ(n));
256                                 sdb_object_deref(SDB_OBJ(n));
257                         }
258                 }
259         ;
261 statement:
262         fetch_statement
263         |
264         list_statement
265         |
266         lookup_statement
267         |
268         timeseries_statement
269         |
270         /* empty */
271                 {
272                         $$ = NULL;
273                 }
274         ;
276 /*
277  * FETCH <type> <hostname> [FILTER <condition>];
278  *
279  * Retrieve detailed information about a single host.
280  */
281 fetch_statement:
282         FETCH object_type STRING filter_clause
283                 {
284                         $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL,
285                                                 conn_fetch_t, conn_fetch_destroy));
286                         CONN_FETCH($$)->type = $2;
287                         CONN_FETCH($$)->host = $3;
288                         CONN_FETCH($$)->name = NULL;
289                         CONN_FETCH($$)->filter = CONN_MATCHER($4);
290                         $$->cmd = SDB_CONNECTION_FETCH;
291                 }
292         |
293         FETCH object_type STRING '.' STRING filter_clause
294                 {
295                         $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL,
296                                                 conn_fetch_t, conn_fetch_destroy));
297                         CONN_FETCH($$)->type = $2;
298                         CONN_FETCH($$)->host = $3;
299                         CONN_FETCH($$)->name = $5;
300                         CONN_FETCH($$)->filter = CONN_MATCHER($6);
301                         $$->cmd = SDB_CONNECTION_FETCH;
302                 }
303         ;
305 /*
306  * LIST <type> [FILTER <condition>];
307  *
308  * Returns a list of all hosts in the store.
309  */
310 list_statement:
311         LIST object_type_plural filter_clause
312                 {
313                         $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL,
314                                                 conn_list_t, conn_list_destroy));
315                         CONN_LIST($$)->type = $2;
316                         CONN_LIST($$)->filter = CONN_MATCHER($3);
317                         $$->cmd = SDB_CONNECTION_LIST;
318                 }
319         ;
321 /*
322  * LOOKUP <type> MATCHING <condition> [FILTER <condition>];
323  *
324  * Returns detailed information about <type> matching condition.
325  */
326 lookup_statement:
327         LOOKUP object_type_plural matching_clause filter_clause
328                 {
329                         $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL,
330                                                 conn_lookup_t, conn_lookup_destroy));
331                         CONN_LOOKUP($$)->type = $2;
332                         CONN_LOOKUP($$)->matcher = CONN_MATCHER($3);
333                         CONN_LOOKUP($$)->filter = CONN_MATCHER($4);
334                         $$->cmd = SDB_CONNECTION_LOOKUP;
335                 }
336         ;
338 matching_clause:
339         MATCHING condition { $$ = $2; }
340         |
341         /* empty */ { $$ = NULL; }
343 filter_clause:
344         FILTER condition { $$ = $2; }
345         |
346         /* empty */ { $$ = NULL; }
348 /*
349  * TIMESERIES <host>.<metric> [START <datetime>] [END <datetime>];
350  *
351  * Returns a time-series for the specified host's metric.
352  */
353 timeseries_statement:
354         TIMESERIES STRING '.' STRING start_clause end_clause
355                 {
356                         $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL,
357                                                 conn_ts_t, conn_ts_destroy));
358                         CONN_TS($$)->hostname = $2;
359                         CONN_TS($$)->metric = $4;
360                         CONN_TS($$)->opts.start = $5;
361                         CONN_TS($$)->opts.end = $6;
362                         $$->cmd = SDB_CONNECTION_TIMESERIES;
363                 }
364         ;
366 start_clause:
367         START datetime { $$ = $2; }
368         |
369         /* empty */ { $$ = sdb_gettime() - SDB_INTERVAL_HOUR; }
371 end_clause:
372         END datetime { $$ = $2; }
373         |
374         /* empty */ { $$ = sdb_gettime(); }
376 /*
377  * Basic expressions.
378  */
380 condition:
381         matcher
382                 {
383                         if (! $1) {
384                                 /* TODO: improve error reporting */
385                                 sdb_fe_yyerror(&yylloc, scanner,
386                                                 YY_("syntax error, invalid condition"));
387                                 YYABORT;
388                         }
390                         $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL,
391                                                 conn_matcher_t, conn_matcher_destroy));
392                         $$->cmd = SDB_CONNECTION_MATCHER;
393                         CONN_MATCHER($$)->matcher = $1;
394                 }
395         ;
397 matcher:
398         '(' matcher ')'
399                 {
400                         $$ = $2;
401                 }
402         |
403         matcher AND matcher
404                 {
405                         $$ = sdb_store_con_matcher($1, $3);
406                         sdb_object_deref(SDB_OBJ($1));
407                         sdb_object_deref(SDB_OBJ($3));
408                 }
409         |
410         matcher OR matcher
411                 {
412                         $$ = sdb_store_dis_matcher($1, $3);
413                         sdb_object_deref(SDB_OBJ($1));
414                         sdb_object_deref(SDB_OBJ($3));
415                 }
416         |
417         NOT matcher
418                 {
419                         $$ = sdb_store_inv_matcher($2);
420                         sdb_object_deref(SDB_OBJ($2));
421                 }
422         |
423         compare_matcher
424                 {
425                         $$ = $1;
426                 }
427         ;
429 compare_matcher:
430         expression cmp expression
431                 {
432                         sdb_store_matcher_op_cb cb = sdb_store_parse_matcher_op($2);
433                         assert(cb); /* else, the grammar accepts invalid 'cmp' */
434                         $$ = cb($1, $3);
435                         sdb_object_deref(SDB_OBJ($1));
436                         sdb_object_deref(SDB_OBJ($3));
437                 }
438         |
439         ANY iterable cmp expression
440                 {
441                         $$ = name_iter_matcher(MATCHER_ANY, $2, $3, $4);
442                         sdb_object_deref(SDB_OBJ($4));
443                 }
444         |
445         ALL iterable cmp expression
446                 {
447                         $$ = name_iter_matcher(MATCHER_ALL, $2, $3, $4);
448                         sdb_object_deref(SDB_OBJ($4));
449                 }
450         |
451         expression IS NULL_T
452                 {
453                         $$ = sdb_store_isnull_matcher($1);
454                         sdb_object_deref(SDB_OBJ($1));
455                 }
456         |
457         expression IS NOT NULL_T
458                 {
459                         $$ = sdb_store_isnnull_matcher($1);
460                         sdb_object_deref(SDB_OBJ($1));
461                 }
462         |
463         expression IN expression
464                 {
465                         $$ = sdb_store_in_matcher($1, $3);
466                         sdb_object_deref(SDB_OBJ($1));
467                         sdb_object_deref(SDB_OBJ($3));
468                 }
469         ;
471 expression:
472         '(' expression ')'
473                 {
474                         $$ = $2;
475                 }
476         |
477         expression '+' expression
478                 {
479                         $$ = sdb_store_expr_create(SDB_DATA_ADD, $1, $3);
480                         sdb_object_deref(SDB_OBJ($1)); $1 = NULL;
481                         sdb_object_deref(SDB_OBJ($3)); $3 = NULL;
482                 }
483         |
484         expression '-' expression
485                 {
486                         $$ = sdb_store_expr_create(SDB_DATA_SUB, $1, $3);
487                         sdb_object_deref(SDB_OBJ($1)); $1 = NULL;
488                         sdb_object_deref(SDB_OBJ($3)); $3 = NULL;
489                 }
490         |
491         expression '*' expression
492                 {
493                         $$ = sdb_store_expr_create(SDB_DATA_MUL, $1, $3);
494                         sdb_object_deref(SDB_OBJ($1)); $1 = NULL;
495                         sdb_object_deref(SDB_OBJ($3)); $3 = NULL;
496                 }
497         |
498         expression '/' expression
499                 {
500                         $$ = sdb_store_expr_create(SDB_DATA_DIV, $1, $3);
501                         sdb_object_deref(SDB_OBJ($1)); $1 = NULL;
502                         sdb_object_deref(SDB_OBJ($3)); $3 = NULL;
503                 }
504         |
505         expression '%' expression
506                 {
507                         $$ = sdb_store_expr_create(SDB_DATA_MOD, $1, $3);
508                         sdb_object_deref(SDB_OBJ($1)); $1 = NULL;
509                         sdb_object_deref(SDB_OBJ($3)); $3 = NULL;
510                 }
511         |
512         expression CONCAT expression
513                 {
514                         $$ = sdb_store_expr_create(SDB_DATA_CONCAT, $1, $3);
515                         sdb_object_deref(SDB_OBJ($1)); $1 = NULL;
516                         sdb_object_deref(SDB_OBJ($3)); $3 = NULL;
517                 }
518         |
519         object_expression
520                 {
521                         $$ = $1;
522                 }
523         |
524         data
525                 {
526                         $$ = sdb_store_expr_constvalue(&$1);
527                         sdb_data_free_datum(&$1);
528                 }
529         ;
531 object_expression:
532         object_type '.' object_expression
533                 {
534                         $$ = sdb_store_expr_typed($1, $3);
535                         sdb_object_deref(SDB_OBJ($3));
536                 }
537         |
538         field
539                 {
540                         $$ = sdb_store_expr_fieldvalue($1);
541                 }
542         |
543         ATTRIBUTE_T '[' STRING ']'
544                 {
545                         $$ = sdb_store_expr_attrvalue($3);
546                         free($3); $3 = NULL;
547                 }
548         ;
550 object_type:
551         HOST_T { $$ = SDB_HOST; }
552         |
553         SERVICE_T { $$ = SDB_SERVICE; }
554         |
555         METRIC_T { $$ = SDB_METRIC; }
556         ;
558 object_type_plural:
559         HOSTS_T { $$ = SDB_HOST; }
560         |
561         SERVICES_T { $$ = SDB_SERVICE; }
562         |
563         METRICS_T { $$ = SDB_METRIC; }
564         ;
566 iterable:
567         SERVICE_T { $$ = SDB_SERVICE; }
568         |
569         METRIC_T { $$ = SDB_METRIC; }
570         |
571         ATTRIBUTE_T { $$ = SDB_ATTRIBUTE; }
572         |
573         BACKEND_T { $$ = SDB_FIELD_BACKEND; }
574         ;
576 field:
577         NAME_T { $$ = SDB_FIELD_NAME; }
578         |
579         LAST_UPDATE_T { $$ = SDB_FIELD_LAST_UPDATE; }
580         |
581         AGE_T { $$ = SDB_FIELD_AGE; }
582         |
583         INTERVAL_T { $$ = SDB_FIELD_INTERVAL; }
584         |
585         BACKEND_T { $$ = SDB_FIELD_BACKEND; }
586         ;
588 cmp:
589         CMP_EQUAL { $$ = "="; }
590         |
591         CMP_NEQUAL { $$ = "!="; }
592         |
593         CMP_REGEX { $$ = "=~"; }
594         |
595         CMP_NREGEX { $$ = "!~"; }
596         |
597         CMP_LT { $$ = "<"; }
598         |
599         CMP_LE { $$ = "<="; }
600         |
601         CMP_GE { $$ = ">="; }
602         |
603         CMP_GT { $$ = ">"; }
604         ;
606 data:
607         STRING { $$.type = SDB_TYPE_STRING; $$.data.string = $1; }
608         |
609         INTEGER { $$ = $1; }
610         |
611         FLOAT { $$ = $1; }
612         |
613         datetime { $$.type = SDB_TYPE_DATETIME; $$.data.datetime = $1; }
614         |
615         interval { $$ = $1; }
616         |
617         array { $$ = $1; }
618         ;
620 datetime:
621         DATE TIME { $$ = $1 + $2; }
622         |
623         DATE { $$ = $1; }
624         |
625         TIME { $$ = $1; }
626         ;
628 interval:
629         interval interval_elem
630                 {
631                         $$.data.datetime = $1.data.datetime + $2.data.datetime;
632                 }
633         |
634         interval_elem { $$ = $1; }
635         ;
637 interval_elem:
638         INTEGER IDENTIFIER
639                 {
640                         sdb_time_t unit = 1;
642                         unit = sdb_strpunit($2);
643                         if (! unit) {
644                                 sdb_fe_yyerrorf(&yylloc, scanner,
645                                                 YY_("syntax error, invalid time unit %s"), $2);
646                                 free($2); $2 = NULL;
647                                 YYABORT;
648                         }
649                         free($2); $2 = NULL;
651                         $$.type = SDB_TYPE_DATETIME;
652                         $$.data.datetime = (sdb_time_t)$1.data.integer * unit;
654                         if ($1.data.integer < 0) {
655                                 sdb_fe_yyerror(&yylloc, scanner,
656                                                 YY_("syntax error, negative intervals not supported"));
657                                 YYABORT;
658                         }
659                 }
660         ;
662 array:
663         '[' array_elem_list ']'
664                 {
665                         $$ = $2;
666                 }
667         ;
669 array_elem_list:
670         array_elem_list ',' data
671                 {
672                         size_t elem_size;
674                         if (($3.type & SDB_TYPE_ARRAY) || (($1.type & 0xff) != $3.type)) {
675                                 sdb_fe_yyerrorf(&yylloc, scanner, YY_("syntax error, "
676                                                 "cannot use element of type %s in array of type %s"),
677                                                 SDB_TYPE_TO_STRING($3.type),
678                                                 SDB_TYPE_TO_STRING($1.type));
679                                 sdb_data_free_datum(&$1);
680                                 sdb_data_free_datum(&$3);
681                                 YYABORT;
682                         }
684                         elem_size = sdb_data_sizeof($3.type);
685                         $1.data.array.values = realloc($1.data.array.values,
686                                         ($1.data.array.length + 1) * elem_size);
687                         if (! $1.data.array.values) {
688                                 sdb_fe_yyerror(&yylloc, scanner, YY_("out of memory"));
689                                 YYABORT;
690                         }
692                         memcpy((char *)$1.data.array.values
693                                                 + $1.data.array.length * elem_size,
694                                         &$3.data, elem_size);
695                         ++$1.data.array.length;
697                         $$ = $1;
698                 }
699         |
700         data
701                 {
702                         size_t elem_size;
704                         if ($1.type & SDB_TYPE_ARRAY) {
705                                 sdb_fe_yyerrorf(&yylloc, scanner, YY_("syntax error, "
706                                                 "cannot construct array of type %s"),
707                                                 SDB_TYPE_TO_STRING($1.type));
708                                 sdb_data_free_datum(&$1);
709                                 YYABORT;
710                         }
712                         $$ = $1;
713                         $$.type = $1.type | SDB_TYPE_ARRAY;
714                         $$.data.array.length = 1;
715                         elem_size = sdb_data_sizeof($1.type);
716                         $$.data.array.values = malloc(elem_size);
717                         if (! $$.data.array.values ) {
718                                 sdb_fe_yyerror(&yylloc, scanner, YY_("out of memory"));
719                                 YYABORT;
720                         }
721                         memcpy($$.data.array.values, &$1.data, elem_size);
722                 }
723         ;
725 %%
727 void
728 sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg)
730         sdb_log(SDB_LOG_ERR, "frontend: parse error: %s", msg);
731         sdb_strbuf_sprintf(errbuf, "%s", msg);
732 } /* sdb_fe_yyerror */
734 void
735 sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...)
737         va_list ap, aq;
738         va_start(ap, fmt);
739         va_copy(aq, ap);
740         sdb_vlog(SDB_LOG_ERR, fmt, ap);
741         sdb_strbuf_vsprintf(errbuf, "%s", aq);
742         va_end(ap);
743 } /* sdb_fe_yyerrorf */
745 static sdb_store_matcher_t *
746 name_iter_matcher(int m_type, int type, const char *cmp,
747                 sdb_store_expr_t *expr)
749         sdb_store_matcher_op_cb cb = sdb_store_parse_matcher_op(cmp);
750         sdb_store_expr_t *e;
751         sdb_store_matcher_t *m, *tmp = NULL;
752         assert(cb);
754         /* hosts are never iterable */
755         if (type == SDB_HOST) {
756                 return NULL;
757         }
759         if (type == SDB_FIELD_BACKEND)
760                 e = sdb_store_expr_fieldvalue(type);
761         else
762                 e = sdb_store_expr_fieldvalue(SDB_FIELD_NAME);
763         m = cb(e, expr);
764         if (m_type == MATCHER_ANY)
765                 tmp = sdb_store_any_matcher(type, m);
766         else if (m_type == MATCHER_ALL)
767                 tmp = sdb_store_all_matcher(type, m);
768         sdb_object_deref(SDB_OBJ(m));
769         sdb_object_deref(SDB_OBJ(e));
770         return tmp;
771 } /* name_iter_matcher */
773 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */