wbemprox: Add support for parsing WQL queries.
This commit is contained in:
parent
52363aef65
commit
f6be21103b
|
@ -135,6 +135,8 @@ dlls/vbscript/parser.tab.c
|
|||
dlls/vbscript/parser.tab.h
|
||||
dlls/vbscript/vbscript_classes.h
|
||||
dlls/vbscript/vbsglobal.h
|
||||
dlls/wbemprox/wql.tab.c
|
||||
dlls/wbemprox/wql.tab.h
|
||||
dlls/windowscodecs/windowscodecs_wincodec.h
|
||||
dlls/windowscodecs/windowscodecs_wincodec_p.c
|
||||
dlls/wshom.ocx/tests/wshom.h
|
||||
|
|
|
@ -4,9 +4,12 @@ IMPORTS = ole32 advapi32
|
|||
C_SRCS = \
|
||||
class.c \
|
||||
main.c \
|
||||
query.c \
|
||||
services.c \
|
||||
wbemlocator.c
|
||||
|
||||
IDL_R_SRCS = wbemprox.idl
|
||||
|
||||
BISON_SRCS = wql.y
|
||||
|
||||
@MAKE_DLL_RULES@
|
||||
|
|
|
@ -35,6 +35,7 @@ struct enum_class_object
|
|||
{
|
||||
IEnumWbemClassObject IEnumWbemClassObject_iface;
|
||||
LONG refs;
|
||||
struct query *query;
|
||||
};
|
||||
|
||||
static inline struct enum_class_object *impl_from_IEnumWbemClassObject(
|
||||
|
@ -58,6 +59,7 @@ static ULONG WINAPI enum_class_object_Release(
|
|||
if (!refs)
|
||||
{
|
||||
TRACE("destroying %p\n", ec);
|
||||
free_query( ec->query );
|
||||
heap_free( ec );
|
||||
}
|
||||
return refs;
|
||||
|
@ -143,7 +145,7 @@ static const IEnumWbemClassObjectVtbl enum_class_object_vtbl =
|
|||
};
|
||||
|
||||
HRESULT EnumWbemClassObject_create(
|
||||
IUnknown *pUnkOuter, LPVOID *ppObj )
|
||||
IUnknown *pUnkOuter, struct query *query, LPVOID *ppObj )
|
||||
{
|
||||
struct enum_class_object *ec;
|
||||
|
||||
|
@ -154,6 +156,7 @@ HRESULT EnumWbemClassObject_create(
|
|||
|
||||
ec->IEnumWbemClassObject_iface.lpVtbl = &enum_class_object_vtbl;
|
||||
ec->refs = 1;
|
||||
ec->query = query;
|
||||
|
||||
*ppObj = &ec->IEnumWbemClassObject_iface;
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright 2012 Hans Leidekker for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#define COBJMACROS
|
||||
|
||||
#include "config.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wbemcli.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
#include "wbemprox_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
|
||||
|
||||
HRESULT create_view( const struct property *proplist, const WCHAR *class,
|
||||
const struct expr *cond, struct view **ret )
|
||||
{
|
||||
struct view *view = heap_alloc( sizeof(struct view) );
|
||||
|
||||
if (!view) return E_OUTOFMEMORY;
|
||||
view->proplist = proplist;
|
||||
view->cond = cond;
|
||||
*ret = view;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void destroy_view( struct view *view )
|
||||
{
|
||||
heap_free( view );
|
||||
}
|
||||
|
||||
static struct query *alloc_query(void)
|
||||
{
|
||||
struct query *query;
|
||||
|
||||
if (!(query = heap_alloc( sizeof(*query) ))) return NULL;
|
||||
list_init( &query->mem );
|
||||
return query;
|
||||
}
|
||||
|
||||
void free_query( struct query *query )
|
||||
{
|
||||
struct list *mem, *next;
|
||||
|
||||
destroy_view( query->view );
|
||||
LIST_FOR_EACH_SAFE( mem, next, &query->mem )
|
||||
{
|
||||
heap_free( mem );
|
||||
}
|
||||
heap_free( query );
|
||||
}
|
||||
|
||||
HRESULT exec_query( const WCHAR *str, IEnumWbemClassObject **result )
|
||||
{
|
||||
HRESULT hr;
|
||||
struct query *query;
|
||||
|
||||
*result = NULL;
|
||||
if (!(query = alloc_query())) return E_OUTOFMEMORY;
|
||||
hr = parse_query( str, &query->view, &query->mem );
|
||||
if (hr != S_OK)
|
||||
{
|
||||
free_query( query );
|
||||
return hr;
|
||||
}
|
||||
hr = EnumWbemClassObject_create( NULL, query, (void **)result );
|
||||
if (hr != S_OK) free_query( query );
|
||||
return hr;
|
||||
}
|
|
@ -158,7 +158,7 @@ static ULONG WINAPI wbem_services_Release(
|
|||
if (!refs)
|
||||
{
|
||||
TRACE("destroying %p\n", ws);
|
||||
HeapFree( GetProcessHeap(), 0, ws );
|
||||
heap_free( ws );
|
||||
}
|
||||
return refs;
|
||||
}
|
||||
|
@ -383,9 +383,14 @@ static HRESULT WINAPI wbem_services_ExecQuery(
|
|||
IWbemContext *pCtx,
|
||||
IEnumWbemClassObject **ppEnum )
|
||||
{
|
||||
FIXME("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage),
|
||||
static const WCHAR wqlW[] = {'W','Q','L',0};
|
||||
|
||||
TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage),
|
||||
debugstr_w(strQuery), lFlags, pCtx, ppEnum);
|
||||
return WBEM_E_FAILED;
|
||||
|
||||
if (!strQueryLanguage || !strQuery) return WBEM_E_INVALID_PARAMETER;
|
||||
if (strcmpiW( strQueryLanguage, wqlW )) return WBEM_E_INVALID_QUERY_TYPE;
|
||||
return exec_query( strQuery, ppEnum );
|
||||
}
|
||||
|
||||
static HRESULT WINAPI wbem_services_ExecQueryAsync(
|
||||
|
@ -487,7 +492,7 @@ HRESULT WbemServices_create( IUnknown *pUnkOuter, LPVOID *ppObj )
|
|||
|
||||
TRACE("(%p,%p)\n", pUnkOuter, ppObj);
|
||||
|
||||
ws = HeapAlloc( GetProcessHeap(), 0, sizeof(*ws) );
|
||||
ws = heap_alloc( sizeof(*ws) );
|
||||
if (!ws) return E_OUTOFMEMORY;
|
||||
|
||||
ws->IWbemServices_iface.lpVtbl = &wbem_services_vtbl;
|
||||
|
|
|
@ -16,8 +16,84 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "wine/list.h"
|
||||
|
||||
#define SIZEOF(array) (sizeof(array)/sizeof((array)[0]))
|
||||
|
||||
struct property
|
||||
{
|
||||
const WCHAR *name;
|
||||
const WCHAR *class;
|
||||
const struct property *next;
|
||||
};
|
||||
|
||||
enum operator
|
||||
{
|
||||
OP_EQ = 1,
|
||||
OP_AND = 2,
|
||||
OP_OR = 3,
|
||||
OP_GT = 4,
|
||||
OP_LT = 5,
|
||||
OP_LE = 6,
|
||||
OP_GE = 7,
|
||||
OP_NE = 8,
|
||||
OP_ISNULL = 9,
|
||||
OP_NOTNULL = 10,
|
||||
OP_LIKE = 11
|
||||
};
|
||||
|
||||
struct expr;
|
||||
struct complex_expr
|
||||
{
|
||||
enum operator op;
|
||||
struct expr *left;
|
||||
struct expr *right;
|
||||
};
|
||||
|
||||
enum expr_type
|
||||
{
|
||||
EXPR_COMPLEX = 1,
|
||||
EXPR_UNARY = 2,
|
||||
EXPR_PROPVAL = 3,
|
||||
EXPR_SVAL = 4,
|
||||
EXPR_IVAL = 5,
|
||||
EXPR_BVAL = 6
|
||||
};
|
||||
|
||||
struct expr
|
||||
{
|
||||
enum expr_type type;
|
||||
union
|
||||
{
|
||||
struct complex_expr expr;
|
||||
const struct property *propval;
|
||||
const WCHAR *sval;
|
||||
int ival;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct view
|
||||
{
|
||||
const struct property *proplist;
|
||||
const struct expr *cond;
|
||||
};
|
||||
|
||||
struct query
|
||||
{
|
||||
struct view *view;
|
||||
struct list mem;
|
||||
};
|
||||
|
||||
void free_query( struct query * ) DECLSPEC_HIDDEN;
|
||||
HRESULT exec_query( const WCHAR *, IEnumWbemClassObject ** ) DECLSPEC_HIDDEN;
|
||||
HRESULT parse_query( const WCHAR *, struct view **, struct list * ) DECLSPEC_HIDDEN;
|
||||
HRESULT create_view( const struct property *, const WCHAR *, const struct expr *,
|
||||
struct view ** ) DECLSPEC_HIDDEN;
|
||||
void destroy_view( struct view * ) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT WbemLocator_create(IUnknown *, LPVOID *) DECLSPEC_HIDDEN;
|
||||
HRESULT WbemServices_create(IUnknown *, LPVOID *) DECLSPEC_HIDDEN;
|
||||
HRESULT EnumWbemClassObject_create(IUnknown *, struct query *, LPVOID *) DECLSPEC_HIDDEN;
|
||||
|
||||
static void *heap_alloc( size_t len ) __WINE_ALLOC_SIZE(1);
|
||||
static inline void *heap_alloc( size_t len )
|
||||
|
|
|
@ -0,0 +1,698 @@
|
|||
%{
|
||||
|
||||
/*
|
||||
* Copyright 2012 Hans Leidekker for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wbemcli.h"
|
||||
#include "wbemprox_private.h"
|
||||
|
||||
#include "wine/list.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
#define YYLEX_PARAM ctx
|
||||
#define YYPARSE_PARAM ctx
|
||||
#define YYERROR_DEBUG 1
|
||||
#define YYERROR_VERBOSE 1
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
|
||||
|
||||
struct parser
|
||||
{
|
||||
const WCHAR *cmd;
|
||||
UINT idx;
|
||||
UINT len;
|
||||
HRESULT error;
|
||||
struct view **view;
|
||||
struct list *mem;
|
||||
};
|
||||
|
||||
struct string
|
||||
{
|
||||
const WCHAR *data;
|
||||
int len;
|
||||
};
|
||||
|
||||
static void *alloc_mem( struct parser *parser, UINT size )
|
||||
{
|
||||
struct list *mem = heap_alloc( sizeof(struct list) + size );
|
||||
list_add_tail( parser->mem, mem );
|
||||
return &mem[1];
|
||||
}
|
||||
|
||||
static struct property *alloc_property( struct parser *parser, const WCHAR *class, const WCHAR *name )
|
||||
{
|
||||
struct property *prop = alloc_mem( parser, sizeof(*prop) );
|
||||
if (prop)
|
||||
{
|
||||
prop->name = name;
|
||||
prop->class = class;
|
||||
prop->next = NULL;
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
static WCHAR *get_string( struct parser *parser, const struct string *str )
|
||||
{
|
||||
const WCHAR *p = str->data;
|
||||
int len = str->len;
|
||||
WCHAR *ret;
|
||||
|
||||
if ((p[0] == '\"' && p[len - 1] != '\"') ||
|
||||
(p[0] == '\'' && p[len - 1] != '\'')) return NULL;
|
||||
if ((p[0] == '\"' && p[len - 1] == '\"') ||
|
||||
(p[0] == '\'' && p[len - 1] == '\''))
|
||||
{
|
||||
p++;
|
||||
len -= 2;
|
||||
}
|
||||
if (!(ret = alloc_mem( parser, (len + 1) * sizeof(WCHAR) ))) return NULL;
|
||||
memcpy( ret, p, len * sizeof(WCHAR) );
|
||||
ret[len] = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_int( struct parser *parser )
|
||||
{
|
||||
const WCHAR *p = &parser->cmd[parser->idx];
|
||||
int i, ret = 0;
|
||||
|
||||
for (i = 0; i < parser->len; i++)
|
||||
{
|
||||
if (p[i] < '0' || p[i] > '9')
|
||||
{
|
||||
ERR("should only be numbers here!\n");
|
||||
break;
|
||||
}
|
||||
ret = (p[i] - '0') + ret * 10;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct expr *expr_complex( struct parser *parser, struct expr *l, UINT op, struct expr *r )
|
||||
{
|
||||
struct expr *e = alloc_mem( parser, sizeof(*e) );
|
||||
if (e)
|
||||
{
|
||||
e->type = EXPR_COMPLEX;
|
||||
e->u.expr.left = l;
|
||||
e->u.expr.op = op;
|
||||
e->u.expr.right = r;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
static struct expr *expr_unary( struct parser *parser, struct expr *l, UINT op )
|
||||
{
|
||||
struct expr *e = alloc_mem( parser, sizeof(*e) );
|
||||
if (e)
|
||||
{
|
||||
e->type = EXPR_UNARY;
|
||||
e->u.expr.left = l;
|
||||
e->u.expr.op = op;
|
||||
e->u.expr.right = NULL;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
static struct expr *expr_ival( struct parser *parser, int val )
|
||||
{
|
||||
struct expr *e = alloc_mem( parser, sizeof *e );
|
||||
if (e)
|
||||
{
|
||||
e->type = EXPR_IVAL;
|
||||
e->u.ival = val;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
static struct expr *expr_sval( struct parser *parser, const struct string *str )
|
||||
{
|
||||
struct expr *e = alloc_mem( parser, sizeof *e );
|
||||
if (e)
|
||||
{
|
||||
e->type = EXPR_SVAL;
|
||||
e->u.sval = get_string( parser, str );
|
||||
if (!e->u.sval)
|
||||
return NULL; /* e will be freed by query destructor */
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
static struct expr *expr_bval( struct parser *parser, int val )
|
||||
{
|
||||
struct expr *e = alloc_mem( parser, sizeof *e );
|
||||
if (e)
|
||||
{
|
||||
e->type = EXPR_BVAL;
|
||||
e->u.ival = val;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
static struct expr *expr_propval( struct parser *parser, const struct property *prop )
|
||||
{
|
||||
struct expr *e = alloc_mem( parser, sizeof *e );
|
||||
if (e)
|
||||
{
|
||||
e->type = EXPR_PROPVAL;
|
||||
e->u.propval = prop;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
static int wql_error( const char *str );
|
||||
static int wql_lex( void *val, struct parser *parser );
|
||||
|
||||
#define PARSER_BUBBLE_UP_VIEW( parser, result, current_view ) \
|
||||
*parser->view = current_view; \
|
||||
result = current_view
|
||||
|
||||
%}
|
||||
|
||||
%pure-parser
|
||||
|
||||
%union
|
||||
{
|
||||
struct string str;
|
||||
WCHAR *string;
|
||||
struct property *proplist;
|
||||
struct view *view;
|
||||
struct expr *expr;
|
||||
int integer;
|
||||
}
|
||||
|
||||
%token TK_SELECT TK_FROM TK_STAR TK_COMMA TK_DOT TK_IS TK_LP TK_RP TK_NULL TK_FALSE TK_TRUE
|
||||
%token TK_INTEGER TK_WHERE TK_SPACE TK_MINUS TK_ILLEGAL TK_BY
|
||||
%token <str> TK_STRING TK_ID
|
||||
|
||||
%type <string> id
|
||||
%type <proplist> prop proplist
|
||||
%type <view> select
|
||||
%type <expr> expr prop_val const_val string_val
|
||||
%type <integer> number
|
||||
|
||||
%left TK_OR
|
||||
%left TK_AND
|
||||
%left TK_NOT
|
||||
%left TK_EQ TK_NE TK_LT TK_GT TK_LE TK_GE TK_LIKE
|
||||
|
||||
%%
|
||||
|
||||
select:
|
||||
TK_SELECT TK_FROM id
|
||||
{
|
||||
HRESULT hr;
|
||||
struct parser *parser = ctx;
|
||||
struct view *view;
|
||||
|
||||
hr = create_view( NULL, $3, NULL, &view );
|
||||
if (hr != S_OK)
|
||||
YYABORT;
|
||||
|
||||
PARSER_BUBBLE_UP_VIEW( parser, $$, view );
|
||||
}
|
||||
| TK_SELECT proplist TK_FROM id
|
||||
{
|
||||
HRESULT hr;
|
||||
struct parser *parser = ctx;
|
||||
struct view *view;
|
||||
|
||||
hr = create_view( $2, $4, NULL, &view );
|
||||
if (hr != S_OK)
|
||||
YYABORT;
|
||||
|
||||
PARSER_BUBBLE_UP_VIEW( parser, $$, view );
|
||||
}
|
||||
| TK_SELECT proplist TK_FROM id TK_WHERE expr
|
||||
{
|
||||
HRESULT hr;
|
||||
struct parser *parser = ctx;
|
||||
struct view *view;
|
||||
|
||||
hr = create_view( $2, $4, $6, &view );
|
||||
if (hr != S_OK)
|
||||
YYABORT;
|
||||
|
||||
PARSER_BUBBLE_UP_VIEW( parser, $$, view );
|
||||
}
|
||||
;
|
||||
|
||||
proplist:
|
||||
prop
|
||||
| prop TK_COMMA proplist
|
||||
{
|
||||
$1->next = $3;
|
||||
}
|
||||
| TK_STAR
|
||||
{
|
||||
$$ = NULL;
|
||||
}
|
||||
;
|
||||
|
||||
prop:
|
||||
id TK_DOT id
|
||||
{
|
||||
$$ = alloc_property( ctx, $1, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| id
|
||||
{
|
||||
$$ = alloc_property( ctx, NULL, $1 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
id:
|
||||
TK_ID
|
||||
{
|
||||
$$ = get_string( ctx, &$1 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
number:
|
||||
TK_INTEGER
|
||||
{
|
||||
$$ = get_int( ctx );
|
||||
}
|
||||
;
|
||||
|
||||
expr:
|
||||
TK_LP expr TK_RP
|
||||
{
|
||||
$$ = $2;
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| expr TK_AND expr
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_AND, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| expr TK_OR expr
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_OR, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| prop_val TK_EQ const_val
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_EQ, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| prop_val TK_GT const_val
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_GT, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| prop_val TK_LT const_val
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_LT, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| prop_val TK_LE const_val
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_LE, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| prop_val TK_GE const_val
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_GE, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| prop_val TK_NE const_val
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_NE, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| const_val TK_EQ prop_val
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_EQ, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| const_val TK_GT prop_val
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_GT, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| const_val TK_LT prop_val
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_LT, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| const_val TK_LE prop_val
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_LE, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| const_val TK_GE prop_val
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_GE, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| const_val TK_NE prop_val
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_NE, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| prop_val TK_LIKE string_val
|
||||
{
|
||||
$$ = expr_complex( ctx, $1, OP_LIKE, $3 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| prop_val TK_IS TK_NULL
|
||||
{
|
||||
$$ = expr_unary( ctx, $1, OP_ISNULL );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| prop_val TK_IS TK_NOT TK_NULL
|
||||
{
|
||||
$$ = expr_unary( ctx, $1, OP_NOTNULL );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
string_val:
|
||||
TK_STRING
|
||||
{
|
||||
$$ = expr_sval( ctx, &$1 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
prop_val:
|
||||
prop
|
||||
{
|
||||
$$ = expr_propval( ctx, $1 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
const_val:
|
||||
number
|
||||
{
|
||||
$$ = expr_ival( ctx, $1 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| TK_STRING
|
||||
{
|
||||
$$ = expr_sval( ctx, &$1 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| TK_TRUE
|
||||
{
|
||||
$$ = expr_bval( ctx, -1 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
| TK_FALSE
|
||||
{
|
||||
$$ = expr_bval( ctx, 0 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
HRESULT parse_query( const WCHAR *str, struct view **view, struct list *mem )
|
||||
{
|
||||
struct parser parser;
|
||||
int ret;
|
||||
|
||||
*view = NULL;
|
||||
|
||||
parser.cmd = str;
|
||||
parser.idx = 0;
|
||||
parser.len = 0;
|
||||
parser.error = WBEM_E_INVALID_QUERY;
|
||||
parser.view = view;
|
||||
parser.mem = mem;
|
||||
|
||||
ret = wql_parse( &parser );
|
||||
TRACE("wql_parse returned %d\n", ret);
|
||||
if (ret)
|
||||
{
|
||||
if (*parser.view)
|
||||
{
|
||||
destroy_view( *parser.view );
|
||||
*parser.view = NULL;
|
||||
}
|
||||
return parser.error;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const char id_char[] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
};
|
||||
|
||||
struct keyword
|
||||
{
|
||||
const WCHAR *name;
|
||||
unsigned int len;
|
||||
int type;
|
||||
};
|
||||
|
||||
#define MAX_TOKEN_LEN 6
|
||||
|
||||
static const WCHAR andW[] = {'A','N','D'};
|
||||
static const WCHAR byW[] = {'B','Y'};
|
||||
static const WCHAR falseW[] = {'F','A','L','S','E'};
|
||||
static const WCHAR fromW[] = {'F','R','O','M'};
|
||||
static const WCHAR isW[] = {'I','S'};
|
||||
static const WCHAR likeW[] = {'L','I','K','E'};
|
||||
static const WCHAR notW[] = {'N','O','T'};
|
||||
static const WCHAR nullW[] = {'N','U','L','L'};
|
||||
static const WCHAR orW[] = {'O','R'};
|
||||
static const WCHAR selectW[] = {'S','E','L','E','C','T'};
|
||||
static const WCHAR trueW[] = {'T','R','U','E'};
|
||||
static const WCHAR whereW[] = {'W','H','E','R','E'};
|
||||
|
||||
static const struct keyword keyword_table[] =
|
||||
{
|
||||
{ andW, SIZEOF(andW), TK_AND },
|
||||
{ byW, SIZEOF(byW), TK_BY },
|
||||
{ falseW, SIZEOF(falseW), TK_FALSE },
|
||||
{ fromW, SIZEOF(fromW), TK_FROM },
|
||||
{ isW, SIZEOF(isW), TK_IS },
|
||||
{ likeW, SIZEOF(likeW), TK_LIKE },
|
||||
{ notW, SIZEOF(notW), TK_NOT },
|
||||
{ nullW, SIZEOF(nullW), TK_NULL },
|
||||
{ orW, SIZEOF(orW), TK_OR },
|
||||
{ selectW, SIZEOF(selectW), TK_SELECT },
|
||||
{ trueW, SIZEOF(trueW), TK_TRUE },
|
||||
{ whereW, SIZEOF(whereW), TK_WHERE }
|
||||
};
|
||||
|
||||
static int cmp_keyword( const void *arg1, const void *arg2 )
|
||||
{
|
||||
const struct keyword *key1 = arg1, *key2 = arg2;
|
||||
int len = min( key1->len, key2->len );
|
||||
int ret;
|
||||
|
||||
if ((ret = memicmpW( key1->name, key2->name, len ))) return ret;
|
||||
if (key1->len < key2->len) return -1;
|
||||
else if (key1->len > key2->len) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int keyword_type( const WCHAR *str, unsigned int len )
|
||||
{
|
||||
struct keyword key, *ret;
|
||||
|
||||
if (len > MAX_TOKEN_LEN) return TK_ID;
|
||||
|
||||
key.name = str;
|
||||
key.len = len;
|
||||
key.type = 0;
|
||||
ret = bsearch( &key, keyword_table, SIZEOF(keyword_table), sizeof(struct keyword), cmp_keyword );
|
||||
if (ret) return ret->type;
|
||||
return TK_ID;
|
||||
}
|
||||
|
||||
static int get_token( const WCHAR *s, int *token )
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (*s)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
for (i = 1; isspaceW( s[i] ); i++) {}
|
||||
*token = TK_SPACE;
|
||||
return i;
|
||||
case '-':
|
||||
if (!s[1]) return -1;
|
||||
*token = TK_MINUS;
|
||||
return 1;
|
||||
case '(':
|
||||
*token = TK_LP;
|
||||
return 1;
|
||||
case ')':
|
||||
*token = TK_RP;
|
||||
return 1;
|
||||
case '*':
|
||||
*token = TK_STAR;
|
||||
return 1;
|
||||
case '=':
|
||||
*token = TK_EQ;
|
||||
return 1;
|
||||
case '<':
|
||||
if (s[1] == '=' )
|
||||
{
|
||||
*token = TK_LE;
|
||||
return 2;
|
||||
}
|
||||
else if (s[1] == '>')
|
||||
{
|
||||
*token = TK_NE;
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*token = TK_LT;
|
||||
return 1;
|
||||
}
|
||||
case '>':
|
||||
if (s[1] == '=')
|
||||
{
|
||||
*token = TK_GE;
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*token = TK_GT;
|
||||
return 1;
|
||||
}
|
||||
case '!':
|
||||
if (s[1] != '=')
|
||||
{
|
||||
*token = TK_ILLEGAL;
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*token = TK_NE;
|
||||
return 2;
|
||||
}
|
||||
case ',':
|
||||
*token = TK_COMMA;
|
||||
return 1;
|
||||
case '\"':
|
||||
case '\'':
|
||||
{
|
||||
for (i = 1; s[i]; i++)
|
||||
{
|
||||
if (s[i] == s[0]) break;
|
||||
}
|
||||
if (s[i]) i++;
|
||||
*token = TK_STRING;
|
||||
return i;
|
||||
}
|
||||
case '.':
|
||||
if (!isdigitW( s[1] ))
|
||||
{
|
||||
*token = TK_DOT;
|
||||
return 1;
|
||||
}
|
||||
/* fall through */
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
*token = TK_INTEGER;
|
||||
for (i = 1; isdigitW( s[i] ); i++) {}
|
||||
return i;
|
||||
default:
|
||||
if (!id_char[*s]) break;
|
||||
|
||||
for (i = 1; id_char[s[i]]; i++) {}
|
||||
*token = keyword_type( s, i );
|
||||
return i;
|
||||
}
|
||||
*token = TK_ILLEGAL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int wql_lex( void *p, struct parser *parser )
|
||||
{
|
||||
struct string *str = p;
|
||||
int token = -1;
|
||||
do
|
||||
{
|
||||
parser->idx += parser->len;
|
||||
if (!parser->cmd[parser->idx]) return 0;
|
||||
parser->len = get_token( &parser->cmd[parser->idx], &token );
|
||||
if (!parser->len) break;
|
||||
|
||||
str->data = &parser->cmd[parser->idx];
|
||||
str->len = parser->len;
|
||||
} while (token == TK_SPACE);
|
||||
return token;
|
||||
}
|
||||
|
||||
static int wql_error( const char *str )
|
||||
{
|
||||
ERR("%s\n", str);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue