wined3d: Don't use persistent BOs from the client thread if we might need to do verte...
[wine.git] / dlls / wbemprox / wql.y
blob637eb6f05fa4b5935d0bff4b3f281074dff5847e
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 struct wql_keyword
650 const WCHAR *name;
651 unsigned int len;
652 int type;
655 #define MIN_TOKEN_LEN 2
656 #define MAX_TOKEN_LEN 11
658 #define X(str) str, ARRAY_SIZE(str) - 1
659 static const struct wql_keyword keyword_table[] =
661 { X(L"AND"), TK_AND },
662 { X(L"ASSOCIATORS"), TK_ASSOCIATORS },
663 { X(L"BY"), TK_BY },
664 { X(L"FALSE"), TK_FALSE },
665 { X(L"FROM"), TK_FROM },
666 { X(L"IS"), TK_IS },
667 { X(L"LIKE"), TK_LIKE },
668 { X(L"NOT"), TK_NOT },
669 { X(L"NULL"), TK_NULL },
670 { X(L"OF"), TK_OF },
671 { X(L"OR"), TK_OR },
672 { X(L"SELECT"), TK_SELECT },
673 { X(L"TRUE"), TK_TRUE },
674 { X(L"WHERE"), TK_WHERE }
676 #undef X
678 static int __cdecl cmp_keyword( const void *arg1, const void *arg2 )
680 const struct wql_keyword *key1 = arg1, *key2 = arg2;
681 int len = min( key1->len, key2->len );
682 int ret;
684 if ((ret = wcsnicmp( key1->name, key2->name, len ))) return ret;
685 if (key1->len < key2->len) return -1;
686 else if (key1->len > key2->len) return 1;
687 return 0;
690 static int keyword_type( const WCHAR *str, unsigned int len )
692 struct wql_keyword key, *ret;
694 if (len < MIN_TOKEN_LEN || len > MAX_TOKEN_LEN) return TK_ID;
696 key.name = str;
697 key.len = len;
698 key.type = 0;
699 ret = bsearch( &key, keyword_table, ARRAY_SIZE(keyword_table), sizeof(struct wql_keyword), cmp_keyword );
700 if (ret) return ret->type;
701 return TK_ID;
704 static int get_token( const WCHAR *s, int *token )
706 int i;
708 switch (*s)
710 case ' ':
711 case '\t':
712 case '\r':
713 case '\n':
714 for (i = 1; iswspace( s[i] ); i++) {}
715 *token = TK_SPACE;
716 return i;
717 case '-':
718 if (!s[1]) return -1;
719 *token = TK_MINUS;
720 return 1;
721 case '(':
722 *token = TK_LP;
723 return 1;
724 case ')':
725 *token = TK_RP;
726 return 1;
727 case '{':
728 for (i = 1; s[i] && s[i] != '}'; i++) {}
729 if (s[i] != '}')
731 *token = TK_ILLEGAL;
732 return i;
734 *token = TK_PATH;
735 return i + 1;
736 case '*':
737 *token = TK_STAR;
738 return 1;
739 case '=':
740 *token = TK_EQ;
741 return 1;
742 case '<':
743 if (s[1] == '=' )
745 *token = TK_LE;
746 return 2;
748 else if (s[1] == '>')
750 *token = TK_NE;
751 return 2;
753 else
755 *token = TK_LT;
756 return 1;
758 case '>':
759 if (s[1] == '=')
761 *token = TK_GE;
762 return 2;
764 else
766 *token = TK_GT;
767 return 1;
769 case '!':
770 if (s[1] != '=')
772 *token = TK_ILLEGAL;
773 return 2;
775 else
777 *token = TK_NE;
778 return 2;
780 case ',':
781 *token = TK_COMMA;
782 return 1;
783 case '\"':
784 case '\'':
785 for (i = 1; s[i]; i++)
787 if (s[i] == s[0]) break;
789 if (s[i]) i++;
790 *token = TK_STRING;
791 return i;
792 case '.':
793 if (!is_digit( s[1] ))
795 *token = TK_DOT;
796 return 1;
798 /* fall through */
799 case '0': case '1': case '2': case '3': case '4':
800 case '5': case '6': case '7': case '8': case '9':
801 *token = TK_INTEGER;
802 for (i = 1; is_digit( s[i] ); i++) {}
803 return i;
804 default:
805 if (!id_char[*s]) break;
807 for (i = 1; id_char[s[i]]; i++) {}
808 *token = keyword_type( s, i );
809 return i;
811 *token = TK_ILLEGAL;
812 return 1;
815 static int wql_lex( void *p, struct parser *parser )
817 struct string *str = p;
818 int token = -1;
821 parser->idx += parser->len;
822 if (!parser->cmd[parser->idx]) return 0;
823 parser->len = get_token( &parser->cmd[parser->idx], &token );
824 if (!parser->len) break;
826 str->data = &parser->cmd[parser->idx];
827 str->len = parser->len;
828 } while (token == TK_SPACE);
829 return token;
832 static int wql_error( struct parser *parser, const char *str )
834 ERR("%s\n", str);
835 return 0;