msvcrt: Added _putwc_nolock implementation.
[wine.git] / dlls / wbemprox / wql.y
blob6eabe19e1ef89ec6135ccbfa3749654c97ea5aa5
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 "config.h"
22 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wbemcli.h"
27 #include "wbemprox_private.h"
29 #include "wine/list.h"
30 #include "wine/debug.h"
31 #include "wine/unicode.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
35 struct parser
37 const WCHAR *cmd;
38 UINT idx;
39 UINT len;
40 HRESULT error;
41 struct view **view;
42 struct list *mem;
45 struct string
47 const WCHAR *data;
48 int len;
51 static void *alloc_mem( struct parser *parser, UINT size )
53 struct list *mem = heap_alloc( sizeof(struct list) + size );
54 list_add_tail( parser->mem, mem );
55 return &mem[1];
58 static struct property *alloc_property( struct parser *parser, const WCHAR *class, const WCHAR *name )
60 struct property *prop = alloc_mem( parser, sizeof(*prop) );
61 if (prop)
63 prop->name = name;
64 prop->class = class;
65 prop->next = NULL;
67 return prop;
70 static WCHAR *get_string( struct parser *parser, const struct string *str )
72 const WCHAR *p = str->data;
73 int len = str->len;
74 WCHAR *ret;
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] == '\''))
81 p++;
82 len -= 2;
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;
90 static int get_int( struct parser *parser )
92 const WCHAR *p = &parser->cmd[parser->idx];
93 int i, ret = 0;
95 for (i = 0; i < parser->len; i++)
97 if (p[i] < '0' || p[i] > '9')
99 ERR("should only be numbers here!\n");
100 break;
102 ret = (p[i] - '0') + ret * 10;
104 return ret;
107 static struct expr *expr_complex( struct parser *parser, struct expr *l, UINT op, struct expr *r )
109 struct expr *e = alloc_mem( parser, sizeof(*e) );
110 if (e)
112 e->type = EXPR_COMPLEX;
113 e->u.expr.left = l;
114 e->u.expr.op = op;
115 e->u.expr.right = r;
117 return e;
120 static struct expr *expr_unary( struct parser *parser, struct expr *l, UINT op )
122 struct expr *e = alloc_mem( parser, sizeof(*e) );
123 if (e)
125 e->type = EXPR_UNARY;
126 e->u.expr.left = l;
127 e->u.expr.op = op;
128 e->u.expr.right = NULL;
130 return e;
133 static struct expr *expr_ival( struct parser *parser, int val )
135 struct expr *e = alloc_mem( parser, sizeof *e );
136 if (e)
138 e->type = EXPR_IVAL;
139 e->u.ival = val;
141 return e;
144 static struct expr *expr_sval( struct parser *parser, const struct string *str )
146 struct expr *e = alloc_mem( parser, sizeof *e );
147 if (e)
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 */
154 return e;
157 static struct expr *expr_bval( struct parser *parser, int val )
159 struct expr *e = alloc_mem( parser, sizeof *e );
160 if (e)
162 e->type = EXPR_BVAL;
163 e->u.ival = val;
165 return e;
168 static struct expr *expr_propval( struct parser *parser, const struct property *prop )
170 struct expr *e = alloc_mem( parser, sizeof *e );
171 if (e)
173 e->type = EXPR_PROPVAL;
174 e->u.propval = prop;
176 return e;
179 static int wql_error( struct parser *parser, const char *str );
180 static int wql_lex( void *val, struct parser *parser );
182 #define PARSER_BUBBLE_UP_VIEW( parser, result, current_view ) \
183 *parser->view = current_view; \
184 result = current_view
188 %lex-param { struct parser *ctx }
189 %parse-param { struct parser *ctx }
190 %error-verbose
191 %pure-parser
193 %union
195 struct string str;
196 WCHAR *string;
197 struct property *proplist;
198 struct view *view;
199 struct expr *expr;
200 int integer;
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
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
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
220 select:
221 TK_SELECT TK_FROM id
223 HRESULT hr;
224 struct parser *parser = ctx;
225 struct view *view;
227 hr = create_view( NULL, $3, NULL, &view );
228 if (hr != S_OK)
229 YYABORT;
231 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
233 | TK_SELECT proplist TK_FROM id
235 HRESULT hr;
236 struct parser *parser = ctx;
237 struct view *view;
239 hr = create_view( $2, $4, NULL, &view );
240 if (hr != S_OK)
241 YYABORT;
243 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
245 | TK_SELECT proplist TK_FROM id TK_WHERE expr
247 HRESULT hr;
248 struct parser *parser = ctx;
249 struct view *view;
251 hr = create_view( $2, $4, $6, &view );
252 if (hr != S_OK)
253 YYABORT;
255 PARSER_BUBBLE_UP_VIEW( parser, $$, view );
259 proplist:
260 prop
261 | prop TK_COMMA proplist
263 $1->next = $3;
265 | TK_STAR
267 $$ = NULL;
271 prop:
272 id TK_DOT id
274 $$ = alloc_property( ctx, $1, $3 );
275 if (!$$)
276 YYABORT;
278 | id
280 $$ = alloc_property( ctx, NULL, $1 );
281 if (!$$)
282 YYABORT;
287 TK_ID
289 $$ = get_string( ctx, &$1 );
290 if (!$$)
291 YYABORT;
295 number:
296 TK_INTEGER
298 $$ = get_int( ctx );
302 expr:
303 TK_LP expr TK_RP
305 $$ = $2;
306 if (!$$)
307 YYABORT;
309 | expr TK_AND expr
311 $$ = expr_complex( ctx, $1, OP_AND, $3 );
312 if (!$$)
313 YYABORT;
315 | expr TK_OR expr
317 $$ = expr_complex( ctx, $1, OP_OR, $3 );
318 if (!$$)
319 YYABORT;
321 | TK_NOT expr
323 $$ = expr_unary( ctx, $2, OP_NOT );
324 if (!$$)
325 YYABORT;
327 | prop_val TK_EQ const_val
329 $$ = expr_complex( ctx, $1, OP_EQ, $3 );
330 if (!$$)
331 YYABORT;
333 | prop_val TK_GT const_val
335 $$ = expr_complex( ctx, $1, OP_GT, $3 );
336 if (!$$)
337 YYABORT;
339 | prop_val TK_LT const_val
341 $$ = expr_complex( ctx, $1, OP_LT, $3 );
342 if (!$$)
343 YYABORT;
345 | prop_val TK_LE const_val
347 $$ = expr_complex( ctx, $1, OP_LE, $3 );
348 if (!$$)
349 YYABORT;
351 | prop_val TK_GE const_val
353 $$ = expr_complex( ctx, $1, OP_GE, $3 );
354 if (!$$)
355 YYABORT;
357 | prop_val TK_NE const_val
359 $$ = expr_complex( ctx, $1, OP_NE, $3 );
360 if (!$$)
361 YYABORT;
363 | const_val TK_EQ prop_val
365 $$ = expr_complex( ctx, $1, OP_EQ, $3 );
366 if (!$$)
367 YYABORT;
369 | const_val TK_GT prop_val
371 $$ = expr_complex( ctx, $1, OP_GT, $3 );
372 if (!$$)
373 YYABORT;
375 | const_val TK_LT prop_val
377 $$ = expr_complex( ctx, $1, OP_LT, $3 );
378 if (!$$)
379 YYABORT;
381 | const_val TK_LE prop_val
383 $$ = expr_complex( ctx, $1, OP_LE, $3 );
384 if (!$$)
385 YYABORT;
387 | const_val TK_GE prop_val
389 $$ = expr_complex( ctx, $1, OP_GE, $3 );
390 if (!$$)
391 YYABORT;
393 | const_val TK_NE prop_val
395 $$ = expr_complex( ctx, $1, OP_NE, $3 );
396 if (!$$)
397 YYABORT;
399 | prop_val TK_LIKE string_val
401 $$ = expr_complex( ctx, $1, OP_LIKE, $3 );
402 if (!$$)
403 YYABORT;
405 | prop_val TK_IS TK_NULL
407 $$ = expr_unary( ctx, $1, OP_ISNULL );
408 if (!$$)
409 YYABORT;
411 | prop_val TK_IS TK_NOT TK_NULL
413 $$ = expr_unary( ctx, $1, OP_NOTNULL );
414 if (!$$)
415 YYABORT;
419 string_val:
420 TK_STRING
422 $$ = expr_sval( ctx, &$1 );
423 if (!$$)
424 YYABORT;
428 prop_val:
429 prop
431 $$ = expr_propval( ctx, $1 );
432 if (!$$)
433 YYABORT;
437 const_val:
438 number
440 $$ = expr_ival( ctx, $1 );
441 if (!$$)
442 YYABORT;
444 | TK_STRING
446 $$ = expr_sval( ctx, &$1 );
447 if (!$$)
448 YYABORT;
450 | TK_TRUE
452 $$ = expr_bval( ctx, -1 );
453 if (!$$)
454 YYABORT;
456 | TK_FALSE
458 $$ = expr_bval( ctx, 0 );
459 if (!$$)
460 YYABORT;
466 HRESULT parse_query( const WCHAR *str, struct view **view, struct list *mem )
468 struct parser parser;
469 int ret;
471 *view = NULL;
473 parser.cmd = str;
474 parser.idx = 0;
475 parser.len = 0;
476 parser.error = WBEM_E_INVALID_QUERY;
477 parser.view = view;
478 parser.mem = mem;
480 ret = wql_parse( &parser );
481 TRACE("wql_parse returned %d\n", ret);
482 if (ret)
484 if (*parser.view)
486 destroy_view( *parser.view );
487 *parser.view = NULL;
489 return parser.error;
491 return S_OK;
494 static const char id_char[] =
496 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
497 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
498 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
499 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
500 0, 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, 0, 0, 0, 0, 1,
502 0, 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, 0, 0, 0, 0, 0,
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 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
509 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
510 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
511 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
514 struct keyword
516 const WCHAR *name;
517 unsigned int len;
518 int type;
521 #define MAX_TOKEN_LEN 6
523 static const WCHAR andW[] = {'A','N','D'};
524 static const WCHAR byW[] = {'B','Y'};
525 static const WCHAR falseW[] = {'F','A','L','S','E'};
526 static const WCHAR fromW[] = {'F','R','O','M'};
527 static const WCHAR isW[] = {'I','S'};
528 static const WCHAR likeW[] = {'L','I','K','E'};
529 static const WCHAR notW[] = {'N','O','T'};
530 static const WCHAR nullW[] = {'N','U','L','L'};
531 static const WCHAR orW[] = {'O','R'};
532 static const WCHAR selectW[] = {'S','E','L','E','C','T'};
533 static const WCHAR trueW[] = {'T','R','U','E'};
534 static const WCHAR whereW[] = {'W','H','E','R','E'};
536 static const struct keyword keyword_table[] =
538 { andW, SIZEOF(andW), TK_AND },
539 { byW, SIZEOF(byW), TK_BY },
540 { falseW, SIZEOF(falseW), TK_FALSE },
541 { fromW, SIZEOF(fromW), TK_FROM },
542 { isW, SIZEOF(isW), TK_IS },
543 { likeW, SIZEOF(likeW), TK_LIKE },
544 { notW, SIZEOF(notW), TK_NOT },
545 { nullW, SIZEOF(nullW), TK_NULL },
546 { orW, SIZEOF(orW), TK_OR },
547 { selectW, SIZEOF(selectW), TK_SELECT },
548 { trueW, SIZEOF(trueW), TK_TRUE },
549 { whereW, SIZEOF(whereW), TK_WHERE }
552 static int cmp_keyword( const void *arg1, const void *arg2 )
554 const struct keyword *key1 = arg1, *key2 = arg2;
555 int len = min( key1->len, key2->len );
556 int ret;
558 if ((ret = memicmpW( key1->name, key2->name, len ))) return ret;
559 if (key1->len < key2->len) return -1;
560 else if (key1->len > key2->len) return 1;
561 return 0;
564 static int keyword_type( const WCHAR *str, unsigned int len )
566 struct keyword key, *ret;
568 if (len > MAX_TOKEN_LEN) return TK_ID;
570 key.name = str;
571 key.len = len;
572 key.type = 0;
573 ret = bsearch( &key, keyword_table, SIZEOF(keyword_table), sizeof(struct keyword), cmp_keyword );
574 if (ret) return ret->type;
575 return TK_ID;
578 static int get_token( const WCHAR *s, int *token )
580 int i;
582 switch (*s)
584 case ' ':
585 case '\t':
586 case '\n':
587 for (i = 1; isspaceW( s[i] ); i++) {}
588 *token = TK_SPACE;
589 return i;
590 case '-':
591 if (!s[1]) return -1;
592 *token = TK_MINUS;
593 return 1;
594 case '(':
595 *token = TK_LP;
596 return 1;
597 case ')':
598 *token = TK_RP;
599 return 1;
600 case '*':
601 *token = TK_STAR;
602 return 1;
603 case '=':
604 *token = TK_EQ;
605 return 1;
606 case '<':
607 if (s[1] == '=' )
609 *token = TK_LE;
610 return 2;
612 else if (s[1] == '>')
614 *token = TK_NE;
615 return 2;
617 else
619 *token = TK_LT;
620 return 1;
622 case '>':
623 if (s[1] == '=')
625 *token = TK_GE;
626 return 2;
628 else
630 *token = TK_GT;
631 return 1;
633 case '!':
634 if (s[1] != '=')
636 *token = TK_ILLEGAL;
637 return 2;
639 else
641 *token = TK_NE;
642 return 2;
644 case ',':
645 *token = TK_COMMA;
646 return 1;
647 case '\"':
648 case '\'':
650 for (i = 1; s[i]; i++)
652 if (s[i] == s[0]) break;
654 if (s[i]) i++;
655 *token = TK_STRING;
656 return i;
658 case '.':
659 if (!isdigitW( s[1] ))
661 *token = TK_DOT;
662 return 1;
664 /* fall through */
665 case '0': case '1': case '2': case '3': case '4':
666 case '5': case '6': case '7': case '8': case '9':
667 *token = TK_INTEGER;
668 for (i = 1; isdigitW( s[i] ); i++) {}
669 return i;
670 default:
671 if (!id_char[*s]) break;
673 for (i = 1; id_char[s[i]]; i++) {}
674 *token = keyword_type( s, i );
675 return i;
677 *token = TK_ILLEGAL;
678 return 1;
681 static int wql_lex( void *p, struct parser *parser )
683 struct string *str = p;
684 int token = -1;
687 parser->idx += parser->len;
688 if (!parser->cmd[parser->idx]) return 0;
689 parser->len = get_token( &parser->cmd[parser->idx], &token );
690 if (!parser->len) break;
692 str->data = &parser->cmd[parser->idx];
693 str->len = parser->len;
694 } while (token == TK_SPACE);
695 return token;
698 static int wql_error( struct parser *parser, const char *str )
700 ERR("%s\n", str);
701 return 0;