[THEMES]
[reactos.git] / reactos / dll / win32 / wbemprox / wql.y
1 %{
2
3 /*
4 * Copyright 2012 Hans Leidekker for CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "config.h"
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wbemcli.h"
27 #include "wbemprox_private.h"
28
29 #include "wine/list.h"
30 #include "wine/debug.h"
31 #include "wine/unicode.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
34
35 struct parser
36 {
37 const WCHAR *cmd;
38 UINT idx;
39 UINT len;
40 HRESULT error;
41 struct view **view;
42 struct list *mem;
43 };
44
45 struct string
46 {
47 const WCHAR *data;
48 int len;
49 };
50
51 static void *alloc_mem( struct parser *parser, UINT size )
52 {
53 struct list *mem = heap_alloc( sizeof(struct list) + size );
54 list_add_tail( parser->mem, mem );
55 return &mem[1];
56 }
57
58 static struct property *alloc_property( struct parser *parser, const WCHAR *class, const WCHAR *name )
59 {
60 struct property *prop = alloc_mem( parser, sizeof(*prop) );
61 if (prop)
62 {
63 prop->name = name;
64 prop->class = class;
65 prop->next = NULL;
66 }
67 return prop;
68 }
69
70 static WCHAR *get_string( struct parser *parser, const struct string *str )
71 {
72 const WCHAR *p = str->data;
73 int len = str->len;
74 WCHAR *ret;
75
76 if ((p[0] == '\"' && p[len - 1] != '\"') ||
77 (p[0] == '\'' && p[len - 1] != '\'')) return NULL;
78 if ((p[0] == '\"' && p[len - 1] == '\"') ||
79 (p[0] == '\'' && p[len - 1] == '\''))
80 {
81 p++;
82 len -= 2;
83 }
84 if (!(ret = alloc_mem( parser, (len + 1) * sizeof(WCHAR) ))) return NULL;
85 memcpy( ret, p, len * sizeof(WCHAR) );
86 ret[len] = 0;
87 return ret;
88 }
89
90 static int get_int( struct parser *parser )
91 {
92 const WCHAR *p = &parser->cmd[parser->idx];
93 int i, ret = 0;
94
95 for (i = 0; i < parser->len; i++)
96 {
97 if (p[i] < '0' || p[i] > '9')
98 {
99 ERR("should only be numbers here!\n");
100 break;
101 }
102 ret = (p[i] - '0') + ret * 10;
103 }
104 return ret;
105 }
106
107 static struct expr *expr_complex( struct parser *parser, struct expr *l, UINT op, struct expr *r )
108 {
109 struct expr *e = alloc_mem( parser, sizeof(*e) );
110 if (e)
111 {
112 e->type = EXPR_COMPLEX;
113 e->u.expr.left = l;
114 e->u.expr.op = op;
115 e->u.expr.right = r;
116 }
117 return e;
118 }
119
120 static struct expr *expr_unary( struct parser *parser, struct expr *l, UINT op )
121 {
122 struct expr *e = alloc_mem( parser, sizeof(*e) );
123 if (e)
124 {
125 e->type = EXPR_UNARY;
126 e->u.expr.left = l;
127 e->u.expr.op = op;
128 e->u.expr.right = NULL;
129 }
130 return e;
131 }
132
133 static struct expr *expr_ival( struct parser *parser, int val )
134 {
135 struct expr *e = alloc_mem( parser, sizeof *e );
136 if (e)
137 {
138 e->type = EXPR_IVAL;
139 e->u.ival = val;
140 }
141 return e;
142 }
143
144 static struct expr *expr_sval( struct parser *parser, const struct string *str )
145 {
146 struct expr *e = alloc_mem( parser, sizeof *e );
147 if (e)
148 {
149 e->type = EXPR_SVAL;
150 e->u.sval = get_string( parser, str );
151 if (!e->u.sval)
152 return NULL; /* e will be freed by query destructor */
153 }
154 return e;
155 }
156
157 static struct expr *expr_bval( struct parser *parser, int val )
158 {
159 struct expr *e = alloc_mem( parser, sizeof *e );
160 if (e)
161 {
162 e->type = EXPR_BVAL;
163 e->u.ival = val;
164 }
165 return e;
166 }
167
168 static struct expr *expr_propval( struct parser *parser, const struct property *prop )
169 {
170 struct expr *e = alloc_mem( parser, sizeof *e );
171 if (e)
172 {
173 e->type = EXPR_PROPVAL;
174 e->u.propval = prop;
175 }
176 return e;
177 }
178
179 static int wql_error( struct parser *parser, const char *str );
180 static int wql_lex( void *val, struct parser *parser );
181
182 #define PARSER_BUBBLE_UP_VIEW( parser, result, current_view ) \
183 *parser->view = current_view; \
184 result = current_view
185
186 %}
187
188 %lex-param { struct parser *ctx }
189 %parse-param { struct parser *ctx }
190 %error-verbose
191 %pure-parser
192
193 %union
194 {
195 struct string str;
196 WCHAR *string;
197 struct property *proplist;
198 struct view *view;
199 struct expr *expr;
200 int integer;
201 }
202
203 %token TK_SELECT TK_FROM TK_STAR TK_COMMA TK_DOT TK_IS TK_LP TK_RP TK_NULL TK_FALSE TK_TRUE
204 %token TK_INTEGER TK_WHERE TK_SPACE TK_MINUS TK_ILLEGAL TK_BY
205 %token <str> TK_STRING TK_ID
206
207 %type <string> id
208 %type <proplist> prop proplist
209 %type <view> select
210 %type <expr> expr prop_val const_val string_val
211 %type <integer> number
212
213 %left TK_OR
214 %left TK_AND
215 %left TK_NOT
216 %left TK_EQ TK_NE TK_LT TK_GT TK_LE TK_GE TK_LIKE
217
218 %%
219
220 select:
221 TK_SELECT TK_FROM id
222 {
223 HRESULT hr;
224 struct parser *parser = ctx;
225 struct view *view;
226
227 hr = create_view( NULL, $3, NULL, &view );
228 if (hr != S_OK)
229 YYABORT;
230
231 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
232 }
233 | TK_SELECT proplist TK_FROM id
234 {
235 HRESULT hr;
236 struct parser *parser = ctx;
237 struct view *view;
238
239 hr = create_view( $2, $4, NULL, &view );
240 if (hr != S_OK)
241 YYABORT;
242
243 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
244 }
245 | TK_SELECT proplist TK_FROM id TK_WHERE expr
246 {
247 HRESULT hr;
248 struct parser *parser = ctx;
249 struct view *view;
250
251 hr = create_view( $2, $4, $6, &view );
252 if (hr != S_OK)
253 YYABORT;
254
255 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
256 }
257 ;
258
259 proplist:
260 prop
261 | prop TK_COMMA proplist
262 {
263 $1->next = $3;
264 }
265 | TK_STAR
266 {
267 $$ = NULL;
268 }
269 ;
270
271 prop:
272 id TK_DOT id
273 {
274 $$ = alloc_property( ctx, $1, $3 );
275 if (!$$)
276 YYABORT;
277 }
278 | id
279 {
280 $$ = alloc_property( ctx, NULL, $1 );
281 if (!$$)
282 YYABORT;
283 }
284 ;
285
286 id:
287 TK_ID
288 {
289 $$ = get_string( ctx, &$1 );
290 if (!$$)
291 YYABORT;
292 }
293 ;
294
295 number:
296 TK_INTEGER
297 {
298 $$ = get_int( ctx );
299 }
300 ;
301
302 expr:
303 TK_LP expr TK_RP
304 {
305 $$ = $2;
306 if (!$$)
307 YYABORT;
308 }
309 | expr TK_AND expr
310 {
311 $$ = expr_complex( ctx, $1, OP_AND, $3 );
312 if (!$$)
313 YYABORT;
314 }
315 | expr TK_OR expr
316 {
317 $$ = expr_complex( ctx, $1, OP_OR, $3 );
318 if (!$$)
319 YYABORT;
320 }
321 | prop_val TK_EQ const_val
322 {
323 $$ = expr_complex( ctx, $1, OP_EQ, $3 );
324 if (!$$)
325 YYABORT;
326 }
327 | prop_val TK_GT const_val
328 {
329 $$ = expr_complex( ctx, $1, OP_GT, $3 );
330 if (!$$)
331 YYABORT;
332 }
333 | prop_val TK_LT const_val
334 {
335 $$ = expr_complex( ctx, $1, OP_LT, $3 );
336 if (!$$)
337 YYABORT;
338 }
339 | prop_val TK_LE const_val
340 {
341 $$ = expr_complex( ctx, $1, OP_LE, $3 );
342 if (!$$)
343 YYABORT;
344 }
345 | prop_val TK_GE const_val
346 {
347 $$ = expr_complex( ctx, $1, OP_GE, $3 );
348 if (!$$)
349 YYABORT;
350 }
351 | prop_val TK_NE const_val
352 {
353 $$ = expr_complex( ctx, $1, OP_NE, $3 );
354 if (!$$)
355 YYABORT;
356 }
357 | const_val TK_EQ prop_val
358 {
359 $$ = expr_complex( ctx, $1, OP_EQ, $3 );
360 if (!$$)
361 YYABORT;
362 }
363 | const_val TK_GT prop_val
364 {
365 $$ = expr_complex( ctx, $1, OP_GT, $3 );
366 if (!$$)
367 YYABORT;
368 }
369 | const_val TK_LT prop_val
370 {
371 $$ = expr_complex( ctx, $1, OP_LT, $3 );
372 if (!$$)
373 YYABORT;
374 }
375 | const_val TK_LE prop_val
376 {
377 $$ = expr_complex( ctx, $1, OP_LE, $3 );
378 if (!$$)
379 YYABORT;
380 }
381 | const_val TK_GE prop_val
382 {
383 $$ = expr_complex( ctx, $1, OP_GE, $3 );
384 if (!$$)
385 YYABORT;
386 }
387 | const_val TK_NE prop_val
388 {
389 $$ = expr_complex( ctx, $1, OP_NE, $3 );
390 if (!$$)
391 YYABORT;
392 }
393 | prop_val TK_LIKE string_val
394 {
395 $$ = expr_complex( ctx, $1, OP_LIKE, $3 );
396 if (!$$)
397 YYABORT;
398 }
399 | prop_val TK_IS TK_NULL
400 {
401 $$ = expr_unary( ctx, $1, OP_ISNULL );
402 if (!$$)
403 YYABORT;
404 }
405 | prop_val TK_IS TK_NOT TK_NULL
406 {
407 $$ = expr_unary( ctx, $1, OP_NOTNULL );
408 if (!$$)
409 YYABORT;
410 }
411 ;
412
413 string_val:
414 TK_STRING
415 {
416 $$ = expr_sval( ctx, &$1 );
417 if (!$$)
418 YYABORT;
419 }
420 ;
421
422 prop_val:
423 prop
424 {
425 $$ = expr_propval( ctx, $1 );
426 if (!$$)
427 YYABORT;
428 }
429 ;
430
431 const_val:
432 number
433 {
434 $$ = expr_ival( ctx, $1 );
435 if (!$$)
436 YYABORT;
437 }
438 | TK_STRING
439 {
440 $$ = expr_sval( ctx, &$1 );
441 if (!$$)
442 YYABORT;
443 }
444 | TK_TRUE
445 {
446 $$ = expr_bval( ctx, -1 );
447 if (!$$)
448 YYABORT;
449 }
450 | TK_FALSE
451 {
452 $$ = expr_bval( ctx, 0 );
453 if (!$$)
454 YYABORT;
455 }
456 ;
457
458 %%
459
460 HRESULT parse_query( const WCHAR *str, struct view **view, struct list *mem )
461 {
462 struct parser parser;
463 int ret;
464
465 *view = NULL;
466
467 parser.cmd = str;
468 parser.idx = 0;
469 parser.len = 0;
470 parser.error = WBEM_E_INVALID_QUERY;
471 parser.view = view;
472 parser.mem = mem;
473
474 ret = wql_parse( &parser );
475 TRACE("wql_parse returned %d\n", ret);
476 if (ret)
477 {
478 if (*parser.view)
479 {
480 destroy_view( *parser.view );
481 *parser.view = NULL;
482 }
483 return parser.error;
484 }
485 return S_OK;
486 }
487
488 static const char id_char[] =
489 {
490 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
491 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
492 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
493 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
494 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
495 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
496 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
497 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
498 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
499 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
500 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
501 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
502 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
503 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
504 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
505 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
506 };
507
508 struct keyword
509 {
510 const WCHAR *name;
511 unsigned int len;
512 int type;
513 };
514
515 #define MAX_TOKEN_LEN 6
516
517 static const WCHAR andW[] = {'A','N','D'};
518 static const WCHAR byW[] = {'B','Y'};
519 static const WCHAR falseW[] = {'F','A','L','S','E'};
520 static const WCHAR fromW[] = {'F','R','O','M'};
521 static const WCHAR isW[] = {'I','S'};
522 static const WCHAR likeW[] = {'L','I','K','E'};
523 static const WCHAR notW[] = {'N','O','T'};
524 static const WCHAR nullW[] = {'N','U','L','L'};
525 static const WCHAR orW[] = {'O','R'};
526 static const WCHAR selectW[] = {'S','E','L','E','C','T'};
527 static const WCHAR trueW[] = {'T','R','U','E'};
528 static const WCHAR whereW[] = {'W','H','E','R','E'};
529
530 static const struct keyword keyword_table[] =
531 {
532 { andW, SIZEOF(andW), TK_AND },
533 { byW, SIZEOF(byW), TK_BY },
534 { falseW, SIZEOF(falseW), TK_FALSE },
535 { fromW, SIZEOF(fromW), TK_FROM },
536 { isW, SIZEOF(isW), TK_IS },
537 { likeW, SIZEOF(likeW), TK_LIKE },
538 { notW, SIZEOF(notW), TK_NOT },
539 { nullW, SIZEOF(nullW), TK_NULL },
540 { orW, SIZEOF(orW), TK_OR },
541 { selectW, SIZEOF(selectW), TK_SELECT },
542 { trueW, SIZEOF(trueW), TK_TRUE },
543 { whereW, SIZEOF(whereW), TK_WHERE }
544 };
545
546 static int cmp_keyword( const void *arg1, const void *arg2 )
547 {
548 const struct keyword *key1 = arg1, *key2 = arg2;
549 int len = min( key1->len, key2->len );
550 int ret;
551
552 if ((ret = memicmpW( key1->name, key2->name, len ))) return ret;
553 if (key1->len < key2->len) return -1;
554 else if (key1->len > key2->len) return 1;
555 return 0;
556 }
557
558 static int keyword_type( const WCHAR *str, unsigned int len )
559 {
560 struct keyword key, *ret;
561
562 if (len > MAX_TOKEN_LEN) return TK_ID;
563
564 key.name = str;
565 key.len = len;
566 key.type = 0;
567 ret = bsearch( &key, keyword_table, SIZEOF(keyword_table), sizeof(struct keyword), cmp_keyword );
568 if (ret) return ret->type;
569 return TK_ID;
570 }
571
572 static int get_token( const WCHAR *s, int *token )
573 {
574 int i;
575
576 switch (*s)
577 {
578 case ' ':
579 case '\t':
580 case '\n':
581 for (i = 1; isspaceW( s[i] ); i++) {}
582 *token = TK_SPACE;
583 return i;
584 case '-':
585 if (!s[1]) return -1;
586 *token = TK_MINUS;
587 return 1;
588 case '(':
589 *token = TK_LP;
590 return 1;
591 case ')':
592 *token = TK_RP;
593 return 1;
594 case '*':
595 *token = TK_STAR;
596 return 1;
597 case '=':
598 *token = TK_EQ;
599 return 1;
600 case '<':
601 if (s[1] == '=' )
602 {
603 *token = TK_LE;
604 return 2;
605 }
606 else if (s[1] == '>')
607 {
608 *token = TK_NE;
609 return 2;
610 }
611 else
612 {
613 *token = TK_LT;
614 return 1;
615 }
616 case '>':
617 if (s[1] == '=')
618 {
619 *token = TK_GE;
620 return 2;
621 }
622 else
623 {
624 *token = TK_GT;
625 return 1;
626 }
627 case '!':
628 if (s[1] != '=')
629 {
630 *token = TK_ILLEGAL;
631 return 2;
632 }
633 else
634 {
635 *token = TK_NE;
636 return 2;
637 }
638 case ',':
639 *token = TK_COMMA;
640 return 1;
641 case '\"':
642 case '\'':
643 {
644 for (i = 1; s[i]; i++)
645 {
646 if (s[i] == s[0]) break;
647 }
648 if (s[i]) i++;
649 *token = TK_STRING;
650 return i;
651 }
652 case '.':
653 if (!isdigitW( s[1] ))
654 {
655 *token = TK_DOT;
656 return 1;
657 }
658 /* fall through */
659 case '0': case '1': case '2': case '3': case '4':
660 case '5': case '6': case '7': case '8': case '9':
661 *token = TK_INTEGER;
662 for (i = 1; isdigitW( s[i] ); i++) {}
663 return i;
664 default:
665 if (!id_char[*s]) break;
666
667 for (i = 1; id_char[s[i]]; i++) {}
668 *token = keyword_type( s, i );
669 return i;
670 }
671 *token = TK_ILLEGAL;
672 return 1;
673 }
674
675 static int wql_lex( void *p, struct parser *parser )
676 {
677 struct string *str = p;
678 int token = -1;
679 do
680 {
681 parser->idx += parser->len;
682 if (!parser->cmd[parser->idx]) return 0;
683 parser->len = get_token( &parser->cmd[parser->idx], &token );
684 if (!parser->len) break;
685
686 str->data = &parser->cmd[parser->idx];
687 str->len = parser->len;
688 } while (token == TK_SPACE);
689 return token;
690 }
691
692 static int wql_error( struct parser *parser, const char *str )
693 {
694 ERR("%s\n", str);
695 return 0;
696 }