vbscript: Added RegExp2::Test implementation.
This commit is contained in:
parent
820c7635ab
commit
4b0f475344
|
@ -7,6 +7,7 @@ C_SRCS = \
|
||||||
global.c \
|
global.c \
|
||||||
interp.c \
|
interp.c \
|
||||||
lex.c \
|
lex.c \
|
||||||
|
regexp.c \
|
||||||
vbdisp.c \
|
vbdisp.c \
|
||||||
vbregexp.c \
|
vbregexp.c \
|
||||||
vbscript.c \
|
vbscript.c \
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 Jacek Caban 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Code in this file is based on files:
|
||||||
|
* js/src/jsregexp.h
|
||||||
|
* js/src/jsregexp.c
|
||||||
|
* from Mozilla project, released under LGPL 2.1 or later.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code, released
|
||||||
|
* March 31, 1998.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Netscape Communications Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define REG_FOLD 0x01 /* fold uppercase to lowercase */
|
||||||
|
#define REG_GLOB 0x02 /* global exec, creates array of matches */
|
||||||
|
#define REG_MULTILINE 0x04 /* treat ^ and $ as begin and end of line */
|
||||||
|
#define REG_STICKY 0x08 /* only match starting at lastIndex */
|
||||||
|
|
||||||
|
typedef struct RECapture {
|
||||||
|
ptrdiff_t index; /* start of contents, -1 for empty */
|
||||||
|
size_t length; /* length of capture */
|
||||||
|
} RECapture;
|
||||||
|
|
||||||
|
typedef struct match_state_t {
|
||||||
|
const WCHAR *cp;
|
||||||
|
DWORD match_len;
|
||||||
|
|
||||||
|
DWORD paren_count;
|
||||||
|
RECapture parens[1];
|
||||||
|
} match_state_t;
|
||||||
|
|
||||||
|
typedef BYTE jsbytecode;
|
||||||
|
|
||||||
|
typedef struct regexp_t {
|
||||||
|
WORD flags; /* flags, see jsapi.h's REG_* defines */
|
||||||
|
size_t parenCount; /* number of parenthesized submatches */
|
||||||
|
size_t classCount; /* count [...] bitmaps */
|
||||||
|
struct RECharSet *classList; /* list of [...] bitmaps */
|
||||||
|
const WCHAR *source; /* locked source string, sans // */
|
||||||
|
DWORD source_len;
|
||||||
|
jsbytecode program[1]; /* regular expression bytecode */
|
||||||
|
} regexp_t;
|
||||||
|
|
||||||
|
regexp_t* regexp_new(void*, heap_pool_t*, const WCHAR*, DWORD, WORD, BOOL) DECLSPEC_HIDDEN;
|
||||||
|
void regexp_destroy(regexp_t*) DECLSPEC_HIDDEN;
|
||||||
|
HRESULT regexp_execute(regexp_t*, void*, heap_pool_t*, const WCHAR*,
|
||||||
|
DWORD, match_state_t*) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
static inline match_state_t* alloc_match_state(regexp_t *regexp,
|
||||||
|
heap_pool_t *pool, const WCHAR *pos)
|
||||||
|
{
|
||||||
|
size_t size = offsetof(match_state_t, parens) + regexp->parenCount*sizeof(RECapture);
|
||||||
|
match_state_t *ret;
|
||||||
|
|
||||||
|
ret = pool ? heap_pool_alloc(pool, size) : heap_alloc(size);
|
||||||
|
if(!ret)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret->cp = pos;
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "vbscript.h"
|
#include "vbscript.h"
|
||||||
|
#include "regexp.h"
|
||||||
#include "vbsregexp55.h"
|
#include "vbsregexp55.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
@ -86,6 +87,9 @@ typedef struct {
|
||||||
LONG ref;
|
LONG ref;
|
||||||
|
|
||||||
WCHAR *pattern;
|
WCHAR *pattern;
|
||||||
|
regexp_t *regexp;
|
||||||
|
heap_pool_t pool;
|
||||||
|
WORD flags;
|
||||||
} RegExp2;
|
} RegExp2;
|
||||||
|
|
||||||
static inline RegExp2 *impl_from_IRegExp2(IRegExp2 *iface)
|
static inline RegExp2 *impl_from_IRegExp2(IRegExp2 *iface)
|
||||||
|
@ -138,6 +142,9 @@ static ULONG WINAPI RegExp2_Release(IRegExp2 *iface)
|
||||||
|
|
||||||
if(!ref) {
|
if(!ref) {
|
||||||
heap_free(This->pattern);
|
heap_free(This->pattern);
|
||||||
|
if(This->regexp)
|
||||||
|
regexp_destroy(This->regexp);
|
||||||
|
heap_pool_free(&This->pool);
|
||||||
heap_free(This);
|
heap_free(This);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +221,10 @@ static HRESULT WINAPI RegExp2_put_Pattern(IRegExp2 *iface, BSTR pattern)
|
||||||
|
|
||||||
if(!pattern) {
|
if(!pattern) {
|
||||||
heap_free(This->pattern);
|
heap_free(This->pattern);
|
||||||
|
if(This->regexp) {
|
||||||
|
regexp_destroy(This->regexp);
|
||||||
|
This->regexp = NULL;
|
||||||
|
}
|
||||||
This->pattern = NULL;
|
This->pattern = NULL;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -226,6 +237,10 @@ static HRESULT WINAPI RegExp2_put_Pattern(IRegExp2 *iface, BSTR pattern)
|
||||||
heap_free(This->pattern);
|
heap_free(This->pattern);
|
||||||
This->pattern = p;
|
This->pattern = p;
|
||||||
memcpy(p, pattern, size);
|
memcpy(p, pattern, size);
|
||||||
|
if(This->regexp) {
|
||||||
|
regexp_destroy(This->regexp);
|
||||||
|
This->regexp = NULL;
|
||||||
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,8 +297,43 @@ static HRESULT WINAPI RegExp2_Execute(IRegExp2 *iface,
|
||||||
static HRESULT WINAPI RegExp2_Test(IRegExp2 *iface, BSTR sourceString, VARIANT_BOOL *pMatch)
|
static HRESULT WINAPI RegExp2_Test(IRegExp2 *iface, BSTR sourceString, VARIANT_BOOL *pMatch)
|
||||||
{
|
{
|
||||||
RegExp2 *This = impl_from_IRegExp2(iface);
|
RegExp2 *This = impl_from_IRegExp2(iface);
|
||||||
FIXME("(%p)->(%s %p)\n", This, debugstr_w(sourceString), pMatch);
|
match_state_t *result;
|
||||||
return E_NOTIMPL;
|
heap_pool_t *mark;
|
||||||
|
HRESULT hres;
|
||||||
|
|
||||||
|
TRACE("(%p)->(%s %p)\n", This, debugstr_w(sourceString), pMatch);
|
||||||
|
|
||||||
|
if(!This->pattern) {
|
||||||
|
*pMatch = VARIANT_TRUE;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!This->regexp) {
|
||||||
|
This->regexp = regexp_new(NULL, &This->pool, This->pattern,
|
||||||
|
strlenW(This->pattern), This->flags, FALSE);
|
||||||
|
if(!This->regexp)
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mark = heap_pool_mark(&This->pool);
|
||||||
|
result = alloc_match_state(This->regexp, &This->pool, sourceString);
|
||||||
|
if(!result) {
|
||||||
|
heap_pool_clear(mark);
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
hres = regexp_execute(This->regexp, NULL, &This->pool,
|
||||||
|
sourceString, SysStringLen(sourceString), result);
|
||||||
|
|
||||||
|
heap_pool_clear(mark);
|
||||||
|
|
||||||
|
if(hres == S_OK) {
|
||||||
|
*pMatch = VARIANT_TRUE;
|
||||||
|
}else if(hres == S_FALSE) {
|
||||||
|
*pMatch = VARIANT_FALSE;
|
||||||
|
hres = S_OK;
|
||||||
|
}
|
||||||
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI RegExp2_Replace(IRegExp2 *iface, BSTR sourceString,
|
static HRESULT WINAPI RegExp2_Replace(IRegExp2 *iface, BSTR sourceString,
|
||||||
|
@ -466,6 +516,7 @@ HRESULT WINAPI VBScriptRegExpFactory_CreateInstance(IClassFactory *iface, IUnkno
|
||||||
ret->IRegExp_iface.lpVtbl = &RegExpVtbl;
|
ret->IRegExp_iface.lpVtbl = &RegExpVtbl;
|
||||||
|
|
||||||
ret->ref = 1;
|
ret->ref = 1;
|
||||||
|
heap_pool_init(&ret->pool);
|
||||||
|
|
||||||
hres = IRegExp2_QueryInterface(&ret->IRegExp2_iface, riid, ppv);
|
hres = IRegExp2_QueryInterface(&ret->IRegExp2_iface, riid, ppv);
|
||||||
IRegExp2_Release(&ret->IRegExp2_iface);
|
IRegExp2_Release(&ret->IRegExp2_iface);
|
||||||
|
|
|
@ -36,12 +36,16 @@ typedef struct {
|
||||||
DWORD block_cnt;
|
DWORD block_cnt;
|
||||||
DWORD last_block;
|
DWORD last_block;
|
||||||
DWORD offset;
|
DWORD offset;
|
||||||
|
BOOL mark;
|
||||||
struct list custom_blocks;
|
struct list custom_blocks;
|
||||||
} heap_pool_t;
|
} heap_pool_t;
|
||||||
|
|
||||||
void heap_pool_init(heap_pool_t*) DECLSPEC_HIDDEN;
|
void heap_pool_init(heap_pool_t*) DECLSPEC_HIDDEN;
|
||||||
void *heap_pool_alloc(heap_pool_t*,size_t) __WINE_ALLOC_SIZE(2) DECLSPEC_HIDDEN;
|
void *heap_pool_alloc(heap_pool_t*,size_t) __WINE_ALLOC_SIZE(2) DECLSPEC_HIDDEN;
|
||||||
|
void *heap_pool_grow(heap_pool_t*,void*,DWORD,DWORD) DECLSPEC_HIDDEN;
|
||||||
|
void heap_pool_clear(heap_pool_t*) DECLSPEC_HIDDEN;
|
||||||
void heap_pool_free(heap_pool_t*) DECLSPEC_HIDDEN;
|
void heap_pool_free(heap_pool_t*) DECLSPEC_HIDDEN;
|
||||||
|
heap_pool_t *heap_pool_mark(heap_pool_t*) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
typedef struct _function_t function_t;
|
typedef struct _function_t function_t;
|
||||||
typedef struct _vbscode_t vbscode_t;
|
typedef struct _vbscode_t vbscode_t;
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
|
WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
|
||||||
|
WINE_DECLARE_DEBUG_CHANNEL(heap);
|
||||||
|
|
||||||
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
|
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
|
||||||
|
|
||||||
|
@ -127,6 +128,7 @@ const char *debugstr_variant(const VARIANT *v)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MIN_BLOCK_SIZE 128
|
#define MIN_BLOCK_SIZE 128
|
||||||
|
#define ARENA_FREE_FILLER 0xaa
|
||||||
|
|
||||||
static inline DWORD block_size(DWORD block)
|
static inline DWORD block_size(DWORD block)
|
||||||
{
|
{
|
||||||
|
@ -194,19 +196,65 @@ void *heap_pool_alloc(heap_pool_t *heap, size_t size)
|
||||||
return list+1;
|
return list+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void heap_pool_free(heap_pool_t *heap)
|
void *heap_pool_grow(heap_pool_t *heap, void *mem, DWORD size, DWORD inc)
|
||||||
{
|
{
|
||||||
struct list *iter;
|
void *ret;
|
||||||
|
|
||||||
|
if(mem == (BYTE*)heap->blocks[heap->last_block] + heap->offset-size
|
||||||
|
&& heap->offset+inc < block_size(heap->last_block)) {
|
||||||
|
heap->offset += inc;
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = heap_pool_alloc(heap, size+inc);
|
||||||
|
if(ret) /* FIXME: avoid copying for custom blocks */
|
||||||
|
memcpy(ret, mem, size);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void heap_pool_clear(heap_pool_t *heap)
|
||||||
|
{
|
||||||
|
struct list *tmp;
|
||||||
|
|
||||||
|
if(!heap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while((tmp = list_next(&heap->custom_blocks, &heap->custom_blocks))) {
|
||||||
|
list_remove(tmp);
|
||||||
|
heap_free(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(WARN_ON(heap)) {
|
||||||
DWORD i;
|
DWORD i;
|
||||||
|
|
||||||
while((iter = list_next(&heap->custom_blocks, &heap->custom_blocks))) {
|
for(i=0; i < heap->block_cnt; i++)
|
||||||
list_remove(iter);
|
memset(heap->blocks[i], ARENA_FREE_FILLER, block_size(i));
|
||||||
heap_free(iter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
heap->last_block = heap->offset = 0;
|
||||||
|
heap->mark = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void heap_pool_free(heap_pool_t *heap)
|
||||||
|
{
|
||||||
|
DWORD i;
|
||||||
|
|
||||||
|
heap_pool_clear(heap);
|
||||||
|
|
||||||
for(i=0; i < heap->block_cnt; i++)
|
for(i=0; i < heap->block_cnt; i++)
|
||||||
heap_free(heap->blocks[i]);
|
heap_free(heap->blocks[i]);
|
||||||
heap_free(heap->blocks);
|
heap_free(heap->blocks);
|
||||||
|
|
||||||
|
heap_pool_init(heap);
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_pool_t *heap_pool_mark(heap_pool_t *heap)
|
||||||
|
{
|
||||||
|
if(heap->mark)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
heap->mark = TRUE;
|
||||||
|
return heap;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
|
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
|
||||||
|
|
Loading…
Reference in New Issue