Jacek Caban : vbscript: Added support for sub local variables.

Alexandre Julliard julliard at winehq.org
Wed Sep 14 12:25:40 CDT 2011


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

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

vbscript: Added support for sub local variables.

---

 dlls/vbscript/compile.c      |   37 ++++++++++++++++++++++++++++++++++---
 dlls/vbscript/interp.c       |   29 +++++++++++++++++++++++++++--
 dlls/vbscript/tests/lang.vbs |   11 +++++++++++
 dlls/vbscript/vbscript.h     |    6 ++++++
 4 files changed, 78 insertions(+), 5 deletions(-)

diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index 84a97a7..dd756b3 100644
--- a/dlls/vbscript/compile.c
+++ b/dlls/vbscript/compile.c
@@ -500,12 +500,24 @@ static BOOL lookup_dim_decls(compile_ctx_t *ctx, const WCHAR *name)
     return FALSE;
 }
 
+static BOOL lookup_args_name(compile_ctx_t *ctx, const WCHAR *name)
+{
+    unsigned i;
+
+    for(i = 0; i < ctx->func->arg_cnt; i++) {
+        if(!strcmpiW(ctx->func->args[i].name, name))
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
 static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat)
 {
     dim_decl_t *dim_decl = stat->dim_decls;
 
     while(1) {
-        if(lookup_dim_decls(ctx, dim_decl->name)) {
+        if(lookup_dim_decls(ctx, dim_decl->name) || lookup_args_name(ctx, dim_decl->name)) {
             FIXME("dim %s name redefined\n", debugstr_w(dim_decl->name));
             return E_FAIL;
         }
@@ -517,6 +529,7 @@ static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat)
 
     dim_decl->next = ctx->dim_decls;
     ctx->dim_decls = stat->dim_decls;
+    ctx->func->var_cnt++;
     return S_OK;
 }
 
@@ -627,12 +640,14 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f
 
     resolve_labels(ctx, func->code_off);
 
-    if(ctx->dim_decls) {
+    if(func->var_cnt) {
         dim_decl_t *dim_decl;
 
         if(func->type == FUNC_GLOBAL) {
             dynamic_var_t *new_var;
 
+            func->var_cnt = 0;
+
             for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
                 new_var = compiler_alloc(ctx->code, sizeof(*new_var));
                 if(!new_var)
@@ -648,7 +663,19 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f
                 ctx->global_vars = new_var;
             }
         }else {
-            FIXME("var not implemented for functions\n");
+            unsigned i;
+
+            func->vars = compiler_alloc(ctx->code, func->var_cnt * sizeof(var_desc_t));
+            if(!func->vars)
+                return E_OUTOFMEMORY;
+
+            for(dim_decl = ctx->dim_decls, i=0; dim_decl; dim_decl = dim_decl->next, i++) {
+                func->vars[i].name = compiler_alloc_string(ctx->code, dim_decl->name);
+                if(!func->vars[i].name)
+                    return E_OUTOFMEMORY;
+            }
+
+            assert(i == func->var_cnt);
         }
     }
 
@@ -685,6 +712,8 @@ static HRESULT create_function(compile_ctx_t *ctx, function_decl_t *decl, functi
     if(!func->name)
         return E_OUTOFMEMORY;
 
+    func->vars = NULL;
+    func->var_cnt = 0;
     func->code_ctx = ctx->code;
     func->type = decl->type;
 
@@ -808,6 +837,8 @@ static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source)
     ret->global_code.type = FUNC_GLOBAL;
     ret->global_code.name = NULL;
     ret->global_code.code_ctx = ret;
+    ret->global_code.vars = NULL;
+    ret->global_code.var_cnt = 0;
     ret->global_code.arg_cnt = 0;
     ret->global_code.args = NULL;
 
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c
index 9dbce68..bb2c282 100644
--- a/dlls/vbscript/interp.c
+++ b/dlls/vbscript/interp.c
@@ -32,6 +32,7 @@ typedef struct {
     function_t *func;
 
     VARIANT *args;
+    VARIANT *vars;
 
     unsigned stack_size;
     unsigned top;
@@ -88,6 +89,14 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, ref_t *ref)
     DISPID id;
     HRESULT hres;
 
+    for(i=0; i < ctx->func->var_cnt; i++) {
+        if(!strcmpiW(ctx->func->vars[i].name, name)) {
+            ref->type = REF_VAR;
+            ref->u.v = ctx->vars+i;
+            return TRUE;
+        }
+    }
+
     for(i=0; i < ctx->func->arg_cnt; i++) {
         if(!strcmpiW(ctx->func->args[i].name, name)) {
             ref->type = REF_VAR;
@@ -827,14 +836,20 @@ OP_LIST
 
 static void release_exec(exec_ctx_t *ctx)
 {
-    if(ctx->args) {
-        unsigned i;
+    unsigned i;
 
+    if(ctx->args) {
         for(i=0; i < ctx->func->arg_cnt; i++)
             VariantClear(ctx->args+i);
     }
 
+    if(ctx->vars) {
+        for(i=0; i < ctx->func->var_cnt; i++)
+            VariantClear(ctx->vars+i);
+    }
+
     heap_free(ctx->args);
+    heap_free(ctx->vars);
     heap_free(ctx->stack);
 }
 
@@ -885,6 +900,16 @@ HRESULT exec_script(script_ctx_t *ctx, function_t *func, DISPPARAMS *dp, VARIANT
         exec.args = NULL;
     }
 
+    if(func->var_cnt) {
+        exec.vars = heap_alloc_zero(func->var_cnt * sizeof(VARIANT));
+        if(!exec.vars) {
+            release_exec(&exec);
+            return E_OUTOFMEMORY;
+        }
+    }else {
+        exec.vars = NULL;
+    }
+
     exec.stack_size = 16;
     exec.top = 0;
     exec.stack = heap_alloc(exec.stack_size * sizeof(VARIANT));
diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs
index 1140326..a46394b 100644
--- a/dlls/vbscript/tests/lang.vbs
+++ b/dlls/vbscript/tests/lang.vbs
@@ -230,4 +230,15 @@ Call TestSubExit(true)
 TestSubMultiArgs 1, 2, 3, 4, 5
 Call TestSubMultiArgs(1, 2, 3, 4, 5)
 
+Sub TestSubLocalVal
+    x = false
+    Call ok(not x, "local x is not false?")
+    Dim x
+End Sub
+
+x = true
+y = true
+Call TestSubLocalVal
+Call ok(x, "global x is not true?")
+
 reportSuccess()
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h
index 1362d9e..cf625cc 100644
--- a/dlls/vbscript/vbscript.h
+++ b/dlls/vbscript/vbscript.h
@@ -167,11 +167,17 @@ typedef enum {
     FUNC_SUB
 } function_type_t;
 
+typedef struct {
+    const WCHAR *name;
+} var_desc_t;
+
 struct _function_t {
     function_type_t type;
     const WCHAR *name;
     arg_desc_t *args;
     unsigned arg_cnt;
+    var_desc_t *vars;
+    unsigned var_cnt;
     unsigned code_off;
     vbscode_t *code_ctx;
     function_t *next;




More information about the wine-cvs mailing list