Module: wine Branch: master Commit: e0d027830e6d359d390c257bbb5419157d9d5aac URL: https://gitlab.winehq.org/wine/wine/-/commit/e0d027830e6d359d390c257bbb54191...
Author: Robert Wilhelm robert.wilhelm@gmx.net Date: Wed Dec 6 12:48:30 2023 +0100
vbscript: For for loop bounds coerce string to real.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55052
---
dlls/vbscript/compile.c | 6 ++++-- dlls/vbscript/interp.c | 31 +++++++++++++++++++++++++++++++ dlls/vbscript/tests/lang.vbs | 27 +++++++++++++++++++++++++++ dlls/vbscript/vbscript.h | 1 + 4 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 683c71e2f4e..baddc51d7e4 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -875,6 +875,8 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st hres = compile_expression(ctx, stat->from_expr); if(FAILED(hres)) return hres; + if(!push_instr(ctx, OP_numval)) + return E_OUTOFMEMORY;
/* FIXME: Assign should happen after both expressions evaluation. */ instr = push_instr(ctx, OP_assign_ident); @@ -887,7 +889,7 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st if(FAILED(hres)) return hres;
- if(!push_instr(ctx, OP_val)) + if(!push_instr(ctx, OP_numval)) return E_OUTOFMEMORY;
if(stat->step_expr) { @@ -895,7 +897,7 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st if(FAILED(hres)) return hres;
- if(!push_instr(ctx, OP_val)) + if(!push_instr(ctx, OP_numval)) return E_OUTOFMEMORY; }else { hres = push_instr_int(ctx, OP_int, 1); diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index 2d979f07605..937cdaf1c8c 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -1088,6 +1088,37 @@ static HRESULT interp_val(exec_ctx_t *ctx) return stack_push(ctx, val.owned ? val.v : &v); }
+static HRESULT interp_numval(exec_ctx_t *ctx) +{ + variant_val_t val; + VARIANT v; + HRESULT hres; + + TRACE("\n"); + + hres = stack_pop_val(ctx, &val); + if(FAILED(hres)) + return hres; + + if (V_VT(val.v) == VT_BSTR) { + V_VT(&v) = VT_EMPTY; + hres = VariantChangeType(&v, val.v, 0, VT_R8); + if(FAILED(hres)) + return hres; + release_val(&val); + return stack_push(ctx, &v); + } + + if(!val.owned) { + V_VT(&v) = VT_EMPTY; + hres = VariantCopy(&v, val.v); + if(FAILED(hres)) + return hres; + } + + return stack_push(ctx, val.owned ? val.v : &v); +} + static HRESULT interp_pop(exec_ctx_t *ctx) { const unsigned n = ctx->instr->arg1.uint; diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 42af6df0e76..3c6ce656f1c 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -679,6 +679,33 @@ for x = 5 to 8 next Call ok(y = "for8: 5 7", "y = " & y)
+function testfor( startvalue, endvalue, stepvalue, steps) + Dim s + s=0 + for x=startvalue to endvalue step stepvalue + s = s + 1 + Next + Call ok( s = steps, "counted " & s & " steps in for loop, expected " & steps) +end function + +Call testfor (1, 2, 1, 2) +Call testfor ("1", 2, 1, 2) +Call testfor (1, "2", 1, 2) +Call testfor (1, 2, "1", 2) +Call testfor ("1", "2", "1", 2) +if (isEnglishLang) then + Call testfor (1, 2, 0.5, 3) + Call testfor (1, 2.5, 0.5, 4) + Call testfor ("1", 2, 0.5, 3) + Call testfor ("1", 2.5, 0.5, 4) + Call testfor (1, "2", 0.5, 3) + Call testfor (1, "2.5", 0.5, 4) + Call testfor (1, 2, "0.5", 3) + Call testfor (1, 2.5, "0.5", 4) + Call testfor ("1", "2", "0.5", 3) + Call testfor ("1", "2.5", "0.5", 4) +end if + for x = 1.5 to 1 Call ok(false, "for..to called when unexpected") next diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index 24915a5ca04..56e68411f45 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -278,6 +278,7 @@ typedef enum { X(not, 1, 0, 0) \ X(nothing, 1, 0, 0) \ X(null, 1, 0, 0) \ + X(numval, 1, 0, 0) \ X(or, 1, 0, 0) \ X(pop, 1, ARG_UINT, 0) \ X(redim, 1, ARG_BSTR, ARG_UINT) \