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