Module: wine Branch: master Commit: 0b9b021aa3f3a9412f588d8a25f72bb9a7f524d7 URL: http://source.winehq.org/git/wine.git/?a=commit;h=0b9b021aa3f3a9412f588d8a25...
Author: Jacek Caban jacek@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;