msvcrt: Improve acosf compatibility with native ucrtbase.
[wine.git] / dlls / wbemprox / wql.y
blob95c8d8fe817de74bd2e071235e2373405181b0e4
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;
43 struct string
45 const WCHAR *data;
46 int len;
49 static void *alloc_mem( struct parser *parser, UINT size )
51 struct list *mem = heap_alloc( sizeof(struct list) + size );
52 list_add_tail( parser->mem, mem );
53 return &mem[1];
56 static struct property *alloc_property( struct parser *parser, const WCHAR *class, const WCHAR *name )
58 struct property *prop = alloc_mem( parser, sizeof(*prop) );
59 if (prop)
61 prop->name = name;
62 prop->class = class;
63 prop->next = NULL;
65 return prop;
68 static struct keyword *alloc_keyword( struct parser *parser, const WCHAR *name, const WCHAR *value )
70 struct keyword *keyword = alloc_mem( parser, sizeof(*keyword) );
71 if (keyword)
73 keyword->name = name;
74 keyword->value = value;
75 keyword->next = NULL;
77 return keyword;
80 static WCHAR *get_string( struct parser *parser, const struct string *str )
82 const WCHAR *p = str->data;
83 int len = str->len;
84 WCHAR *ret;
86 if ((p[0] == '\"' && p[len - 1] != '\"') ||
87 (p[0] == '\'' && p[len - 1] != '\'')) return NULL;
88 if ((p[0] == '\"' && p[len - 1] == '\"') ||
89 (p[0] == '\'' && p[len - 1] == '\''))
91 p++;
92 len -= 2;
94 if (!(ret = alloc_mem( parser, (len + 1) * sizeof(WCHAR) ))) return NULL;
95 memcpy( ret, p, len * sizeof(WCHAR) );
96 ret[len] = 0;
97 return ret;
100 static WCHAR *get_path( struct parser *parser, const struct string *str )
102 const WCHAR *p = str->data;
103 int len = str->len;
104 WCHAR *ret;
106 if (p[0] == '{' && p[len - 1] == '}')
108 p++;
109 len -= 2;
112 if (!(ret = alloc_mem( parser, (len + 1) * sizeof(WCHAR) ))) return NULL;
113 memcpy( ret, p, len * sizeof(WCHAR) );
114 ret[len] = 0;
115 return ret;
118 static int get_int( struct parser *parser )
120 const WCHAR *p = &parser->cmd[parser->idx];
121 int i, ret = 0;
123 for (i = 0; i < parser->len; i++)
125 if (p[i] < '0' || p[i] > '9')
127 ERR("should only be numbers here!\n");
128 break;
130 ret = (p[i] - '0') + ret * 10;
132 return ret;
135 static struct expr *expr_complex( struct parser *parser, struct expr *l, UINT op, struct expr *r )
137 struct expr *e = alloc_mem( parser, sizeof(*e) );
138 if (e)
140 e->type = EXPR_COMPLEX;
141 e->u.expr.left = l;
142 e->u.expr.op = op;
143 e->u.expr.right = r;
145 return e;
148 static struct expr *expr_unary( struct parser *parser, struct expr *l, UINT op )
150 struct expr *e = alloc_mem( parser, sizeof(*e) );
151 if (e)
153 e->type = EXPR_UNARY;
154 e->u.expr.left = l;
155 e->u.expr.op = op;
156 e->u.expr.right = NULL;
158 return e;
161 static struct expr *expr_ival( struct parser *parser, int val )
163 struct expr *e = alloc_mem( parser, sizeof *e );
164 if (e)
166 e->type = EXPR_IVAL;
167 e->u.ival = val;
169 return e;
172 static struct expr *expr_sval( struct parser *parser, const struct string *str )
174 struct expr *e = alloc_mem( parser, sizeof *e );
175 if (e)
177 e->type = EXPR_SVAL;
178 e->u.sval = get_string( parser, str );
179 if (!e->u.sval)
180 return NULL; /* e will be freed by query destructor */
182 return e;
185 static struct expr *expr_bval( struct parser *parser, int val )
187 struct expr *e = alloc_mem( parser, sizeof *e );
188 if (e)
190 e->type = EXPR_BVAL;
191 e->u.ival = val;
193 return e;
196 static struct expr *expr_propval( struct parser *parser, const struct property *prop )
198 struct expr *e = alloc_mem( parser, sizeof *e );
199 if (e)
201 e->type = EXPR_PROPVAL;
202 e->u.propval = prop;
204 return e;
207 static int wql_error( struct parser *parser, const char *str );
208 static int wql_lex( void *val, struct parser *parser );
210 #define PARSER_BUBBLE_UP_VIEW( parser, result, current_view ) \
211 *parser->view = current_view; \
212 result = current_view
216 %lex-param { struct parser *ctx }
217 %parse-param { struct parser *ctx }
218 %define parse.error verbose
219 %define api.pure
221 %union
223 struct string str;
224 WCHAR *string;
225 struct property *proplist;
226 struct keyword *keywordlist;
227 struct view *view;
228 struct expr *expr;
229 int integer;
232 %token TK_SELECT TK_FROM TK_STAR TK_COMMA TK_DOT TK_IS TK_LP TK_RP TK_NULL TK_FALSE TK_TRUE
233 %token TK_INTEGER TK_WHERE TK_SPACE TK_MINUS TK_ILLEGAL TK_BY TK_ASSOCIATORS TK_OF
234 %token <str> TK_STRING TK_ID TK_PATH
236 %type <string> id path
237 %type <proplist> prop proplist
238 %type <keywordlist> keyword keywordlist
239 %type <view> query select associatorsof
240 %type <expr> expr prop_val const_val string_val
241 %type <integer> number
243 %left TK_OR TK_AND TK_NOT TK_EQ TK_NE TK_LT TK_GT TK_LE TK_GE TK_LIKE
247 query:
248 select
250 associatorsof
253 path:
254 TK_PATH
256 $$ = get_path( ctx, &$1 );
257 if (!$$)
258 YYABORT;
262 keyword:
265 $$ = alloc_keyword( ctx, $1, NULL );
266 if (!$$)
267 YYABORT;
269 | id TK_EQ id
271 $$ = alloc_keyword( ctx, $1, $3 );
272 if (!$$)
273 YYABORT;
277 keywordlist:
278 keyword
279 | keyword keywordlist
281 $1->next = $2;
285 associatorsof:
286 TK_ASSOCIATORS TK_OF path
288 HRESULT hr;
289 struct parser *parser = ctx;
290 struct view *view;
292 hr = create_view( VIEW_TYPE_ASSOCIATORS, $3, NULL, NULL, NULL, NULL, &view );
293 if (hr != S_OK)
294 YYABORT;
296 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
298 | TK_ASSOCIATORS TK_OF path TK_WHERE keywordlist
300 HRESULT hr;
301 struct parser *parser = ctx;
302 struct view *view;
304 hr = create_view( VIEW_TYPE_ASSOCIATORS, $3, $5, NULL, NULL, NULL, &view );
305 if (hr != S_OK)
306 YYABORT;
308 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
312 select:
313 TK_SELECT TK_FROM id
315 HRESULT hr;
316 struct parser *parser = ctx;
317 struct view *view;
319 hr = create_view( VIEW_TYPE_SELECT, NULL, NULL, $3, NULL, NULL, &view );
320 if (hr != S_OK)
321 YYABORT;
323 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
325 | TK_SELECT proplist TK_FROM id
327 HRESULT hr;
328 struct parser *parser = ctx;
329 struct view *view;
331 hr = create_view( VIEW_TYPE_SELECT, NULL, NULL, $4, $2, NULL, &view );
332 if (hr != S_OK)
333 YYABORT;
335 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
337 | TK_SELECT proplist TK_FROM id TK_WHERE expr
339 HRESULT hr;
340 struct parser *parser = ctx;
341 struct view *view;
343 hr = create_view( VIEW_TYPE_SELECT, NULL, NULL, $4, $2, $6, &view );
344 if (hr != S_OK)
345 YYABORT;
347 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
351 proplist:
352 prop
353 | prop TK_COMMA proplist
355 $1->next = $3;
357 | TK_STAR
359 $$ = NULL;
363 prop:
364 id TK_DOT id
366 $$ = alloc_property( ctx, $1, $3 );
367 if (!$$)
368 YYABORT;
370 | id
372 $$ = alloc_property( ctx, NULL, $1 );
373 if (!$$)
374 YYABORT;
379 TK_ID
381 $$ = get_string( ctx, &$1 );
382 if (!$$)
383 YYABORT;
387 number:
388 TK_INTEGER
390 $$ = get_int( ctx );
394 expr:
395 TK_LP expr TK_RP
397 $$ = $2;
398 if (!$$)
399 YYABORT;
401 | expr TK_AND expr
403 $$ = expr_complex( ctx, $1, OP_AND, $3 );
404 if (!$$)
405 YYABORT;
407 | expr TK_OR expr
409 $$ = expr_complex( ctx, $1, OP_OR, $3 );
410 if (!$$)
411 YYABORT;
413 | TK_NOT expr
415 $$ = expr_unary( ctx, $2, OP_NOT );
416 if (!$$)
417 YYABORT;
419 | prop_val TK_EQ const_val
421 $$ = expr_complex( ctx, $1, OP_EQ, $3 );
422 if (!$$)
423 YYABORT;
425 | prop_val TK_GT const_val
427 $$ = expr_complex( ctx, $1, OP_GT, $3 );
428 if (!$$)
429 YYABORT;
431 | prop_val TK_LT const_val
433 $$ = expr_complex( ctx, $1, OP_LT, $3 );
434 if (!$$)
435 YYABORT;
437 | prop_val TK_LE const_val
439 $$ = expr_complex( ctx, $1, OP_LE, $3 );
440 if (!$$)
441 YYABORT;
443 | prop_val TK_GE const_val
445 $$ = expr_complex( ctx, $1, OP_GE, $3 );
446 if (!$$)
447 YYABORT;
449 | prop_val TK_NE const_val
451 $$ = expr_complex( ctx, $1, OP_NE, $3 );
452 if (!$$)
453 YYABORT;
455 | const_val TK_EQ prop_val
457 $$ = expr_complex( ctx, $1, OP_EQ, $3 );
458 if (!$$)
459 YYABORT;
461 | const_val TK_GT prop_val
463 $$ = expr_complex( ctx, $1, OP_GT, $3 );
464 if (!$$)
465 YYABORT;
467 | const_val TK_LT prop_val
469 $$ = expr_complex( ctx, $1, OP_LT, $3 );
470 if (!$$)
471 YYABORT;
473 | const_val TK_LE prop_val
475 $$ = expr_complex( ctx, $1, OP_LE, $3 );
476 if (!$$)
477 YYABORT;
479 | const_val TK_GE prop_val
481 $$ = expr_complex( ctx, $1, OP_GE, $3 );
482 if (!$$)
483 YYABORT;
485 | const_val TK_NE prop_val
487 $$ = expr_complex( ctx, $1, OP_NE, $3 );
488 if (!$$)
489 YYABORT;
491 | prop_val TK_LIKE string_val
493 $$ = expr_complex( ctx, $1, OP_LIKE, $3 );
494 if (!$$)
495 YYABORT;
497 | prop_val TK_IS TK_NULL
499 $$ = expr_unary( ctx, $1, OP_ISNULL );
500 if (!$$)
501 YYABORT;
503 | prop_val TK_IS TK_NOT TK_NULL
505 $$ = expr_unary( ctx, $1, OP_NOTNULL );
506 if (!$$)
507 YYABORT;
509 | prop_val TK_EQ TK_NULL
511 $$ = expr_unary( ctx, $1, OP_ISNULL );
512 if (!$$)
513 YYABORT;
515 | TK_NULL TK_EQ prop_val
517 $$ = expr_unary( ctx, $3, OP_ISNULL );
518 if (!$$)
519 YYABORT;
521 | prop_val TK_NE TK_NULL
523 $$ = expr_unary( ctx, $1, OP_NOTNULL );
524 if (!$$)
525 YYABORT;
527 | TK_NULL TK_NE prop_val
529 $$ = expr_unary( ctx, $3, OP_NOTNULL );
530 if (!$$)
531 YYABORT;
535 string_val:
536 TK_STRING
538 $$ = expr_sval( ctx, &$1 );
539 if (!$$)
540 YYABORT;
544 prop_val:
545 prop
547 $$ = expr_propval( ctx, $1 );
548 if (!$$)
549 YYABORT;
553 const_val:
554 number
556 $$ = expr_ival( ctx, $1 );
557 if (!$$)
558 YYABORT;
560 | TK_STRING
562 $$ = expr_sval( ctx, &$1 );
563 if (!$$)
564 YYABORT;
566 | TK_TRUE
568 $$ = expr_bval( ctx, -1 );
569 if (!$$)
570 YYABORT;
572 | TK_FALSE
574 $$ = expr_bval( ctx, 0 );
575 if (!$$)
576 YYABORT;
582 HRESULT parse_query( const WCHAR *str, struct view **view, struct list *mem )
584 struct parser parser;
585 int ret;
587 *view = NULL;
589 parser.cmd = str;
590 parser.idx = 0;
591 parser.len = 0;
592 parser.error = WBEM_E_INVALID_QUERY;
593 parser.view = view;
594 parser.mem = mem;
596 ret = wql_parse( &parser );
597 TRACE("wql_parse returned %d\n", ret);
598 if (ret)
600 if (*parser.view)
602 destroy_view( *parser.view );
603 *parser.view = NULL;
605 return parser.error;
607 return S_OK;
610 static const char id_char[] =
612 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
613 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
614 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
615 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
616 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
617 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
618 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
619 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
620 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
621 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
622 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
623 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
624 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
625 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
626 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
627 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
630 struct wql_keyword
632 const WCHAR *name;
633 unsigned int len;
634 int type;
637 #define MIN_TOKEN_LEN 2
638 #define MAX_TOKEN_LEN 11
640 #define X(str) str, ARRAY_SIZE(str) - 1
641 static const struct wql_keyword keyword_table[] =
643 { X(L"AND"), TK_AND },
644 { X(L"ASSOCIATORS"), TK_ASSOCIATORS },
645 { X(L"BY"), TK_BY },
646 { X(L"FALSE"), TK_FALSE },
647 { X(L"FROM"), TK_FROM },
648 { X(L"IS"), TK_IS },
649 { X(L"LIKE"), TK_LIKE },
650 { X(L"NOT"), TK_NOT },
651 { X(L"NULL"), TK_NULL },
652 { X(L"OF"), TK_OF },
653 { X(L"OR"), TK_OR },
654 { X(L"SELECT"), TK_SELECT },
655 { X(L"TRUE"), TK_TRUE },
656 { X(L"WHERE"), TK_WHERE }
658 #undef X
660 static int __cdecl cmp_keyword( const void *arg1, const void *arg2 )
662 const struct wql_keyword *key1 = arg1, *key2 = arg2;
663 int len = min( key1->len, key2->len );
664 int ret;
666 if ((ret = wcsnicmp( key1->name, key2->name, len ))) return ret;
667 if (key1->len < key2->len) return -1;
668 else if (key1->len > key2->len) return 1;
669 return 0;
672 static int keyword_type( const WCHAR *str, unsigned int len )
674 struct wql_keyword key, *ret;
676 if (len < MIN_TOKEN_LEN || len > MAX_TOKEN_LEN) return TK_ID;
678 key.name = str;
679 key.len = len;
680 key.type = 0;
681 ret = bsearch( &key, keyword_table, ARRAY_SIZE(keyword_table), sizeof(struct wql_keyword), cmp_keyword );
682 if (ret) return ret->type;
683 return TK_ID;
686 static int get_token( const WCHAR *s, int *token )
688 int i;
690 switch (*s)
692 case ' ':
693 case '\t':
694 case '\r':
695 case '\n':
696 for (i = 1; iswspace( s[i] ); i++) {}
697 *token = TK_SPACE;
698 return i;
699 case '-':
700 if (!s[1]) return -1;
701 *token = TK_MINUS;
702 return 1;
703 case '(':
704 *token = TK_LP;
705 return 1;
706 case ')':
707 *token = TK_RP;
708 return 1;
709 case '{':
710 for (i = 1; s[i] && s[i] != '}'; i++) {}
711 if (s[i] != '}')
713 *token = TK_ILLEGAL;
714 return i;
716 *token = TK_PATH;
717 return i + 1;
718 case '*':
719 *token = TK_STAR;
720 return 1;
721 case '=':
722 *token = TK_EQ;
723 return 1;
724 case '<':
725 if (s[1] == '=' )
727 *token = TK_LE;
728 return 2;
730 else if (s[1] == '>')
732 *token = TK_NE;
733 return 2;
735 else
737 *token = TK_LT;
738 return 1;
740 case '>':
741 if (s[1] == '=')
743 *token = TK_GE;
744 return 2;
746 else
748 *token = TK_GT;
749 return 1;
751 case '!':
752 if (s[1] != '=')
754 *token = TK_ILLEGAL;
755 return 2;
757 else
759 *token = TK_NE;
760 return 2;
762 case ',':
763 *token = TK_COMMA;
764 return 1;
765 case '\"':
766 case '\'':
767 for (i = 1; s[i]; i++)
769 if (s[i] == s[0]) break;
771 if (s[i]) i++;
772 *token = TK_STRING;
773 return i;
774 case '.':
775 if (!is_digit( s[1] ))
777 *token = TK_DOT;
778 return 1;
780 /* fall through */
781 case '0': case '1': case '2': case '3': case '4':
782 case '5': case '6': case '7': case '8': case '9':
783 *token = TK_INTEGER;
784 for (i = 1; is_digit( s[i] ); i++) {}
785 return i;
786 default:
787 if (!id_char[*s]) break;
789 for (i = 1; id_char[s[i]]; i++) {}
790 *token = keyword_type( s, i );
791 return i;
793 *token = TK_ILLEGAL;
794 return 1;
797 static int wql_lex( void *p, struct parser *parser )
799 struct string *str = p;
800 int token = -1;
803 parser->idx += parser->len;
804 if (!parser->cmd[parser->idx]) return 0;
805 parser->len = get_token( &parser->cmd[parser->idx], &token );
806 if (!parser->len) break;
808 str->data = &parser->cmd[parser->idx];
809 str->len = parser->len;
810 } while (token == TK_SPACE);
811 return token;
814 static int wql_error( struct parser *parser, const char *str )
816 ERR("%s\n", str);
817 return 0;