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
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
);
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
);
58 static struct property
*alloc_property
( struct parser
*parser
, const WCHAR
*class
, const WCHAR
*name
)
60 struct property
*prop
= alloc_mem
( parser
, sizeof
(*prop
) );
70 static WCHAR
*get_string
( struct parser
*parser
, const struct string *str
)
72 const WCHAR
*p
= str
->data
;
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] == '\''))
84 if
(!(ret
= alloc_mem
( parser
, (len
+ 1) * sizeof
(WCHAR
) ))) return NULL
;
85 memcpy
( ret
, p
, len
* sizeof
(WCHAR
) );
90 static int get_int
( struct parser
*parser
)
92 const WCHAR
*p
= &parser
->cmd
[parser
->idx
];
95 for
(i
= 0; i
< parser
->len
; i
++)
97 if
(p
[i
] < '0' || p
[i
] > '9')
99 ERR
("should only be numbers here!\n");
102 ret
= (p
[i
] - '0') + ret
* 10;
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
) );
112 e
->type
= EXPR_COMPLEX
;
120 static struct expr
*expr_unary
( struct parser
*parser
, struct expr
*l
, UINT op
)
122 struct expr
*e
= alloc_mem
( parser
, sizeof
(*e
) );
125 e
->type
= EXPR_UNARY
;
128 e
->u.expr.right
= NULL
;
133 static struct expr
*expr_ival
( struct parser
*parser
, int val
)
135 struct expr
*e
= alloc_mem
( parser
, sizeof
*e
);
144 static struct expr
*expr_sval
( struct parser
*parser
, const struct string *str
)
146 struct expr
*e
= alloc_mem
( parser
, sizeof
*e
);
150 e
->u.sval
= get_string
( parser
, str
);
152 return NULL
; /* e will be freed by query destructor */
157 static struct expr
*expr_bval
( struct parser
*parser
, int val
)
159 struct expr
*e
= alloc_mem
( parser
, sizeof
*e
);
168 static struct expr
*expr_propval
( struct parser
*parser
, const struct property
*prop
)
170 struct expr
*e
= alloc_mem
( parser
, sizeof
*e
);
173 e
->type
= EXPR_PROPVAL
;
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
}
197 struct property
*proplist
;
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
208 %type
<proplist
> prop proplist
210 %type
<expr
> expr prop_val const_val string_val
211 %type
<integer
> number
216 %left TK_EQ TK_NE TK_LT TK_GT TK_LE TK_GE TK_LIKE
224 struct parser
*parser
= ctx
;
227 hr
= create_view
( NULL
, $3, NULL
, &view
);
231 PARSER_BUBBLE_UP_VIEW
( parser
, $$
, view
);
233 | TK_SELECT proplist TK_FROM id
236 struct parser
*parser
= ctx
;
239 hr
= create_view
( $2, $4, NULL
, &view
);
243 PARSER_BUBBLE_UP_VIEW
( parser
, $$
, view
);
245 | TK_SELECT proplist TK_FROM id TK_WHERE expr
248 struct parser
*parser
= ctx
;
251 hr
= create_view
( $2, $4, $6, &view
);
255 PARSER_BUBBLE_UP_VIEW
( parser
, $$
, view
);
261 | prop TK_COMMA proplist
274 $$
= alloc_property
( ctx
, $1, $3 );
280 $$
= alloc_property
( ctx
, NULL
, $1 );
289 $$
= get_string
( ctx
, &$1 );
311 $$
= expr_complex
( ctx
, $1, OP_AND
, $3 );
317 $$
= expr_complex
( ctx
, $1, OP_OR
, $3 );
323 $$
= expr_unary
( ctx
, $2, OP_NOT
);
327 | prop_val TK_EQ const_val
329 $$
= expr_complex
( ctx
, $1, OP_EQ
, $3 );
333 | prop_val TK_GT const_val
335 $$
= expr_complex
( ctx
, $1, OP_GT
, $3 );
339 | prop_val TK_LT const_val
341 $$
= expr_complex
( ctx
, $1, OP_LT
, $3 );
345 | prop_val TK_LE const_val
347 $$
= expr_complex
( ctx
, $1, OP_LE
, $3 );
351 | prop_val TK_GE const_val
353 $$
= expr_complex
( ctx
, $1, OP_GE
, $3 );
357 | prop_val TK_NE const_val
359 $$
= expr_complex
( ctx
, $1, OP_NE
, $3 );
363 | const_val TK_EQ prop_val
365 $$
= expr_complex
( ctx
, $1, OP_EQ
, $3 );
369 | const_val TK_GT prop_val
371 $$
= expr_complex
( ctx
, $1, OP_GT
, $3 );
375 | const_val TK_LT prop_val
377 $$
= expr_complex
( ctx
, $1, OP_LT
, $3 );
381 | const_val TK_LE prop_val
383 $$
= expr_complex
( ctx
, $1, OP_LE
, $3 );
387 | const_val TK_GE prop_val
389 $$
= expr_complex
( ctx
, $1, OP_GE
, $3 );
393 | const_val TK_NE prop_val
395 $$
= expr_complex
( ctx
, $1, OP_NE
, $3 );
399 | prop_val TK_LIKE string_val
401 $$
= expr_complex
( ctx
, $1, OP_LIKE
, $3 );
405 | prop_val TK_IS TK_NULL
407 $$
= expr_unary
( ctx
, $1, OP_ISNULL
);
411 | prop_val TK_IS TK_NOT TK_NULL
413 $$
= expr_unary
( ctx
, $1, OP_NOTNULL
);
417 | prop_val TK_EQ TK_NULL
419 $$
= expr_unary
( ctx
, $1, OP_ISNULL
);
423 | TK_NULL TK_EQ prop_val
425 $$
= expr_unary
( ctx
, $3, OP_ISNULL
);
429 | prop_val TK_NE TK_NULL
431 $$
= expr_unary
( ctx
, $1, OP_NOTNULL
);
435 | TK_NULL TK_NE prop_val
437 $$
= expr_unary
( ctx
, $3, OP_NOTNULL
);
446 $$
= expr_sval
( ctx
, &$1 );
455 $$
= expr_propval
( ctx
, $1 );
464 $$
= expr_ival
( ctx
, $1 );
470 $$
= expr_sval
( ctx
, &$1 );
476 $$
= expr_bval
( ctx
, -1 );
482 $$
= expr_bval
( ctx
, 0 );
490 HRESULT parse_query
( const WCHAR
*str
, struct view
**view
, struct list
*mem
)
492 struct parser parser
;
500 parser.
error = WBEM_E_INVALID_QUERY
;
504 ret
= wql_parse
( &parser
);
505 TRACE
("wql_parse returned %d\n", ret
);
510 destroy_view
( *parser.view
);
518 static const char id_char
[] =
520 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
521 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
522 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
523 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
524 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
525 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
526 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
527 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
528 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
529 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
530 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
531 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
532 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
533 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
534 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
535 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
545 #define MAX_TOKEN_LEN 6
547 static const WCHAR andW
[] = {'A','N','D'};
548 static const WCHAR byW
[] = {'B','Y'};
549 static const WCHAR falseW
[] = {'F','A','L','S','E'};
550 static const WCHAR fromW
[] = {'F','R','O','M'};
551 static const WCHAR isW
[] = {'I','S'};
552 static const WCHAR likeW
[] = {'L','I','K','E'};
553 static const WCHAR notW
[] = {'N','O','T'};
554 static const WCHAR nullW
[] = {'N','U','L','L'};
555 static const WCHAR orW
[] = {'O','R'};
556 static const WCHAR selectW
[] = {'S','E','L','E','C','T'};
557 static const WCHAR trueW
[] = {'T','R','U','E'};
558 static const WCHAR whereW
[] = {'W','H','E','R','E'};
560 static const struct keyword keyword_table
[] =
562 { andW
, ARRAY_SIZE
(andW
), TK_AND
},
563 { byW
, ARRAY_SIZE
(byW
), TK_BY
},
564 { falseW
, ARRAY_SIZE
(falseW
), TK_FALSE
},
565 { fromW
, ARRAY_SIZE
(fromW
), TK_FROM
},
566 { isW
, ARRAY_SIZE
(isW
), TK_IS
},
567 { likeW
, ARRAY_SIZE
(likeW
), TK_LIKE
},
568 { notW
, ARRAY_SIZE
(notW
), TK_NOT
},
569 { nullW
, ARRAY_SIZE
(nullW
), TK_NULL
},
570 { orW
, ARRAY_SIZE
(orW
), TK_OR
},
571 { selectW
, ARRAY_SIZE
(selectW
), TK_SELECT
},
572 { trueW
, ARRAY_SIZE
(trueW
), TK_TRUE
},
573 { whereW
, ARRAY_SIZE
(whereW
), TK_WHERE
}
576 static int cmp_keyword
( const void *arg1
, const void *arg2
)
578 const struct keyword
*key1
= arg1
, *key2
= arg2
;
579 int len
= min
( key1
->len
, key2
->len
);
582 if
((ret
= memicmpW
( key1
->name
, key2
->name
, len
))) return ret
;
583 if
(key1
->len
< key2
->len
) return
-1;
584 else if
(key1
->len
> key2
->len
) return
1;
588 static int keyword_type
( const WCHAR
*str
, unsigned int len
)
590 struct keyword key
, *ret
;
592 if
(len
> MAX_TOKEN_LEN
) return TK_ID
;
597 ret
= bsearch
( &key
, keyword_table
, ARRAY_SIZE
(keyword_table
), sizeof
(struct keyword
), cmp_keyword
);
598 if
(ret
) return ret
->type
;
602 static int get_token
( const WCHAR
*s
, int *token
)
612 for
(i
= 1; isspaceW
( s
[i
] ); i
++) {}
616 if
(!s
[1]) return
-1;
637 else if
(s
[1] == '>')
674 for
(i
= 1; s
[i
]; i
++)
676 if
(s
[i
] == s
[0]) break
;
682 if
(!isdigitW
( s
[1] ))
688 case
'0': case
'1': case
'2': case
'3': case
'4':
689 case
'5': case
'6': case
'7': case
'8': case
'9':
691 for
(i
= 1; isdigitW
( s
[i
] ); i
++) {}
694 if
(!id_char
[*s
]) break
;
696 for
(i
= 1; id_char
[s
[i
]]; i
++) {}
697 *token
= keyword_type
( s
, i
);
704 static int wql_lex
( void *p
, struct parser
*parser
)
706 struct string *str
= p
;
710 parser
->idx
+= parser
->len
;
711 if
(!parser
->cmd
[parser
->idx
]) return
0;
712 parser
->len
= get_token
( &parser
->cmd
[parser
->idx
], &token
);
713 if
(!parser
->len
) break
;
715 str
->data
= &parser
->cmd
[parser
->idx
];
716 str
->len
= parser
->len
;
717 } while
(token
== TK_SPACE
);
721 static int wql_error
( struct parser
*parser
, const char *str
)