vbscript: Added beginning bytecode compiler implementation.
This commit is contained in:
parent
a28ddddcbc
commit
c674c7a7ae
|
@ -1,6 +1,7 @@
|
|||
MODULE = vbscript.dll
|
||||
|
||||
C_SRCS = \
|
||||
compile.c \
|
||||
lex.c \
|
||||
vbdisp.c \
|
||||
vbscript.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 <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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue