Code

Merged branch 'master' of git://git.tokkee.org/sysdb.
[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
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         field
520                 {
521                         $$ = sdb_store_expr_fieldvalue($1);
522                 }
523         |
524         ATTRIBUTE_T '[' STRING ']'
525                 {
526                         $$ = sdb_store_expr_attrvalue($3);
527                         free($3); $3 = NULL;
528                 }
529         |
530         data
531                 {
532                         $$ = sdb_store_expr_constvalue(&$1);
533                         sdb_data_free_datum(&$1);
534                 }
535         ;
537 object_type:
538         HOST_T { $$ = SDB_HOST; }
539         |
540         SERVICE_T { $$ = SDB_SERVICE; }
541         |
542         METRIC_T { $$ = SDB_METRIC; }
543         ;
545 object_type_plural:
546         HOSTS_T { $$ = SDB_HOST; }
547         |
548         SERVICES_T { $$ = SDB_SERVICE; }
549         |
550         METRICS_T { $$ = SDB_METRIC; }
551         ;
553 iterable:
554         SERVICE_T { $$ = SDB_SERVICE; }
555         |
556         METRIC_T { $$ = SDB_METRIC; }
557         |
558         ATTRIBUTE_T { $$ = SDB_ATTRIBUTE; }
559         |
560         BACKEND_T { $$ = SDB_FIELD_BACKEND; }
561         ;
563 field:
564         NAME_T { $$ = SDB_FIELD_NAME; }
565         |
566         LAST_UPDATE_T { $$ = SDB_FIELD_LAST_UPDATE; }
567         |
568         AGE_T { $$ = SDB_FIELD_AGE; }
569         |
570         INTERVAL_T { $$ = SDB_FIELD_INTERVAL; }
571         |
572         BACKEND_T { $$ = SDB_FIELD_BACKEND; }
573         ;
575 cmp:
576         CMP_EQUAL { $$ = "="; }
577         |
578         CMP_NEQUAL { $$ = "!="; }
579         |
580         CMP_REGEX { $$ = "=~"; }
581         |
582         CMP_NREGEX { $$ = "!~"; }
583         |
584         CMP_LT { $$ = "<"; }
585         |
586         CMP_LE { $$ = "<="; }
587         |
588         CMP_GE { $$ = ">="; }
589         |
590         CMP_GT { $$ = ">"; }
591         ;
593 data:
594         STRING { $$.type = SDB_TYPE_STRING; $$.data.string = $1; }
595         |
596         INTEGER { $$ = $1; }
597         |
598         FLOAT { $$ = $1; }
599         |
600         datetime { $$.type = SDB_TYPE_DATETIME; $$.data.datetime = $1; }
601         |
602         interval { $$ = $1; }
603         |
604         array { $$ = $1; }
605         ;
607 datetime:
608         DATE TIME { $$ = $1 + $2; }
609         |
610         DATE { $$ = $1; }
611         |
612         TIME { $$ = $1; }
613         ;
615 interval:
616         interval interval_elem
617                 {
618                         $$.data.datetime = $1.data.datetime + $2.data.datetime;
619                 }
620         |
621         interval_elem { $$ = $1; }
622         ;
624 interval_elem:
625         INTEGER IDENTIFIER
626                 {
627                         sdb_time_t unit = 1;
629                         unit = sdb_strpunit($2);
630                         if (! unit) {
631                                 sdb_fe_yyerrorf(&yylloc, scanner,
632                                                 YY_("syntax error, invalid time unit %s"), $2);
633                                 free($2); $2 = NULL;
634                                 YYABORT;
635                         }
636                         free($2); $2 = NULL;
638                         $$.type = SDB_TYPE_DATETIME;
639                         $$.data.datetime = (sdb_time_t)$1.data.integer * unit;
641                         if ($1.data.integer < 0) {
642                                 sdb_fe_yyerror(&yylloc, scanner,
643                                                 YY_("syntax error, negative intervals not supported"));
644                                 YYABORT;
645                         }
646                 }
647         ;
649 array:
650         '[' array_elem_list ']'
651                 {
652                         $$ = $2;
653                 }
654         ;
656 array_elem_list:
657         array_elem_list ',' data
658                 {
659                         size_t elem_size;
661                         if (($3.type & SDB_TYPE_ARRAY) || (($1.type & 0xff) != $3.type)) {
662                                 sdb_fe_yyerrorf(&yylloc, scanner, YY_("syntax error, "
663                                                 "cannot use element of type %s in array of type %s"),
664                                                 SDB_TYPE_TO_STRING($3.type),
665                                                 SDB_TYPE_TO_STRING($1.type));
666                                 sdb_data_free_datum(&$1);
667                                 sdb_data_free_datum(&$3);
668                                 YYABORT;
669                         }
671                         elem_size = sdb_data_sizeof($3.type);
672                         $1.data.array.values = realloc($1.data.array.values,
673                                         ($1.data.array.length + 1) * elem_size);
674                         if (! $1.data.array.values) {
675                                 sdb_fe_yyerror(&yylloc, scanner, YY_("out of memory"));
676                                 YYABORT;
677                         }
679                         memcpy((char *)$1.data.array.values
680                                                 + $1.data.array.length * elem_size,
681                                         &$3.data, elem_size);
682                         ++$1.data.array.length;
684                         $$ = $1;
685                 }
686         |
687         data
688                 {
689                         size_t elem_size;
691                         if ($1.type & SDB_TYPE_ARRAY) {
692                                 sdb_fe_yyerrorf(&yylloc, scanner, YY_("syntax error, "
693                                                 "cannot construct array of type %s"),
694                                                 SDB_TYPE_TO_STRING($1.type));
695                                 sdb_data_free_datum(&$1);
696                                 YYABORT;
697                         }
699                         $$ = $1;
700                         $$.type = $1.type | SDB_TYPE_ARRAY;
701                         $$.data.array.length = 1;
702                         elem_size = sdb_data_sizeof($1.type);
703                         $$.data.array.values = malloc(elem_size);
704                         if (! $$.data.array.values ) {
705                                 sdb_fe_yyerror(&yylloc, scanner, YY_("out of memory"));
706                                 YYABORT;
707                         }
708                         memcpy($$.data.array.values, &$1.data, elem_size);
709                 }
710         ;
712 %%
714 void
715 sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg)
717         sdb_log(SDB_LOG_ERR, "frontend: parse error: %s", msg);
718         sdb_strbuf_sprintf(errbuf, "%s", msg);
719 } /* sdb_fe_yyerror */
721 void
722 sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...)
724         va_list ap, aq;
725         va_start(ap, fmt);
726         va_copy(aq, ap);
727         sdb_vlog(SDB_LOG_ERR, fmt, ap);
728         sdb_strbuf_vsprintf(errbuf, "%s", aq);
729         va_end(ap);
730 } /* sdb_fe_yyerrorf */
732 static sdb_store_matcher_t *
733 name_iter_matcher(int m_type, int type, const char *cmp,
734                 sdb_store_expr_t *expr)
736         sdb_store_matcher_op_cb cb = sdb_store_parse_matcher_op(cmp);
737         sdb_store_expr_t *e;
738         sdb_store_matcher_t *m, *tmp = NULL;
739         assert(cb);
741         /* hosts are never iterable */
742         if (type == SDB_HOST) {
743                 return NULL;
744         }
746         if (type == SDB_FIELD_BACKEND)
747                 e = sdb_store_expr_fieldvalue(type);
748         else
749                 e = sdb_store_expr_fieldvalue(SDB_FIELD_NAME);
750         m = cb(e, expr);
751         if (m_type == MATCHER_ANY)
752                 tmp = sdb_store_any_matcher(type, m);
753         else if (m_type == MATCHER_ALL)
754                 tmp = sdb_store_all_matcher(type, m);
755         sdb_object_deref(SDB_OBJ(m));
756         sdb_object_deref(SDB_OBJ(e));
757         return tmp;
758 } /* name_iter_matcher */
760 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */