vbscript: Added beginning bytecode compiler implementation.

This commit is contained in:
Jacek Caban 2011-09-07 14:07:12 +02:00 committed by Alexandre Julliard
parent a28ddddcbc
commit c674c7a7ae
4 changed files with 177 additions and 5 deletions

View File

@ -1,6 +1,7 @@
MODULE = vbscript.dll
C_SRCS = \
compile.c \
lex.c \
vbdisp.c \
vbscript.c \

125
dlls/vbscript/compile.c Normal file
View File

@ -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 <assert.h>
#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;
}

View File

@ -20,8 +20,6 @@
#include <assert.h>
#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;
}

View File

@ -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);