From c674c7a7ae4e0d1e6022d16d7e70ac67d4961133 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 7 Sep 2011 14:07:12 +0200 Subject: [PATCH] vbscript: Added beginning bytecode compiler implementation. --- dlls/vbscript/Makefile.in | 1 + dlls/vbscript/compile.c | 125 ++++++++++++++++++++++++++++++++++++++ dlls/vbscript/vbscript.c | 15 +++-- dlls/vbscript/vbscript.h | 41 +++++++++++++ 4 files changed, 177 insertions(+), 5 deletions(-) create mode 100644 dlls/vbscript/compile.c diff --git a/dlls/vbscript/Makefile.in b/dlls/vbscript/Makefile.in index ba267f4f9b0..977bcde9e36 100644 --- a/dlls/vbscript/Makefile.in +++ b/dlls/vbscript/Makefile.in @@ -1,6 +1,7 @@ MODULE = vbscript.dll C_SRCS = \ + compile.c \ lex.c \ vbdisp.c \ vbscript.c \ diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c new file mode 100644 index 00000000000..c51dd97641a --- /dev/null +++ b/dlls/vbscript/compile.c @@ -0,0 +1,125 @@ +/* + * Copyright 2011 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 + */ + +#include + +#include "vbscript.h" +#include "parse.h" +#include "parser.tab.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(vbscript); + +typedef struct { + parser_ctx_t parser; + + unsigned instr_cnt; + unsigned instr_size; + vbscode_t *code; +} compile_ctx_t; + +static unsigned push_instr(compile_ctx_t *ctx, vbsop_t op) +{ + assert(ctx->instr_size && ctx->instr_size >= ctx->instr_cnt); + + if(ctx->instr_size == ctx->instr_cnt) { + instr_t *new_instr; + + new_instr = heap_realloc(ctx->code->instrs, ctx->instr_size*2*sizeof(instr_t)); + if(!new_instr) + return -1; + + ctx->code->instrs = new_instr; + ctx->instr_size *= 2; + } + + ctx->code->instrs[ctx->instr_cnt].op = op; + return ctx->instr_cnt++; +} + +static HRESULT compile_func(compile_ctx_t *ctx, function_t *func) +{ + func->code_off = ctx->instr_cnt; + + if(push_instr(ctx, OP_ret) == -1) + return E_OUTOFMEMORY; + + return S_OK; +} + +void release_vbscode(vbscode_t *code) +{ + list_remove(&code->entry); + heap_free(code->source); + heap_free(code->instrs); + heap_free(code); +} + +static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source) +{ + vbscode_t *ret; + + ret = heap_alloc(sizeof(*ret)); + if(!ret) + return NULL; + + ret->source = heap_strdupW(source); + if(!ret->source) { + heap_free(ret); + return NULL; + } + + ret->instrs = heap_alloc(32*sizeof(instr_t)); + if(!ret->instrs) { + release_vbscode(ret); + return NULL; + } + + ctx->instr_cnt = 0; + ctx->instr_size = 32; + + ret->global_code.code_ctx = ret; + + list_init(&ret->entry); + return ret; +} + +HRESULT compile_script(script_ctx_t *script, const WCHAR *src, vbscode_t **ret) +{ + compile_ctx_t ctx; + HRESULT hres; + + hres = parse_script(&ctx.parser, src); + if(FAILED(hres)) + return hres; + + ctx.code = alloc_vbscode(&ctx, src); + if(!ctx.code) + return E_OUTOFMEMORY; + + hres = compile_func(&ctx, &ctx.code->global_code); + if(FAILED(hres)) { + release_vbscode(ctx.code); + return hres; + } + + list_add_tail(&script->code_list, &ctx.code->entry); + *ret = ctx.code; + return S_OK; +} diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index 53e90eb8fd3..ff9d2c9e214 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -20,8 +20,6 @@ #include #include "vbscript.h" -#include "parse.h" - #include "objsafe.h" #include "wine/debug.h" @@ -89,6 +87,9 @@ static HRESULT set_ctx_site(VBScript *This) static void destroy_script(script_ctx_t *ctx) { + while(!list_empty(&ctx->code_list)) + release_vbscode(LIST_ENTRY(list_head(&ctx->code_list), vbscode_t, entry)); + while(!list_empty(&ctx->named_items)) { named_item_t *iter = LIST_ENTRY(list_head(&ctx->named_items), named_item_t, entry); @@ -483,6 +484,7 @@ static HRESULT WINAPI VBScriptParse_InitNew(IActiveScriptParse *iface) if(!ctx) return E_OUTOFMEMORY; + list_init(&ctx->code_list); list_init(&ctx->named_items); old_ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL); @@ -514,18 +516,21 @@ static HRESULT WINAPI VBScriptParse_ParseScriptText(IActiveScriptParse *iface, DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo) { VBScript *This = impl_from_IActiveScriptParse(iface); - parser_ctx_t parser; + vbscode_t *code; HRESULT hres; TRACE("(%p)->(%s %s %p %s %s %u %x %p %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter), wine_dbgstr_longlong(dwSourceContextCookie), ulStartingLine, dwFlags, pvarResult, pexcepinfo); - hres = parse_script(&parser, pstrCode); + if(This->thread_id != GetCurrentThreadId() || This->state == SCRIPTSTATE_CLOSED) + return E_UNEXPECTED; + + hres = compile_script(This->ctx, pstrCode, &code); if(FAILED(hres)) return hres; - FIXME("compiling script not implemented\n"); + FIXME("executing script not implemented\n"); return E_NOTIMPL; } diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index 9c1d35c09a6..88f7552cee3 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -31,6 +31,9 @@ #include "wine/list.h" #include "wine/unicode.h" +typedef struct _function_t function_t; +typedef struct _vbscode_t vbscode_t; + typedef struct named_item_t { IDispatch *disp; DWORD flags; @@ -53,11 +56,44 @@ typedef struct { vbdisp_t *script_obj; + struct list code_list; struct list named_items; } script_ctx_t; HRESULT init_global(script_ctx_t*); +#define OP_LIST \ + X(ret, 0) + +typedef enum { +#define X(x,n) OP_##x, +OP_LIST +#undef X + OP_LAST +} vbsop_t; + +typedef struct { + vbsop_t op; +} instr_t; + +struct _function_t { + unsigned code_off; + vbscode_t *code_ctx; +}; + +struct _vbscode_t { + instr_t *instrs; + WCHAR *source; + + BOOL global_executed; + function_t global_code; + + struct list entry; +}; + +void release_vbscode(vbscode_t*) DECLSPEC_HIDDEN; +HRESULT compile_script(script_ctx_t*,const WCHAR*,vbscode_t**) DECLSPEC_HIDDEN; + HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**); static inline void *heap_alloc(size_t len) @@ -70,6 +106,11 @@ static inline void *heap_alloc_zero(size_t len) return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); } +static inline void *heap_realloc(void *mem, size_t len) +{ + return HeapReAlloc(GetProcessHeap(), 0, mem, len); +} + static inline BOOL heap_free(void *mem) { return HeapFree(GetProcessHeap(), 0, mem);