Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
f6be2110
Commit
f6be2110
authored
Jun 15, 2012
by
Hans Leidekker
Committed by
Alexandre Julliard
Jun 15, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wbemprox: Add support for parsing WQL queries.
parent
52363aef
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
879 additions
and
5 deletions
+879
-5
.gitignore
.gitignore
+2
-0
Makefile.in
dlls/wbemprox/Makefile.in
+3
-0
class.c
dlls/wbemprox/class.c
+4
-1
query.c
dlls/wbemprox/query.c
+87
-0
services.c
dlls/wbemprox/services.c
+9
-4
wbemprox_private.h
dlls/wbemprox/wbemprox_private.h
+76
-0
wql.y
dlls/wbemprox/wql.y
+698
-0
No files found.
.gitignore
View file @
f6be2110
...
...
@@ -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
...
...
dlls/wbemprox/Makefile.in
View file @
f6be2110
...
...
@@ -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@
dlls/wbemprox/class.c
View file @
f6be2110
...
...
@@ -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
;
...
...
dlls/wbemprox/query.c
0 → 100644
View file @
f6be2110
/*
* 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
;
}
dlls/wbemprox/services.c
View file @
f6be2110
...
...
@@ -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
;
...
...
dlls/wbemprox/wbemprox_private.h
View file @
f6be2110
...
...
@@ -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
)
...
...
dlls/wbemprox/wql.y
0 → 100644
View file @
f6be2110
%{
/*
* 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;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment