Jacek Caban : vbscript: Added beginning bytecode compiler implementation.

Alexandre Julliard julliard at winehq.org
Wed Sep 7 12:35:30 CDT 2011


Module: wine
Branch: master
Commit: c674c7a7ae4e0d1e6022d16d7e70ac67d4961133
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c674c7a7ae4e0d1e6022d16d7e70ac67d4961133

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Sep  7 14:07:12 2011 +0200

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(-)

diff --git a/dlls/vbscript/Makefile.in b/dlls/vbscript/Makefile.in
index ba267f4..977bcde 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 0000000..c51dd97
--- /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 <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;
+}
diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c
index 53e90eb..ff9d2c9 100644
--- a/dlls/vbscript/vbscript.c
+++ b/dlls/vbscript/vbscript.c
@@ -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;
 }
 
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h
index 9c1d35c..88f7552 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);




More information about the wine-cvs mailing list