From 0b9b021aa3f3a9412f588d8a25f72bb9a7f524d7 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 14 Sep 2011 12:57:37 +0200 Subject: [PATCH] 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 84a97a7610..dd756b3377 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 9dbce6869c..bb2c282a5f 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 1140326394..a46394b61f 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 1362d9ed4f..cf625cc911 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; -- 2.33.8