d3dx9: Unify calling parse_mesh helper functions.
[wine.git] / dlls / wbemprox / wql.y
blobba33396ddeb46a62846c54be833ada6de7b63c30
1 %{
3 /*
4 * Copyright 2012 Hans Leidekker for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wbemcli.h"
26 #include "wbemprox_private.h"
28 #include "wine/list.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
33 struct parser
35 const WCHAR *cmd;
36 UINT idx;
37 UINT len;
38 HRESULT error;
39 struct view **view;
40 struct list *mem;
41 enum wbm_namespace ns;
44 struct string
46 const WCHAR *data;
47 int len;
50 static void *alloc_mem( struct parser *parser, UINT size )
52 struct list *mem = malloc( sizeof(struct list) + size );
53 list_add_tail( parser->mem, mem );
54 return &mem[1];
57 static struct property *alloc_property( struct parser *parser, const WCHAR *class, const WCHAR *name )
59 struct property *prop = alloc_mem( parser, sizeof(*prop) );
60 if (prop)
62 prop->name = name;
63 prop->class = class;
64 prop->next = NULL;
66 return prop;
69 static struct keyword *alloc_keyword( struct parser *parser, const WCHAR *name, const WCHAR *value )
71 struct keyword *keyword = alloc_mem( parser, sizeof(*keyword) );
72 if (keyword)
74 keyword->name = name;
75 keyword->value = value;
76 keyword->next = NULL;
78 return keyword;
81 static WCHAR *get_string( struct parser *parser, const struct string *str )
83 const WCHAR *p = str->data;
84 int len = str->len;
85 WCHAR *ret;
87 if ((p[0] == '\"' && p[len - 1] != '\"') ||
88 (p[0] == '\'' && p[len - 1] != '\'')) return NULL;
89 if ((p[0] == '\"' && p[len - 1] == '\"') ||
90 (p[0] == '\'' && p[len - 1] == '\''))
92 p++;
93 len -= 2;
95 if (!(ret = alloc_mem( parser, (len + 1) * sizeof(WCHAR) ))) return NULL;
96 memcpy( ret, p, len * sizeof(WCHAR) );
97 ret[len] = 0;
98 return ret;
101 static WCHAR *get_path( struct parser *parser, const struct string *str )
103 const WCHAR *p = str->data;
104 int len = str->len;
105 WCHAR *ret;
107 if (p[0] == '{' && p[len - 1] == '}')
109 p++;
110 len -= 2;
113 if (!(ret = alloc_mem( parser, (len + 1) * sizeof(WCHAR) ))) return NULL;
114 memcpy( ret, p, len * sizeof(WCHAR) );
115 ret[len] = 0;
116 return ret;
119 static int get_int( struct parser *parser )
121 const WCHAR *p = &parser->cmd[parser->idx];
122 int i, ret = 0;
124 for (i = 0; i < parser->len; i++)
126 if (p[i] < '0' || p[i] > '9')
128 ERR("should only be numbers here!\n");
129 break;
131 ret = (p[i] - '0') + ret * 10;
133 return ret;
136 static struct expr *expr_complex( struct parser *parser, struct expr *l, UINT op, struct expr *r )
138 struct expr *e = alloc_mem( parser, sizeof(*e) );
139 if (e)
141 e->type = EXPR_COMPLEX;
142 e->u.expr.left = l;
143 e->u.expr.op = op;
144 e->u.expr.right = r;
146 return e;
149 static struct expr *expr_unary( struct parser *parser, struct expr *l, UINT op )
151 struct expr *e = alloc_mem( parser, sizeof(*e) );
152 if (e)
154 e->type = EXPR_UNARY;
155 e->u.expr.left = l;
156 e->u.expr.op = op;
157 e->u.expr.right = NULL;
159 return e;
162 static struct expr *expr_ival( struct parser *parser, int val )
164 struct expr *e = alloc_mem( parser, sizeof *e );
165 if (e)
167 e->type = EXPR_IVAL;
168 e->u.ival = val;
170 return e;
173 static struct expr *expr_sval( struct parser *parser, const struct string *str )
175 struct expr *e = alloc_mem( parser, sizeof *e );
176 if (e)
178 e->type = EXPR_SVAL;
179 e->u.sval = get_string( parser, str );
180 if (!e->u.sval)
181 return NULL; /* e will be freed by query destructor */
183 return e;
186 static struct expr *expr_bval( struct parser *parser, int val )
188 struct expr *e = alloc_mem( parser, sizeof *e );
189 if (e)
191 e->type = EXPR_BVAL;
192 e->u.ival = val;
194 return e;
197 static struct expr *expr_propval( struct parser *parser, const struct property *prop )
199 struct expr *e = alloc_mem( parser, sizeof *e );
200 if (e)
202 e->type = EXPR_PROPVAL;
203 e->u.propval = prop;
205 return e;
208 static int wql_error( struct parser *parser, const char *str );
209 static int wql_lex( void *val, struct parser *parser );
211 #define PARSER_BUBBLE_UP_VIEW( parser, result, current_view ) \
212 *parser->view = current_view; \
213 result = current_view
217 %lex-param { struct parser *ctx }
218 %parse-param { struct parser *ctx }
219 %define parse.error verbose
220 %define api.prefix {wql_}
221 %define api.pure
223 %union
225 struct string str;
226 WCHAR *string;
227 struct property *proplist;
228 struct keyword *keywordlist;
229 struct view *view;
230 struct expr *expr;
231 int integer;
234 %token TK_SELECT TK_FROM TK_STAR TK_COMMA TK_DOT TK_IS TK_LP TK_RP TK_NULL TK_FALSE TK_TRUE
235 %token TK_INTEGER TK_WHERE TK_SPACE TK_MINUS TK_ILLEGAL TK_BY TK_ASSOCIATORS TK_OF
236 %token <str> TK_STRING TK_ID TK_PATH
238 %type <string> id path
239 %type <proplist> prop proplist
240 %type <keywordlist> keyword keywordlist
241 %type <view> query select associatorsof
242 %type <expr> expr prop_val const_val string_val
243 %type <integer> number
245 %left TK_OR TK_AND TK_NOT TK_EQ TK_NE TK_LT TK_GT TK_LE TK_GE TK_LIKE
249 query:
250 select
252 associatorsof
255 path:
256 TK_PATH
258 $$ = get_path( ctx, &$1 );
259 if (!$$)
260 YYABORT;
264 keyword:
267 $$ = alloc_keyword( ctx, $1, NULL );
268 if (!$$)
269 YYABORT;
271 | id TK_EQ id
273 $$ = alloc_keyword( ctx, $1, $3 );
274 if (!$$)
275 YYABORT;
279 keywordlist:
280 keyword
281 | keyword keywordlist
283 $1->next = $2;
287 associatorsof:
288 TK_ASSOCIATORS TK_OF path
290 HRESULT hr;
291 struct parser *parser = ctx;
292 struct view *view;
294 hr = create_view( VIEW_TYPE_ASSOCIATORS, ctx->ns, $3, NULL, NULL, NULL, NULL, &view );
295 if (hr != S_OK)
297 ctx->error = hr;
298 YYABORT;
301 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
303 | TK_ASSOCIATORS TK_OF path TK_WHERE keywordlist
305 HRESULT hr;
306 struct parser *parser = ctx;
307 struct view *view;
309 hr = create_view( VIEW_TYPE_ASSOCIATORS, ctx->ns, $3, $5, NULL, NULL, NULL, &view );
310 if (hr != S_OK)
312 ctx->error = hr;
313 YYABORT;
316 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
320 select:
321 TK_SELECT TK_FROM id
323 HRESULT hr;
324 struct parser *parser = ctx;
325 struct view *view;
327 hr = create_view( VIEW_TYPE_SELECT, ctx->ns, NULL, NULL, $3, NULL, NULL, &view );
328 if (hr != S_OK)
330 ctx->error = hr;
331 YYABORT;
334 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
336 | TK_SELECT proplist TK_FROM id
338 HRESULT hr;
339 struct parser *parser = ctx;
340 struct view *view;
342 hr = create_view( VIEW_TYPE_SELECT, ctx->ns, NULL, NULL, $4, $2, NULL, &view );
343 if (hr != S_OK)
345 ctx->error = hr;
346 YYABORT;
349 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
351 | TK_SELECT proplist TK_FROM id TK_WHERE expr
353 HRESULT hr;
354 struct parser *parser = ctx;
355 struct view *view;
357 hr = create_view( VIEW_TYPE_SELECT, ctx->ns, NULL, NULL, $4, $2, $6, &view );
358 if (hr != S_OK)
360 ctx->error = hr;
361 YYABORT;
364 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
368 proplist:
369 prop
370 | prop TK_COMMA proplist
372 $1->next = $3;
374 | TK_STAR
376 $$ = NULL;
380 prop:
381 id TK_DOT id
383 $$ = alloc_property( ctx, $1, $3 );
384 if (!$$)
385 YYABORT;
387 | id
389 $$ = alloc_property( ctx, NULL, $1 );
390 if (!$$)
391 YYABORT;
396 TK_ID
398 $$ = get_string( ctx, &$1 );
399 if (!$$)
400 YYABORT;
404 number:
405 TK_INTEGER
407 $$ = get_int( ctx );
411 expr:
412 TK_LP expr TK_RP
414 $$ = $2;
415 if (!$$)
416 YYABORT;
418 | expr TK_AND expr
420 $$ = expr_complex( ctx, $1, OP_AND, $3 );
421 if (!$$)
422 YYABORT;
424 | expr TK_OR expr
426 $$ = expr_complex( ctx, $1, OP_OR, $3 );
427 if (!$$)
428 YYABORT;
430 | TK_NOT expr
432 $$ = expr_unary( ctx, $2, OP_NOT );
433 if (!$$)
434 YYABORT;
436 | prop_val TK_EQ const_val
438 $$ = expr_complex( ctx, $1, OP_EQ, $3 );
439 if (!$$)
440 YYABORT;
442 | prop_val TK_GT const_val
444 $$ = expr_complex( ctx, $1, OP_GT, $3 );
445 if (!$$)
446 YYABORT;
448 | prop_val TK_LT const_val
450 $$ = expr_complex( ctx, $1, OP_LT, $3 );
451 if (!$$)
452 YYABORT;
454 | prop_val TK_LE const_val
456 $$ = expr_complex( ctx, $1, OP_LE, $3 );
457 if (!$$)
458 YYABORT;
460 | prop_val TK_GE const_val
462 $$ = expr_complex( ctx, $1, OP_GE, $3 );
463 if (!$$)
464 YYABORT;
466 | prop_val TK_NE const_val
468 $$ = expr_complex( ctx, $1, OP_NE, $3 );
469 if (!$$)
470 YYABORT;
472 | const_val TK_EQ prop_val
474 $$ = expr_complex( ctx, $1, OP_EQ, $3 );
475 if (!$$)
476 YYABORT;
478 | const_val TK_GT prop_val
480 $$ = expr_complex( ctx, $1, OP_GT, $3 );
481 if (!$$)
482 YYABORT;
484 | const_val TK_LT prop_val
486 $$ = expr_complex( ctx, $1, OP_LT, $3 );
487 if (!$$)
488 YYABORT;
490 | const_val TK_LE prop_val
492 $$ = expr_complex( ctx, $1, OP_LE, $3 );
493 if (!$$)
494 YYABORT;
496 | const_val TK_GE prop_val
498 $$ = expr_complex( ctx, $1, OP_GE, $3 );
499 if (!$$)
500 YYABORT;
502 | const_val TK_NE prop_val
504 $$ = expr_complex( ctx, $1, OP_NE, $3 );
505 if (!$$)
506 YYABORT;
508 | prop_val TK_LIKE string_val
510 $$ = expr_complex( ctx, $1, OP_LIKE, $3 );
511 if (!$$)
512 YYABORT;
514 | prop_val TK_IS TK_NULL
516 $$ = expr_unary( ctx, $1, OP_ISNULL );
517 if (!$$)
518 YYABORT;
520 | prop_val TK_IS TK_NOT TK_NULL
522 $$ = expr_unary( ctx, $1, OP_NOTNULL );
523 if (!$$)
524 YYABORT;
526 | prop_val TK_EQ TK_NULL
528 $$ = expr_unary( ctx, $1, OP_ISNULL );
529 if (!$$)
530 YYABORT;
532 | TK_NULL TK_EQ prop_val
534 $$ = expr_unary( ctx, $3, OP_ISNULL );
535 if (!$$)
536 YYABORT;
538 | prop_val TK_NE TK_NULL
540 $$ = expr_unary( ctx, $1, OP_NOTNULL );
541 if (!$$)
542 YYABORT;
544 | TK_NULL TK_NE prop_val
546 $$ = expr_unary( ctx, $3, OP_NOTNULL );
547 if (!$$)
548 YYABORT;
552 string_val:
553 TK_STRING
555 $$ = expr_sval( ctx, &$1 );
556 if (!$$)
557 YYABORT;
561 prop_val:
562 prop
564 $$ = expr_propval( ctx, $1 );
565 if (!$$)
566 YYABORT;
570 const_val:
571 number
573 $$ = expr_ival( ctx, $1 );
574 if (!$$)
575 YYABORT;
577 | TK_STRING
579 $$ = expr_sval( ctx, &$1 );
580 if (!$$)
581 YYABORT;
583 | TK_TRUE
585 $$ = expr_bval( ctx, -1 );
586 if (!$$)
587 YYABORT;
589 | TK_FALSE
591 $$ = expr_bval( ctx, 0 );
592 if (!$$)
593 YYABORT;
599 HRESULT parse_query( enum wbm_namespace ns, const WCHAR *str, struct view **view, struct list *mem )
601 struct parser parser;
602 int ret;
604 *view = NULL;
606 parser.cmd = str;
607 parser.idx = 0;
608 parser.len = 0;
609 parser.error = WBEM_E_INVALID_QUERY;
610 parser.view = view;
611 parser.mem = mem;
612 parser.ns = ns;
614 ret = wql_parse( &parser );
615 TRACE("wql_parse returned %d\n", ret);
616 if (ret)
618 if (*parser.view)
620 destroy_view( *parser.view );
621 *parser.view = NULL;
623 return parser.error;
625 return S_OK;
628 static const char id_char[] =
630 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
631 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
632 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
633 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
634 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
635 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
636 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
637 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
638 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
639 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
640 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
641 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
642 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
643 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
644 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
645 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
648 static int is_idchar(WCHAR chr)
650 return chr >= ARRAY_SIZE(id_char) || id_char[chr];
653 struct wql_keyword
655 const WCHAR *name;
656 unsigned int len;
657 int type;
660 #define MIN_TOKEN_LEN 2
661 #define MAX_TOKEN_LEN 11
663 #define X(str) str, ARRAY_SIZE(str) - 1
664 static const struct wql_keyword keyword_table[] =
666 { X(L"AND"), TK_AND },
667 { X(L"ASSOCIATORS"), TK_ASSOCIATORS },
668 { X(L"BY"), TK_BY },
669 { X(L"FALSE"), TK_FALSE },
670 { X(L"FROM"), TK_FROM },
671 { X(L"IS"), TK_IS },
672 { X(L"LIKE"), TK_LIKE },
673 { X(L"NOT"), TK_NOT },
674 { X(L"NULL"), TK_NULL },
675 { X(L"OF"), TK_OF },
676 { X(L"OR"), TK_OR },
677 { X(L"SELECT"), TK_SELECT },
678 { X(L"TRUE"), TK_TRUE },
679 { X(L"WHERE"), TK_WHERE }
681 #undef X
683 static int __cdecl cmp_keyword( const void *arg1, const void *arg2 )
685 const struct wql_keyword *key1 = arg1, *key2 = arg2;
686 int len = min( key1->len, key2->len );
687 int ret;
689 if ((ret = wcsnicmp( key1->name, key2->name, len ))) return ret;
690 if (key1->len < key2->len) return -1;
691 else if (key1->len > key2->len) return 1;
692 return 0;
695 static int keyword_type( const WCHAR *str, unsigned int len )
697 struct wql_keyword key, *ret;
699 if (len < MIN_TOKEN_LEN || len > MAX_TOKEN_LEN) return TK_ID;
701 key.name = str;
702 key.len = len;
703 key.type = 0;
704 ret = bsearch( &key, keyword_table, ARRAY_SIZE(keyword_table), sizeof(struct wql_keyword), cmp_keyword );
705 if (ret) return ret->type;
706 return TK_ID;
709 static int get_token( const WCHAR *s, int *token )
711 int i;
713 switch (*s)
715 case ' ':
716 case '\t':
717 case '\r':
718 case '\n':
719 for (i = 1; iswspace( s[i] ); i++) {}
720 *token = TK_SPACE;
721 return i;
722 case '-':
723 if (!s[1]) return -1;
724 *token = TK_MINUS;
725 return 1;
726 case '(':
727 *token = TK_LP;
728 return 1;
729 case ')':
730 *token = TK_RP;
731 return 1;
732 case '{':
733 for (i = 1; s[i] && s[i] != '}'; i++) {}
734 if (s[i] != '}')
736 *token = TK_ILLEGAL;
737 return i;
739 *token = TK_PATH;
740 return i + 1;
741 case '*':
742 *token = TK_STAR;
743 return 1;
744 case '=':
745 *token = TK_EQ;
746 return 1;
747 case '<':
748 if (s[1] == '=' )
750 *token = TK_LE;
751 return 2;
753 else if (s[1] == '>')
755 *token = TK_NE;
756 return 2;
758 else
760 *token = TK_LT;
761 return 1;
763 case '>':
764 if (s[1] == '=')
766 *token = TK_GE;
767 return 2;
769 else
771 *token = TK_GT;
772 return 1;
774 case '!':
775 if (s[1] != '=')
777 *token = TK_ILLEGAL;
778 return 2;
780 else
782 *token = TK_NE;
783 return 2;
785 case ',':
786 *token = TK_COMMA;
787 return 1;
788 case '\"':
789 case '\'':
790 for (i = 1; s[i]; i++)
792 if (s[i] == s[0]) break;
794 if (s[i]) i++;
795 *token = TK_STRING;
796 return i;
797 case '.':
798 if (!is_digit( s[1] ))
800 *token = TK_DOT;
801 return 1;
803 /* fall through */
804 case '0': case '1': case '2': case '3': case '4':
805 case '5': case '6': case '7': case '8': case '9':
806 *token = TK_INTEGER;
807 for (i = 1; is_digit( s[i] ); i++) {}
808 return i;
809 default:
810 if (!is_idchar(*s)) break;
812 for (i = 1; is_idchar(s[i]); i++) {}
813 *token = keyword_type( s, i );
814 return i;
816 *token = TK_ILLEGAL;
817 return 1;
820 static int wql_lex( void *p, struct parser *parser )
822 struct string *str = p;
823 int token = -1;
826 parser->idx += parser->len;
827 if (!parser->cmd[parser->idx]) return 0;
828 parser->len = get_token( &parser->cmd[parser->idx], &token );
829 if (!parser->len) break;
831 str->data = &parser->cmd[parser->idx];
832 str->len = parser->len;
833 } while (token == TK_SPACE);
834 return token;
837 static int wql_error( struct parser *parser, const char *str )
839 ERR("%s\n", str);
840 return 0;