vbscript: Added support for sub local variables.
authorJacek Caban <jacek@codeweavers.com>
Wed, 14 Sep 2011 10:57:37 +0000 (12:57 +0200)
committerAlexandre Julliard <julliard@winehq.org>
Wed, 14 Sep 2011 12:56:36 +0000 (14:56 +0200)
dlls/vbscript/compile.c
dlls/vbscript/interp.c
dlls/vbscript/tests/lang.vbs
dlls/vbscript/vbscript.h

index 84a97a7610e5b36150d087a2530aac9c7ffd7a6b..dd756b33773d1ca4972cfa1e9740f79147780333 100644 (file)
@@ -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;
 
index 9dbce6869cf6d40d31925ceb0a4316d6a0783abb..bb2c282a5f54ebb82108f1dd5be7a91f985a8594 100644 (file)
@@ -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));
index 11403263949738d0bfc76ce0db8244472d119826..a46394b61fb210b7cd2f88d71822df7f693004e2 100644 (file)
@@ -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()
index 1362d9ed4faa006f384c2b234e719a7452a57b37..cf625cc911f4bb31ba23ee87a1d86c3fa7084d00 100644 (file)
@@ -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;